[
  {
    "path": "README.md",
    "content": "#1、 IM 运行环境\n\t1. Linux CentOS\n\t2. Oracle jdk 1.8。\n\n#2、 运行文件部署\n##2.1 数据库建表\n\t1. 在数据库创建数据库tigase，并给tigase库授权用户(建议创建新用户，例如：tigase)。\n\t2. 导入tigase.sql文件\n\t3. 执行下面命令，手动创建管理员用户名和密码(可以自定义domian，与init.properties文件中对应，例如 app.im)：call TigAddUserPlainPw('admin@domian',xx);\n\n##2.2 部署文件包tigase.tar.gz\n\t1. 将tigase.gz解压到/usr/local目录。\n\t2. 执行ln -s /usr/local/tigase/scripts/tigase.sh /usr/bin/tigase创建软连接。\n\t3. 修改 /usr/local/tigase/etc/init.properties文件。修改下列数据库连接的相关配置项（ip、port、user、pwd）\n\t\n```\n\t\t--admins=admin@domain\n\t\t--virt-hosts = domain\n\t\t--user-db-uri=jdbc:mysql://ip:port/tigase?user=user&password=pwd&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\n\t\t#维护apns记录\n\t\tsess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:\\xmpp-bind/apns-token-db-uri=jdbc:mysql://ip:port/tigase?user=user&password=pwd&useUnicode=true&characterEncoding=UTF8\n```\n\n\n\t4.创建 /usr/local/tigase/etc/init-apns.properties文件。APNs_HTMessage_Dev.p12文件保存在etc目录下\n```\n\t\tcert_file=APNs_HTMessage_Dev.p12\n\t\t#cert_file=htmessage_production_APNs.p12\n\t\t#cert_file=HTMessage_Dev_APNs.p12\n\t\tpwd=123456\n\t\texecutor_size=20\n\t\tmaxConnections=20\n```\n\n\n##2.3 系统相关设置\n\t1.添加环境变量。修改 /etc/profile 文件，在末尾添加如下，然后执行source /etc/profile 使环境变量立即生效\n```\n\texport TIGASE_HOME=/usr/local/tigase\n\texport JAVA_HOME=/usr/java/jdk1.8.0_45/\n\texport CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar\n\texport PATH=$JAVA_HOME/bin:$PATH\n\t\n\tJAVA_HOME指向jdk实际安装目录\n```\n\t\n##2.4 IM服务器的启动，停止，重启\n\t启动命令： tigase start\n \t停止命令： tigase stop\n \t\n##2.5 登录测试\n\n![](/images/002.jpg)\n![](/images/001.jpg))\n\t\n#3.为所有消息加上时间戳 C-101\n\t OfflineMessages.java  \n\t Message.java\t\n\n#4.类型为5000的消息不存库 C-102\n\tOfflineMessages.java \n\t\n#5. Apns 相关 C-103\n\tBindResource.java\n\tTigase.apns.*\n\tMessagePush.java\n\t\n#6.消息回执相关 C-110\n\tMessage.java\n\tMessageReceipts.java\n\tTigase.receipt.*\n\t\n\t\n\t\n----------\n# 相关工程 #\n \n#最具诚意的开源IM系统 YiChat#\n1. github地址:[https://github.com/YiChat](https://github.com/YiChat)\n2. 开源中国地址:[https://git.oschina.net/zhangfeng_tech](https://git.oschina.net/zhangfeng_tech)\n\n\n##本项目的开源内容##\n\n\n###已开源的所有源码:###\n1. IM服务器(负责即时通讯消息)-直接部署,无需修改参数\n2. api服务器(非IM模块相关的其他业务逻辑)-修改一处参数,详见工程下文档\n3. android客户端-配置参数,连接自己的服务器ip.详见工程文档\n\n###待开源的工程源码:###\n\n- iOS客户端:前面三个工程的github star数超过3000马上开源\n\n##这个开源项目的意义在于##\n1. 拥有自己的IM服务器,不再受制于第三方通讯云的限制.\n2. 提供了一个完善优化的客户端源码,具体参见体验包:\n    \n - Android:[https://www.pgyer.com/YiChatLite](https://www.pgyer.com/YiChatLite)\n - iOS:[https://www.pgyer.com/9sVQ](https://www.pgyer.com/9sVQ)\n\n\n\t\n##QQ:84543217 (技术相关请提交Issus,商务合作可联系QQ)\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\n"
  },
  {
    "path": "tigase-server 7.1.0/License.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n<html><head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <title>GNU Affero General Public License - GNU Project - Free Software Foundation (FSF)</title>\n</head>\n <link rel=\"alternate\" type=\"application/rdf+xml\"\n       href=\"http://www.gnu.org/licenses/agpl-3.0.rdf\" />\n<body>\n<h3 style=\"text-align: center;\">GNU AFFERO GENERAL PUBLIC LICENSE</h3>\n<p style=\"text-align: center;\">Version 3, 19 November 2007</p>\n\n<p>Copyright &copy; 2007 Free Software Foundation,\nInc. &lt;<a href=\"http://fsf.org/\">http://fsf.org/</a>&gt;\n <br />\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.</p>\n\n<h3><a name=\"preamble\"></a>Preamble</h3>\n\n<p>The GNU Affero General Public License is a free, copyleft license\nfor software and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.</p>\n\n<p>The licenses for most software and other practical works are\ndesigned to take away your freedom to share and change the works.  By\ncontrast, our General Public Licenses are intended to guarantee your\nfreedom to share and change all versions of a program--to make sure it\nremains free software for all its users.</p>\n\n<p>When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.</p>\n\n<p>Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.</p>\n\n<p>A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.</p>\n\n<p>The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.</p>\n\n<p>An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.</p>\n\n<p>The precise terms and conditions for copying, distribution and\nmodification follow.</p>\n\n<h3><a name=\"terms\"></a>TERMS AND CONDITIONS</h3>\n\n<h4><a name=\"section0\"></a>0. Definitions.</h4>\n\n<p>&quot;This License&quot; refers to version 3 of the GNU Affero General Public\nLicense.</p>\n\n<p>&quot;Copyright&quot; also means copyright-like laws that apply to other kinds\nof works, such as semiconductor masks.</p>\n\n<p>&quot;The Program&quot; refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as &quot;you&quot;.  &quot;Licensees&quot; and\n&quot;recipients&quot; may be individuals or organizations.</p>\n\n<p>To &quot;modify&quot; a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a &quot;modified version&quot; of the\nearlier work or a work &quot;based on&quot; the earlier work.</p>\n\n<p>A &quot;covered work&quot; means either the unmodified Program or a work based\non the Program.</p>\n\n<p>To &quot;propagate&quot; a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.</p>\n\n<p>To &quot;convey&quot; a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.</p>\n\n<p>An interactive user interface displays &quot;Appropriate Legal Notices&quot;\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.</p>\n\n<h4><a name=\"section1\"></a>1. Source Code.</h4>\n\n<p>The &quot;source code&quot; for a work means the preferred form of the work\nfor making modifications to it.  &quot;Object code&quot; means any non-source\nform of a work.</p>\n\n<p>A &quot;Standard Interface&quot; means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.</p>\n\n<p>The &quot;System Libraries&quot; of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n&quot;Major Component&quot;, in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.</p>\n\n<p>The &quot;Corresponding Source&quot; for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.</p>\n\n<p>The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.</p>\n\n<p>The Corresponding Source for a work in source code form is that\nsame work.</p>\n\n<h4><a name=\"section2\"></a>2. Basic Permissions.</h4>\n\n<p>All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.</p>\n\n<p>You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.</p>\n\n<p>Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.</p>\n\n<h4><a name=\"section3\"></a>3. Protecting Users' Legal Rights From Anti-Circumvention Law.</h4>\n\n<p>No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.</p>\n\n<p>When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.</p>\n\n<h4><a name=\"section4\"></a>4. Conveying Verbatim Copies.</h4>\n\n<p>You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.</p>\n\n<p>You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.</p>\n\n<h4><a name=\"section5\"></a>5. Conveying Modified Source Versions.</h4>\n\n<p>You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:</p>\n\n<ul>\n\n<li>a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.</li>\n\n<li>b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    &quot;keep intact all notices&quot;.</li>\n\n<li>c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.</li>\n\n<li>d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.</li>\n\n</ul>\n\n<p>A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n&quot;aggregate&quot; if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.</p>\n\n<h4><a name=\"section6\"></a>6. Conveying Non-Source Forms.</h4>\n\n<p>You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:</p>\n\n<ul>\n\n<li>a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.</li>\n\n<li>b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.</li>\n\n<li>c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.</li>\n\n<li>d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.</li>\n\n<li>e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.</li>\n\n</ul>\n\n<p>A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.</p>\n\n<p>A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, &quot;normally used&quot; refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.</p>\n\n<p>&quot;Installation Information&quot; for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.</p>\n\n<p>If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).</p>\n\n<p>The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.</p>\n\n<p>Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.</p>\n\n<h4><a name=\"section7\"></a>7. Additional Terms.</h4>\n\n<p>&quot;Additional permissions&quot; are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.</p>\n\n<p>When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.</p>\n\n<p>Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:</p>\n\n<ul>\n\n<li>a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or</li>\n\n<li>b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or</li>\n\n<li>c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or</li>\n\n<li>d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or</li>\n\n<li>e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or</li>\n\n<li>f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.</li>\n\n</ul>\n\n<p>All other non-permissive additional terms are considered &quot;further\nrestrictions&quot; within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further restriction,\nyou may remove that term.  If a license document contains a further\nrestriction but permits relicensing or conveying under this License, you\nmay add to a covered work material governed by the terms of that license\ndocument, provided that the further restriction does not survive such\nrelicensing or conveying.</p>\n\n<p>If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.</p>\n\n<p>Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.</p>\n\n<h4><a name=\"section8\"></a>8. Termination.</h4>\n\n<p>You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).</p>\n\n<p>However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.</p>\n\n<p>Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.</p>\n\n<p>Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.</p>\n\n<h4><a name=\"section9\"></a>9. Acceptance Not Required for Having Copies.</h4>\n\n<p>You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.</p>\n\n<h4><a name=\"section10\"></a>10. Automatic Licensing of Downstream Recipients.</h4>\n\n<p>Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.</p>\n\n<p>An &quot;entity transaction&quot; is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.</p>\n\n<p>You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.</p>\n\n<h4><a name=\"section11\"></a>11. Patents.</h4>\n\n<p>A &quot;contributor&quot; is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's &quot;contributor version&quot;.</p>\n\n<p>A contributor's &quot;essential patent claims&quot; are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, &quot;control&quot; includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.</p>\n\n<p>Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.</p>\n\n<p>In the following three paragraphs, a &quot;patent license&quot; is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To &quot;grant&quot; such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.</p>\n\n<p>If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  &quot;Knowingly relying&quot; means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.</p>\n\n<p>If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.</p>\n\n<p>A patent license is &quot;discriminatory&quot; if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.</p>\n\n<p>Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.</p>\n\n<h4><a name=\"section12\"></a>12. No Surrender of Others' Freedom.</h4>\n\n<p>If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.</p>\n\n<h4><a name=\"section13\"></a>13. Remote Network Interaction; Use with the GNU General Public License.</h4>\n\n<p>Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.</p>\n\n<p>Notwithstanding any other provision of this License, you have permission\nto link or combine any covered work with a work licensed under version 3\nof the GNU General Public License into a single combined work, and to\nconvey the resulting work.  The terms of this License will continue to\napply to the part which is the covered work, but the work with which it is\ncombined will remain governed by version 3 of the GNU General Public\nLicense.</p>\n\n<h4><a name=\"section14\"></a>14. Revised Versions of this License.</h4>\n\n<p>The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new\nversions will be similar in spirit to the present version, but may differ\nin detail to address new problems or concerns.</p>\n\n<p>Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero\nGeneral Public License &quot;or any later version&quot; applies to it, you have\nthe option of following the terms and conditions either of that\nnumbered version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number\nof the GNU Affero General Public License, you may choose any version\never published by the Free Software Foundation.</p>\n\n<p>If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that\nproxy's public statement of acceptance of a version permanently\nauthorizes you to choose that version for the Program.</p>\n\n<p>Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.</p>\n\n<h4><a name=\"section15\"></a>15. Disclaimer of Warranty.</h4>\n\n<p>THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>\n\n<h4><a name=\"section16\"></a>16. Limitation of Liability.</h4>\n\n<p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.</p>\n\n<h4><a name=\"section17\"></a>17. Interpretation of Sections 15 and 16.</h4>\n\n<p>If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.</p>\n\n<p>END OF TERMS AND CONDITIONS</p>\n\n<h3><a name=\"howto\"></a>How to Apply These Terms to Your New Programs</h3>\n\n<p>If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.</p>\n\n<p>To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe &quot;copyright&quot; line and a pointer to where the full notice is found.</p>\n\n<pre>    &lt;one line to give the program's name and a brief idea of what it does.&gt;\n    Copyright (C) &lt;year&gt;  &lt;name of author&gt;\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as\n    published by the Free Software Foundation, either version 3 of the\n    License, or (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.\n</pre>\n\n<p>Also add information on how to contact you by electronic and paper mail.</p>\n\n<p>If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a &quot;Source&quot; link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.</p>\n\n<p>You should also get your employer (if you work as a programmer) or school,\nif any, to sign a &quot;copyright disclaimer&quot; for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n&lt;<a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>&gt;.</p>\n\n</body></html>\n"
  },
  {
    "path": "tigase-server 7.1.0/conf/config.properties",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n#\n# Framework config properties.\n#\n\n# To override the packages the framework exports by default from the\n# class path, set this variable.\n#org.osgi.framework.system.packages=\n\n# To append packages to the default set of exported system packages,\n# set this value.\n#org.osgi.framework.system.packages.extra=javax.*\n\n# The following property makes specified packages from the class path\n# available to all bundles. You should avoid using this property.\norg.osgi.framework.bootdelegation=sun.*,com.sun.*,org.xml.sax.*\n\n# Felix tries to guess when to implicitly boot delegate in certain\n# situations to ease integration without outside code. This feature\n# is enabled by default, uncomment the following line to disable it.\n#felix.bootdelegation.implicit=false\n\n# The following property explicitly specifies the location of the bundle\n# cache, which defaults to \"felix-cache\" in the current working directory.\n# If this value is not absolute, then the felix.cache.rootdir controls\n# how the absolute location is calculated. (See next property)\n#org.osgi.framework.storage=${dollar}{felix.cache.rootdir}/felix-cache\n\n# The following property is used to convert a relative bundle cache\n# location into an absolute one by specifying the root to prepend to\n# the relative cache path. The default for this property is the\n# current working directory.\n#felix.cache.rootdir=${dollar}{user.dir}\n\n# The following property controls whether the bundle cache is flushed\n# the first time the framework is initialized. Possible values are\n# \"none\" and \"onFirstInit\"; the default is \"none\".\norg.osgi.framework.storage.clean=onFirstInit\n\n# The following property determines which actions are performed when\n# processing the auto-deploy directory. It is a comma-delimited list of\n# the following values: 'install', 'start', 'update', and 'uninstall'.\n# An undefined or blank value is equivalent to disabling auto-deploy\n# processing.\nfelix.auto.deploy.action=install,start\n\n# The following property specifies the directory to use as the bundle\n# auto-deploy directory; the default is 'bundle' in the working directory.\nfelix.auto.deploy.dir=jars\n\n# The following property is a space-delimited list of bundle URLs\n# to install when the framework starts. The ending numerical component\n# is the target start level. Any number of these properties may be\n# specified for different start levels.\n#felix.auto.install.1=\n\n# The following property is a space-delimited list of bundle URLs\n# to install and start when the framework starts. The ending numerical\n# component is the target start level. Any number of these properties\n# may be specified for different start levels.\n#felix.auto.start.1=\n\nfelix.log.level=1\n\n# Sets the initial start level of the framework upon startup.\n#org.osgi.framework.startlevel.beginning=1\n\n# Sets the start level of newly installed bundles.\n#felix.startlevel.bundle=1\n\n# Felix installs a stream and content handler factories by default,\n# uncomment the following line to not install them.\n#felix.service.urlhandlers=false\n\n# The launcher registers a shutdown hook to cleanly stop the framework\n# by default, uncomment the following line to disable it.\nfelix.shutdown.hook=true\n\n#\n# Bundle config properties.\n#\n\nosgi.shell.telnet.ip=127.0.0.1\nosgi.shell.telnet.port=9070\nosgi.shell.telnet.maxconn=2\nosgi.shell.telnet.socketTimeout=0\n\n# debugging\n#felix.log.level=4\n#org.apache.felix.http.debug=true"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-installer-create-db.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-installer-post.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-4-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- This is a dummy user who keeps all the database-properties\n-- QUERY START:\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '4.0');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-4-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\ncreate table tig_users (\n\tuid BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,\n\n\t-- Jabber User ID\n\tuser_id varchar(2049) NOT NULL,\n\t-- User password encrypted or not\n\tuser_pw varchar(255) default NULL,\n\t-- Time the account has been created\n\tacc_create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n\t-- Time of the last user login\n\tlast_login timestamp,\n\t-- Time of the last user logout\n\tlast_logout timestamp,\n\t-- User online status, if > 0 then user is online, the value\n\t-- indicates the number of user connections.\n\t-- It is incremented on each user login and decremented on each\n\t-- user logout.\n\tonline_status int default 0,\n\t-- Number of failed login attempts\n\tfailed_logins int default 0,\n\t-- User status, whether the account is active or disabled\n\t-- >0 - account active, 0 - account disabled\n\taccount_status int default 1\n);\n-- QUERY END:\n\n-- QUERY START:\ncreate unique index user_id on tig_users ( user_id );\n-- QUERY END:\n-- QUERY START:\ncreate index user_pw on tig_users (user_pw);\n-- QUERY END:\n-- QUERY START:\ncreate index last_login on tig_users (last_login);\n-- QUERY END:\n-- QUERY START:\ncreate index last_logout on tig_users (last_logout);\n-- QUERY END:\n-- QUERY START:\ncreate index account_status on tig_users (account_status);\n-- QUERY END:\n-- QUERY START:\ncreate index online_status on tig_users (online_status);\n-- QUERY END:\n\n-- QUERY START:\ncreate table tig_nodes (\n\tnid BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,\n\tparent_nid bigint,\n\tuid bigint NOT NULL references tig_users(uid),\n\tnode varchar(255) NOT NULL\n);\n-- QUERY END:\n-- QUERY START:\ncreate unique index tnode on tig_nodes ( parent_nid, uid, node );\n-- QUERY END:\n-- QUERY START:\ncreate index node on tig_nodes ( node );\n-- QUERY END:\n-- QUERY START:\n-- The new index is a duplicate of an existing index\ncreate index nuid on tig_nodes (uid);\n-- QUERY END:\n-- QUERY START:\ncreate index parent_nid on tig_nodes (parent_nid);\n-- QUERY END:\n\n-- QUERY START:\ncreate table tig_pairs (\n\tnid bigint references tig_nodes(nid),\n\tuid bigint NOT NULL references tig_users(uid),\n\tpkey varchar(255) NOT NULL,\n\tpval long varchar\n);\n-- QUERY END:\n-- QUERY START:\n-- The new index is a duplicate of an existing index\ncreate index pkey on tig_pairs ( pkey );\n-- QUERY END:\n-- QUERY START:\n-- The new index is a duplicate of an existing index\ncreate index puid on tig_pairs (uid);\n-- QUERY END:\n-- QUERY START:\ncreate index pnid on tig_pairs (nid);\n-- QUERY END:\n\n-- QUERY START:\ncreate table short_news (\n\tsnid BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,\n\tpublishing_time timestamp default current timestamp,\n\tnews_type varchar(10),\n\tauthor varchar(128) NOT NULL,\n\tsubject varchar(128) NOT NULL,\n\tbody varchar(1024) NOT NULL\n);\n-- QUERY END:\n-- QUERY START:\ncreate index publishing_time on short_news (publishing_time);\n-- QUERY END:\n-- QUERY START:\ncreate index author on short_news (author);\n-- QUERY END:\n-- QUERY START:\ncreate index news_type on short_news (news_type);\n-- QUERY END:\n\n-- QUERY START:\ncreate table xmpp_stanza (\n\tid BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,\n\tstanza long varchar NOT NULL\n);\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-4-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\nCREATE function TigGetDBProperty(tkey varchar(255)) returns long varchar\n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigGetDBProperty';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigPutDBProperty(tkey varchar(255), tval varchar(32672)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigPutDBProperty';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigInitdb() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigInitdb';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigAddUser(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAddUser';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigAddUserPlainPw(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAddUserPlainPw';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigGetUserDBUid(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigGetUserDBUid';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigRemoveUser(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigRemoveUser';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigGetPassword(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigGetPassword';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUpdatePasswordPlainPwRev(userId varchar(2049), userPw varchar(255))\n  PARAMETER STYLE JAVA\n  LANGUAGE JAVA\n  MODIFIES SQL DATA\n  EXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePasswordPlainPwRev';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUpdatePasswordPlainPw(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePasswordPlainPw';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUpdatePassword(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePassword';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigOnlineUsers() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigOnlineUsers';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigOfflineUsers() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigOfflineUsers';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigAllUsers() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAllUsers';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigAllUsersCount() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAllUsersCount';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUserLoginPlainPw(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUserLoginPlainPw';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUserLogin(userId varchar(2049), userPw varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUserLogin';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUserLogout(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUserLogout';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigDisableAccount(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigDisableAccount';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigEnableAccount(userId varchar(2049)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigEnableAccount';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigActiveAccounts() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigActiveAccounts';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigDisabledAccounts() \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tREADS SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigDisabledAccounts';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigAddNode(parentNid bigint, uid bigint, node varchar(255)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tDYNAMIC RESULT SETS 1\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAddNode';\n-- QUERY END:\n\n-- QUERY START:\nCREATE procedure TigUpdatePairs(nid bigint, uid bigint, tkey varchar(255), tval varchar(32672)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePairs';\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-4.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- LOAD FILE: database/derby-schema-4-schema.sql\n\n-- LOAD FILE: database/derby-schema-4-sp.sql\n\n-- LOAD FILE: database/derby-schema-4-props.sql\n\nrun 'database/derby-schema-4-schema.sql';\n\nrun 'database/derby-schema-4-sp.sql';\n\nrun 'database/derby-schema-4-props.sql';\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-5-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- This is a dummy user who keeps all the database-properties\n-- QUERY START:\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '5.1');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-5-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nrun 'database/derby-schema-4-schema.sql';\n\n-- LOAD FILE: database/derby-schema-4-schema.sql\n\n-- QUERY START:\nalter table tig_pairs ADD column pval2 CLOB;\n-- QUERY END:\n\n-- QUERY START:\nupdate tig_pairs set pval2=pval;\n-- QUERY END:\n\n-- QUERY START:\nalter table tig_pairs drop column pval;\n-- QUERY END:\n\n-- QUERY START:\nRENAME COLUMN tig_pairs.pval2 to pval;\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-5-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nrun 'database/derby-schema-4-sp.sql';\n\n-- LOAD FILE: database/derby-schema-4-sp.sql\n\n-- QUERY START:\ndrop procedure TigUpdatePairs;\n-- QUERY END:\n\n\n-- QUERY START:\nCREATE procedure TigUpdatePairs(nid bigint, uid bigint, tkey varchar(255), tval clob) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePairs';\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nrun 'database/derby-schema-5-1-schema.sql';\n\nrun 'database/derby-schema-5-1-sp.sql';\n\nrun 'database/derby-schema-5-1-props.sql';\n\n-- LOAD FILE: database/derby-schema-5-1-schema.sql\n\n-- LOAD FILE: database/derby-schema-5-1-sp.sql\n\n-- LOAD FILE: database/derby-schema-5-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-5.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nrun 'database/derby-schema-4-schema.sql';\n\nrun 'database/derby-schema-4-sp.sql';\n\nrun 'database/derby-schema-4-props.sql';\n\n-- LOAD FILE: database/derby-schema-4-schema.sql\n\n-- LOAD FILE: database/derby-schema-4-sp.sql\n\n-- LOAD FILE: database/derby-schema-4-props.sql"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-7-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- This is a dummy user who keeps all the database-properties\n-- QUERY START:\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-7-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\nrun 'database/derby-schema-5-1-schema.sql';\n\n-- LOAD FILE: database/derby-schema-5-1-schema.sql\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD COLUMN PID INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL PRIMARY KEY;\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-7-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\nrun 'database/derby-schema-5-1-sp.sql';\n\n-- LOAD FILE: database/derby-schema-5-1-sp.sql\n\n-- QUERY START:\ndrop procedure TigPutDBProperty;\n-- QUERY END:\n\n\n-- QUERY START:\nCREATE procedure TigPutDBProperty(tkey varchar(255), tval varchar(32672)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigPutDBProperty';\n-- QUERY END:"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\nrun 'database/derby-schema-7-1-schema.sql';\n\nrun 'database/derby-schema-7-1-sp.sql';\n\nrun 'database/derby-schema-7-1-props.sql';\n\n-- LOAD FILE: database/derby-schema-7-1-schema.sql\n\n-- LOAD FILE: database/derby-schema-7-1-sp.sql\n\n-- LOAD FILE: database/derby-schema-7-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-upgrade-to-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version','5.1');\n-- QUERY END:\n\n-- QUERY START:\ndrop procedure  TigUpdatePairs;\n-- QUERY END:\n\n\n-- QUERY START:\nCREATE procedure TigUpdatePairs(nid bigint, uid bigint, tkey varchar(255), tval clob) \n        PARAMETER STYLE JAVA\n        LANGUAGE JAVA\n        MODIFIES SQL DATA\n        EXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdatePairs';\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/derby-schema-upgrade-to-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n\n\n\n-- QUERY START:\ndrop procedure TigPutDBProperty;\n-- QUERY END:\n\n\n-- QUERY START:\nCREATE procedure TigPutDBProperty(tkey varchar(255), tval varchar(32672)) \n\tPARAMETER STYLE JAVA\n\tLANGUAGE JAVA\n\tMODIFIES SQL DATA\n\tEXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigPutDBProperty';\n-- QUERY END:\n\n-- QUERY START:\nupdate tig_pairs set nid = (select nid from tig_nodes where uid=(select uid from tig_users where user_id='db-properties') and node='root') where uid=(select uid from tig_users where user_id='db-properties');\n-- QUERY END:\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD COLUMN PID INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL PRIMARY KEY;\n-- QUERY END:\n\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version','7.1');\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-installer-create-db.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START: create database\n\ncreate database ${dbName};\n\n-- QUERY END: create database\n\n-- QUERY START: add user\n\nGRANT ALL ON ${dbName}.* TO ${dbUser}@'%' IDENTIFIED BY '${dbPass}';\n\n-- QUERY END: add user\n\n-- QUERY START: add user\n\nGRANT ALL ON ${dbName}.* TO ${dbUser}@'localhost' IDENTIFIED BY '${dbPass}';\n\n-- QUERY END: add user\n\n-- QUERY START: add user\n\nGRANT ALL ON ${dbName}.* TO ${dbUser} IDENTIFIED BY '${dbPass}';\n\n-- QUERY END: user\n\n-- QUERY START: update user privileges\n\nGRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${dbUser}@'localhost';\n\n-- QUERY END: update user privileges\n\n-- QUERY START: update user privileges\n\nGRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${dbUser}@'%';\n\n-- QUERY END: update user privileges\n\n-- QUERY START: update user privileges\n\nGRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${dbUser};\n\n-- QUERY END: update user privileges\n\n-- QUERY START: flush privileges\n\nFLUSH PRIVILEGES;\n\n-- QUERY END: flush privileges\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-installer-post.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-3.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to MySQL database execute following commands:\n--\n--  mysqladmin -u root -pdbpass create tigase\n--  mysql -u root -pdbpass tigase < database/mysql-schema.sql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user@'%' \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user@'localhost' \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n\n\ncreate table short_news (\n  -- Automatic record ID\n  snid            bigint unsigned NOT NULL auto_increment,\n  -- Automaticly generated timestamp and automaticly updated on change\n  publishing_time timestamp,\n\t-- Optional news type: 'shorts', 'minis', 'techs', 'funs'....\n\tnews_type       varchar(10),\n  -- Author JID\n  author          varchar(128) NOT NULL,\n  -- Short subject - this is short news, right?\n  subject         varchar(128) NOT NULL,\n  -- Short news message - this is short news, right?\n  body            varchar(1024) NOT NULL,\n  primary key(snid),\n  key publishing_time (publishing_time),\n  key author (author),\n  key news_type (news_type)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\ncreate table xmpp_stanza (\n\t\t\t id bigint unsigned NOT NULL auto_increment,\n\t\t\t stanza text NOT NULL,\n\n\t\t\t primary key (id)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\ncreate table tig_users (\n       uid bigint unsigned NOT NULL,\n\n       user_id varchar(128) NOT NULL,\n\n       primary key (uid),\n       unique key user_id (user_id)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\ncreate table tig_nodes (\n       nid bigint unsigned NOT NULL,\n       parent_nid bigint unsigned,\n       uid bigint unsigned NOT NULL,\n\n       node varchar(64) NOT NULL,\n\n       primary key (nid),\n       unique key tnode (parent_nid, uid, node),\n       key node (node),\n\t\t\t constraint tig_nodes_constr foreign key (uid) references tig_users (uid)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\ncreate table tig_pairs (\n       nid bigint unsigned,\n       uid bigint unsigned NOT NULL,\n\n       pkey varchar(128) NOT NULL,\n       pval varchar(65535),\n\n       key pkey (pkey),\n\t\t\t constraint tig_pairs_constr_1 foreign key (uid) references tig_users (uid),\n\t\t\t constraint tig_pairs_constr_2 foreign key (nid) references tig_nodes (nid)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\n-- create table tig_max_ids (\n--        max_uid bigint unsigned,\n--        max_nid bigint unsigned\n-- )\n-- ENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\n-- insert into tig_max_ids (max_uid, max_nid) values (1, 1);\n\n-- Get top nodes for the user: user1@hostname\n--\n-- select nid, node from nodes, users\n--   where ('user1@hostname' = user_id)\n--     AND (nodes.uid = users.uid)\n--     AND (parent_nid is null);\n\n-- Get all subnodes of the node: /privacy/default for user: user1@hostname\n--\n-- select nid, node from nodes,\n-- (\n--   select nid as dnid from nodes,\n--   (\n--     select nid as pnid from nodes, users\n--       where ('user1@hostname' = user_id)\n--         AND (nodes.uid = users.uid)\n--         AND (parent_nid is null)\n--         AND (node = 'privacy')\n--   ) ptab where (parent_nid = pnid)\n--       AND (node = 'default')\n-- ) dtab where (parent_nid = dnid);\n\n-- Get all keys (pairs) for the node: /privacy/default/24 for user: user1@hostname\n--\n-- select  pkey, pval from pairs,\n-- (\n--   select nid, node from nodes,\n--   (\n--     select nid as dnid from nodes,\n--     (\n--       select nid as pnid from nodes, users\n--         where ('user1@hostname' = user_id)\n--           AND (nodes.uid = users.uid)\n--     \t  AND (parent_nid is null)\n--     \t  AND (node = 'privacy')\n--     ) ptab where (parent_nid = pnid)\n--         AND (node = 'default')\n--   ) dtab where (parent_nid = dnid)\n-- ) ntab where (pairs.nid = ntab.nid) AND (node = '24');\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-4-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect NOW(), ' - Setting schema version to 4.0';\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '4.0');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-4-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to MySQL database execute following commands:\n--\n--  mysqladmin -u root -pdbpass create tigase\n--  mysql -u root -pdbpass tigase < database/mysql-schema-4.sql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user@'%' \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user@'localhost' \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n--  echo \"GRANT ALL ON tigase.* TO tigase_user \\\n--                  IDENTIFIED BY 'tigase_passwd'; \\\n--                  FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n\n-- QUERY START:\n\ncreate table if not exists tig_users (\n\tuid bigint unsigned NOT NULL auto_increment,\n\n\t-- Jabber User ID\n\tuser_id varchar(2049) NOT NULL,\n\t-- UserID SHA1 hash to prevent duplicate user_ids\n\tsha1_user_id char(128) NOT NULL,\n\t-- User password encrypted or not\n\tuser_pw varchar(255) default NULL,\n\t-- Time the account has been created\n\tacc_create_time timestamp DEFAULT CURRENT_TIMESTAMP,\n\t-- Time of the last user login\n\tlast_login timestamp DEFAULT 0,\n\t-- Time of the last user logout\n\tlast_logout timestamp DEFAULT 0,\n\t-- User online status, if > 0 then user is online, the value\n\t-- indicates the number of user connections.\n\t-- It is incremented on each user login and decremented on each\n\t-- user logout.\n\tonline_status int default 0,\n\t-- Number of failed login attempts\n\tfailed_logins int default 0,\n\t-- User status, whether the account is active or disabled\n\t-- >0 - account active, 0 - account disabled\n\taccount_status int default 1,\n\n\tprimary key (uid),\n\tunique key sha1_user_id (sha1_user_id),\n\tkey user_pw (user_pw),\n--\tkey user_id (user_id(765)),\n\tkey last_login (last_login),\n\tkey last_logout (last_logout),\n\tkey account_status (account_status),\n\tkey online_status (online_status)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;\n\n-- QUERY END:\n\n-- QUERY START:\n\nCREATE INDEX part_of_user_id ON tig_users (user_id(255));\n\n-- QUERY END:\n\n-- QUERY START:\n\ncreate table if not exists tig_nodes (\n       nid bigint unsigned NOT NULL auto_increment,\n       parent_nid bigint unsigned,\n       uid bigint unsigned NOT NULL,\n\n       node varchar(255) NOT NULL,\n\n       primary key (nid),\n       unique key tnode (parent_nid, uid, node),\n       key node (node),\n\t\t\t key uid (uid),\n\t\t\t key parent_nid (parent_nid),\n\t\t\t constraint tig_nodes_constr foreign key (uid) references tig_users (uid)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\n-- QUERY END:\n\n-- QUERY START:\n\ncreate table if not exists tig_pairs (\n       nid bigint unsigned,\n       uid bigint unsigned NOT NULL,\n\n       pkey varchar(255) NOT NULL,\n       pval mediumtext,\n\n       key pkey (pkey),\n\t\t\t key uid (uid),\n\t\t\t key nid (nid),\n\t\t\t constraint tig_pairs_constr_1 foreign key (uid) references tig_users (uid),\n\t\t\t constraint tig_pairs_constr_2 foreign key (nid) references tig_nodes (nid)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;\n\n-- QUERY END:\n\n-- QUERY START:\n\ncreate table if not exists short_news (\n  -- Automatic record ID\n  snid            bigint unsigned NOT NULL auto_increment,\n  -- Automaticly generated timestamp and automaticly updated on change\n  publishing_time timestamp,\n\t-- Optional news type: 'shorts', 'minis', 'techs', 'funs'....\n\tnews_type       varchar(10),\n  -- Author JID\n  author          varchar(128) NOT NULL,\n  -- Short subject - this is short news, right?\n  subject         varchar(128) NOT NULL,\n  -- Short news message - this is short news, right?\n  body            varchar(1024) NOT NULL,\n  primary key(snid),\n  key publishing_time (publishing_time),\n  key author (author),\n  key news_type (news_type)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\n-- QUERY END:\n\n-- QUERY START:\n\ncreate table if not exists xmpp_stanza (\n\t\t\t id bigint unsigned NOT NULL auto_increment,\n\t\t\t stanza text NOT NULL,\n\n\t\t\t primary key (id)\n)\nENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\n\n-- QUERY END:"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-4-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Database stored procedures and functions for Tigase schema version 4.0.0\n\n-- QUERY START:\ndrop procedure if exists TigInitdb;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigAddUser;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigAddUserPlainPw;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigGetUserDBUid;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigRemoveUser;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUpdatePassword;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUpdatePasswordPlainPw;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUpdatePasswordPlainPwRev;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigGetPassword;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUserLogin;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUserLoginPlainPw;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUserLogout;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigOnlineUsers;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigOfflineUsers;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigAllUsers;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigAllUsersCount;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigDisableAccount;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigEnableAccount;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigActiveAccounts;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigDisabledAccounts;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigAddNode;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigTestAddUser;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUsers2Ver4Convert;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigPutDBProperty;\n-- QUERY END:\n-- QUERY START:\ndrop function if exists TigGetDBProperty;\n-- QUERY END:\n-- QUERY START:\ndrop procedure if exists TigUpdatePairs;\n-- QUERY END:\n\ndelimiter //\n\n-- QUERY START:\n-- Database properties get - function\ncreate function TigGetDBProperty(_tkey varchar(255) CHARSET utf8) returns mediumtext CHARSET utf8\nREADS SQL DATA\nbegin\n\tdeclare _result mediumtext CHARSET utf8;\n\n\tselect pval into _result from tig_pairs, tig_users\n\t\twhere (pkey = _tkey) AND (sha1_user_id = sha1(lower('db-properties')))\n\t\t\t\t\tAND (tig_pairs.uid = tig_users.uid);\n\n\treturn (_result);\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure TigPutDBProperty(_tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists( select 1 from tig_pairs, tig_users where\n    (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n    AND (pkey = _tkey))\n  then\n    update tig_pairs, tig_users set pval = _tval\n    where (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n      AND (pkey = _tkey);\n  else\n    insert into tig_pairs (pkey, pval, uid)\n      select _tkey, _tval, uid from tig_users\n        where (sha1_user_id = sha1(lower('db-properties')));\n  end if;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- The initialization of the database.\n-- The procedure should be called manually somehow before starting the\n-- server. In theory the server could call the procedure automatically\n-- at the startup time but I don't know yet how to solve the problem\n-- with multiple cluster nodes starting at later time when the server\n-- is already running.\ncreate procedure TigInitdb()\nbegin\n  update tig_users set online_status = 0;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Add a new user to the database assuming the user password is already\n-- encoded properly according to the database settings.\n-- If password is not encoded TigAddUserPlainPw should be used instead.\ncreate procedure TigAddUser(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tdeclare res_uid bigint unsigned;\n\n\tinsert into tig_users (user_id, sha1_user_id, user_pw)\n\t\tvalues (_user_id, sha1(lower(_user_id)), _user_pw);\n\n\tselect LAST_INSERT_ID() into res_uid;\n\n\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (NULL, res_uid, 'root');\n\n\tif _user_pw is NULL then\n\t\tupdate tig_users set account_status = -1 where uid = res_uid;\n\tend if;\n\n\tselect res_uid as uid;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\n-- and creates a new user account.\ncreate procedure TigAddUserPlainPw(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigAddUser(_user_id, _user_pw);\n\t\tend case;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Low level database user id as big number. Used only for performance reasons\n-- and save database space. Besides JID is too large to server as UID\ncreate procedure TigGetUserDBUid(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tselect uid from tig_users where sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Removes a user from the database\ncreate procedure TigRemoveUser(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tdeclare res_uid bigint unsigned;\n\n\tselect uid into res_uid from tig_users where sha1_user_id = sha1(lower(_user_id));\n\n\tdelete from tig_pairs where uid = res_uid;\n\tdelete from tig_nodes where uid = res_uid;\n\tdelete from tig_users where uid = res_uid;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Returns user's password from the database\ncreate procedure TigGetPassword(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tselect user_pw from tig_users where sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\ncreate procedure TigUpdatePasswordPlainPw(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigUpdatePassword(_user_id, _user_pw);\n\t\tend case;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Variant of TigUpdatePasswordPlainPw SP with parameters in reverse order.\n-- Some implementations require the parameters to be in the same order as\n-- the update query.\ncreate procedure TigUpdatePasswordPlainPwRev(_user_pw varchar(255) CHARSET utf8, _user_id varchar(2049) CHARSET utf8)\nbegin\n\tcall TigUpdatePasswordPlainPw(_user_id, _user_pw);\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Update user password\ncreate procedure TigUpdatePassword(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tupdate tig_users set user_pw = _user_pw where sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- List all online users\ncreate procedure TigOnlineUsers()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status > 0;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- List all offline users\ncreate procedure TigOfflineUsers()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status = 0;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- List of all users in database\ncreate procedure TigAllUsers()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- All users count\ncreate procedure TigAllUsersCount()\nbegin\n\tselect count(*) from tig_users;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Performs user login for a plain text password, converting it to an internal\n-- representation if necessary\ncreate procedure TigUserLoginPlainPw(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigUserLogin(_user_id, _user_pw);\n\t\tend case;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Perforrm user login. It returns user_id uppon success and NULL\n-- on failure.\n-- If the login is successful it also increases online_status and sets\n-- last_login time to the current timestamp\ncreate procedure TigUserLogin(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tif exists(select 1 from tig_users\n\t\twhere (account_status > 0) AND (sha1_user_id = sha1(lower(_user_id))) AND (user_pw = _user_pw) AND (user_id = _user_id))\n\tthen\n\t\tupdate tig_users\n\t\t\tset online_status = online_status + 1, last_login = CURRENT_TIMESTAMP\n\t\t\twhere sha1_user_id = sha1(lower(_user_id));\n\t\tselect _user_id as user_id;\n\telse\n\t\tupdate tig_users set failed_logins = failed_logins + 1 where sha1_user_id = sha1(lower(_user_id));\n\t\tselect NULL as user_id;\n\tend if;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- It decreases online_status and sets last_logout time to the current timestamp\ncreate procedure TigUserLogout(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users\n\t\tset online_status = greatest(online_status - 1, 0),\n\t\t\tlast_logout = CURRENT_TIMESTAMP\n\t\twhere user_id = _user_id;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Disable user account\ncreate procedure TigDisableAccount(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users set account_status = 0 where sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Enable user account\ncreate procedure TigEnableAccount(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users set account_status = 1 where sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Get list of all active user accounts\ncreate procedure TigActiveAccounts()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status > 0;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Get list of all disabled user accounts\ncreate procedure TigDisabledAccounts()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status = 0;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Helper procedure for adding a new node\ncreate procedure TigAddNode(_parent_nid bigint, _uid bigint, _node varchar(255) CHARSET utf8)\nbegin\n\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (_parent_nid, _uid, _node);\n\tselect LAST_INSERT_ID() as nid;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Procedure to efficiently and safely update data in tig_pairs table\ncreate procedure TigUpdatePairs(_nid bigint, _uid bigint, _tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_pairs WHERE nid = _nid AND uid = _uid AND pkey = _tkey)\n  then\n    UPDATE tig_pairs SET pval = _tval WHERE nid = _nid AND uid = _uid AND pkey = _tkey;\n  ELSE\n    INSERT INTO tig_pairs (nid, uid, pkey, pval) VALUES (_nid, _uid, _tkey, _tval);\n  END IF;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- For testing only:\ncreate procedure TigTestAddUser(_user_id varchar(2049) CHARSET utf8, _user_passwd varchar(255) CHARSET utf8,\n\t\t\t success_text text CHARSET utf8, failure_text text CHARSET utf8)\nbegin\n\tdeclare insert_status int default 0;\n\tDECLARE CONTINUE HANDLER FOR 1062 SET insert_status=1;\n\tcall TigAddUserPLainPw(_user_id, _user_passwd);\n\tif insert_status = 0 then\n\t\t select success_text;\n \telse\n\t\t select failure_text;\n\tend if;\nend //\n-- QUERY END:\n\n-- QUERY START:\ncreate procedure TigUsers2Ver4Convert()\nbegin\n\n\tdeclare _user_id varchar(2049) CHARSET utf8;\n\tdeclare _password varchar(255) CHARSET utf8;\n\tdeclare _parent_nid bigint;\n\tdeclare _uid bigint;\n\tdeclare _node varchar(255) CHARSET utf8;\n\tdeclare l_last_row_fetched int default 0;\n\n\tDECLARE cursor_users CURSOR FOR\n\t\tselect user_id, pval as password\n\t\t\tfrom tig_users, tig_pairs\n\t\t\twhere tig_users.uid = tig_pairs.uid and pkey = 'password';\n\tDECLARE CONTINUE HANDLER FOR NOT FOUND SET l_last_row_fetched=1;\n\n\tSTART TRANSACTION;\n\n\t\tSET l_last_row_fetched=0;\n\n\t\tOPEN cursor_users;\n\t\t\tcursor_loop:LOOP\n\t\t\t\tFETCH cursor_users INTO _user_id, _password;\n    \t\tIF l_last_row_fetched=1 THEN\n      \t\tLEAVE cursor_loop;\n    \t\tEND IF;\n\t\t\t\tcall TigUpdatePasswordPlainPw(_user_id, _password);\n\t\t\tEND LOOP cursor_loop;\n\t\tCLOSE cursor_users;\n\n\t\tSET l_last_row_fetched=0;\n\n\tCOMMIT;\n\nend //\n-- QUERY END:\n\ndelimiter ;\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-4-test.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nselect 'Initializing database..';\ncall TigInitdb();\n\n-- Possible encodings are:\n-- - 'MD5-USERID-PASSWORD'\n-- - 'MD5-PASSWORD'\n-- - 'PLAIN'\n-- More can be added if needed.\ncall TigPutDBProperty('password-encoding', 'PLAIN');\ncall TigPutDBProperty('schema-version', '4.0');\n\nselect 'Adding new user with PlainPw: ', 'test_user', 'test_password';\ncall TigTestAddUser('test_user', 'test_passwd', 'SUCCESS - adding new user',\n\t\t 'ERROR - adding new user');\n\ncall TigUserLogin('test_user', 'wrong_passwd', @res_user_id);\nselect @res_user_id as user_id\\g\nselect if(@res_user_id is NULL,\n         'SUCCESS - User login failed as expected, used UserLogin',\n\t\t\t \t 'ERROR - User login succeeded as NOT expected');\n\ncall TigUserLoginPlainPw('test_user', 'wrong_passwd', @res_user_id);\nselect if(@res_user_id is NULL,\n\t\t\t   'SUCCESS - User login failed as expected, used wrong password',\n\t\t\t \t 'ERROR - User login succeeded as NOT expected');\n\ncall TigUserLoginPlainPw('test_user', 'test_passwd', @res_user_id);\nselect if(@res_user_id is not NULL,\n\t\t\t   'SUCCESS - User login OK as expected, used UserLoginPlainPw',\n\t\t\t \t 'ERROR - User login failed as NOT expected');\n\ncall TigUserLogout('test_user');\ncall TigUserLogout('test_user');\nselect online_status into @res_online_status from tig_users\n  where user_id = 'test_user';\nselect if(@res_online_status = 0,\n\t\t\t   'SUCCESS - online status OK after 2 logouts',\n\t\t\t \t 'ERROR - online status incorrect after 2 logouts');\n\nselect 'Changing password using UpdatePassword';\ncall TigUpdatePassword('test_user', 'new_password');\ncall TigUserLoginPlainPw('test_user', 'new_password', @res_user_id);\nselect if(@res_user_id is NULL,\n\t\t\t   'SUCCESS - User login failed as expected, password incorrectly changed',\n\t\t\t \t 'ERROR - User login succeeded as NOT expected');\n\nselect 'Changing password using UpdatePasswordPlainPw';\ncall TigUpdatePasswordPlainPw('test_user', 'new_password');\ncall TigUserLoginPlainPw('test_user', 'new_password', @res_user_id);\nselect if(@res_user_id is not NULL,\n\t\t\t   'SUCCESS - User login OK as expected, password updated with PlainPw',\n\t\t\t \t 'ERROR - User login failed as NOT expected');\n\ncall TigUserLogout('test_user');\nselect 'Disabling user account';\ncall TigDisableAccount('test_user');\ncall TigUserLoginPlainPw('test_user', 'new_password', @res_user_id);\nselect if(@res_user_id is NULL,\n\t\t\t   'SUCCESS - User login failed as expected, account disabled',\n\t\t\t \t 'ERROR - User login succeeded as NOT expected');\n\nselect 'Enabling user account';\ncall TigEnableAccount('test_user');\ncall TigUserLoginPlainPw('test_user', 'new_password', @res_user_id);\nselect if(@res_user_id is not NULL,\n\t\t\t   'SUCCESS - User login OK as expected, account enabled',\n\t\t\t \t 'ERROR - User login failed as NOT expected');\n\ncall TigUserLogout('test_user');\n\nselect 'Adding new user with PlainPw: ', 'test_user_2', 'test_password_2';\ncall TigTestAddUser('test_user_2', 'test_passwd_2', 'SUCCESS - adding new user',\n\t\t 'ERROR - adding new user');\n\nselect 'Adding a user with the same user_id: ', 'test_user', 'test_password_2';\ncall TigTestAddUser('test_user', 'test_password_2', 'ERROR, that was duplicate entry insertion and it should fail.', 'SUCCESS - user adding failure as expected as that was duplicate entry insertion attempt');\n\ncall TigRemoveUser('test_user');\ncall TigRemoveUser('test_user_2');\ncall TigOnlineUsers();\ncall TigOfflineUsers();\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-4.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nsource database/mysql-schema-4-schema.sql;\n\nsource database/mysql-schema-4-sp.sql;\n\nsource database/mysql-schema-4-props.sql;\n\n-- LOAD FILE: database/mysql-schema-4-schema.sql\n\n-- LOAD FILE: database/mysql-schema-4-sp.sql\n\n-- LOAD FILE: database/mysql-schema-4-props.sql\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-5-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect NOW(), ' - Setting schema version to 5.1';\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '5.1');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-5-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Database stored procedures and functions for Tigase schema version 5.1\n\nsource database/mysql-schema-4-schema.sql;\n\n-- LOAD FILE: database/mysql-schema-4-schema.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-5-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Database stored procedures and functions for Tigase schema version 5.1\n\nsource database/mysql-schema-4-sp.sql;\n\n-- LOAD FILE: database/mysql-schema-4-sp.sql\n\n-- QUERY START:\ndrop procedure if exists TigUpdatePairs;\n-- QUERY END:\n \ndelimiter //\n\n-- QUERY START:\n-- Procedure to efficiently and safely update data in tig_pairs table\ncreate procedure TigUpdatePairs(_nid bigint, _uid bigint, _tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_pairs WHERE nid = _nid AND uid = _uid AND pkey = _tkey)\n  then\n    UPDATE tig_pairs SET pval = _tval WHERE nid = _nid AND uid = _uid AND pkey = _tkey;\n  ELSE\n    INSERT INTO tig_pairs (nid, uid, pkey, pval) VALUES (_nid, _uid, _tkey, _tval);\n  END IF;\nend //\n-- QUERY END:\n\n\ndelimiter ;\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nsource database/mysql-schema-4-schema.sql;\n\nsource database/mysql-schema-5-1-sp.sql;\n\nsource database/mysql-schema-5-1-props.sql;\n\n-- LOAD FILE: database/mysql-schema-4-schema.sql;\n\n-- LOAD FILE: database/mysql-schema-5-1-sp.sql;\n\n-- LOAD FILE: database/mysql-schema-5-1-props.sql;\n "
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-5.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nsource database/mysql-schema-4-schema.sql;\n\nsource database/mysql-schema-4-sp.sql;\n\nsource database/mysql-schema-4-props.sql;\n\n-- LOAD FILE: database/mysql-schema-4-schema.sql;\n\n-- LOAD FILE: database/mysql-schema-4-sp.sql;\n\n-- LOAD FILE: database/mysql-schema-4-props.sql;\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-7-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect NOW(), ' - Setting schema version to 7.1';\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-7-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- Database stored procedures and functions for Tigase schema version 5.1\n\nsource database/mysql-schema-5-1-schema.sql;\n\n-- LOAD FILE: database/mysql-schema-5-1-schema.sql\n\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD `pid` INT NOT NULL AUTO_INCREMENT PRIMARY KEY\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-7-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- Database stored procedures and functions for Tigase schema version 5.1\n\nsource database/mysql-schema-5-1-sp.sql;\n\n-- LOAD FILE: database/mysql-schema-5-1-sp.sql\n\n-- QUERY START:\ndrop procedure if exists TigAddNode;\n-- QUERY END:\n\n-- QUERY START:\ndrop procedure if exists TigPutDBProperty;\n-- QUERY END:\n\n-- QUERY START:\ndrop procedure if exists TigUserLogout;\n-- QUERY END:\n \n \ndelimiter //\n\n-- QUERY START:\n-- Helper procedure for adding a new node\ncreate procedure TigAddNode(_parent_nid bigint, _uid bigint, _node varchar(255) CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_nodes WHERE parent_nid = _parent_nid AND uid = _uid AND node = _node)  then\n    SELECT nid FROM tig_nodes WHERE parent_nid = _parent_nid AND uid = _uid AND node = _node;\n  ELSEIF exists(SELECT 1 FROM tig_nodes WHERE _parent_nid is null AND uid = _uid AND 'root' = _node)  then\n    SELECT nid FROM tig_nodes WHERE uid = _uid AND node = _node;\n  ELSE\n\tinsert into tig_nodes (parent_nid, uid, node) values (_parent_nid, _uid, _node);\n\tselect LAST_INSERT_ID() as nid;\n  END IF;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure TigPutDBProperty(_tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists( select 1 from tig_pairs, tig_users where\n    (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n    AND (pkey = _tkey))\n  then\n    update tig_pairs tp, tig_users tu, tig_nodes tn set pval = _tval\n    where (tu.sha1_user_id = sha1(lower('db-properties'))) AND (tu.uid = tp.uid)\n      AND (tp.pkey = _tkey) AND (tn.node = \"root\");\n  else\n    insert into tig_pairs (pkey, pval, uid, nid)\n          select _tkey, _tval, tu.uid, tn.nid from tig_users tu left join tig_nodes tn on tn.uid=tu.uid\n        where (tu.sha1_user_id = sha1(lower('db-properties')) and tn.node=\"root\");\n  end if;\nend //\n-- QUERY END:\n\n\n-- QUERY START:\n-- It decreases online_status and sets last_logout time to the current timestamp\ncreate procedure TigUserLogout(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users\n\t\tset online_status = greatest(online_status - 1, 0),\n\t\t\tlast_logout = CURRENT_TIMESTAMP\n\t\twhere sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\ndelimiter ;\n\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\nsource database/mysql-schema-7-1-schema.sql;\n\nsource database/mysql-schema-7-1-sp.sql;\n\nsource database/mysql-schema-7-1-props.sql;\n\n-- LOAD FILE: database/mysql-schema-7-1-schema.sql;\n\n-- LOAD FILE: database/mysql-schema-7-1-sp.sql;\n\n-- LOAD FILE: database/mysql-schema-7-1-props.sql;\n "
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-upgrade-to-4.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Database schema upgrade for Tigase version 4.0.0\n\nselect NOW(), ' - Dropping foreign indexes';\n-- QUERY START:\nalter table tig_nodes DROP FOREIGN KEY tig_nodes_constr;\n-- QUERY END:\n-- QUERY START:\nalter table tig_pairs DROP FOREIGN KEY tig_pairs_constr_1;\n-- QUERY END:\n-- QUERY START:\nalter table tig_pairs DROP FOREIGN KEY tig_pairs_constr_2;\n-- QUERY END:\n\nselect NOW(), ' - Renaming old tig_pairs table for later convertion';\n-- QUERY START:\nalter table tig_pairs rename to tig_pairs_old;\n-- QUERY END:\nselect NOW(), ' - Renaming old tig_nodes table for later convertion';\n-- QUERY START:\nalter table tig_nodes rename to tig_nodes_old;\n-- QUERY END:\n-- QUERY START:\nalter table tig_nodes_old add index parent_nid (parent_nid);\n-- QUERY END:\n-- QUERY START:\nalter table tig_nodes_old add index uid (uid);\n-- QUERY END:\nselect NOW(), ' - Renaming old tig_users table for later convertion';\n-- QUERY START:\nalter table tig_users rename to tig_users_old;\n-- QUERY END:\n\nselect NOW(), ' - Loading new database schema 4.0';\n-- LOAD SCHEMA:\nsource database/mysql-schema-4-schema.sql;\n\nselect NOW(), ' - Setting passwords encoding in the database';\n-- Possible encodings are:\n-- - 'MD5-USERID-PASSWORD'\n-- - 'MD5-PASSWORD'\n-- - 'PLAIN'\n-- More can be added if needed.\n-- QUERY START:\ncall TigPutDBProperty('password-encoding', 'PLAIN');\n-- QUERY END:\n\nselect NOW(), ' - Temporarly adding old_uid column to tig_users table';\n-- QUERY START:\nalter table tig_users add column old_uid bigint;\n-- QUERY END:\n-- QUERY START:\nalter table tig_users add index old_uid (old_uid);\n-- QUERY END:\nselect NOW(), ' - Temporarly adding old_nid column to tig_nodes table';\n-- QUERY START:\nalter table tig_nodes add column old_nid bigint;\n-- QUERY END:\n-- QUERY START:\nalter table tig_nodes add index old_nid (old_nid);\n-- QUERY END:\n\nselect NOW(), ' - Copying tig_users data to a new table';\n-- QUERY START:\ninsert into tig_users (user_id, sha1_user_id, old_uid)\n\tselect user_id, sha1(user_id), uid from tig_users_old;\n-- QUERY END:\n\nselect NOW(), ' - Copying tig_nodes data to a new table';\n-- QUERY START:\ninsert into tig_nodes (uid, old_nid, node)\n\tselect tig_users.uid, nid, node from tig_users, tig_nodes_old\n\t\twhere (tig_nodes_old.uid = tig_users.old_uid);\n-- QUERY END:\n\nselect NOW(), ' - Updating parent_nids in the new tig_nodes table';\n-- QUERY START:\ncreate temporary table temp_nodes\n\tselect tig_nodes.uid as new_uid, tig_nodes.nid as new_nid,\n\t\t\ttig_nodes_old.nid as old_nid, tig_nodes_old.parent_nid as old_parent_nid\n\t\tfrom tig_nodes, tig_nodes_old where tig_nodes.old_nid = tig_nodes_old.nid;\n-- QUERY END:\n-- QUERY START:\n\nalter table temp_nodes add index new_nid (new_nid);\n-- QUERY END:\n-- QUERY START:\nalter table temp_nodes add index old_nid (old_nid);\n-- QUERY END:\n-- QUERY START:\n\nupdate tig_nodes, tig_nodes_old, temp_nodes\n\tset tig_nodes.parent_nid = temp_nodes.new_nid\n\twhere (tig_nodes.old_nid = tig_nodes_old.nid)\n\t\tAND (tig_nodes_old.parent_nid = temp_nodes.old_nid);\n-- QUERY END:\n\nselect NOW(), ' - Loading tig_pairs table from old one with new uids and nids';\n-- QUERY START:\ninsert into tig_pairs (nid, uid, pkey, pval)\n\tselect tig_nodes.nid, tig_users.uid, pkey, pval\n\t\tfrom tig_pairs_old, tig_users, tig_nodes\n\t\twhere (tig_pairs_old.uid = tig_users.old_uid)\n\t\t\tAND (tig_pairs_old.nid = tig_nodes.old_nid);\n-- QUERY END:\n\nselect NOW(), ' - Droping temporarly columns';\n-- QUERY START:\nalter table tig_users drop index old_uid;\n-- QUERY END:\n-- QUERY START:\nalter table tig_users drop column old_uid;\n-- QUERY END:\n-- QUERY START:\nalter table tig_nodes drop index old_nid;\n-- QUERY END:\n-- QUERY START:\nalter table tig_nodes drop column old_nid;\n-- QUERY END:\n\nselect NOW(), ' - Converting user passwords to a new format';\n-- QUERY START:\ncall TigUsers2Ver4Convert();\n-- QUERY END:\n\nselect NOW(), ' - All done, database ready to use!';\n"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-upgrade-to-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\nselect NOW(), ' - Installing missing stored procedures';\n\n-- QUERY START:\ndrop procedure if exists TigUpdatePairs;\n-- QUERY END:\n \ndelimiter //\n\n-- QUERY START:\n-- Procedure to efficiently and safely update data in tig_pairs table\ncreate procedure TigUpdatePairs(_nid bigint, _uid bigint, _tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_pairs WHERE nid = _nid AND uid = _uid AND pkey = _tkey)\n  then\n    UPDATE tig_pairs SET pval = _tval WHERE nid = _nid AND uid = _uid AND pkey = _tkey;\n  ELSE\n    INSERT INTO tig_pairs (nid, uid, pkey, pval) VALUES (_nid, _uid, _tkey, _tval);\n  END IF;\nend //\n-- QUERY END:\n\ndelimiter ;\n\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '5.1');\n-- QUERY END:\n\nselect NOW(), ' - All done, database ver 5.1 ready to use!';"
  },
  {
    "path": "tigase-server 7.1.0/database/mysql-schema-upgrade-to-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\nselect NOW(), ' - Upgrading schema to version 7.1';\n\nselect NOW(), 'modifying stored procedures';\n\n-- QUERY START:\ndrop procedure if exists TigUserLogout;\n-- QUERY END:\n\n-- QUERY START:\ndrop procedure if exists TigAddNode;\n-- QUERY END:\n\n-- QUERY START:\ndrop procedure if exists TigPutDBProperty;\n-- QUERY END:\n \ndelimiter //\n\n-- QUERY START:\n-- It decreases online_status and sets last_logout time to the current timestamp\ncreate procedure TigUserLogout(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users\n\t\tset online_status = greatest(online_status - 1, 0),\n\t\t\tlast_logout = CURRENT_TIMESTAMP\n\t\twhere sha1_user_id = sha1(lower(_user_id));\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Helper procedure for adding a new node\ncreate procedure TigAddNode(_parent_nid bigint, _uid bigint, _node varchar(255) CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_nodes WHERE parent_nid = _parent_nid AND uid = _uid AND node = _node)  then\n    SELECT nid FROM tig_nodes WHERE parent_nid = _parent_nid AND uid = _uid AND node = _node;\n  ELSEIF exists(SELECT 1 FROM tig_nodes WHERE _parent_nid is null AND uid = _uid AND 'root' = _node)  then\n    SELECT nid FROM tig_nodes WHERE uid = _uid AND node = _node;\n  ELSE\n\tinsert into tig_nodes (parent_nid, uid, node) values (_parent_nid, _uid, _node);\n\tselect LAST_INSERT_ID() as nid;\n  END IF;\nend //\n-- QUERY END:\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure TigPutDBProperty(_tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists( select 1 from tig_pairs, tig_users where\n    (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n    AND (pkey = _tkey))\n  then\n    update tig_pairs tp, tig_users tu, tig_nodes tn set pval = _tval\n    where (tu.sha1_user_id = sha1(lower('db-properties'))) AND (tu.uid = tp.uid)\n      AND (tp.pkey = _tkey) AND (tn.node = \"root\");\n  else\n    insert into tig_pairs (pkey, pval, uid, nid)\n          select _tkey, _tval, tu.uid, tn.nid from tig_users tu left join tig_nodes tn on tn.uid=tu.uid\n        where (tu.sha1_user_id = sha1(lower('db-properties')) and tn.node=\"root\");\n  end if;\nend //\n-- QUERY END:\n\ndelimiter ;\n\n-- QUERY START:\nselect NOW(), 'adding root node for db-properties';\n-- QUERY END:\n\n-- QUERY START:\ncall TigAddNode(null,(select uid from tig_users where user_id=\"db-properties\"),\"root\");\n-- QUERY END:\n\n-- QUERY START:\nupdate tig_pairs set nid = (select nid from tig_nodes where uid=(select uid from tig_users where user_id=\"db-properties\") and node=\"root\") where uid=(select uid from tig_users where user_id=\"db-properties\");\n-- QUERY END:\n\n-- QUERY START:\nselect NOW(), 'altering tig_pairs table to add missing indexes';\n-- QUERY END:\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD `pid` INT NOT NULL AUTO_INCREMENT PRIMARY KEY\n-- QUERY END:\n\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n\n-- QUERY START:\nselect NOW(), ' - All done, database ver 7.1 ready to use!';\n-- QUERY END:\n\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-installer-create-db.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START: create database\ncreate database ${dbName};\n-- QUERY END: create database\n\n-- QUERY START: add user\ncreate user ${dbUser} with password '${dbPass}';\n-- QUERY END: add user\n\n-- QUERY START: GRANT ALL\nGRANT ALL ON database ${dbName} TO ${dbUser};\n-- QUERY END: GRANT ALL\n\n-- QUERY START: ALTER DATABASE\nALTER DATABASE ${dbName} OWNER TO ${dbUser};\n-- QUERY END: ALTER DATABASE\n\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-installer-post.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Permissions fix\n\n-- QUERY START: ALTER SCHEMA\nALTER SCHEMA public OWNER TO ${dbUser};\n-- QUERY END: ALTER SCHEMA\n\n-- QUERY START: GRANT ALL ON ALL TABLES\nGRANT ALL ON ALL TABLES IN SCHEMA public TO ${dbUser};\n-- QUERY END: GRANT ALL ON ALL TABLES\n\n-- QUERY START: GRANT ALL ON ALL FUNCTIONS\nGRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO ${dbUser};\n-- QUERY END: GRANT ALL ON ALL FUNCTIONS\n\n-- QUERY START: GRANT ALL ON ALL SEQUENCES\nGRANT ALL ON ALL SEQUENCES IN SCHEMA public TO ${dbUser};\n-- QUERY END: GRANT ALL ON ALL SEQUENCES\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-3.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n\ncreate table short_news (\n  -- Automatic record ID\n  snid            serial,\n  -- Automaticly generated timestamp and automaticly updated on change\n  publishing_time timestamp default now(),\n\t-- Optional news type: 'shorts', 'minis', 'techs', 'funs'....\n\tnews_type\t\t\t\tvarchar(10),\n  -- Author JID\n  author          varchar(128) NOT NULL,\n  -- Short subject - this is short news, right?\n  subject         varchar(128) NOT NULL,\n  -- Short news message - this is short news, right?\n  body            varchar(1024) NOT NULL,\n  primary key(snid)\n);\ncreate index publishing_time on short_news (publishing_time);\ncreate index author on short_news (author);\ncreate index news_type on short_news (news_type);\n\ncreate table xmpp_stanza (\n\t\t\t id serial,\n\t\t\t stanza text NOT NULL\n);\n\ncreate table tig_users (\n       uid bigint NOT NULL,\n\n       user_id varchar(128) NOT NULL,\n\n       primary key (uid)\n);\ncreate unique index user_id on tig_users ( user_id );\n\ncreate table tig_nodes (\n       nid bigint NOT NULL,\n       parent_nid bigint,\n       uid bigint NOT NULL references tig_users(uid),\n\n       node varchar(64) NOT NULL,\n\n       primary key (nid)\n);\ncreate unique index tnode on tig_nodes ( parent_nid, uid, node );\ncreate index node on tig_nodes ( node );\n\ncreate table tig_pairs (\n       nid bigint references tig_nodes(nid),\n       uid bigint NOT NULL references tig_users(uid),\n\n       pkey varchar(128) NOT NULL,\n       pval varchar(65535)\n);\ncreate index pkey on tig_pairs ( pkey );\n\ncreate table tig_max_ids (\n       max_uid bigint,\n       max_nid bigint\n);\n\n\ninsert into tig_max_ids (max_uid, max_nid) values (1, 1);\n\n-- Get top nodes for the user: user1@hostname\n--\n-- select nid, node from nodes, users\n--   where ('user1@hostname' = user_id)\n--     AND (nodes.uid = users.uid)\n--     AND (parent_nid is null);\n\n-- Get all subnodes of the node: /privacy/default for user: user1@hostname\n--\n-- select nid, node from nodes,\n-- (\n--   select nid as dnid from nodes,\n--   (\n--     select nid as pnid from nodes, users\n--       where ('user1@hostname' = user_id)\n--         AND (nodes.uid = users.uid)\n--         AND (parent_nid is null)\n--         AND (node = 'privacy')\n--   ) ptab where (parent_nid = pnid)\n--       AND (node = 'default')\n-- ) dtab where (parent_nid = dnid);\n\n-- Get all keys (pairs) for the node: /privacy/default/24 for user: user1@hostname\n--\n-- select  pkey, pval from pairs,\n-- (\n--   select nid, node from nodes,\n--   (\n--     select nid as dnid from nodes,\n--     (\n--       select nid as pnid from nodes, users\n--         where ('user1@hostname' = user_id)\n--           AND (nodes.uid = users.uid)\n--     \t  AND (parent_nid is null)\n--     \t  AND (node = 'privacy')\n--     ) ptab where (parent_nid = pnid)\n--         AND (node = 'default')\n--   ) dtab where (parent_nid = dnid)\n-- ) ntab where (pairs.nid = ntab.nid) AND (node = '24');\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-4-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\nselect TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect now(), ' - Setting schema version to 4.0';\n\n-- QUERY START:\nselect TigPutDBProperty('schema-version', '4.0');\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-4-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\ncreate table tig_users (\n\tuid bigserial,\n\n\t-- Jabber User ID\n\tuser_id varchar(2049) NOT NULL,\n\t-- User password encrypted or not\n\tuser_pw varchar(255) default NULL,\n\t-- Time the account has been created\n\tacc_create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n\t-- Time of the last user login\n\tlast_login timestamp,\n\t-- Time of the last user logout\n\tlast_logout timestamp,\n\t-- User online status, if > 0 then user is online, the value\n\t-- indicates the number of user connections.\n\t-- It is incremented on each user login and decremented on each\n\t-- user logout.\n\tonline_status int default 0,\n\t-- Number of failed login attempts\n\tfailed_logins int default 0,\n\t-- User status, whether the account is active or disabled\n\t-- >0 - account active, 0 - account disabled\n\taccount_status int default 1,\n\n\tprimary key (uid)\n);\n-- QUERY END:\n-- QUERY START:\ncreate unique index user_id on tig_users ( lower(user_id) );\n-- QUERY END:\n-- QUERY START:\ncreate index user_pw on tig_users (user_pw);\n-- QUERY END:\n-- QUERY START:\ncreate index last_login on tig_users (last_login);\n-- QUERY END:\n-- QUERY START:\ncreate index last_logout on tig_users (last_logout);\n-- QUERY END:\n-- QUERY START:\ncreate index account_status on tig_users (account_status);\n-- QUERY END:\n-- QUERY START:\ncreate index online_status on tig_users (online_status);\n-- QUERY END:\n\n-- QUERY START:\ncreate table tig_nodes (\n       nid bigserial,\n       parent_nid bigint,\n       uid bigint NOT NULL references tig_users(uid),\n\n       node varchar(255) NOT NULL,\n\n       primary key (nid)\n);\n-- QUERY END:\n-- QUERY START:\ncreate unique index tnode on tig_nodes ( parent_nid, uid, node );\n-- QUERY END:\n-- QUERY START:\ncreate index node on tig_nodes ( node );\n-- QUERY END:\n-- QUERY START:\ncreate index nuid on tig_nodes (uid);\n-- QUERY END:\n-- QUERY START:\ncreate index parent_nid on tig_nodes (parent_nid);\n-- QUERY END:\n\n-- QUERY START:\ncreate table tig_pairs (\n       nid bigint references tig_nodes(nid),\n       uid bigint NOT NULL references tig_users(uid),\n\n       pkey varchar(255) NOT NULL,\n       pval text\n);\n-- QUERY END:\n-- QUERY START:\ncreate index pkey on tig_pairs ( pkey );\n-- QUERY END:\n-- QUERY START:\ncreate index puid on tig_pairs (uid);\n-- QUERY END:\n-- QUERY START:\ncreate index pnid on tig_pairs (nid);\n-- QUERY END:\n\n-- QUERY START:\ncreate table short_news (\n  -- Automatic record ID\n  snid            bigserial,\n  -- Automaticly generated timestamp and automaticly updated on change\n  publishing_time timestamp default now(),\n\t-- Optional news type: 'shorts', 'minis', 'techs', 'funs'....\n\tnews_type\t\t\t\tvarchar(10),\n  -- Author JID\n  author          varchar(128) NOT NULL,\n  -- Short subject - this is short news, right?\n  subject         varchar(128) NOT NULL,\n  -- Short news message - this is short news, right?\n  body            varchar(1024) NOT NULL,\n  primary key(snid)\n);\n-- QUERY END:\n-- QUERY START:\ncreate index publishing_time on short_news (publishing_time);\n-- QUERY END:\n-- QUERY START:\ncreate index author on short_news (author);\n-- QUERY END:\n-- QUERY START:\ncreate index news_type on short_news (news_type);\n-- QUERY END:\n\n-- QUERY START:\ncreate table xmpp_stanza (\n\t\t\t id bigserial,\n\t\t\t stanza text NOT NULL\n);\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-4-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n-- Database stored procedures and fucntions for Tigase schema version 4.0.0\n\n-- QUERY START:\nCREATE OR REPLACE FUNCTION public.create_plpgsql_language ()\n        RETURNS TEXT\n        AS $$\n            CREATE LANGUAGE plpgsql;\n            SELECT 'language plpgsql created'::TEXT;\n        $$\nLANGUAGE 'sql';\n\nSELECT CASE WHEN\n              (SELECT true::BOOLEAN\n                 FROM pg_language\n                WHERE lanname='plpgsql')\n            THEN\n              (SELECT 'language already installed'::TEXT)\n            ELSE\n              (SELECT public.create_plpgsql_language())\n            END;\n\nDROP FUNCTION public.create_plpgsql_language ();\n-- QUERY END:\n\n-- QUERY START:\n-- Database properties get - function\ncreate or replace function TigGetDBProperty(varchar(255)) returns text as '\ndeclare\n  _result text;\n  _tkey alias for $1;\nbegin\n\n\tselect pval into _result from tig_pairs, tig_users\n\t\twhere (pkey = _tkey) AND (lower(user_id) = lower(''db-properties''))\n\t\t\t\t\tAND (tig_pairs.uid = tig_users.uid);\n\n\treturn _result;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate or replace function TigPutDBProperty(varchar(255), text) returns void as '\ndeclare\n  _tkey alias for $1;\n  _tval alias for $2;\nbegin\n  if exists( select pval from tig_pairs, tig_users where\n\t\t(lower(user_id) = lower(''db-properties'')) AND (tig_users.uid = tig_pairs.uid)\n\t\tAND (pkey = _tkey))\n  then\n\t  update tig_pairs set pval = _tval from tig_users\n      where (lower(tig_users.user_id) = lower(''db-properties''))\n        AND (tig_users.uid = tig_pairs.uid)\n        AND (pkey = _tkey);\n  else\n    insert into tig_pairs (pkey, pval, uid)\n\t\t  select _tkey, _tval, uid from tig_users\n\t\t\t  where (lower(user_id) = lower(''db-properties''));\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- The initialization of the database.\n-- The procedure should be called manually somehow before starting the\n-- server. In theory the server could call the procedure automatically\n-- at the startup time but I don't know yet how to solve the problem\n-- with multiple cluster nodes starting at later time when the server\n-- is already running.\ncreate or replace function TigInitdb() returns void as '\nbegin\n\tupdate tig_users set online_status = 0;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Add a new user to the database assuming the user password is already\n-- encoded properly according to the database settings.\n-- If password is not encoded TigAddUserPlainPw should be used instead.\ncreate or replace function TigAddUser(varchar(2049), varchar(255))\n  returns bigint as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\n  _res_uid bigint;\nbegin\n\tif exists( select uid from tig_users where\n\t\t(lower(user_id) = lower(_user_id)) AND (user_pw = _user_pw) )\n\tthen\n\t\treturn null;\n\telse\n\t\tinsert into tig_users (user_id, user_pw)\n\t\t\tvalues (_user_id, _user_pw);\n\t\tselect currval(''tig_users_uid_seq'') into _res_uid;\n\n\t\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (NULL, _res_uid, ''root'');\n\n\t\treturn _res_uid as uid;\n\tend if;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\n-- and creates a new user account.\ncreate or replace function TigAddUserPlainPw(varchar(2049), varchar(255))\n  returns bigint as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\n  _enc text;\n  _res_uid bigint;\nbegin\n\tselect TigGetDBProperty(''password-encoding'') into _enc;\n  select\n    case _enc\n \t\twhen ''MD5-PASSWORD'' then TigAddUser(_user_id, MD5(_user_pw))\n\t  when ''MD5-USERID-PASSWORD'' then TigAddUser(_user_id, MD5(_user_id || _user_pw))\n\t  when ''MD5-USERNAME-PASSWORD'' then\n      TigAddUser(_user_id, MD5(split_part(_user_id, ''@'', 1) || _user_pw))\n\t  else TigAddUser(_user_id, _user_pw)\n\t  end into _res_uid;\n\treturn _res_uid as uid;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Low level database user id as big number. Used only for performance reasons\n-- and save database space. Besides JID is too large to server as UID\ncreate or replace function TigGetUserDBUid(varchar(2049)) returns bigint as '\ndeclare\n  _user_id alias for $1;\n  res_uid bigint;\nbegin\n\tselect uid into res_uid from tig_users where lower(user_id) = lower(_user_id);\n  return res_uid;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Removes a user from the database\ncreate or replace function TigRemoveUser(varchar(2049)) returns void as '\ndeclare\n  _user_id alias for $1;\n  res_uid bigint;\nbegin\n\tselect uid into res_uid from tig_users where lower(user_id) = lower(_user_id);\n\n\tdelete from tig_pairs where uid = res_uid;\n\tdelete from tig_nodes where uid = res_uid;\n\tdelete from tig_users where uid = res_uid;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Returns user's password from the database\ncreate or replace function TigGetPassword(varchar(2049)) returns varchar(255) as '\ndeclare\n  _user_id alias for $1;\n  res_pw varchar(255);\nbegin\n\tselect user_pw into res_pw from tig_users where lower(user_id) = lower(_user_id);\n  return res_pw;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\ncreate or replace function TigUpdatePasswordPlainPw(varchar(2049), varchar(255))\n  returns void as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\n  _enc text;\nbegin\n\tselect TigGetDBProperty(''password-encoding'') into _enc;\n  perform\n    case _enc\n\t\twhen ''MD5-PASSWORD'' then TigUpdatePassword(_user_id, MD5(_user_pw))\n\t\twhen ''MD5-USERID-PASSWORD'' then\n      TigUpdatePassword(_user_id, MD5(_user_id || _user_pw))\n\t  when ''MD5-USERNAME-PASSWORD'' then\n      TigUpdatePassword(_user_id, MD5(split_part(_user_id, ''@'', 1) || _user_pw))\n\t\telse TigUpdatePassword(_user_id, _user_pw)\n\t\tend;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Variant of TigUpdatePasswordPlainPw SP with parameters in reverse order.\n-- Some implementations require the parameters to be in the same order as\n-- the update query.\ncreate or replace function TigUpdatePasswordPlainPwRev(varchar(255), varchar(2049))\n  returns void as '\ndeclare\n  _user_pw alias for $1;\n  _user_id alias for $2;\nbegin\n  perform TigUpdatePasswordPlainPw(_user_id, _user_pw);\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Update user password\ncreate or replace function TigUpdatePassword(varchar(2049), varchar(255))\n  returns void as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\nbegin\n\tupdate tig_users set user_pw = _user_pw where lower(user_id) = lower(_user_id);\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- List all online users\ncreate or replace function TigOnlineUsers() returns void as '\nbegin\n  return;\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status > 0;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- List all offline users\ncreate or replace function TigOfflineUsers() returns void as '\nbegin\n  return;\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status = 0;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- List of all users in database\ncreate or replace function TigAllUsers() returns setof varchar(2049) as\n\t'select user_id from tig_users;'\nLANGUAGE 'sql';\n-- create or replace function TigAllUsers() returns void as '\n-- begin\n--  return;\n--\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n--\t\tfrom tig_users;\n-- end;\n-- ' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- All users count\ncreate or replace function TigAllUsersCount() returns bigint as '\ndeclare\n  res_cnt bigint;\nbegin\n\tselect count(*) into res_cnt from tig_users;\n  return res_cnt;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Performs user login for a plain text password, converting it to an internal\n-- representation if necessary\ncreate or replace function TigUserLoginPlainPw(varchar(2049), varchar(255))\n\t\t\t \t\t\t\t\t  returns varchar(2049) as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\n  res_user_id varchar(2049);\n  _enc text;\nbegin\n\tselect TigGetDBProperty(''password-encoding'') into _enc;\n  select\n    case _enc\n\t\twhen ''MD5-PASSWORD'' then TigUserLogin(_user_id, MD5(_user_pw))\n\t\twhen ''MD5-USERID-PASSWORD'' then\n      TigUserLogin(_user_id, MD5(_user_id || _user_pw))\n\t  when ''MD5-USERNAME-PASSWORD'' then\n      TigUserLogin(_user_id, MD5(split_part(_user_id, ''@'', 1) || _user_pw))\n\t\telse TigUserLogin(_user_id, _user_pw)\n\t\tend into res_user_id;\n  return res_user_id;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Perforrm user login. It returns user_id uppon success and NULL\n-- on failure.\n-- If the login is successful it also increases online_status and sets\n-- last_login time to the current timestamp\ncreate or replace function TigUserLogin(varchar(2049), varchar(255))\n\t\t\t \t\t\t\t\t  returns varchar(2049) as '\ndeclare\n  _user_id alias for $1;\n  _user_pw alias for $2;\n  res_user_id varchar(2049);\nbegin\n\tif exists(select user_id from tig_users\n\t\twhere (account_status > 0) AND (lower(user_id) = lower(_user_id)) AND (user_pw = _user_pw))\n\tthen\n\t\tupdate tig_users\n\t\t\tset online_status = online_status + 1, last_login = now()\n\t\t\twhere lower(user_id) = lower(_user_id);\n    select _user_id into res_user_id;\n\telse\n\t\tupdate tig_users set failed_logins = failed_logins + 1 where lower(user_id) = lower(_user_id);\n    select NULL into res_user_id;\n\tend if;\n  return res_user_id;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- It decreases online_status and sets last_logout time to the current timestamp\ncreate or replace function TigUserLogout(varchar(2049)) returns void as '\ndeclare\n  _user_id alias for $1;\nbegin\n\tupdate tig_users\n\t\tset online_status = greatest(online_status - 1, 0),\n\t\t\tlast_logout = now()\n\t\twhere lower(user_id) = lower(_user_id);\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Disable user account\ncreate or replace function TigDisableAccount(varchar(2049)) returns void as '\ndeclare\n  _user_id alias for $1;\nbegin\n\tupdate tig_users set account_status = 0 where lower(user_id) = lower(_user_id);\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Enable user account\ncreate or replace function TigEnableAccount(varchar(2049)) returns void as '\ndeclare\n  _user_id alias for $1;\nbegin\n\tupdate tig_users set account_status = 1 where lower(user_id) = lower(_user_id);\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Get list of all active user accounts\ncreate or replace function TigActiveAccounts() returns void as '\nbegin\n  return;\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status > 0;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\n-- Get list of all disabled user accounts\ncreate or replace function TigDisabledAccounts() returns table(user_id varchar(2049), last_login timestamp, last_logout timestamp, online_status int, failed_logins int, account_status int) as '\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status = 0;\n' LANGUAGE 'sql';\n-- QUERY END:\n\n-- QUERY START:\n-- Helper procedure for adding a new node\ncreate or replace function TigAddNode(bigint, bigint, varchar(255))\n  returns bigint as '\ndeclare\n  _parent_nid alias for $1;\n  _uid alias for $2;\n  _node alias for $3;\n  res_nid bigint;\nbegin\n\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (_parent_nid, _uid, _node);\n  select currval(''tig_nodes_nid_seq'') into res_nid;\n  return res_nid;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\ncreate or replace function TigUsers2Ver4Convert() returns void as '\ndeclare\n  user_row RECORD;\nbegin\n\n  for user_row in\n\t\tselect user_id, pval as password\n\t\t\tfrom tig_users, tig_pairs\n\t\t\twhere tig_users.uid = tig_pairs.uid and pkey = ''password'' loop\n\t\tperform TigUpdatePasswordPlainPw(user_row.user_id, user_row.password);\n\tEND LOOP;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n-- QUERY START:\ncreate or replace function TigUpdatePairs(bigint, bigint, varchar(255), text) returns void as '\ndeclare\n  _nid alias for $1;\n  _uid alias for $2;\n  _tkey alias for $3;\n  _tval alias for $4;\nbegin\n  if exists(select 1 from tig_pairs where nid = _nid and uid = _uid and pkey = _tkey)\n  then\n        update tig_pairs set pval = _tval where nid = _nid and uid = _uid and pkey = _tkey;\n  else\n        insert into tig_pairs (nid, uid, pkey, pval) values (_nid, _uid, _tkey, _tval);\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-4.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n\\i database/postgresql-schema-4-schema.sql\n\n\\i database/postgresql-schema-4-sp.sql\n\n\\i database/postgresql-schema-4-props.sql\n\n-- LOAD FILE: database/postgresql-schema-4-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-4-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-4-props.sql\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-5-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\nselect TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect now(), ' - Setting schema version to 5.1';\n\n-- QUERY START:\nselect TigPutDBProperty('schema-version', '5.1');\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-5-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n-- Database stored procedures and fucntions for Tigase schema version 5.1\n\n\\i database/postgresql-schema-4-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-4-schema.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-5-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n-- Database stored procedures and fucntions for Tigase schema version 5.1\n\n\\i database/postgresql-schema-4-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-4-sp.sql\n\n-- QUERY START:\ncreate or replace function TigUpdatePairs(bigint, bigint, varchar(255), text) returns void as '\ndeclare\n  _nid alias for $1;\n  _uid alias for $2;\n  _tkey alias for $3;\n  _tval alias for $4;\nbegin\n  if exists(select 1 from tig_pairs where nid = _nid and uid = _uid and pkey = _tkey)\n  then\n        update tig_pairs set pval = _tval where nid = _nid and uid = _uid and pkey = _tkey;\n  else\n        insert into tig_pairs (nid, uid, pkey, pval) values (_nid, _uid, _tkey, _tval);\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n\\i database/postgresql-schema-4-schema.sql\n\n\\i database/postgresql-schema-5-1-sp.sql\n\n\\i database/postgresql-schema-5-1-props.sql\n\n-- LOAD FILE: database/postgresql-schema-4-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-5.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n\\i database/postgresql-schema-4-schema.sql\n\n\\i database/postgresql-schema-4-sp.sql\n\n\\i database/postgresql-schema-4-props.sql\n\n-- LOAD FILE: database/postgresql-schema-4-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-4-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-4-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-7-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\nselect TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect now(), ' - Setting schema version to 7.1';\n\n-- QUERY START:\nselect TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-7-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\n-- Database stored procedures and fucntions for Tigase schema version 5.1\n\n\\i database/postgresql-schema-5-1-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-schema.sql\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD COLUMN pid BIGSERIAL PRIMARY KEY;\n-- QUERY END:\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-7-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\n-- Database stored procedures and fucntions for Tigase schema version 5.1\n\n\\i database/postgresql-schema-5-1-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-sp.sql\n\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate or replace function TigPutDBProperty(varchar(255), text) returns void as '\ndeclare\n  _tkey alias for $1;\n  _tval alias for $2;\nbegin\n  if exists( select pval from tig_pairs, tig_users where\n\t\t(lower(user_id) = lower(''db-properties'')) AND (tig_users.uid = tig_pairs.uid)\n\t\tAND (pkey = _tkey))\n  then\n\t  update tig_pairs set pval = _tval from tig_users\n      where (lower(tig_users.user_id) = lower(''db-properties''))\n        AND (tig_users.uid = tig_pairs.uid)\n        AND (pkey = _tkey);\n  else\n    insert into tig_pairs (pkey, pval, uid, nid)\n\t\t  select _tkey, _tval, tu.uid, tn.nid from tig_users tu  left join tig_nodes tn on tn.uid=tu.uid\n\t\t\t  where (lower(user_id) = lower(''db-properties'')  and tn.node=''root'' );\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n\\i database/postgresql-schema-4-schema.sql\n\n\\i database/postgresql-schema-5-1-sp.sql\n\n\\i database/postgresql-schema-5-1-props.sql\n\n-- LOAD FILE: database/postgresql-schema-4-schema.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-sp.sql\n\n-- LOAD FILE: database/postgresql-schema-5-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-upgrade-to-4.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- Database schema upgrade for Tigase version 4.0.0\n\nselect NOW(), ' - Dropping foreign indexes';\nalter table tig_nodes DROP constraint tig_nodes_uid_fkey;\nalter table tig_pairs DROP constraint tig_pairs_uid_fkey;\nalter table tig_pairs DROP constraint tig_pairs_nid_fkey;\nalter table tig_users DROP constraint tig_users_pkey;\nalter table tig_nodes DROP constraint tig_nodes_pkey;\ndrop index user_id;\ndrop index tnode;\ndrop index node;\ndrop index pkey;\n\nselect NOW(), ' - Renaming old tig_pairs table for later convertion';\nalter table tig_pairs rename to tig_pairs_old;\ncreate index pkey_old on tig_pairs_old (pkey);\ncreate index puid_old on tig_pairs_old (uid);\ncreate index pnid_old on tig_pairs_old (nid);\n\nselect NOW(), ' - Renaming old tig_nodes table for later convertion';\nalter table tig_nodes rename to tig_nodes_old;\ncreate index nnid_old on tig_nodes_old (nid);\ncreate index parent_nid_old on tig_nodes_old (parent_nid);\ncreate index nuid_old on tig_nodes_old (uid);\ncreate index node_old on tig_nodes_old (node);\n\nselect NOW(), ' - Renaming old tig_users table for later convertion';\nalter table tig_users rename to tig_users_old;\ncreate index uuid_old on tig_users_old (uid);\ncreate index user_id_old on tig_users_old (user_id);\n\nselect NOW(), ' - Loading new database schema 4.0';\n\\i database/postgresql-schema-4.sql;\n\nselect NOW(), ' - Setting passwords encoding in the database';\n-- Possible encodings are:\n-- - 'MD5-USERID-PASSWORD'\n-- - 'MD5-PASSWORD'\n-- - 'PLAIN'\n-- More can be added if needed.\nselect TigPutDBProperty('password-encoding', 'PLAIN');\n\nselect NOW(), ' - Temporarly adding old_uid column to tig_users table';\nalter table tig_users add column old_uid bigint;\ncreate index old_uid on tig_users (old_uid);\nselect NOW(), ' - Temporarly adding old_nid column to tig_nodes table';\nalter table tig_nodes add column old_nid bigint;\ncreate index old_nid on tig_nodes (old_nid);\n\nselect NOW(), ' - Copying tig_users data to a new table';\ninsert into tig_users (user_id, old_uid)\n\tselect user_id, uid from tig_users_old;\n\nselect NOW(), ' - Copying tig_nodes data to a new table';\ninsert into tig_nodes (uid, old_nid, node)\n\tselect tig_users.uid, nid, node from tig_users, tig_nodes_old\n\t\twhere (tig_nodes_old.uid = tig_users.old_uid);\n\nselect NOW(), ' - Updating parent_nids in the new tig_nodes table';\ncreate temporary table temp_nodes as\n\tselect tig_nodes.uid as new_uid, tig_nodes.nid as new_nid,\n\t\t\ttig_nodes_old.nid as old_nid, tig_nodes_old.parent_nid as old_parent_nid\n\t\tfrom tig_nodes, tig_nodes_old where tig_nodes.old_nid = tig_nodes_old.nid;\n\ncreate index new_nid on temp_nodes (new_nid);\ncreate index old_nid on temp_nodes (old_nid);\n\nupdate tig_nodes\n\tset parent_nid = temp_nodes.new_nid from tig_nodes_old, temp_nodes\n\twhere (tig_nodes.old_nid = tig_nodes_old.nid)\n\t\tAND (tig_nodes_old.parent_nid = temp_nodes.old_nid);\n\nselect NOW(), ' - Loading tig_pairs table from old one with new uids and nids';\ninsert into tig_pairs (nid, uid, pkey, pval)\n\tselect tig_nodes.nid, tig_users.uid, pkey, pval\n\t\tfrom tig_pairs_old, tig_users, tig_nodes\n\t\twhere (tig_pairs_old.uid = tig_users.old_uid)\n\t\t\tAND (tig_pairs_old.nid = tig_nodes.old_nid);\n\nselect NOW(), ' - Droping temporarly columns';\ndrop index old_uid;\nalter table tig_users drop column old_uid;\ndrop index old_nid;\nalter table tig_nodes drop column old_nid;\n\nselect NOW(), ' - Converting user passwords to a new format';\nselect TigUsers2Ver4Convert();\n\nselect NOW(), ' - All done, database ready to use!';\n"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-upgrade-to-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n\n\nselect NOW(), ' - Installing missing stored procedures';\n\n-- QUERY START:\ncreate or replace function TigUpdatePairs(bigint, bigint, varchar(255), text) returns void as '\ndeclare\n  _nid alias for $1;\n  _uid alias for $2;\n  _tkey alias for $3;\n  _tval alias for $4;\nbegin\n  if exists(select 1 from tig_pairs where nid = _nid and uid = _uid and pkey = _tkey)\n  then\n        update tig_pairs set pval = _tval where nid = _nid and uid = _uid and pkey = _tkey;\n  else\n        insert into tig_pairs (nid, uid, pkey, pval) values (_nid, _uid, _tkey, _tval);\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n\n-- QUERY START:\nselect TigPutDBProperty('schema-version', '5.1');\n-- QUERY END:\n\nselect NOW(), ' - All done, database ver 5.1 ready to use!';"
  },
  {
    "path": "tigase-server 7.1.0/database/postgresql-schema-upgrade-to-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\n\nselect NOW(), ' - Updating database version';\n\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate or replace function TigPutDBProperty(varchar(255), text) returns void as '\ndeclare\n  _tkey alias for $1;\n  _tval alias for $2;\nbegin\n  if exists( select pval from tig_pairs, tig_users where\n\t\t(lower(user_id) = lower(''db-properties'')) AND (tig_users.uid = tig_pairs.uid)\n\t\tAND (pkey = _tkey))\n  then\n\t  update tig_pairs set pval = _tval from tig_users\n      where (lower(tig_users.user_id) = lower(''db-properties''))\n        AND (tig_users.uid = tig_pairs.uid)\n        AND (pkey = _tkey);\n  else\n    insert into tig_pairs (pkey, pval, uid, nid)\n\t\t  select _tkey, _tval, tu.uid, tn.nid from tig_users tu  left join tig_nodes tn on tn.uid=tu.uid\n\t\t\t  where (lower(user_id) = lower(''db-properties'')  and tn.node=''root'' );\n  end if;\n  return;\nend;\n' LANGUAGE 'plpgsql';\n-- QUERY END:\n\n\n-- QUERY START:\nALTER TABLE tig_pairs ADD COLUMN pid BIGSERIAL PRIMARY KEY;\n-- QUERY END:\n\n-- QUERY START:\nupdate tig_pairs set nid = (select nid from tig_nodes where uid=(select uid from tig_users where user_id='db-properties') and node='root') where uid=(select uid from tig_users where user_id='db-properties');\n-- QUERY END:\n\n-- QUERY START:\nselect TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n\nselect NOW(), ' - All done, database ver 7.1 ready to use!';"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-installer-create-db.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START: USE database\nUSE [master]\n-- QUERY END: USE database\nGO\n\n-- QUERY START: create database\nCREATE DATABASE ${dbName};\n-- QUERY END: create database\nGO\n\n-- QUERY START: add user\nCREATE LOGIN [${dbUser}] WITH PASSWORD=N'${dbPass}', DEFAULT_DATABASE=[${dbName}]\n-- QUERY END: add user\nGO\n\n-- QUERY START: ALTER DATABASE\nIF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [${dbName}] MODIFY FILEGROUP [PRIMARY] DEFAULT\n-- QUERY END: ALTER DATABASE\nGO\n\n-- QUERY START: USE DATABASE\nUSE [${dbName}]\n-- QUERY END: USE DATABASE\nGO\n\n-- QUERY START: GRANT ALL\nCREATE USER [${dbUser}] FOR LOGIN [${dbUser}]\n-- QUERY END: GRANT ALL\nGO\n\n-- QUERY START: ALTER DATABASE\nALTER USER [${dbUser}] WITH DEFAULT_SCHEMA=[dbo]\n-- QUERY END: ALTER DATABASE\nGO\n\n-- QUERY START: ALTER DATABASE\nALTER ROLE [db_owner] ADD MEMBER [${dbUser}]\n-- QUERY END: ALTER DATABASE\nGO\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-installer-post.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START: USE DATABASE\nUSE [${dbName}]\n-- QUERY END: USE DATABASE\nGO\n\n-- QUERY START: ALTER DATABASE\nALTER ROLE [db_owner] ADD MEMBER [${dbUser}]\n-- QUERY END: ALTER DATABASE\nGO\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-4.sql",
    "content": "SET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_max_ids](\n\t[max_uid] [bigint] NULL,\n\t[max_nid] [bigint] NULL\n) ON [PRIMARY]\n\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_users](\n\t[uid] [bigint] NOT NULL,\n\t[user_id] [varchar](256) NOT NULL\n) ON [PRIMARY]\n\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_users] ON [dbo].[tig_users] \n(\n\t[user_id] ASC\n) ON [PRIMARY]\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_users_1] ON [dbo].[tig_users] \n(\n\t[uid] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[short_news](\n\t[snid] [bigint] IDENTITY(1,1) NOT NULL,\n\t[publishing_time] [datetime] NOT NULL CONSTRAINT [DF_short_news_publishing_time]  DEFAULT (getdate()),\n\t[news_type] [varchar](50) NULL,\n\t[author] [varchar](128) NOT NULL,\n\t[subject] [varchar](128) NOT NULL,\n\t[body] [varchar](1024) NOT NULL,\n CONSTRAINT [PK_short_news] PRIMARY KEY CLUSTERED \n(\n\t[snid] ASC\n) ON [PRIMARY]\n) ON [PRIMARY]\n\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news] ON [dbo].[short_news] \n(\n\t[publishing_time] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news_1] ON [dbo].[short_news] \n(\n\t[author] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news_2] ON [dbo].[short_news] \n(\n\t[news_type] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[xmpp_stanza](\n\t[id] [bigint] IDENTITY(1,1) NOT NULL,\n\t[stanza] [text] NOT NULL\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_nodes](\n\t[nid] [bigint] NOT NULL,\n\t[parent_nid] [bigint] NULL,\n\t[uid] [bigint] NOT NULL,\n\t[node] [varchar](128) NOT NULL\n) ON [PRIMARY]\n\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_nodes] ON [dbo].[tig_nodes] \n(\n\t[parent_nid] ASC,\n\t[node] ASC,\n\t[uid] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_tig_nodes_1] ON [dbo].[tig_nodes] \n(\n\t[node] ASC\n) ON [PRIMARY]\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_nodes_2] ON [dbo].[tig_nodes] \n(\n\t[nid] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_pairs](\n\t[nid] [bigint] NOT NULL,\n\t[uid] [bigint] NOT NULL,\n\t[pkey] [varchar](128) NOT NULL,\n\t[pval] [text] NULL\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n\nGO\n\nCREATE NONCLUSTERED INDEX [IX_tig_pairs] ON [dbo].[tig_pairs] \n(\n\t[pkey] ASC\n) ON [PRIMARY]\nGO\nALTER TABLE [dbo].[tig_nodes]  WITH CHECK ADD  CONSTRAINT [FK_tig_nodes_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\nGO\nALTER TABLE [dbo].[tig_nodes] CHECK CONSTRAINT [FK_tig_nodes_tig_users]\nGO\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_nodes] FOREIGN KEY([nid])\nREFERENCES [dbo].[tig_nodes] ([nid])\nGO\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_nodes]\nGO\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\nGO\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_users]\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-5-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\nexec dbo.TigAddUserPlainPw 'db-properties', NULL;\n-- QUERY END:\nGO\n\nselect GETDATE(), ' - Setting schema version to 5.1';\n\n-- QUERY START:\nexec dbo.TigPutDBProperty 'schema-version', '5.1';\n-- QUERY END:\nGO"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-5-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\n--  To load schema to execute following commands:\n--\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE TABLE [dbo].[tig_users](\n\t[uid] [bigint] IDENTITY(1,1) NOT NULL,\n\n\t-- Jabber User ID\n\t[user_id] [nvarchar](2049) NOT NULL,\n\t\n\t-- UserID SHA1 hash to prevent duplicate user_ids\n\t[sha1_user_id] [varbinary](32) NOT NULL,\n\t-- User password encrypted or not\n\t[user_pw] [nvarchar](255) NULL,\n\t-- Time the account has been created\n\t[acc_create_time] [datetime] DEFAULT getdate(),\n\t-- Time of the last user login\n\t[last_login] [datetime] default 0,\n\t-- Time of the last user logout\n\t[last_logout] [datetime] default 0,\n\t-- User online status, if > 0 then user is online, the value\n\t-- indicates the number of user connections.\n\t-- It is incremented on each user login and decremented on each\n\t-- user logout.\n\t[online_status] [int] default 0,\n\t-- Number of failed login attempts\n\t[failed_logins] [int] default 0,\n\t-- User status, whether the account is active or disabled\n\t-- >0 - account active, 0 - account disabled\n\t[account_status] [int] default 1,\n\t-- helper column for indexing due to limitation of SQL server \n\tuser_id_fragment AS LEFT (user_id, 256), \n\n\tCONSTRAINT [PK_tig_users] PRIMARY KEY CLUSTERED ( [uid] ASC ) ON [PRIMARY],\n\tCONSTRAINT [IX_tig_users_sha1_user_id] UNIQUE NONCLUSTERED ( [sha1_user_id] ASC ) ON [PRIMARY]\n) ON [PRIMARY]\n-- QUERY END:\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_account_status] ON [dbo].[tig_users] ([account_status] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_last_login] ON [dbo].[tig_users] ([last_login] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_last_logout] ON [dbo].[tig_users] ( [last_logout] ASC)  ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_online_status] ON [dbo].[tig_users] ([online_status] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_user_id_fragment] ON [dbo].[tig_users] ( [user_id_fragment] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_users_user_pw] ON [dbo].[tig_users] ([user_pw] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n\n\n-- QUERY START:\nCREATE TABLE [dbo].[tig_nodes](\n\t[nid] [bigint] IDENTITY(1,1) NOT NULL,\n\t[parent_nid] [bigint] NULL,\n\t[uid] [bigint] NOT NULL,\n\t[node] [nvarchar](255) NOT NULL,\n CONSTRAINT [PK_tig_nodes_nid] PRIMARY KEY CLUSTERED ( [nid] ASC ) ON [PRIMARY],\n CONSTRAINT [IX_tnode] UNIQUE NONCLUSTERED ( [parent_nid] ASC, [uid] ASC, [node] ASC ) ON [PRIMARY]\n) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_nodes_node] ON [dbo].[tig_nodes] ( [node] ASC) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_nodes_parent_nid] ON [dbo].[tig_nodes] ( [parent_nid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_nodes_uid] ON [dbo].[tig_nodes] ( [uid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_nodes]  WITH CHECK ADD  CONSTRAINT [FK_tig_nodes_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_nodes] CHECK CONSTRAINT [FK_tig_nodes_tig_users]\n-- QUERY END:\nGO\n\n\n-- QUERY START:\nCREATE TABLE [dbo].[tig_pairs](\n\t[nid] [bigint] NULL,\n\t[uid] [bigint] NOT NULL,\n\t[pkey] [nvarchar](255) NOT NULL,\n\t[pval] [ntext] NULL\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_pairs_nid] ON [dbo].[tig_pairs] ( [nid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_pairs_pkey] ON [dbo].[tig_pairs] ( [pkey] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_tig_pairs_uid] ON [dbo].[tig_pairs] ( [uid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_nodes] FOREIGN KEY([nid])\nREFERENCES [dbo].[tig_nodes] ([nid])\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_nodes]\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_users]\n-- QUERY END:\nGO\n\n\n-- QUERY START:\nCREATE TABLE [dbo].[xmpp_stanza](\n\t[id] [bigint] IDENTITY(1,1) NOT NULL,\n\t[stanza] [ntext] NOT NULL,\n CONSTRAINT [PK_xmpp_stanza] PRIMARY KEY CLUSTERED ( [id] ASC ) ON [PRIMARY]\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n-- QUERY END:\nGO\n\n\n-- QUERY START:\nCREATE TABLE [dbo].[short_news](\n\t[snid] [bigint] IDENTITY(1,1) NOT NULL,\n\t[publishing_time] [datetime] NOT NULL,\n\t[news_type] [varchar](50) NULL,\n\t[author] [nvarchar](128) NOT NULL,\n\t[subject] [nvarchar](128) NOT NULL,\n\t[body] [nvarchar](1024) NOT NULL,\n CONSTRAINT [PK_short_news_snid] PRIMARY KEY CLUSTERED ( [snid] ASC ) ON [PRIMARY]\n) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_short_news_author] ON [dbo].[short_news] ( [author] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_short_news_news_type] ON [dbo].[short_news] ( [news_type] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nCREATE NONCLUSTERED INDEX [IX_short_news_publishing_time] ON [dbo].[short_news] ( [publishing_time] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[short_news] ADD  CONSTRAINT [DF_short_news_publishing_time]  DEFAULT (getdate()) FOR [publishing_time]\n-- QUERY END:\nGO\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-5-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n-- Database stored procedures and functions for Tigase schema version 5.2.0\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigInitdb')\nDROP PROCEDURE TigInitdb\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAddUserPlainPw')\nDROP PROCEDURE TigAddUserPlainPw\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAddUser')\nDROP PROCEDURE TigAddUser\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigGetUserDBUid')\nDROP PROCEDURE TigGetUserDBUid\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigRemoveUser')\nDROP PROCEDURE TigRemoveUser\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUpdatePasswordPlainPw')\nDROP PROCEDURE TigUpdatePasswordPlainPw\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUpdatePassword')\nDROP PROCEDURE TigUpdatePassword\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUpdatePasswordPlainPwRev')\nDROP PROCEDURE TigUpdatePasswordPlainPwRev\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigGetPassword')\nDROP PROCEDURE TigGetPassword\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUserLoginPlainPw')\nDROP PROCEDURE TigUserLoginPlainPw\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUserLogin')\nDROP PROCEDURE TigUserLogin\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUserLogout')\nDROP PROCEDURE TigUserLogout\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigOnlineUsers')\nDROP PROCEDURE TigOnlineUsers\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigOfflineUsers')\nDROP PROCEDURE TigOfflineUsers\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAllUsers')\nDROP PROCEDURE TigAllUsers\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAllUsersCount')\nDROP PROCEDURE TigAllUsersCount\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigDisableAccount')\nDROP PROCEDURE TigDisableAccount\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigEnableAccount')\nDROP PROCEDURE TigEnableAccount\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigActiveAccounts')\nDROP PROCEDURE TigActiveAccounts\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigDisabledAccounts')\nDROP PROCEDURE TigDisabledAccounts\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAddNode')\nDROP PROCEDURE TigAddNode\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigTestAddUser')\nDROP PROCEDURE TigTestAddUser\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUsers2Ver4Convert')\nDROP PROCEDURE TigUsers2Ver4Convert\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigPutDBProperty')\nDROP PROCEDURE TigPutDBProperty\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'FN' AND name = 'TigGetDBProperty')\nDROP FUNCTION TigGetDBProperty\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUpdatePairs')\nDROP PROCEDURE TigUpdatePairs\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'FN' AND name = 'InlineMax')\nDROP FUNCTION InlineMax\n-- QUERY END:\nGO\n\n\n\n\n-- QUERY START:\n-- The initialization of the database.\n-- The procedure should be called manually somehow before starting the\n-- server. In theory the server could call the procedure automatically\n-- at the startup time but I don't know yet how to solve the problem\n-- with multiple cluster nodes starting at later time when the server\n-- is already running.\ncreate procedure dbo.TigInitdb\nAS\nbegin\n  update dbo.tig_users set online_status = 0;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Database properties get - function\ncreate function TigGetDBProperty(@_tkey nvarchar(255)) returns nvarchar(MAX)\nAS\nbegin\n--Declare @_result nvarchar(MAX);\nreturn (select pval  from dbo.tig_pairs AS p, dbo.tig_users AS u\n\t\twhere (pkey = @_tkey) AND (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\tAND (p.uid = u.uid));\n\nend\n-- QUERY END:\nGO\n\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure dbo.TigPutDBProperty\n\t@_tkey nvarchar(255),\n\t@_tval ntext\n\tAS\n\tbegin\n\t\tDeclare @_nid int;\n\t\tDeclare @_uid int;\n\t\tDeclare @_count int;\n\t\tif exists (select 1 from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey))\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tupdate dbo.tig_pairs set pval = @_tval\n\t\t\t\t\twhere (@_uid = uid) AND (pkey = @_tkey) ;\n\t\t\tend\n\t\telse\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tinsert into dbo.tig_pairs (pkey, pval, uid)\n\t\t\t\t\tselect @_tkey, @_tval, uid from dbo.tig_users\n\t\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')));\n\t\t\tend\n\tend\n-- QUERY END:\nGO\n\n\n-- QUERY START:\n-- Add a new user to the database assuming the user password is already\n-- encoded properly according to the database settings.\n-- If password is not encoded TigAddUserPlainPw should be used instead.\ncreate procedure dbo.TigAddUser\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\n\tbegin\n\t\tSET NOCOUNT ON;\n\t\t\n\t\tdeclare @res_uid bigint;\n\n\t\tinsert into dbo.tig_users (user_id, sha1_user_id, user_pw)\n\t\t\tvalues (@_user_id, HASHBYTES('SHA1', LOWER(@_user_id)) , @_user_pw);\n\n\t\tset  @res_uid = (select SCOPE_IDENTITY());\n\n\t\tif (@res_uid is not NULL)\n\t\t\tinsert into dbo.tig_nodes (parent_nid, uid, node)\n\t\t\t\tvalues (NULL, @res_uid, N'root');\n\n\t\tif (@_user_pw is NULL) \n\t\t\tupdate dbo.tig_users set account_status = -1 where uid = @res_uid;\n\n\t\tselect @res_uid as uid;\n\tend;\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\n-- and creates a new user account.\ncreate procedure dbo.TigAddUserPlainPw\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\nbegin\n\tdeclare @_encoding nvarchar(512)\n\tdeclare @_hashed_pass varbinary(32)\n\tset @_encoding = dbo.TigGetDBProperty(N'password-encoding')\n\tif @_encoding = N'MD5-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_pw);\n\t\t\texec TigAddUser @_user_id, @_hashed_pass;\n\t\tend\n\tif @_encoding = N'MD5-USERID-PASSWORD' \n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_id + @_user_pw);\n\t\t\texec TigAddUser @_user_id, @_hashed_pass\n\t\tend\n\tif @_encoding = N'MD5-USERNAME-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', (LEFT (@_user_id, CHARINDEX(N'@',@_user_id)-1)) + @_user_pw);\n\t\t\texec TigAddUser @_user_id, @_hashed_pass;\n\t\tend\n\telse\n\t\texec TigAddUser @_user_id, @_user_pw ;\n\tend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Low level database user id as big number. Used only for performance reasons\n-- and save database space. Besides JID is too large to server as UID\ncreate procedure dbo.TigGetUserDBUid\n\t@_user_id nvarchar(2049)\nAS\t\nbegin\n\tselect uid from dbo.tig_users where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Removes a user from the database\ncreate procedure dbo.TigRemoveUser\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\tdeclare @res_uid bigint;\n\n\tset @res_uid = (select uid from dbo.tig_users where sha1_user_id = hashbytes('SHA1', lower(@_user_id)));\n\n\tdelete from dbo.tig_pairs where uid = @res_uid;\n\tdelete from dbo.tig_nodes where uid = @res_uid;\n\tdelete from dbo.tig_users where uid = @res_uid;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Returns user's password from the database\ncreate procedure dbo.TigGetPassword\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\tselect user_pw from dbo.tig_users where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Update user password\ncreate procedure dbo.TigUpdatePassword\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\nbegin\n\tupdate dbo.tig_users set user_pw = @_user_pw where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Takes plain text user password and converts it to internal representation\ncreate procedure dbo.TigUpdatePasswordPlainPw\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\nbegin\n\tdeclare @_encoding nvarchar(512)\n\tdeclare @_hashed_pass varbinary(32)\n\tset @_encoding = dbo.TigGetDBProperty(N'password-encoding')\n\tif @_encoding = N'MD5-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_pw);\n\t\t\texec TigUpdatePassword @_user_id, @_hashed_pass;\n\t\tend\n\tif @_encoding = N'MD5-USERID-PASSWORD' \n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_id + @_user_pw);\n\t\t\texec TigUpdatePassword @_user_id, @_hashed_pass\n\t\tend\n\tif @_encoding = N'MD5-USERNAME-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', (LEFT (@_user_id, CHARINDEX(N'@',@_user_id)-1)) + @_user_pw);\n\t\t\texec TigUpdatePassword @_user_id, @_hashed_pass;\n\t\tend\n\telse\n\t\texec TigUpdatePassword @_user_id, @_user_pw ;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Variant of TigUpdatePasswordPlainPw SP with parameters in reverse order.\n-- Some implementations require the parameters to be in the same order as\n-- the update query.\ncreate procedure dbo.TigUpdatePasswordPlainPwRev\n\t@_user_pw nvarchar(255),\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\texec TigUpdatePasswordPlainPw @_user_id, @_user_pw;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- List all online users\ncreate procedure dbo.TigOnlineUsers\nAS\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom dbo.tig_users where online_status > 0;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- List all offline users\ncreate procedure dbo.TigOfflineUsers\nAS\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom dbo.tig_users where online_status = 0;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- List of all users in database\ncreate procedure dbo.TigAllUsers\nAS\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom dbo.tig_users;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- All users count\ncreate procedure dbo.TigAllUsersCount\nAS\nbegin\n\tselect count(*) from dbo.tig_users;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Perforrm user login. It returns user_id uppon success and NULL\n-- on failure.\n-- If the login is successful it also increases online_status and sets\n-- last_login time to the current timestamp\ncreate procedure dbo.TigUserLogin\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\nbegin\n\tif exists(select 1 from dbo.tig_users\n\t\twhere (account_status > 0) AND (sha1_user_id = hashbytes('SHA1', lower(@_user_id)))\n\t\t\tAND (user_pw = @_user_pw) AND (user_id = @_user_id))\n\t\tbegin\n\t\tupdate dbo.tig_users\n\t\t\tset online_status = online_status + 1, last_login = CURRENT_TIMESTAMP\n\t\t\t\twhere sha1_user_id = hashbytes('SHA1', lower(@_user_id));\n\t\t\tselect @_user_id as user_id;\n\t\tend\n\telse\n\t\tbegin\n\t\t\tupdate dbo.tig_users set failed_logins = failed_logins + 1 where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\n\t\t\tselect NULL as user_id;\n\t\tend\n\tend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Performs user login for a plain text password, converting it to an internal\n-- representation if necessary\ncreate procedure dbo.TigUserLoginPlainPw\n\t@_user_id nvarchar(2049),\n\t@_user_pw nvarchar(255)\nAS\nbegin\n\tdeclare @_encoding nvarchar(512)\n\tdeclare @_hashed_pass varbinary(32)\n\tset @_encoding = dbo.TigGetDBProperty(N'password-encoding')\n\tif @_encoding = 'MD5-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_pw);\n\t\t\texec TigUserLogin @_user_id, @_hashed_pass;\n\t\tend\n\tif @_encoding = N'MD5-USERID-PASSWORD' \n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', @_user_id + @_user_pw);\n\t\t\texec TigUserLogin @_user_id, @_hashed_pass\n\t\tend\n\tif @_encoding = N'MD5-USERNAME-PASSWORD'\n\t\tbegin\n\t\t\tset @_hashed_pass = HASHBYTES('MD5', (LEFT (@_user_id, CHARINDEX(N'@',@_user_id)-1)) + @_user_pw);\n\t\t\texec TigUserLogin @_user_id, @_hashed_pass;\n\t\tend\n\telse\n\t\texec TigUserLogin @_user_id, @_user_pw ;\n\tend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- helper function\ncreate function dbo.InlineMax(@val1 int, @val2 int)\nreturns int\nas\nbegin\n  if @val1 > @val2\n    return @val1\n  return isnull(@val2,@val1)\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- It decreases online_status and sets last_logout time to the current timestamp\ncreate procedure dbo.TigUserLogout\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\tupdate dbo.tig_users\n\t\tset online_status = dbo.InlineMax(online_status - 1, 0),\n\t\t\tlast_logout = CURRENT_TIMESTAMP\n\t\twhere user_id = @_user_id;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Disable user account\ncreate procedure dbo.TigDisableAccount\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\tupdate dbo.tig_users set account_status = 0 where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Enable user account\ncreate procedure dbo.TigEnableAccount\n\t@_user_id nvarchar(2049)\nAS\nbegin\n\tupdate dbo.tig_users set account_status = 1 where sha1_user_id = hashbytes('SHA1', lower(@_user_id));\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Get list of all active user accounts\ncreate procedure dbo.TigActiveAccounts\nAS\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom dbo.tig_users where account_status > 0;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Get list of all disabled user accounts\ncreate procedure dbo.TigDisabledAccounts\nAS\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom dbo.tig_users where account_status = 0;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Helper procedure for adding a new node\ncreate procedure dbo.TigAddNode\n@_parent_nid bigint,\n@_uid bigint,\n@_node nvarchar(255)\nAS\nbegin\n\tSET NOCOUNT ON;\n\t\n\tinsert into dbo.tig_nodes (parent_nid, uid, node)\n\t\tvalues (@_parent_nid, @_uid, @_node);\n\tselect SCOPE_IDENTITY() as nid;\nend\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- Procedure to efficiently and safely update data in tig_pairs table\ncreate procedure dbo.TigUpdatePairs\n@_nid bigint,\n@_uid bigint,\n@_tkey nvarchar(255),\n@_tval ntext\nAS\nbegin\n  if exists(SELECT 1 FROM dbo.tig_pairs WHERE nid = @_nid AND uid = @_uid AND pkey = @_tkey)\n    UPDATE dbo.tig_pairs SET pval = @_tval WHERE nid = @_nid AND uid = @_uid AND pkey = @_tkey;\n  ELSE\n    INSERT INTO dbo.tig_pairs (nid, uid, pkey, pval) VALUES (@_nid, @_uid, @_tkey, @_tval);\nEND\n-- QUERY END:\nGO\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-5-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--  $Rev: $\n--  Last modified by $Author: $\n--  $Date: $\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n-- LOAD FILE: database/sqlserver-schema-5-1-schema.sql\n\n-- LOAD FILE: database/sqlserver-schema-5-1-sp.sql\n\n-- LOAD FILE: database/sqlserver-schema-5-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-7-1-props.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- QUERY START:\n-- This is a dummy user who keeps all the database-properties\nexec dbo.TigAddUserPlainPw 'db-properties', NULL;\n-- QUERY END:\nGO\n\nselect GETDATE(), ' - Setting schema version to 7.1';\n\n-- QUERY START:\nexec dbo.TigPutDBProperty 'schema-version', '7.1';\n-- QUERY END:\nGO"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-7-1-schema.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n\n--  To load schema to execute following commands:\n--\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- LOAD FILE: database/sqlserver-schema-5-1-schema.sql\n\n-- QUERY START:\nIF EXISTS(SELECT * FROM sys.indexes WHERE object_id = object_id('dbo.tig_pairs') AND NAME ='IX_clustered_tig_pairs_nid_uid_pkey')\n    DROP INDEX IX_clustered_tig_pairs_nid_uid_pkey ON dbo.tig_pairs;\n-- QUERY END:\nGO\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs]\n   ADD [pid] [bigint] IDENTITY(1,1) NOT NULL,\n   CONSTRAINT [PK_tig_pairs] PRIMARY KEY CLUSTERED ( [pid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-7-1-sp.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n-- Database stored procedures and functions for Tigase schema version 7.1.0\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n-- LOAD FILE: database/sqlserver-schema-5-1-sp.sql\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigPutDBProperty')\nDROP PROCEDURE TigPutDBProperty\n-- QUERY END:\nGO\n\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure dbo.TigPutDBProperty\n\t@_tkey nvarchar(255),\n\t@_tval ntext\n\tAS\n\tbegin\n\t\tDeclare @_nid int;\n\t\tDeclare @_uid int;\n\t\tDeclare @_count int;\n\t\tif exists (select 1 from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey))\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tupdate dbo.tig_pairs set pval = @_tval\n\t\t\t\t\twhere (@_uid = uid) AND (pkey = @_tkey) ;\n\t\t\tend\n\t\telse\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tinsert into dbo.tig_pairs (pkey, pval, uid, nid)\n\t\t\t\t\tselect @_tkey, @_tval, tu.uid, tn.nid from dbo.tig_users tu  left join tig_nodes tn on tn.uid=tu.uid\n\t\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')) and tn.node='root');\n\t\t\t\t\t\t\n\t\t\tend\n\tend\n-- QUERY END:\nGO\n\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n--  To load schema to PostgreSQL database execute following commands:\n--\n--  createuser tigase\n--  createdb -U tigase tigase\n--  psql -q -U tigase -d tigase -f postgresql-schema.sql\n\n-- LOAD FILE: database/sqlserver-schema-7-1-schema.sql\n\n-- LOAD FILE: database/sqlserver-schema-7-1-sp.sql\n\n-- LOAD FILE: database/sqlserver-schema-7-1-props.sql\n"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema-upgrade-to-7-1.sql",
    "content": "--\n--  Tigase Jabber/XMPP Server\n--  Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n--\n--  This program is free software: you can redistribute it and/or modify\n--  it under the terms of the GNU Affero General Public License as published by\n--  the Free Software Foundation, either version 3 of the License.\n--\n--  This program is distributed in the hope that it will be useful,\n--  but WITHOUT ANY WARRANTY; without even the implied warranty of\n--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n--  GNU Affero General Public License for more details.\n--\n--  You should have received a copy of the GNU Affero General Public License\n--  along with this program. Look for COPYING file in the top folder.\n--  If not, see http://www.gnu.org/licenses/.\n--\n--\n\n-- QUERY START:\nSET QUOTED_IDENTIFIER ON\n-- QUERY END:\nGO\n\n\n-- QUERY START:\nIF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigPutDBProperty')\nDROP PROCEDURE TigPutDBProperty\n-- QUERY END:\nGO\n\n-- QUERY START:\nIF EXISTS(SELECT * FROM sys.indexes WHERE object_id = object_id('dbo.tig_pairs') AND NAME ='IX_clustered_tig_pairs_nid_uid_pkey')\n    DROP INDEX IX_clustered_tig_pairs_nid_uid_pkey ON dbo.tig_pairs;\n-- QUERY END:\nGO\n\n\n\n-- QUERY START:\n-- Database properties set - procedure\ncreate procedure dbo.TigPutDBProperty\n\t@_tkey nvarchar(255),\n\t@_tval ntext\n\tAS\n\tbegin\n\t\tDeclare @_nid int;\n\t\tDeclare @_uid int;\n\t\tDeclare @_count int;\n\t\tif exists (select 1 from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey))\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tupdate dbo.tig_pairs set pval = @_tval\n\t\t\t\t\twhere (@_uid = uid) AND (pkey = @_tkey) ;\n\t\t\tend\n\t\telse\n\t\t\tbegin\n\t\t\t\tselect @_nid = dbo.tig_pairs.nid, @_uid = dbo.tig_pairs.uid from dbo.tig_pairs, dbo.tig_users\n\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')))\n\t\t\t\t\t\tAND (dbo.tig_users.uid = dbo.tig_pairs.uid)  AND (pkey = @_tkey);\n\t\t\t\tinsert into dbo.tig_pairs (pkey, pval, uid, nid)\n\t\t\t\t\tselect @_tkey, @_tval, tu.uid, tn.nid from dbo.tig_users tu  left join tig_nodes tn on tn.uid=tu.uid\n\t\t\t\t\t\twhere (sha1_user_id = HASHBYTES('SHA1', LOWER(N'db-properties')) and tn.node='root');\n\t\t\t\t\t\t\n\t\t\tend\n\tend\n-- QUERY END:\nGO\n\n\n\n-- QUERY START:\nALTER TABLE [dbo].[tig_pairs]\n   ADD [pid] [bigint] IDENTITY(1,1) NOT NULL,\n   CONSTRAINT [PK_tig_pairs] PRIMARY KEY CLUSTERED ( [pid] ASC ) ON [PRIMARY]\n-- QUERY END:\nGO\n\n\n-- QUERY START:\nupdate tig_pairs set nid = (select nid from tig_nodes where uid=(select uid from tig_users where user_id='db-properties') and node='root') where uid=(select uid from tig_users where user_id='db-properties');\n-- QUERY END:\nGO\n\n\nselect GETDATE(), ' - Setting schema version to 7.1';\n\n-- QUERY START:\nexec dbo.TigPutDBProperty 'schema-version', '7.1';\n-- QUERY END:\nGO"
  },
  {
    "path": "tigase-server 7.1.0/database/sqlserver-schema.sql",
    "content": "SET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_max_ids](\n\t[max_uid] [bigint] NULL,\n\t[max_nid] [bigint] NULL\n) ON [PRIMARY]\n\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_users](\n\t[uid] [bigint] NOT NULL,\n\t[user_id] [nvarchar](128) NOT NULL\n) ON [PRIMARY]\n\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_users] ON [dbo].[tig_users] \n(\n\t[user_id] ASC\n) ON [PRIMARY]\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_users_1] ON [dbo].[tig_users] \n(\n\t[uid] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[short_news](\n\t[snid] [bigint] IDENTITY(1,1) NOT NULL,\n\t[publishing_time] [datetime] NOT NULL CONSTRAINT [DF_short_news_publishing_time]  DEFAULT (getdate()),\n\t[news_type] [nvarchar](50) NULL,\n\t[author] [nvarchar](128) NOT NULL,\n\t[subject] [nvarchar](128) NOT NULL,\n\t[body] [nvarchar](1024) NOT NULL,\n CONSTRAINT [PK_short_news] PRIMARY KEY CLUSTERED \n(\n\t[snid] ASC\n) ON [PRIMARY]\n) ON [PRIMARY]\n\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news] ON [dbo].[short_news] \n(\n\t[publishing_time] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news_1] ON [dbo].[short_news] \n(\n\t[author] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_short_news_2] ON [dbo].[short_news] \n(\n\t[news_type] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[xmpp_stanza](\n\t[id] [bigint] IDENTITY(1,1) NOT NULL,\n\t[stanza] [text] NOT NULL\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_nodes](\n\t[nid] [bigint] NOT NULL,\n\t[parent_nid] [bigint] NULL,\n\t[uid] [bigint] NOT NULL,\n\t[node] [nvarchar](64) NOT NULL\n) ON [PRIMARY]\n\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_nodes] ON [dbo].[tig_nodes] \n(\n\t[parent_nid] ASC,\n\t[node] ASC,\n\t[uid] ASC\n) ON [PRIMARY]\nGO\n\nCREATE NONCLUSTERED INDEX [IX_tig_nodes_1] ON [dbo].[tig_nodes] \n(\n\t[node] ASC\n) ON [PRIMARY]\nGO\n\nCREATE UNIQUE NONCLUSTERED INDEX [IX_tig_nodes_2] ON [dbo].[tig_nodes] \n(\n\t[nid] ASC\n) ON [PRIMARY]\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nCREATE TABLE [dbo].[tig_pairs](\n\t[nid] [bigint] NOT NULL,\n\t[uid] [bigint] NOT NULL,\n\t[pkey] [nvarchar](128) NOT NULL,\n\t[pval] [text] NULL\n) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n\nGO\n\nCREATE NONCLUSTERED INDEX [IX_tig_pairs] ON [dbo].[tig_pairs] \n(\n\t[pkey] ASC\n) ON [PRIMARY]\nGO\nALTER TABLE [dbo].[tig_nodes]  WITH CHECK ADD  CONSTRAINT [FK_tig_nodes_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\nGO\nALTER TABLE [dbo].[tig_nodes] CHECK CONSTRAINT [FK_tig_nodes_tig_users]\nGO\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_nodes] FOREIGN KEY([nid])\nREFERENCES [dbo].[tig_nodes] ([nid])\nGO\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_nodes]\nGO\nALTER TABLE [dbo].[tig_pairs]  WITH CHECK ADD  CONSTRAINT [FK_tig_pairs_tig_users] FOREIGN KEY([uid])\nREFERENCES [dbo].[tig_users] ([uid])\nGO\nALTER TABLE [dbo].[tig_pairs] CHECK CONSTRAINT [FK_tig_pairs_tig_users]\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/README.Debian",
    "content": "Tigase for Debian\n-----------------\n\nTigase Jabber/XMPP Server is Open Source and Free (GPLv3) Java based server.\n\n -- Tomasz Sterna <tomek@xiaoka.com>, Thu Mar 13 10:40:12 CET 2009\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/changelog",
    "content": "tigase-server (4.1.5-b1686-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1686: Changed SQL scripts to server-database\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 14:29:23 +0000\n\ntigase-server (4.1.5-b1685-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1685: Proper paths to derby jars in scripts\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 14:24:26 +0000\n\ntigase-server (4.1.5-b1684-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1684: Added derbytools jar to CLASSPATH\n    during postinst\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 14:16:10 +0000\n\ntigase-server (4.1.5-b1683-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1683: Added statistics displaying number of\n    data buffers waiting in the I/O component. Attempt to make data\n    writing more efficient by writing as much data as possible in a\n    single method call. Added method returning number of buffers waiting\n    to send in the I/O. Switching to Sun Java implementation during\n    postinstall Added derby jar to CLASSPATH during postinst\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 14:10:17 +0000\n\ntigase-server (4.1.5-b1678-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1678: Attempt to make data reading more\n    efficient, reading as much characters from the network socket as\n    possible in a single method run.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 12:11:09 +0000\n\ntigase-server (4.1.5-b1677-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1677: Added check for JRE version to init\n    script\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 10:11:08 +0000\n\ntigase-server (4.1.5-b1676-xk2) hardy; urgency=low\n\n  * Checking JRE version during init.d startup script.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 25 May 2009 08:52:49 +0000\n\ntigase-server (4.1.5-b1676-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1676: Presence optimizations switched off\n    temporarily. Fixed problem with excessive CPU usage by tigase.net\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 24 May 2009 00:11:09 +0000\n\ntigase-server (4.1.5-b1674-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1674: Fixed a bug with SM initialization and\n    now the cluster sends broadcast to all cluster nodes about new user\n    connection after initial presence.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 23 May 2009 20:11:09 +0000\n\ntigase-server (4.1.5-b1673-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1673: Typo fixes. Typo fixes. Typo fixes.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 23 May 2009 18:11:09 +0000\n\ntigase-server (4.1.5-b1670-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1670: Broadcasted presence are always sent\n    to bare user jid now. Added msg and check to block user installing\n    over existing Tigase dir Broadcasted presence are always sent to\n    bare user jid now. Added new connection status: REMOTE for user\n    connections established to different cluster nodes. Fixed a bug with\n    token authentication which used getUserId() which couldn't work as\n    user id is only available after successful authentication. Now it\n    takes user id as a parameter. Minor code adjustments. Added method\n    returning number of user connections with a given connection status\n    and fixed a bug in removing invalid user connections from the list.\n    Added callback: handleResourceBind(), now special actions can be\n    performed on the user resource bind. Major code fixes and\n    improvements related to the new clustering implementation. Minor\n    code adjustments. Added local domain name to the statistics list to\n    make it easier to find out from which cluster node statistics come.\n    Logic bug fixed. Code changes related to a possible bug in detecting\n    empty read calls, tests don't show any improvements though. Minor\n    code adjustements. Minor code adjustements. Minor code adjustements.\n    Minor code adjustements. A few fixes related to possible conflicts\n    in the cluster mode. Added simple caching code for the connection\n    pool. Added initRepository call for the connection pool to allow for\n    the pool to initialize itself. For now it initializes internal\n    cache. Clustering code reworked and new, simpler but more effective\n    implementation created. No more connections hangs on resource bind\n    in case of cluster communications problems. Fresh code needs more\n    tests though.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 23 May 2009 12:11:10 +0000\n\ntigase-server (4.1.5-b1649-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1649: changed the code adding admin in the\n    installer to use Tigase repo classes\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 23 May 2009 10:11:08 +0000\n\ntigase-server (4.1.5-b1648-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1648: Fixed incorrect features providing, i\n    hope.... Fixed incorrect features providing, i hope....\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Thu, 21 May 2009 16:26:41 +0000\n\ntigase-server (4.1.5-b1646-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1646: Fixed incorrect features providing, i\n    hope....\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Wed, 20 May 2009 22:11:08 +0000\n\ntigase-server (4.1.5-b1645-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1645: fixed installer bug, where user\n    selection of JDK path was overwrited by JAVA_HOME\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Tue, 19 May 2009 08:11:09 +0000\n\ntigase-server (4.1.5-b1644-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1644: activated user adding task adding xmpp\n    admin user from installer activated user adding task Added jmx files\n    to the installation and a groovy script for user mgmt\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 18 May 2009 16:11:08 +0000\n\ntigase-server (4.1.5-b1640-xk2) hardy; urgency=low\n\n  * Updated to SVN revision 1640\n    Merged r1637 to debian init script\n  * Fixed bug in init script\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 18 May 2009 13:50:04 +0000\n\ntigase-server (4.1.5-b1637-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1637:\\nPresence incorrect broadcast fixed\n    for probe and initial presence. Code formatting update CLASSPATH\n    generating now excludes wrapper libraries\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 18 May 2009 13:33:22 +0000\n\ntigase-server (4.1.5-b1634-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1634:\\nAdded GC calls when memory is Low.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 17 May 2009 20:11:09 +0000\n\ntigase-server (4.1.5-b1633-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1633:\\nTypo fixes.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 16 May 2009 18:11:09 +0000\n\ntigase-server (4.1.5-b1632-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1632:\\nTypo fixes.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 16 May 2009 16:11:08 +0000\n\ntigase-server (4.1.5-b1631-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1631:\\navoid-stale-pid.patch was merged to\n    SVN Added info about using discovered config file\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 16 May 2009 12:11:08 +0000\n\ntigase-server (4.1.5-b1628-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1628:\\nAdded debian source directory\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Thu, 14 May 2009 12:12:53 +0000\n\ntigase-server (4.1.5-b1627-xk2) hardy; urgency=low\n\n  * Added tigase.extras.io.PEMSSLContextContainer as default\n    tigase.io.SSLContextContainer in init.properties\n  * Added dependency: libbcprov-java. Required by PEMSSLContextContainer.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Tue, 12 May 2009 10:51:21 +0000\n\ntigase-server (4.1.5-b1627-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1627:\\nReverted to old and apparently\n    correct behaviour with sending initial presence to all from and both\n    contacts.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 11 May 2009 22:37:08 +0000\n\ntigase-server (4.1.5-b1626-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1626:\\nProbably fixed a bug with concurrent\n    data reading from network socket. Each new server connection is\n    opened in a separate thread to avoid DNS blocking.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 11 May 2009 18:11:33 +0000\n\ntigase-server (4.1.5-b1624-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1624:\\nadding xmpp admin user from installer\n    unneeded file cleanup config file saving fix in console installer\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 11 May 2009 12:11:09 +0000\n\ntigase-server (4.1.5-b1621-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1621:\\nMerge branch 'dbfix'\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 10 May 2009 20:11:08 +0000\n\ntigase-server (4.1.5-b1620-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1620:\\nAdded db and config screens Fixed\n    wrong Derby location selection in console mode Improved packs\n    selection, ignoring packs for other systems\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 10 May 2009 16:11:08 +0000\n\ntigase-server (4.1.5-b1616-xk3) hardy; urgency=low\n\n  * Added Stored procedures for Digest Auth\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 10 May 2009 00:56:21 +0000\n\ntigase-server (4.1.5-b1616-xk2) hardy; urgency=low\n\n  * Added digest auth methods to TigaseAuth.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sun, 10 May 2009 00:01:56 +0000\n\ntigase-server (4.1.5-b1616-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1616:\\nA few fixes and spelling corrections\n    in scripts\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Sat, 09 May 2009 16:11:08 +0000\n\ntigase-server (4.1.5-b1615-xk2) hardy; urgency=low\n\n  * Fixed init script to properly include JDBC drivers\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Fri, 08 May 2009 10:14:32 +0000\n\ntigase-server (4.1.5-b1615-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1615\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Fri, 08 May 2009 09:01:07 +0000\n\ntigase-server (4.1.5-b1614-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1614\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Fri, 08 May 2009 09:00:07 +0000\n\ntigase-server (4.1.5-b1613-xk1) hardy; urgency=low\n\n  * Updated to SVN revision 1613\n  * Separated packages:\n    - tigase-xmltools\n    - tigase-utils\n    - tigase-extras\n    - tigase-muc\n    - tigase-pubsub\n  * Using /usr/share/tigase for all Tigase shared data\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Thu, 07 May 2009 13:46:50 +0000\n\ntigase-server (4.1.4-xk2) dapper; urgency=low\n\n  * Moved Derby Database to /var/spool/tigase/tigase-derbydb\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Fri, 17 Apr 2009 10:30:21 +0000\n\ntigase-server (4.1.4-xk1) unstable; urgency=low\n\n  * Updated Tigase to version 4.1.4:\n    * tigase-extras-0.3.0.jar\n    * tigase-muc-1.0.2.jar\n    * tigase-pubsub-1.0.1.jar\n    * tigase-server-4.1.4.jar\n    * tigase-utils-3.1.2.jar\n    * tigase-xmltools-3.1.1.jar\n  * Updated SQLDB connectors:\n    * mysql-connector-java-5.1.7.tar.gz\n    * postgresql-8.3-604.jdbc3.jar\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Mon, 16 Mar 2009 09:40:18 +0000\n\ntigase-server (4.1.0-b1315-1) unstable; urgency=low\n\n  * Initial Release.\n\n -- Tomasz Sterna <tomek@xiaoka.com>  Thu, 13 Mar 2009 10:42:12 +0200\n\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/compat",
    "content": "4\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/control",
    "content": "Source: tigase-server\nSection: net\nPriority: extra\nMaintainer: Tomasz Sterna <tomek@xiaoka.com>\nBuild-Depends: cdbs, debhelper (>= 5), sun-java6-jdk, maven2\nStandards-Version: 3.8.0\n\nPackage: tigase-server\nArchitecture: all\nDepends: sun-java6-jre | sun-java6-jdk, sun-java6-javadb | libmysql-java | libpg-java,\n tigase-xmltools, tigase-utils, tigase-extras, libbcprov-java,\n adduser, ${misc:Depends}\nDescription: Open Source and Free (GPLv3) Java based Jabber/XMPP server\n The design and implementation goals of the Tigase Jabber/XMPP Server\n  * Make the server robust and reliable.\n  * Make the server secure communication platform.\n  * Make flexible server which can be applied to different use cases.\n  * Make extensible server which takes full advantage of XMPP protocol\n    extensibility.\n  * Make the server easy to setup and maintain.\n .\n See http://www.tigase.org/\nHomepage: http://www.tigase.org/\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/copyright",
    "content": "This package was debianized by Tomasz Sterna <tomek@xiaoka.com>\non Thu, 13 Mar 2009 10:46:12 +0200.\n\nIt was downloaded from https://svn.tigase.org/reps/tigase-server/trunk\n\nUpstream Author: Artur Hefczyc\n\nCopyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as published by\n the Free Software Foundation, version 3 of the License.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License with\nthe Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL-3\nIf not, see <http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/init.properties",
    "content": "--user-db=derby\n--user-db-uri=jdbc:derby:/var/spool/tigase/tigase-derbydb;create=true;logDevice=/var/log/tigase\n--ssl-container-class=tigase.extras.io.PEMSSLContextContainer\nbasic-conf/logging/java.util.logging.FileHandler.pattern = /var/log/tigase/tigase.log\ns2s/connections/tls/keys-store = /etc/tigase/certs/rsa-keystore\ns2s/connections/tls/trusts-store = /etc/tigase/certs/truststore\ns2s/connections/tls/server-certs-dir = /etc/tigase/certs\nc2s/connections/tls/keys-store = /etc/tigase/certs/rsa-keystore\nc2s/connections/tls/trusts-store = /etc/tigase/certs/truststore\nc2s/connections/tls/server-certs-dir = /etc/tigase/certs\nbosh/connections/tls/keys-store = /etc/tigase/certs/rsa-keystore\nbosh/connections/tls/trusts-store = /etc/tigase/certs/truststore\nbosh/connections/tls/server-certs-dir = /etc/tigase/certs\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/rules",
    "content": "#!/usr/bin/make -f\n# debian/rules for Jetty (uses CDBS)\n\ninclude /usr/share/cdbs/1/rules/debhelper.mk\ninclude /usr/share/cdbs/1/rules/simple-patchsys.mk\n\nbuild:\n\tmvn package\n\nclean::\n\trm -rf target\n\nbinary-post-install/tigase-server::\n\tmv debian/tigase-server/usr/share/tigase/database debian/tigase-server/usr/share/tigase/server-database\n\tsed -i 's#jars/\\|libs/#lib/#g' debian/tigase-server/usr/share/tigase/scripts/*.sh\n\tsed -i 's#lib/tigase-server[^.]*.jar#lib/'`basename debian/tigase-server/usr/share/tigase/lib/tigase-server*.jar`'#g' debian/tigase-server/usr/share/tigase/scripts/*.sh\n\tsed -i 's#lib/derby#/usr/lib/jvm/java-6-sun/db/lib/derby#g' debian/tigase-server/usr/share/tigase/scripts/*.sh\n\tsed -i 's#database/#server-database/#g' debian/tigase-server/usr/share/tigase/scripts/*.sh\n\tchmod +x debian/tigase-server/usr/share/tigase/scripts/*.sh\n\tcat debian/init.properties >> debian/tigase-server/etc/tigase/init.properties\n\tfind debian/tigase-server -depth -type d -name .svn -exec rm -rf {} \\;\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/std-logger.sh",
    "content": "#!/bin/sh\nLOG=$1\nshift\nexec $* >>$LOG 2>&1 </dev/null\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.default",
    "content": "# Defaults for tigase-server see /etc/init.d/tigase-server for more\n#TIGASE_DBDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver:org.apache.derby.jdbc.EmbeddedDriver\"\n#TIGASE_USER=tigase\n\nNO_START=1\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.dirs",
    "content": "usr/share/tigase\nusr/share/tigase/lib\nvar/log/tigase\nvar/run\nvar/spool/tigase\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.init",
    "content": "#!/bin/sh -e\n#\n# /etc/init.d/tigase-server -- startup script for tigase-server 4.1.x\n#\n### BEGIN INIT INFO\n# Provides:\t  tigase-server\n# Required-Start:    $network\n# Required-Stop:     $network\n# Should-Start:      $local_fs\n# Should-Stop:       $local_fs\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: Start Tigase Server\n# Description:       Start Tigase Jabber/XMPP Server.\n### END INIT INFO\n\nPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\nNAME=tigase-server\nDESC=\"Tigase Jabber/XMPP Server\"\nTIGASE_HOME=/usr/share/tigase\nTIGASE_RUN=\"tigase.server.XMPPServer\"\nTIGASE_JAR=\"$TIGASE_HOME/lib/tigase-server.jar\"\n\n# The following variables can be overwritten in /etc/default/tigase-server\n\n# Whether to start tigase-server (as a daemon) or not\nNO_START=0\n\n# Run Tigase as this user ID (default: tigase-server)\n# Set this to an empty string to prevent Tigase from starting automatically\nTIGASE_USER=tigase\n\t\t\t  \n# Database drivers loaded to server\t\t\t\t\t\t      \nTIGASE_DBDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver:org.apache.derby.jdbc.EmbeddedDriver\"\n\n# Path to config file\n# It will be generated from init.properties, if absent\nTIGASE_CONFIG=\"/etc/tigase/tigase.xml\"\n\n# File for the tigase-server stdout/stderr output\nTIGASE_CONSOLE_LOG=\"/var/log/tigase/tigase-console.log\"\n\n# Additional server options\nTIGASE_OPTIONS=\"--property-file /etc/tigase/init.properties\"\n\n# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not\n# defined in /etc/default/tigase-server)\nJDK_DIRS=\"\n\t  /usr/lib/jvm/java-6-sun \\\n\t  /usr/lib/j2sdk1.6-sun \\\n\t \"\n\n# End of variables that can be overwritten in /etc/default/tigase-server\n\t\t\t\t\t\t\t\t\t\t\n# overwrite settings from default file\nif [ -f /etc/default/tigase-server ]; then\n\t. /etc/default/tigase-server\nfi\n\n# Find tigase-server jar\nfor jar in $TIGASE_HOME/lib/tigase-server*.jar ; do\n\tif [ -f $jar ] ; then\n\t  TIGASE_JAR=$jar\n\t  break\n\tfi\ndone\n\n# Check whether tigase-server is still installed (it might not be if this package was\n# removed and not purged)\nif [ -r \"$TIGASE_JAR\" ]; then\n    HAVE_TIGASE=1\nelse\n    exit 0\nfi\n\n# Check whether startup has been disabled\nif [ \"$NO_START\" != \"0\" -a \"$1\" != \"stop\" ]; then \n\t[ \"$VERBOSE\" != \"no\" ] && echo \"Not starting $DESC - edit /etc/default/tigase-server and change NO_START to be 0 (or comment it out).\";\n\texit 0;\nfi\n\nif [ -z \"$TIGASE_USER\" ]; then\n\techo \"Not starting/stopping $DESC as configured (TIGASE_USER is\"\n\techo \"empty in /etc/default/tigase-server).\"\n\texit 0\nfi\n\n# Look for the right JVM to use\nfor jdir in $JDK_DIRS; do\n\tif [ -d \"$jdir\" -a -z \"${JAVA_HOME}\" ]; then\n\t\tJAVA_HOME=\"$jdir\"\n\tfi\ndone\nexport JAVA_HOME\n\nexport JAVA=\"$JAVA_HOME/bin/java\"\n\nif [ -z \"$JAVA_OPTIONS\" ]; then\n\tJAVA_OPTIONS=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 \\\n\t\t      -server -Xms100M -Xmx200M \\\n\t\t      -Djava.library.path=/usr/lib\"\nfi\nexport JAVA_OPTIONS\n\t\t\t\t\t\t\t\t\t\t\n# Define other required variables\nPIDFILE=\"/var/run/$NAME.pid\"\nLOGDIR=\"/var/log/tigase\"\n\n##################################################\n# Check for JAVA_HOME and JRE version\n##################################################\nif [ -z \"$JAVA_HOME\" ] || ! \"$JAVA\" -version 2>&1 | grep -q 'java version[^0-9]\\+\\([2-9]\\|1\\.[6-9]\\)'; then\n\tif [ -z \"$JAVA_HOME\" ]; then\n\t\techo \"Could not start $DESC because no Java Runtime Environment (JRE) was found.\"\n\telse\n\t\techo \"$DESC needs Sun Java(TM) SE Runtime Environment at least version 1.6.\"\n\tfi\n\techo \"Please download and install JRE 1.6 or higher and set\"\n\techo \"JAVA_HOME in /etc/default/tigase-server to the JRE's installation directory.\"\n\texit 0\nfi\n\n# Put all jars in classpath\nCLASSPATH=\"$TIGASE_JAR\"\n\nCLASSPATH=\"`ls -d $TIGASE_HOME/lib/*.jar 2>/dev/null | grep -v wrapper | tr '\\n' :`$CLASSPATH\"\nfor lib in /usr/lib/jvm/java-6-sun/db/lib/derby.jar \\\n           /usr/share/java/postgresql.jar \\\n           /usr/share/java/mysql.jar \\\n           /usr/share/java/bcprov.jar ; do\n  if [ -r $lib ]; then CLASSPATH=\"$CLASSPATH:$lib\"; fi\ndone\n\nARGUMENTS=\"$JAVA_OPTIONS $TIGASE_DBDRV -cp $CLASSPATH $TIGASE_RUN -c $TIGASE_CONFIG $TIGASE_OPTIONS\"\n\n##################################################\n# Do the action\n##################################################\ncase \"$1\" in\n  start)\n\tif start-stop-daemon --quiet --test --start --pidfile \"$PIDFILE\" \\\n\t\t\t     --user \"$TIGASE_USER\" --exec \"$JAVA\" > /dev/null; then \n\n\t    if [ -f $PIDFILE ]; then\n\t\techo \"$PIDFILE exists, but $NAME was not running. Ignoring $PIDFILE\"\n\t    fi\n\n\t    echo -n \"Starting $DESC: \"\n\t\ttouch $TIGASE_CONSOLE_LOG\n\t\tchown $TIGASE_USER:adm $TIGASE_CONSOLE_LOG\n\t\techo \"STARTED Tigase `date`\" >>$TIGASE_CONSOLE_LOG\n\t\tstart-stop-daemon --quiet --start --background --pidfile \"$PIDFILE\" --make-pidfile \\\n\t\t                  --chuid \"$TIGASE_USER\" --startas \"$TIGASE_HOME/scripts/std-logger.sh\" \\\n\t\t                  -- \"$TIGASE_CONSOLE_LOG\" \"$JAVA\" $ARGUMENTS\n\t\tsleep 1\n\t\tif [ -e \"$TIGASE_CONFIG\" ]; then\n\t\t\tchown $TIGASE_USER:adm $TIGASE_CONFIG\n\t\t\tchmod 0640 $TIGASE_CONFIG\n\t\tfi\n\t\techo \"$NAME.\"\n\telse\n\techo \"(already running).\"\n\t\texit 1\n\tfi\n\t;;\n\n  stop)\n  \techo -n \"Stopping $DESC: \"\n\n\tif start-stop-daemon --quiet --test --start --pidfile \"$PIDFILE\" \\\n\t\t--user \"$TIGASE_USER\" --exec \"$JAVA\" > /dev/null; then\n\t\tif [ -x \"$PIDFILE\" ]; then\n\t\t\techo \"(not running but $PIDFILE exists).\"\n\t\telse\n\t\t\techo \"(not running).\"\n\t\tfi\n\telse\n\t\tstart-stop-daemon --quiet --stop \\\n\t\t\t--pidfile \"$PIDFILE\" --user \"$TIGASE_USER\" --exec \"$JAVA\" > /dev/null\n\t\tsleep 1\n\t\twhile ! start-stop-daemon --quiet --test --start \\\n\t\t\t--pidfile \"$PIDFILE\" --user \"$TIGASE_USER\" \\\n\t\t\t--startas \"$JAVA\" > /dev/null; do \n\t\t\tsleep 1\n\t\t\techo -n \".\"\n\t\t\tstart-stop-daemon --oknodo --quiet --stop \\\n\t\t\t\t--pidfile \"$PIDFILE\" --user \"$TIGASE_USER\" --exec \"$JAVA\"\n\t\tdone\n\t\trm -f \"$PIDFILE\"\n\t\techo \"$NAME.\"\n\tfi\n\t;;\n\n  restart|force-reload)\n\t$0 stop $*\n\tsleep 1\n\t$0 start $*\n\t;;\n\n  check)\n\techo \"Checking arguments to Tigase: \"\n\techo\n\techo \"PIDFILE         =  $PIDFILE\"\n\techo \"JAVA_OPTIONS    =  $JAVA_OPTIONS\"\n\techo \"JAVA            =  $JAVA\"\n\techo \"TIGASE_USER     =  $TIGASE_USER\"\n\techo \"ARGUMENTS       =  $ARGUMENTS\"\n\techo \"TIGASE_HOME     =  $TIGASE_HOME\"\n\techo \"TIGASE_JAR      =  $TIGASE_JAR\"\n\techo \"TIGASE_CONFIG   =  $TIGASE_CONFIG\"\n\techo \"TIGASE_OPTIONS  =  $TIGASE_OPTIONS\"\n\techo \"CLASSPATH       =  $CLASSPATH\"\n\techo \"TIGASE_CONSOLE_LOG  =  $TIGASE_CONSOLE_LOG\"\n\t\n\tif [ -f $PIDFILE ] && kill -0 `cat $PIDFILE` 2>/dev/null\n\tthen\n\t\techo \"Tigase running pid=\"`cat $PIDFILE`\n\t\texit 0\n\tfi\n\texit 1\n\t;;\n\n  zap)\n\trm -f $TIGASE_PID\n\t;;\n\n  *)\n\techo \"Usage: /etc/init.d/tigase-server {start|stop|restart|force-reload|check}\" >&2\n\texit 1\n\t;;\nesac\n\nexit 0\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.install",
    "content": "target/*.jar\tusr/share/tigase/lib\nscripts/*.sh\tusr/share/tigase/scripts\ndebian/*.sh\tusr/share/tigase/scripts\ndatabase\tusr/share/tigase\netc\t\tusr/share/tigase\netc/init.properties\tetc/tigase\ncerts\t\t\tetc/tigase\n*.html\t\tusr/share/doc/tigase-server\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.postinst",
    "content": "#!/bin/sh -e\n\ncase \"$1\" in\n    configure)\n\tif ! id tigase > /dev/null 2>&1 ; then\n\t    adduser --system --home /usr/share/tigase --no-create-home \\\n\t\t--ingroup nogroup --disabled-password --shell /bin/false \\\n\t\ttigase\n\tfi\n\tchown tigase:adm /var/log/tigase\n\tchown tigase:root /etc/tigase /etc/tigase/certs \\\n\t\t/etc/tigase/certs/rsa-keystore /etc/tigase/certs/truststore \\\n\t\t/var/spool/tigase\n\tchmod 750 /var/log/tigase /var/spool/tigase \\\n\t\t/etc/tigase /etc/tigase/certs\n\tsed -i 's/$HOST_NAME/'`hostname --fqdn`'/g' /etc/tigase/init.properties*\n\n\tif grep -q 'db=derby$' /etc/tigase/init.properties\n\t\tDERBYDB=`sed -n 's/.*user-db-uri.*jdbc:derby://;s/;.*//p' /etc/tigase/init.properties`\n\tthen\n\t\tif [ -n \"$DERBYDB\" ] && [ ! -d \"$DERBYDB\" ] && [ -r /usr/lib/jvm/java-6-sun/db/lib/derby.jar ]\n\t\tthen\n\t\t\techo \"Creating Derby database for Tigase in \\`$DERBYDB' ...\"\n\t\t\tOLDCWD=`pwd`\n\t\t\tcd /usr/share/tigase\n\t\t\tscripts/derby-db-create.sh \"$DERBYDB\" >/dev/null\n\t\t\t[ -e derby.log ] && rm *.log\n\t\t\tchown -R tigase \"$DERBYDB\"\n\t\t\tcd $OLDCWD\n\t\tfi\n\tfi\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n\techo \"$0 called with unknown argument \\`$1'\" >&2\n\texit 1\n    ;;\nesac\n\n#DEBHELPER#\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/tigase-server.postrm",
    "content": "#!/bin/sh -e\n\n#DEBHELPER#\n\ncase \"$1\" in\n    purge)\n\tuserdel tigase || true\n        rm -rf /var/log/tigase /var/spool/tigase\n    ;;\n\n    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n        # Nothing to do here\n    ;;\n\n    *)\n        echo \"$0 called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n"
  },
  {
    "path": "tigase-server 7.1.0/debian/watch",
    "content": "version=3\nhttp://www.tigase.org/files/downloads/tigase-server/tigase-server-(.*)\\.tar\\.gz debian uupdate\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/APNs_HTMessage_Dev.pem",
    "content": "Bag Attributes\n    friendlyName: Apple Development IOS Push Services: com.fanxinmsg.htmssage\n    localKeyID: 5B 6C 87 73 6E 92 50 34 49 52 51 A2 6A 41 DB 96 8A 60 E4 66 \nsubject=/UID=com.fanxinmsg.htmssage/CN=Apple Development IOS Push Services: com.fanxinmsg.htmssage/OU=TQHAZ76T65/C=US\nissuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority\n-----BEGIN CERTIFICATE-----\nMIIFkTCCBHmgAwIBAgIIcVR8mKzwXSAwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js\nZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3\naWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw\nHhcNMTcwMTAzMDU1MDQyWhcNMTgwMTAzMDU1MDQyWjCBkDEmMCQGCgmSJomT8ixk\nAQEMFmNvbS5mYW54aW5tc2cuaHRtc3NhZ2UxRDBCBgNVBAMMO0FwcGxlIERldmVs\nb3BtZW50IElPUyBQdXNoIFNlcnZpY2VzOiBjb20uZmFueGlubXNnLmh0bXNzYWdl\nMRMwEQYDVQQLDApUUUhBWjc2VDY1MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPnjSNyC3DM3quWeZym8dgfIGeHl/b1/hfSbW6tx\nWn6tAfwGxjvytmRNp86lXk1nZNLzl4AteoPhqzYztsuKeaxsD8tQ8DfyZU12LGEn\nMcz5ZGadK6gLKhSzgMtNW8taWIuOEqz8VLesK+Rxdeq7O/LX6Vc1Cr7cnGufDWwu\nZyT4xpmI44GkfjG4OjTp4EP+BG7pH8XHN5MzSqFs9406RTCW3v9ixKjRKz5Iemr8\nQ1zXWA8ra5jHBwOLYxLy3SzQ2pgoiCLs3lO1MmfeShbYZANLY3DJwuAv/rBlWrPF\ngrPOsZIDTRHJeYOl/bmmOYkXG4dNr9HjOLnB52jIacqyO50CAwEAAaOCAeUwggHh\nMB0GA1UdDgQWBBRbbIdzbpJQNElSUaJqQduWimDkZjAJBgNVHRMEAjAAMB8GA1Ud\nIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCCAQIwgf8G\nCSqGSIb3Y2QFATCB8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlz\nIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2Yg\ndGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9u\ncyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBw\ncmFjdGljZSBzdGF0ZW1lbnRzLjApBggrBgEFBQcCARYdaHR0cDovL3d3dy5hcHBs\nZS5jb20vYXBwbGVjYS8wTQYDVR0fBEYwRDBCoECgPoY8aHR0cDovL2RldmVsb3Bl\nci5hcHBsZS5jb20vY2VydGlmaWNhdGlvbmF1dGhvcml0eS93d2RyY2EuY3JsMAsG\nA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAQBgoqhkiG92NkBgMBBAIF\nADANBgkqhkiG9w0BAQUFAAOCAQEAPDZc18IZn5e+5PGNgnH8y0yTNALeDqKbbgPs\n4+oci/zDGXwU1dyHPG1/2a5Q+YlRAQHhIHeXlRjtft+LDR1GhOWWrrI79WHaw2q0\n9CdTxnvRlXz9XrbUjo9DVyIpvidJuNXiG+KYhYHDCRFaMqPBC3gNd6Pj6073OKCX\nLTbGmuJo2/H5cO1/7B4+/AUNHqJG2DEH/YDwTSVcvHDm2APesPcNyvU94S111REO\n+3lDMYYCi7PpwhdWOPxBpyK6mlAmeHBkjlzk5dBrlePCqxjdERGhQflS1W1wqxz7\nRie3yW7WQxjYOUiAGx7C6Tpr9TFt2KN7OPsEGBJtYlXPDV8Btw==\n-----END CERTIFICATE-----\nBag Attributes\n    friendlyName: apple\n    localKeyID: 5B 6C 87 73 6E 92 50 34 49 52 51 A2 6A 41 DB 96 8A 60 E4 66 \nKey Attributes: <No Attributes>\n-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA+eNI3ILcMzeq5Z5nKbx2B8gZ4eX9vX+F9Jtbq3Fafq0B/AbG\nO/K2ZE2nzqVeTWdk0vOXgC16g+GrNjO2y4p5rGwPy1DwN/JlTXYsYScxzPlkZp0r\nqAsqFLOAy01by1pYi44SrPxUt6wr5HF16rs78tfpVzUKvtyca58NbC5nJPjGmYjj\ngaR+Mbg6NOngQ/4Ebukfxcc3kzNKoWz3jTpFMJbe/2LEqNErPkh6avxDXNdYDytr\nmMcHA4tjEvLdLNDamCiIIuzeU7UyZ95KFthkA0tjcMnC4C/+sGVas8WCs86xkgNN\nEcl5g6X9uaY5iRcbh02v0eM4ucHnaMhpyrI7nQIDAQABAoIBAQCDH217MDuFsJ8/\nT+hIMTkqCijyrXGA/yp2WRM4GgnnULcq3Q8mI8zrQwhb2dBrA2cXfnSv8K1KCJ+D\nmI1Brs7719RN1pHGea4IgIr3C88JBJBXe/+NdRZGuI5Ln7McOLMfv5QzK1D09CYw\nAA1k94yUeBFcDlwuHKsDmfk8G/lJnyt6YdFB9vkJQO7nxmD+ro1q67RH9dIyIyAx\nkyWi9AFg/vn/X2Kmn+2HGR9wwAkPI8b4LPYnOivqPDJkeqzTJrZCoT/+vUc8goeB\nnqq4FKyfKN+i0ZaxQMuI/oNId0ZCPWyoM2OXh2DuqilXrOVuqIixd+2COHQnaDxv\npU4zpFxBAoGBAP/xH743M0cnia4FqREKYd++WpLiCWd/hqHw2F9uYfgYu21MUYCq\n6FnbR0BusAXckUbe+Ma8sra0xe6uPbpRWeqFKDWaYsqk1CJYs2ChpqTen8A1q9M5\nnzdQkUcO4pprjKGunifRvb0M+wAPP9B1mxlcm6RKd7oiMYiIF0f2UbNxAoGBAPnx\nzwmk/gXWzzFxA3LEYaNm6uE4cPb5K6mlFYErTUM43MEeltZh/Ep5fS8aXncUulw6\nAJ3BqEY9dIYNtMqdUtKdZLIlszx8kLWgIMcekBFBJBgq15d5i+0+qBJfDDt9erLY\ncbw6OYPMM5mfqeYuDZuVyolo9VYzXI9TYTv3etztAoGASrFd6C9H4b4iKg0w1+5F\nvfxZhoA86l2HNv+IxeD66mKdYDpjlr9J699Yne8vo6ZJJ3uu8qDjLvr2wL9M+HEB\nYrXVlD8oEaek2Rk10D+c2IS37mo7aPtqAcSbgTdQ3mwAsLa7JTfKvb9qCQxqPTX1\nO6ORMJMi+ck813GQCcpS8aECgYEA9ZyyWAbjfLdvGWW1/sSOMfVDoJhHIdsPFgDc\nlfcIUKODAt9dWEQnmMOzyWK/K4OZ8mEpE90m0Ac6BzVW0LgymDcEqa80Z5780Q4O\nx7z304zQvFL1UqulXjhxDsSKD7epqC/b7BzHQgWbOz5TxZbB1n8m7UrPs6p7LXjB\nFx2Fha0CgYA2+Yy/9itc+vrV0YotNpFirFXMFb7ihqHO1rQr0CEiPESHHpFZXN7/\nKDYAkdiysNNKuprsk2db6jpNFSfTtJY6t3XuwkDJoDdVQvDzSeJaQzH170v8AUUP\no5OzXAzOAwG5srWRgJVcvxjXMycFntiZSZT+xzT7VAuUTtFu9bVC9A==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/HTMessage_Dev_APNs.pem",
    "content": "Bag Attributes\n    friendlyName: Apple Development IOS Push Services: com.fanxinmsg.htmssage\n    localKeyID: 5B 6C 87 73 6E 92 50 34 49 52 51 A2 6A 41 DB 96 8A 60 E4 66 \nsubject=/UID=com.fanxinmsg.htmssage/CN=Apple Development IOS Push Services: com.fanxinmsg.htmssage/OU=TQHAZ76T65/C=US\nissuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority\n-----BEGIN CERTIFICATE-----\nMIIFkTCCBHmgAwIBAgIIcVR8mKzwXSAwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js\nZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3\naWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw\nHhcNMTcwMTAzMDU1MDQyWhcNMTgwMTAzMDU1MDQyWjCBkDEmMCQGCgmSJomT8ixk\nAQEMFmNvbS5mYW54aW5tc2cuaHRtc3NhZ2UxRDBCBgNVBAMMO0FwcGxlIERldmVs\nb3BtZW50IElPUyBQdXNoIFNlcnZpY2VzOiBjb20uZmFueGlubXNnLmh0bXNzYWdl\nMRMwEQYDVQQLDApUUUhBWjc2VDY1MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPnjSNyC3DM3quWeZym8dgfIGeHl/b1/hfSbW6tx\nWn6tAfwGxjvytmRNp86lXk1nZNLzl4AteoPhqzYztsuKeaxsD8tQ8DfyZU12LGEn\nMcz5ZGadK6gLKhSzgMtNW8taWIuOEqz8VLesK+Rxdeq7O/LX6Vc1Cr7cnGufDWwu\nZyT4xpmI44GkfjG4OjTp4EP+BG7pH8XHN5MzSqFs9406RTCW3v9ixKjRKz5Iemr8\nQ1zXWA8ra5jHBwOLYxLy3SzQ2pgoiCLs3lO1MmfeShbYZANLY3DJwuAv/rBlWrPF\ngrPOsZIDTRHJeYOl/bmmOYkXG4dNr9HjOLnB52jIacqyO50CAwEAAaOCAeUwggHh\nMB0GA1UdDgQWBBRbbIdzbpJQNElSUaJqQduWimDkZjAJBgNVHRMEAjAAMB8GA1Ud\nIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCCAQIwgf8G\nCSqGSIb3Y2QFATCB8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlz\nIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2Yg\ndGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9u\ncyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBw\ncmFjdGljZSBzdGF0ZW1lbnRzLjApBggrBgEFBQcCARYdaHR0cDovL3d3dy5hcHBs\nZS5jb20vYXBwbGVjYS8wTQYDVR0fBEYwRDBCoECgPoY8aHR0cDovL2RldmVsb3Bl\nci5hcHBsZS5jb20vY2VydGlmaWNhdGlvbmF1dGhvcml0eS93d2RyY2EuY3JsMAsG\nA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAQBgoqhkiG92NkBgMBBAIF\nADANBgkqhkiG9w0BAQUFAAOCAQEAPDZc18IZn5e+5PGNgnH8y0yTNALeDqKbbgPs\n4+oci/zDGXwU1dyHPG1/2a5Q+YlRAQHhIHeXlRjtft+LDR1GhOWWrrI79WHaw2q0\n9CdTxnvRlXz9XrbUjo9DVyIpvidJuNXiG+KYhYHDCRFaMqPBC3gNd6Pj6073OKCX\nLTbGmuJo2/H5cO1/7B4+/AUNHqJG2DEH/YDwTSVcvHDm2APesPcNyvU94S111REO\n+3lDMYYCi7PpwhdWOPxBpyK6mlAmeHBkjlzk5dBrlePCqxjdERGhQflS1W1wqxz7\nRie3yW7WQxjYOUiAGx7C6Tpr9TFt2KN7OPsEGBJtYlXPDV8Btw==\n-----END CERTIFICATE-----\nBag Attributes\n    friendlyName: apple\n    localKeyID: 5B 6C 87 73 6E 92 50 34 49 52 51 A2 6A 41 DB 96 8A 60 E4 66 \nKey Attributes: <No Attributes>\n-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA+eNI3ILcMzeq5Z5nKbx2B8gZ4eX9vX+F9Jtbq3Fafq0B/AbG\nO/K2ZE2nzqVeTWdk0vOXgC16g+GrNjO2y4p5rGwPy1DwN/JlTXYsYScxzPlkZp0r\nqAsqFLOAy01by1pYi44SrPxUt6wr5HF16rs78tfpVzUKvtyca58NbC5nJPjGmYjj\ngaR+Mbg6NOngQ/4Ebukfxcc3kzNKoWz3jTpFMJbe/2LEqNErPkh6avxDXNdYDytr\nmMcHA4tjEvLdLNDamCiIIuzeU7UyZ95KFthkA0tjcMnC4C/+sGVas8WCs86xkgNN\nEcl5g6X9uaY5iRcbh02v0eM4ucHnaMhpyrI7nQIDAQABAoIBAQCDH217MDuFsJ8/\nT+hIMTkqCijyrXGA/yp2WRM4GgnnULcq3Q8mI8zrQwhb2dBrA2cXfnSv8K1KCJ+D\nmI1Brs7719RN1pHGea4IgIr3C88JBJBXe/+NdRZGuI5Ln7McOLMfv5QzK1D09CYw\nAA1k94yUeBFcDlwuHKsDmfk8G/lJnyt6YdFB9vkJQO7nxmD+ro1q67RH9dIyIyAx\nkyWi9AFg/vn/X2Kmn+2HGR9wwAkPI8b4LPYnOivqPDJkeqzTJrZCoT/+vUc8goeB\nnqq4FKyfKN+i0ZaxQMuI/oNId0ZCPWyoM2OXh2DuqilXrOVuqIixd+2COHQnaDxv\npU4zpFxBAoGBAP/xH743M0cnia4FqREKYd++WpLiCWd/hqHw2F9uYfgYu21MUYCq\n6FnbR0BusAXckUbe+Ma8sra0xe6uPbpRWeqFKDWaYsqk1CJYs2ChpqTen8A1q9M5\nnzdQkUcO4pprjKGunifRvb0M+wAPP9B1mxlcm6RKd7oiMYiIF0f2UbNxAoGBAPnx\nzwmk/gXWzzFxA3LEYaNm6uE4cPb5K6mlFYErTUM43MEeltZh/Ep5fS8aXncUulw6\nAJ3BqEY9dIYNtMqdUtKdZLIlszx8kLWgIMcekBFBJBgq15d5i+0+qBJfDDt9erLY\ncbw6OYPMM5mfqeYuDZuVyolo9VYzXI9TYTv3etztAoGASrFd6C9H4b4iKg0w1+5F\nvfxZhoA86l2HNv+IxeD66mKdYDpjlr9J699Yne8vo6ZJJ3uu8qDjLvr2wL9M+HEB\nYrXVlD8oEaek2Rk10D+c2IS37mo7aPtqAcSbgTdQ3mwAsLa7JTfKvb9qCQxqPTX1\nO6ORMJMi+ck813GQCcpS8aECgYEA9ZyyWAbjfLdvGWW1/sSOMfVDoJhHIdsPFgDc\nlfcIUKODAt9dWEQnmMOzyWK/K4OZ8mEpE90m0Ac6BzVW0LgymDcEqa80Z5780Q4O\nx7z304zQvFL1UqulXjhxDsSKD7epqC/b7BzHQgWbOz5TxZbB1n8m7UrPs6p7LXjB\nFx2Fha0CgYA2+Yy/9itc+vrV0YotNpFirFXMFb7ihqHO1rQr0CEiPESHHpFZXN7/\nKDYAkdiysNNKuprsk2db6jpNFSfTtJY6t3XuwkDJoDdVQvDzSeJaQzH170v8AUUP\no5OzXAzOAwG5srWRgJVcvxjXMycFntiZSZT+xzT7VAuUTtFu9bVC9A==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/bosh-extra-headers.txt",
    "content": "Access-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: GET, POST, OPTIONS\nAccess-Control-Allow-Headers: Content-Type\nAccess-Control-Max-Age: 86400\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/client-access-policy.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<access-policy>\n  <cross-domain-access>\n    <policy>\n      <allow-from http-request-headers=\"*\">\n        <domain uri=\"*\"/>\n      </allow-from>\n      <grant-to>\n        <resource path=\"/\" include-subpaths=\"true\"/>\n      </grant-to>\n    </policy>\n  </cross-domain-access>\n</access-policy>"
  },
  {
    "path": "tigase-server 7.1.0/etc/config-dump.properties",
    "content": "sess-man/plugins-conf/message-archive-xep-0136/required-store-method[S]=message\nsess-man/plugins-conf/urn:ietf:params:xml:ns:xmpp-bind/apns-token-db-uri[S]=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF8\nsess-man/plugins-conf/enabled-mechanisms[S]=ANONYMOUS,PLAIN\nsess-man/component-id[S]=sess-man@izwz98w1n1tjfj7xt5ljyqz\nsess-man/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nsess-man/admins[s]=admin@app.im\nsess-man/scripts-dir[S]=scripts/admin\nsess-man/command/ALL[S]=ADMIN\nsess-man/max-queue-size[I]=5060\nsess-man/scheduler-threads[I]=1\nsess-man/incoming-filters[S]=tigase.server.filters.PacketCounter\nsess-man/outgoing-filters[S]=tigase.server.filters.PacketCounter\nsess-man/admin-scripts-dir[S]=scripts/admin/\nsess-man/plugins[s]=session-close, session-open, default-handler, jabber:iq:register, jabber:iq:auth, urn:ietf:params:xml:ns:xmpp-sasl, urn:ietf:params:xml:ns:xmpp-bind, urn:ietf:params:xml:ns:xmpp-session, jabber:iq:roster, jabber:iq:privacy, jabber:iq:version, http://jabber.org/protocol/stats, starttls, vcard-temp, http://jabber.org/protocol/commands, jabber:iq:private, urn:xmpp:ping, presence-state, presence-subscription, disco, domain-filter, zlib, amp, message-carbons, vcard-xep-0292, urn:xmpp:time, urn:xmpp:csi:0, urn:xmpp:receipts, message-push, message-archive-xep-0136\nsess-man/plugins-concurrency[S]=\nsess-man/skip-privacy[B]=false\nsess-man/offline-user-autocreate[S]=false\nsess-man/sm-threads-pool[S]=default\nsess-man/force-detail-stale-connection-check[B]=true\nsess-man/stale-connection-closer-queue-size[I]=1000\nsess-man/auth-timeout[L]=120\nsess-man/sm-threads-factor[I]=1\nbasic-conf/logging/tigase.http.level[S]=FINEST\nbasic-conf/logging/tigase.xmpp.impl.level[S]=FINE\nbasic-conf/logging/tigase.muc.level[S]=FINE\nbasic-conf/logging/tigase.apns.level[S]=FINE\nbasic-conf/logging/tigase.db.jdbc.level[S]=FINER\nbasic-conf/component-id[S]=basic-conf@izwz98w1n1tjfj7xt5ljyqz\nbasic-conf/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nbasic-conf/admins[s]=admin@app.im\nbasic-conf/scripts-dir[S]=scripts/admin\nbasic-conf/command/ALL[S]=ADMIN\nbasic-conf/logging/.level[S]=CONFIG\nbasic-conf/logging/handlers[S]=java.util.logging.ConsoleHandler java.util.logging.FileHandler\nbasic-conf/logging/java.util.logging.ConsoleHandler.formatter[S]=tigase.util.LogFormatter\nbasic-conf/logging/java.util.logging.ConsoleHandler.level[S]=WARNING\nbasic-conf/logging/java.util.logging.FileHandler.append[S]=true\nbasic-conf/logging/java.util.logging.FileHandler.count[S]=5\nbasic-conf/logging/java.util.logging.FileHandler.formatter[S]=tigase.util.LogFormatter\nbasic-conf/logging/java.util.logging.FileHandler.limit[S]=10000000\nbasic-conf/logging/java.util.logging.FileHandler.pattern[S]=logs/tigase.log\nbasic-conf/logging/tigase.useParentHandlers[S]=true\nbasic-conf/logging/java.util.logging.FileHandler.level[S]=ALL\nbasic-conf/user-domain-repo-pool[S]=tigase.db.UserRepositoryMDImpl\nbasic-conf/auth-domain-repo-pool[S]=tigase.db.AuthRepositoryMDImpl\nbasic-conf/user-repo-pool-size[I]=10\nbasic-conf/data-repo-pool-size[I]=10\nbasic-conf/user-repo-class[S]=mysql\nbasic-conf/user-repo-url[S]=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\nbasic-conf/auth-repo-class[S]=tigase.db.jdbc.TigaseCustomAuth\nbasic-conf/auth-repo-url[S]=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\nbasic-conf/ssl-container-class[S]=tigase.io.jdk18.SNISSLContextContainer\nbasic-conf/ssl-certs-location[S]=certs/\nbasic-conf/ssl-def-cert-domain[S]=default\nbasic-conf/config-dump-file[S]=etc/config-dump.properties\nhttp/http/ports[i]=19080, 19081\nhttp/api-keys[s]=open_access\nhttp/component-id[S]=http@izwz98w1n1tjfj7xt5ljyqz\nhttp/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nhttp/admins[s]=admin@app.im\nhttp/scripts-dir[S]=scripts/admin\nhttp/command/ALL[S]=ADMIN\nhttp/max-queue-size[I]=506\nhttp/scheduler-threads[I]=1\nhttp/incoming-filters[S]=tigase.server.filters.PacketCounter\nhttp/outgoing-filters[S]=tigase.server.filters.PacketCounter\nhttp/http/server-class[S]=tigase.http.java.JavaStandaloneHttpServer\nmessage-archive/auto[S]=true\nmessage-archive/component-id[S]=message-archive@izwz98w1n1tjfj7xt5ljyqz\nmessage-archive/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nmessage-archive/admins[s]=admin@app.im\nmessage-archive/scripts-dir[S]=scripts/admin\nmessage-archive/command/ALL[S]=ADMIN\nmessage-archive/max-queue-size[I]=506\nmessage-archive/scheduler-threads[I]=1\nmessage-archive/incoming-filters[S]=tigase.server.filters.PacketCounter\nmessage-archive/outgoing-filters[S]=tigase.server.filters.PacketCounter\nmessage-archive/tags-support[B]=false\nmessage-archive/archive-repo-uri[S]=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\nmessage-archive/remove-expired-messages-delay[S]=PT1H\nmessage-archive/remove-expired-messages-period[S]=P1D\nmessage-archive/remove-expired-messages[B]=false\namp/store-limit[L]=10000\namp/component-id[S]=amp@izwz98w1n1tjfj7xt5ljyqz\namp/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\namp/admins[s]=admin@app.im\namp/scripts-dir[S]=scripts/admin\namp/command/ALL[S]=ADMIN\namp/max-queue-size[I]=506\namp/scheduler-threads[I]=1\namp/incoming-filters[S]=tigase.server.filters.PacketCounter\namp/outgoing-filters[S]=tigase.server.filters.PacketCounter\namp/security-level[S]=STRICT\namp/amp-repo-uri[S]=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\nmessage-router/component-id[S]=message-router@izwz98w1n1tjfj7xt5ljyqz\nmessage-router/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nmessage-router/admins[s]=admin@app.im\nmessage-router/scripts-dir[S]=scripts/admin\nmessage-router/command/ALL[S]=ADMIN\nmessage-router/max-queue-size[I]=5060\nmessage-router/scheduler-threads[I]=1\nmessage-router/incoming-filters[S]=tigase.server.filters.PacketCounter\nmessage-router/outgoing-filters[S]=tigase.server.filters.PacketCounter\nmessage-router/components/msg-receivers/message-archive.class[S]=tigase.archive.MessageArchiveComponent\nmessage-router/components/msg-receivers/message-archive.active[B]=true\nmessage-router/components/msg-receivers/http.class[S]=tigase.http.HttpMessageReceiver\nmessage-router/components/msg-receivers/http.active[B]=true\nmessage-router/components/msg-receivers/id-names[s]=amp, bosh, c2s, eventbus, http, message-archive, monitor, s2s, sess-man, ws2s\nmessage-router/components/msg-receivers/amp.class[S]=tigase.server.amp.AmpComponent\nmessage-router/components/msg-receivers/amp.active[B]=true\nmessage-router/components/msg-receivers/bosh.class[S]=tigase.server.bosh.BoshConnectionManager\nmessage-router/components/msg-receivers/bosh.active[B]=true\nmessage-router/components/msg-receivers/c2s.class[S]=tigase.server.xmppclient.ClientConnectionManager\nmessage-router/components/msg-receivers/c2s.active[B]=true\nmessage-router/components/msg-receivers/eventbus.class[S]=tigase.disteventbus.component.EventBusComponent\nmessage-router/components/msg-receivers/eventbus.active[B]=true\nmessage-router/components/msg-receivers/monitor.class[S]=tigase.monitor.MonitorComponent\nmessage-router/components/msg-receivers/monitor.active[B]=true\nmessage-router/components/msg-receivers/s2s.class[S]=tigase.server.xmppserver.S2SConnectionManager\nmessage-router/components/msg-receivers/s2s.active[B]=true\nmessage-router/components/msg-receivers/sess-man.class[S]=tigase.server.xmppsession.SessionManager\nmessage-router/components/msg-receivers/sess-man.active[B]=true\nmessage-router/components/msg-receivers/ws2s.class[S]=tigase.server.websocket.WebSocketClientConnectionManager\nmessage-router/components/msg-receivers/ws2s.active[B]=true\nmessage-router/components/registrators/id-names[s]=vhost-man, stats\nmessage-router/components/registrators/vhost-man.class[S]=tigase.vhosts.VHostManager\nmessage-router/components/registrators/vhost-man.active[B]=true\nmessage-router/components/registrators/stats.class[S]=tigase.stats.StatisticsCollector\nmessage-router/components/registrators/stats.active[B]=true\nmessage-router/hostnames[s]=app.im\nmessage-router/disco-name[S]=Tigase\nmessage-router/disco-show-version[B]=true\nmessage-router/updates-checking[B]=true\nmessage-router/updates-checking-interval[L]=7\nvhost-man/component-id[S]=vhost-man@izwz98w1n1tjfj7xt5ljyqz\nvhost-man/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nvhost-man/admins[s]=admin@app.im\nvhost-man/scripts-dir[S]=scripts/admin\nvhost-man/command/ALL[S]=ADMIN\nvhost-man/repository-class[S]=tigase.vhosts.VHostJDBCRepository\nvhost-man/hostnames[s]=app.im\nvhost-man/dns-srv-def-addr[S]=izwz98w1n1tjfj7xt5ljyqz\nvhost-man/dns-def-ip[S]=10.30.210.67\nvhost-man/domains-per-user-limit[I]=25\nstats/component-id[S]=stats@izwz98w1n1tjfj7xt5ljyqz\nstats/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nstats/admins[s]=admin@app.im\nstats/scripts-dir[S]=scripts/admin\nstats/command/ALL[S]=ADMIN\nstats/stats-history-size[I]=0\nstats/stats-update-interval[L]=10\nbosh/component-id[S]=bosh@izwz98w1n1tjfj7xt5ljyqz\nbosh/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nbosh/admins[s]=admin@app.im\nbosh/scripts-dir[S]=scripts/admin\nbosh/command/ALL[S]=ADMIN\nbosh/max-queue-size[I]=5060\nbosh/scheduler-threads[I]=1\nbosh/incoming-filters[S]=tigase.server.filters.PacketCounter\nbosh/outgoing-filters[S]=tigase.server.filters.PacketCounter\nbosh/connections/tls/use[B]=true\nbosh/net-buffer[I]=2048\nbosh/traffic-throttling[S]=xmpp:2500:0:disc,bin:20m:0:disc\nbosh/net-buffer-limit[I]=2097152\nbosh/elements-number-limit[I]=1000\nbosh/watchdog_delay[L]=600000\nbosh/watchdog_timeout[L]=1740000\nbosh/watchdog_ping_type[S]=WHITESPACE\nbosh/connections/5280/type[S]=accept\nbosh/connections/5280/socket[S]=plain\nbosh/connections/5280/ifc[s]=*\nbosh/connections/5280/remote-host[S]=localhost\nbosh/connections/5280/connections/tls/required[B]=false\nbosh/connections/ports[i]=5280\nbosh/white-char-ack[B]=false\nbosh/xmpp-ack[B]=false\nbosh/max-inactivity-time[L]=600\nbosh/cm-see-other-host[S]=<null>\nbosh/routings/multi-mode[B]=true\nbosh/routings/.+[S]=sess-man@izwz98w1n1tjfj7xt5ljyqz\nbosh/socket-close-wait[L]=1\nbosh/tls-want-client-auth-enabled[B]=false\nbosh/max-wait[L]=30\nbosh/min-polling[L]=10\nbosh/max-inactivity[L]=10\nbosh/concurrent-requests[I]=2\nbosh/hold-requests[I]=1\nbosh/max-batch-size[I]=15\nbosh/batch-queue-timeout[L]=100\nbosh/max-session-waiting-packets[I]=100\nbosh/send-node-hostname[B]=true\nbosh/sid-logger-level[S]=OFF\nc2s/component-id[S]=c2s@izwz98w1n1tjfj7xt5ljyqz\nc2s/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nc2s/admins[s]=admin@app.im\nc2s/scripts-dir[S]=scripts/admin\nc2s/command/ALL[S]=ADMIN\nc2s/max-queue-size[I]=5060\nc2s/scheduler-threads[I]=1\nc2s/incoming-filters[S]=tigase.server.filters.PacketCounter\nc2s/outgoing-filters[S]=tigase.server.filters.PacketCounter\nc2s/connections/tls/use[B]=true\nc2s/net-buffer[I]=2048\nc2s/traffic-throttling[S]=xmpp:2500:0:disc,bin:20m:0:disc\nc2s/net-buffer-limit[I]=2097152\nc2s/elements-number-limit[I]=1000\nc2s/watchdog_delay[L]=600000\nc2s/watchdog_timeout[L]=1740000\nc2s/watchdog_ping_type[S]=WHITESPACE\nc2s/connections/5222/type[S]=accept\nc2s/connections/5222/socket[S]=plain\nc2s/connections/5222/ifc[s]=*\nc2s/connections/5222/remote-host[S]=localhost\nc2s/connections/5222/connections/tls/required[B]=false\nc2s/connections/5223/type[S]=accept\nc2s/connections/5223/socket[S]=ssl\nc2s/connections/5223/ifc[s]=*\nc2s/connections/5223/remote-host[S]=localhost\nc2s/connections/5223/connections/tls/required[B]=false\nc2s/connections/ports[i]=5222, 5223\nc2s/white-char-ack[B]=false\nc2s/xmpp-ack[B]=false\nc2s/max-inactivity-time[L]=86400\nc2s/cm-see-other-host[S]=<null>\nc2s/routings/multi-mode[B]=true\nc2s/routings/.+[S]=sess-man@izwz98w1n1tjfj7xt5ljyqz\nc2s/socket-close-wait[L]=1\nc2s/tls-want-client-auth-enabled[B]=false\neventbus/component-id[S]=eventbus@izwz98w1n1tjfj7xt5ljyqz\neventbus/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\neventbus/admins[s]=admin@app.im\neventbus/scripts-dir[S]=scripts/admin\neventbus/command/ALL[S]=ADMIN\neventbus/max-queue-size[I]=506\neventbus/scheduler-threads[I]=1\neventbus/incoming-filters[S]=tigase.server.filters.PacketCounter\neventbus/outgoing-filters[S]=tigase.server.filters.PacketCounter\neventbus/modules/jabber:iq:version[S]=tigase.component.modules.impl.JabberVersionModule\neventbus/modules/receiver[S]=tigase.disteventbus.component.EventReceiverModule\neventbus/modules/subscribe[S]=tigase.disteventbus.component.SubscribeModule\neventbus/modules/unsubscribe[S]=tigase.disteventbus.component.UnsubscribeModule\neventbus/modules/urn:xmpp:ping[S]=tigase.component.modules.impl.XmppPingModule\neventbus/modules/disco[S]=tigase.component.modules.impl.DiscoveryModule\neventbus/modules/publisher[S]=tigase.disteventbus.component.EventPublisherModule\neventbus/modules/commands[S]=tigase.component.modules.impl.AdHocCommandModule\nmonitor/component-id[S]=monitor@izwz98w1n1tjfj7xt5ljyqz\nmonitor/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nmonitor/admins[s]=admin@app.im\nmonitor/scripts-dir[S]=scripts/admin\nmonitor/command/ALL[S]=ADMIN\nmonitor/max-queue-size[I]=506\nmonitor/scheduler-threads[I]=1\nmonitor/incoming-filters[S]=tigase.server.filters.PacketCounter\nmonitor/outgoing-filters[S]=tigase.server.filters.PacketCounter\nmonitor/modules/jabber:iq:version[S]=tigase.component.modules.impl.JabberVersionModule\nmonitor/modules/urn:xmpp:ping[S]=tigase.component.modules.impl.XmppPingModule\nmonitor/modules/disco[S]=tigase.monitor.modules.DiscoveryMonitorModule\nmonitor/modules/commands[S]=tigase.monitor.modules.AdHocCommandMonitorModule\ns2s/component-id[S]=s2s@izwz98w1n1tjfj7xt5ljyqz\ns2s/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\ns2s/admins[s]=admin@app.im\ns2s/scripts-dir[S]=scripts/admin\ns2s/command/ALL[S]=ADMIN\ns2s/max-queue-size[I]=506\ns2s/scheduler-threads[I]=1\ns2s/incoming-filters[S]=tigase.server.filters.PacketCounter\ns2s/outgoing-filters[S]=tigase.server.filters.PacketCounter\ns2s/connections/tls/use[B]=true\ns2s/net-buffer[I]=65536\ns2s/traffic-throttling[S]=xmpp:15k:0:disc,bin:120m:0:disc\ns2s/net-buffer-limit[I]=20971520\ns2s/elements-number-limit[I]=1000\ns2s/watchdog_delay[L]=600000\ns2s/watchdog_timeout[L]=1740000\ns2s/watchdog_ping_type[S]=WHITESPACE\ns2s/connections/5269/type[S]=accept\ns2s/connections/5269/socket[S]=plain\ns2s/connections/5269/ifc[s]=*\ns2s/connections/5269/remote-host[S]=localhost\ns2s/connections/5269/connections/tls/required[B]=false\ns2s/connections/ports[i]=5269\ns2s/white-char-ack[B]=false\ns2s/xmpp-ack[B]=false\ns2s/max-inactivity-time[L]=900\ns2s/max-packet-waiting-time[L]=420\ns2s/max-in-conns[I]=4\ns2s/max-out-total-conns[I]=1\ns2s/max-out-per-ip-conns[I]=1\ns2s/s2s-conn-selector[S]=tigase.server.xmppserver.S2SRandomSelector\ns2s/cid-connections-tasks-threads[I]=1\ns2s/s2s-domain-mapping[S]=\nws2s/component-id[S]=ws2s@izwz98w1n1tjfj7xt5ljyqz\nws2s/def-hostname[S]=izwz98w1n1tjfj7xt5ljyqz\nws2s/admins[s]=admin@app.im\nws2s/scripts-dir[S]=scripts/admin\nws2s/command/ALL[S]=ADMIN\nws2s/max-queue-size[I]=5060\nws2s/scheduler-threads[I]=1\nws2s/incoming-filters[S]=tigase.server.filters.PacketCounter\nws2s/outgoing-filters[S]=tigase.server.filters.PacketCounter\nws2s/connections/tls/use[B]=true\nws2s/net-buffer[I]=2048\nws2s/traffic-throttling[S]=xmpp:2500:0:disc,bin:20m:0:disc\nws2s/net-buffer-limit[I]=2097152\nws2s/elements-number-limit[I]=1000\nws2s/watchdog_delay[L]=600000\nws2s/watchdog_timeout[L]=1740000\nws2s/watchdog_ping_type[S]=WHITESPACE\nws2s/connections/5290/type[S]=accept\nws2s/connections/5290/socket[S]=plain\nws2s/connections/5290/ifc[s]=*\nws2s/connections/5290/remote-host[S]=localhost\nws2s/connections/5290/connections/tls/required[B]=false\nws2s/connections/ports[i]=5290\nws2s/white-char-ack[B]=false\nws2s/xmpp-ack[B]=false\nws2s/max-inactivity-time[L]=86400\nws2s/cm-see-other-host[S]=<null>\nws2s/routings/multi-mode[B]=true\nws2s/routings/.+[S]=sess-man@izwz98w1n1tjfj7xt5ljyqz\nws2s/socket-close-wait[L]=1\nws2s/tls-want-client-auth-enabled[B]=false\nws2s/protocol-versions[s]=hybi\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/cross-domain-policy.xml",
    "content": "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n<cross-domain-policy>\n  <allow-access-from domain=\"*\" to-ports=\"80,8080,5222,5223\"/>\n  <site-control permitted-cross-domain-policies=\"all\"/>\n</cross-domain-policy>\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/htmessage_production_APNs.pem",
    "content": "Bag Attributes\n    friendlyName: Apple Push Services: com.fanxinmsg.htmssage\n    localKeyID: 3F 5E 98 55 0A 59 11 29 B1 39 40 8F FD B6 39 16 69 DB 1D 01 \nsubject=/UID=com.fanxinmsg.htmssage/CN=Apple Push Services: com.fanxinmsg.htmssage/OU=TQHAZ76T65/O=Hefei Palm Peak Technology Co., Ltd./C=US\nissuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority\n-----BEGIN CERTIFICATE-----\nMIIGRDCCBSygAwIBAgIIC5vm99Uw+38wDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js\nZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3\naWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw\nHhcNMTcwMzA5MDIxNDM1WhcNMTgwNDA4MDIxNDM1WjCBrzEmMCQGCgmSJomT8ixk\nAQEMFmNvbS5mYW54aW5tc2cuaHRtc3NhZ2UxNDAyBgNVBAMMK0FwcGxlIFB1c2gg\nU2VydmljZXM6IGNvbS5mYW54aW5tc2cuaHRtc3NhZ2UxEzARBgNVBAsMClRRSEFa\nNzZUNjUxLTArBgNVBAoMJEhlZmVpIFBhbG0gUGVhayBUZWNobm9sb2d5IENvLiwg\nTHRkLjELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDHNLE+jn2wrPq0N701D7mfd68sfn8FpgYxkntI+fSICrBDoTQNAai6deKLTX33\nKAO6+uxNyjsibEfJ9NtJ2YMO/kk7gN1KhfJtIrWKmjpjJ+F4G/TagQuEavVfR26+\nQoXNShycnSAF8D6/FSpuZGZ50mzpuBDHElZ+f8kk74zvpKB9oeR3TnjQHzSd9P0V\n/bcdtdBLYsEAWoX2V1v5K1gImD8OXzn735MhiqZx+4oxuiQ7fXfolnwU1AOabfEc\nnLvybtxxhWSe4p1Pe3ZXYtPpwWin9W/QZZ+ZufGjmAvWYQrZq8nZAQNX1ci4AVRU\nKziNoNsNOhTsV1txdUM0H0BNAgMBAAGjggJ5MIICdTAdBgNVHQ4EFgQUP16YVQpZ\nESmxOUCP/bY5FmnbHQEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSIJxcJqbYY\nYIvs67r2R1nFUlSjtzCCARwGA1UdIASCARMwggEPMIIBCwYJKoZIhvdjZAUBMIH9\nMIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUg\nYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBs\naWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2Vy\ndGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRl\nbWVudHMuMDUGCCsGAQUFBwIBFilodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZp\nY2F0ZWF1dGhvcml0eTAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmFwcGxl\nLmNvbS93d2RyY2EuY3JsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEF\nBQcDAjAQBgoqhkiG92NkBgMBBAIFADAQBgoqhkiG92NkBgMCBAIFADCBiQYKKoZI\nhvdjZAYDBgR7MHkMFmNvbS5mYW54aW5tc2cuaHRtc3NhZ2UwBQwDYXBwDBtjb20u\nZmFueGlubXNnLmh0bXNzYWdlLnZvaXAwBgwEdm9pcAwjY29tLmZhbnhpbm1zZy5o\ndG1zc2FnZS5jb21wbGljYXRpb24wDgwMY29tcGxpY2F0aW9uMA0GCSqGSIb3DQEB\nCwUAA4IBAQAFS4u12Ob5s/dvhwO9+ZREo5Jm/MlBthxEN/7gM0oxkMTh+LiPOWwK\n44UFFlFWTOnUP5jl/xjurozS9n4oKA/BS2QDN1sQVR/bidaIAQUn5ZfEz68RDfHW\nrO9Dqzf/Q9gcCU+kY0NC62C1wJ1o0i5qmN04+cgUBvm0B8x26fFDS4TiCrfWyM2P\nSzXmoshivHRMIgtiJVdpizw3qtQTOjiWb26pQfXxTodremlEFZOOL0B9+rnySR8w\nSw79xoug+2M0QRDZ4fA0itsE2tEliVQRBmXLF2f1JoyyYClL/yf8yKRf6RQDFT3X\nZyrQy8ctl8L1FOg676DqsmVZhsgbwQcX\n-----END CERTIFICATE-----\nBag Attributes\n    friendlyName: apple\n    localKeyID: 3F 5E 98 55 0A 59 11 29 B1 39 40 8F FD B6 39 16 69 DB 1D 01 \nKey Attributes: <No Attributes>\n-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAxzSxPo59sKz6tDe9NQ+5n3evLH5/BaYGMZJ7SPn0iAqwQ6E0\nDQGounXii0199ygDuvrsTco7ImxHyfTbSdmDDv5JO4DdSoXybSK1ipo6YyfheBv0\n2oELhGr1X0duvkKFzUocnJ0gBfA+vxUqbmRmedJs6bgQxxJWfn/JJO+M76SgfaHk\nd0540B80nfT9Ff23HbXQS2LBAFqF9ldb+StYCJg/Dl85+9+TIYqmcfuKMbokO313\n6JZ8FNQDmm3xHJy78m7ccYVknuKdT3t2V2LT6cFop/Vv0GWfmbnxo5gL1mEK2avJ\n2QEDV9XIuAFUVCs4jaDbDToU7FdbcXVDNB9ATQIDAQABAoIBAF8vU13z0iUgkm6Y\nj6USDX0gQCi/jMxTJ3R6bMRTA0AZ811tYqSwXUIzX/t2HLGDgjzO9yi4cAcjvC3I\n/RtNfq0kXjO7gIHCfTMeuaYvyaRlgvvUR+w8axdr0DElvcnVmX+dYQyIm6uavzCo\n2WyENt8Q6A/JbuLgZUnun1sxx6Mdq+2JHlRWmp1oZqJavxkuxPfOgvJGsQ7Jyau6\n/1qmljlR91LydJzlVfZ8gIbVdrroVSIpAi52eOYwUVpimHoQDb8gg5Z4CXf05pr2\n6ZfxyE2kvplVaY5NtmjxOq63BcnjzoQB0KvB9JbTrC9RlTy4EcTX5LgCScgUBOAE\nZjDzDUECgYEA40AQ5TbqRuGMwaffOtKlM3XJf9QTEZKziEeZ0VuG+9HBLzsrBGfR\nx+7VwEDnNVtJdHUvJOCZWVrUwe7IU88lXFnCSUOtIo6xRIIDp7s+HUTFmWc9DREy\nfnBa8qfSwmfrQdL92dZQEsJM22jmfVbQ2G8Ufuc49yR+4TbQFKElmpECgYEA4Gha\nnCRu9j8Fppi3GuOHGBvyaB45Hpq20nk2loNmmWFbT8daHLcd6n5QOVhT4ROhJ+Tc\n6Op4w1402wT97AGOn+pwNHSeZ3SrKoRSc3GMcab2KrbKqGJBiUXjbxy34ke0rBR3\nzBOkGBI1qAi+mt5HAUHkPI+iKEQjz3gvMtz3D/0CgYBFJGT/mKnHTzDoaw88coLZ\nGWlpfzkeC6icOkzOqi5zx+ojWLlJ6dymHEDk8dpnHZNH36+sZLnDuiMprmE9PrV7\nV8QJTpILBadh1L0P96R6e0Yz2nl01FqspbrGQdGaXMvzhyK9eLt8OanwyAX49MUu\nVP3Dbs6iQ3RnSaod3Ln4QQKBgCOAXtVU7jkGv14bytv2Iuktgqv2HBM7ZrDlfD1T\njGe3fzqfzyG71n/Ce+6Wiq6Q7G3jRw+SCIjf3nzHzWQI2wdxj069JFI5otqXFHQv\nAoj4YPlg8a6x3Kxa4iAx6uVhcrPGiS0/7jXgq5xpxb26bIFGa1UpY/36ya+I0+64\nBl4BAoGARY09HjFavAwlKGnMNRBXqXhRjBXSfKjKbJz57pYezyYQ1xHuF/GItrgB\nxI/OJeEdVFpo/ApH7/0krIM6AtLLjuEwYSDsUKAHYMhf+Ymb55z4GfhuWP/iDh/+\n/FjEojlv36ykWcKSFXQbKVK7XqNCJ9BHQn8fQxuD8mdFnfZ/O2o=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/init-apns.properties",
    "content": "cert_file=APNs_HTMessage_Dev.p12\n#cert_file=htmessage_production_APNs.p12\n#cert_file=HTMessage_Dev_APNs.p12\npwd=123456\nexecutor_size=20\nmaxConnections=20\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/init.properties",
    "content": "config-type=--gen-config-def\n--admins=admin@app.im\n--virt-hosts = app.im\n\n--user-db=mysql\n--user-db-uri=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull\n\nsess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:\\xmpp-bind/apns-token-db-uri=jdbc:mysql://127.0.0.1:3306/tigase?user=tigase&password=123456&useUnicode=true&characterEncoding=UTF8\n\n\nsess-man/plugins-conf/enabled-mechanisms=ANONYMOUS,PLAIN\n\nbasic-conf/logging/tigase.http.level=FINEST\nbasic-conf/logging/tigase.db.jdbc.level=FINER\nbasic-conf/logging/tigase.xmpp.impl.level=FINE\nbasic-conf/logging/tigase.muc.level=FINE\nbasic-conf/logging/tigase.apns.level=FINE\n\n#sess-man/plugins-conf/amp/user-store-limit-enable[B]=false\n#sess-man/plugins-conf//user-store-limit-enable[B]=false\namp/store-limit[L]=10000\n\n--sm-plugins=+urn:xmpp:receipts,+message-push,+message-archive-xep-0136\n\n--comp-name-1=http\n--comp-class-1=tigase.http.HttpMessageReceiver\nhttp/api-keys[s]=open_access\nhttp/http/ports[i]=19080,19081\n\n\n--comp-name-2=message-archive\n--comp-class-2=tigase.archive.MessageArchiveComponent\nmessage-archive/auto=true\nsess-man/plugins-conf/message-archive-xep-0136/required-store-method=message\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/jmx.access",
    "content": "######################################################################\n#     Default Access Control File for Remote JMX(TM) Monitoring\n######################################################################\n#\n# Access control file for Remote JMX API access to monitoring.\n# This file defines the allowed access for different roles.  The\n# password file (jmxremote.password by default) defines the roles and their\n# passwords.  To be functional, a role must have an entry in\n# both the password and the access files.\n#\n# Default location of this file is $JRE/lib/management/jmxremote.access\n# You can specify an alternate location by specifying a property in \n# the management config file $JRE/lib/management/management.properties\n# (See that file for details)\n#\n# The file format for password and access files is syntactically the same\n# as the Properties file format.  The syntax is described in the Javadoc\n# for java.util.Properties.load.\n# Typical access file has multiple  lines, where each line is blank,\n# a comment (like this one), or an access control entry.\n#\n# An access control entry consists of a role name, and an\n# associated access level.  The role name is any string that does not\n# itself contain spaces or tabs.  It corresponds to an entry in the\n# password file (jmxremote.password).  The access level is one of the\n# following:\n#       \"readonly\" grants access to read attributes of MBeans.\n#                   For monitoring, this means that a remote client in this\n#                   role can read measurements but cannot perform any action\n#                   that changes the environment of the running program.\n#       \"readwrite\" grants access to read and write attributes of MBeans,\n#                   to invoke operations on them, and to create or remove them.\n#\t\t    This access should be granted to only trusted clients, \n#                   since they can potentially interfere with the smooth\n#\t\t    operation of a running program \n#\n# A given role should have at most one entry in this file.  If a role\n# has no entry, it has no access.\n# If multiple entries are found for the same role name, then the last\n# access entry is used.\n#\n#\n# Default access control entries:\n# o The \"monitorRole\" role has readonly access.  \n# o The \"controlRole\" role has readwrite access.\n\nmonitor readonly\nadmin readwrite\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/jmx.password",
    "content": "# ----------------------------------------------------------------------\n#           Template for jmxremote.password\n#\n# o Copy this template to jmxremote.password\n# o Set the user/password entries in jmxremote.password\n# o Change the permission of jmxremote.password to read-only\n#   by the owner.\n#\n# See below for the location of jmxremote.password file.\n# ----------------------------------------------------------------------\n\n##############################################################\n#        Password File for Remote JMX Monitoring\n##############################################################\n#\n# Password file for Remote JMX API access to monitoring.  This\n# file defines the different roles and their passwords.  The access\n# control file (jmxremote.access by default) defines the allowed\n# access for each role.  To be functional, a role must have an entry\n# in both the password and the access files.\n#\n# Default location of this file is $JRE/lib/management/jmxremote.password\n# You can specify an alternate location by specifying a property in \n# the management config file $JRE/lib/management/management.properties\n# or by specifying a system property (See that file for details).\n\n\n##############################################################\n#    File permissions of the jmxremote.password file\n##############################################################\n#      Since there are cleartext passwords stored in this file,\n#      this file must be readable by ONLY the owner,\n#      otherwise the program will exit with an error. \n#\n# The file format for password and access files is syntactically the same\n# as the Properties file format.  The syntax is described in the Javadoc\n# for java.util.Properties.load.\n# Typical password file has multiple  lines, where each line is blank,\n# a comment (like this one), or a password entry.\n#\n#\n# A password entry consists of a role name and an associated\n# password.  The role name is any string that does not itself contain\n# spaces or tabs.  The password is again any string that does not\n# contain spaces or tabs.  Note that passwords appear in the clear in\n# this file, so it is a good idea not to use valuable passwords.\n#\n# A given role should have at most one entry in this file.  If a role\n# has no entry, it has no access.\n# If multiple entries are found for the same role name, then the last one\n# is used.\n#\n# In a typical installation, this file can be read by anybody on the\n# local machine, and possibly by people on other machines.\n# For # security, you should either restrict the access to this file,\n# or specify another, less accessible file in the management config file\n# as described above.\n#\n# Following are two commented-out entries.  The \"measureRole\" role has\n# password \"QED\".  The \"controlRole\" role has password \"R&D\".\n#\n# monitorRole  QED\n# controlRole   R&D\n\nadmin admin_pass\nmonitor monitor_pass"
  },
  {
    "path": "tigase-server 7.1.0/etc/logback.xml",
    "content": "<configuration scan=\"true\">\n    <appender name=\"FILE\" class=\"ch.qos.logback.core.FileAppender\">\n        <file>logs/tigase.log</file>\n        <append>true</append>\n        <encoder>\n            <pattern>%date [%thread] %-5level %logger{35} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <logger name=\"tigase.xmpp.XMPPDomBuilderHandler\" level=\"warn\"/>\n    <logger name=\"tigase.server\" level=\"trace\"/>\n    <logger name=\"tigase.io\" level=\"warn\"/>\n    <logger name=\"tigase.osgi\" level=\"trace\"/>\n    <logger name=\"tigase.xmpp\" level=\"trace\"/>\n\n\t\t<!--jetty / http-api configuration-->\n    <logger name=\"org.eclipse.jetty\" level=\"warn\"/>\n\t\t\n    <root level=\"trace\">\n        <appender-ref ref=\"FILE\"/>\n    </root>\n</configuration>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/snmp.acl",
    "content": "# ----------------------------------------------------------------------\n#           Template for SNMP Access Control List File\n#\n# o Copy this template to snmp.acl\n# o Set access control for SNMP support\n# o Change the permission of snmp.acl to be read-only\n#   by the owner.\n#\n# See below for the location of snmp.acl file.\n# ----------------------------------------------------------------------\n\n############################################################\n#            SNMP Access Control List File  \n############################################################\n#\n# Default location of this file is $JRE/lib/management/snmp.acl.\n# You can specify an alternate location by specifying a property in \n# the management config file $JRE/lib/management/management.properties\n# or by specifying a system property (See that file for details).\n#\n\n\n##############################################################\n#        File permissions of the snmp.acl file\n##############################################################\n# \n#      Since there are cleartext community strings stored in this file,\n#      this ACL file must be readable by ONLY the owner,\n#      otherwise the program will exit with an error. \n#\n##############################################################\n#\t\tFormat of the acl group\n##############################################################\n#\n# communities: a list of SNMP community strings to which the\n#              access control applies separated by commas.\n#\n# access: either \"read-only\" or \"read-write\".\n#\n# managers: a list of hosts to be granted the access rights.\n#    Each can be expressed as any one of the following:\n#    - hostname: hubble\n#    - ip v4 and v6 addresses: 123.456.789.12 , fe80::a00:20ff:fe9b:ea82\n#    - ip v4 and v6 netmask prefix notation: 123.456.789.0/24, \n#         fe80::a00:20ff:fe9b:ea82/64  \n#      see RFC 2373 (http://www.ietf.org/rfc/rfc2373.txt)\n#\n# An example of two community groups for multiple hosts:\n#    acl = {\n#     {\n#       communities = public, private\n#       access = read-only\n#       managers = hubble, snowbell, nanak\n#     }\n#     {\n#       communities = jerry\n#       access = read-write\n#       managers = hubble, telescope\n#     }\n#    }\n# \n##############################################################\n#                   Format of the trap group\n##############################################################\n#\n# trap-community: a single SNMP community string that will be included\n#                 in  the traps sent to the hosts.\n#\n# hosts: a list of hosts to which the SNMP agent will send traps.\n#\n# An example of two trap community definitions for multiple hosts:\n#    trap = {\n#      {\n#        trap-community = public\n#        hosts = hubble, snowbell\n#      }\n#      {\n#        trap-community = private\n#        hosts = telescope\n#      }\n#    }\n#\n############################################################\n#\n#  Update the community strings (public and private) below\n#  before copying this template file\n# \t\n# Common SNMP ACL Example\n# ------------------------\n#\n# o Only localhost can connect, and access rights\n#   are limited to read-only\n# o Traps are sent to localhost only\n#\n#\nacl = {\n  {\n    communities = public, private\n    access = read-write\n    managers = localhost, devel.tigase.org\n  }\n}\n# \n# \n# trap = {\n#   {\n#     trap-community = public\n#     hosts = localhost \n#   }\n# }\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/tigase-http-context.xml",
    "content": "<?xml version=\"1.0\"  encoding=\"UTF-8\"?>\n<!DOCTYPE Configure PUBLIC\n  \"-//Jetty//Configure//EN\"\n  \"http://www.eclipse.org/jetty/configure.dtd\">\n\n<Configure class=\"org.eclipse.jetty.servlet.ServletContextHandler\" />\n"
  },
  {
    "path": "tigase-server 7.1.0/etc/tigase.conf",
    "content": "#osgiEnabled=(true|false)\n#osgiEnabled=false\nOSGI=${osgiEnabled}\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver:org.apache.derby.jdbc.EmbeddedDriver\"\n#GC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:ParallelCMSThreads=2 -XX:-ReduceInitialCardMarks\"\n#EX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n#JMX_REMOTE_IP=\"-Djava.rmi.server.hostname=0.0.0.0\"\n\nJAVA_HOME=\"${JAVA_HOME}\"\nCLASSPATH=\"${CLASSPATH}\"\n\nJAVA_OPTIONS=\"${GC} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=1024m -XX:MaxDirectMemorySize=128m \"\nTIGASE_CONFIG=\"etc/tigase.xml\"\nTIGASE_OPTIONS=\" --property-file etc/init.properties \"\n"
  },
  {
    "path": "tigase-server 7.1.0/logs/server-info.html",
    "content": "<html>\n<head>\n<title>Server informations</title>\n</head>\n<body>\n<h2>Tigase XMPP Server<h2>\n<h3>Server informations</h3>\n</body>\n</html>"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../..</dist_path>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-dist</artifactId>\n\t<name>Tigase XMPP Server Distribution builder</name>\n\n\t<packaging>${packaging.type}</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-master</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t\t<relativePath>../master</relativePath>\n\t</parent>\n\t\n\t<profiles>\n\t\t<profile>\n\t\t\t<activation>\n\t\t\t\t<os>\n\t\t\t\t\t<family>!windows</family>\n\t\t\t\t</os>\n\t\t\t</activation>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<artifactId>exec-maven-plugin</artifactId>\n\t\t\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t\t\t<version>1.2.1</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution><!-- Run our version calculation script -->\n\t\t\t\t\t\t\t\t<id>ChangeLog generation</id>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>exec</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t\t<executable>${project.basedir}/scripts/genChangeLog.sh</executable>\n\t\t\t\t\t\t\t\t\t<workingDirectory>${project.basedir}</workingDirectory>\n\t\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<artifactId>maven-antrun-plugin</artifactId>\n\t\t\t\t\t\t<version>1.7</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t\t<target>\n\t\t\t\t\t\t\t\t\t\t<exec executable=\"sed\" output=\"README\">\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"-e\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"s/&lt;[^>]*>//g\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"-e\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"s/&#60;[^>]*>//g\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"-e\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"s/&amp;[^; ]*;//g\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"-e\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"s/${APP_VER}/${project.version}/g\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"${dist_path}/package.html\"/>\n\t\t\t\t\t\t\t\t\t\t</exec>\n\t\t\t\t\t\t\t\t\t\t<exec executable=\"sed\" output=\"package.html\">\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"s/${APP_VER}/${project.version}--b${gitVersion}/g\"/>\n\t\t\t\t\t\t\t\t\t\t\t<arg value=\"${dist_path}/package.html\"/>\n\t\t\t\t\t\t\t\t\t\t</exec>\n\t\t\t\t\t\t\t\t\t\t<copy file=\"${dist_path}/License.html\" tofile=\"License.html\"/>\n\t\t\t\t\t\t\t\t\t\t<!--<copy file=\"${dist_path}/ChangeLog\" tofile=\"ChangeLog\"/>-->\n\n\t\t\t\t\t\t\t\t\t</target>\n\t\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>run</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t</profiles>\t\t\n\t\n\t<build>\n\t\t<plugins>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-assembly-plugin</artifactId>\n\t\t\t\t<version>2.4</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>dist</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>single</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<descriptors>\n\t\t\t\t\t\t\t\t<descriptor>src/main/assembly/dist.xml</descriptor>\n\t\t\t\t\t\t\t\t<descriptor>src/main/assembly/dist-max.xml</descriptor>\n\t\t\t\t\t\t\t</descriptors>\n\t\t\t\t\t\t\t<tarLongFileMode>gnu</tarLongFileMode>\n\t\t\t\t\t\t\t<finalName>tigase-server-${project.version}-b${gitVersion}</finalName>\n\t\t\t\t\t\t\t<outputDirectory>../../pack</outputDirectory>\n\t\t\t\t\t\t\t<!--<appendAssemblyId>false</appendAssemblyId>-->\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<version>2.6.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>default-clean</id>\n\t\t\t\t\t\t<phase>clean</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>clean</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>clean-deps</id>\n\t\t\t\t\t\t<phase>clean</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>clean</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<filesets>\n\t\t\t\t\t\t\t\t<fileset>\n\t\t\t\t\t\t\t\t\t<directory>${project.basedir}/../../jars</directory>\n\t\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t\t<include>**/*.jar</include>\n\t\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t\t\t<followSymlinks>false</followSymlinks>\n\t\t\t\t\t\t\t\t</fileset>\n\t\t\t\t\t\t\t</filesets>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-dependency-plugin</artifactId>\n\t\t\t\t<version>2.8</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>copy-dependencies</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>copy-dependencies</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../../jars</outputDirectory>\n\t\t\t\t\t\t\t<stripVersion>true</stripVersion>\n\t\t\t\t\t\t\t<excludeTransitive>true</excludeTransitive>\n\t\t\t\t\t\t\t<overWriteIfNewer>true</overWriteIfNewer>\n\t\t\t\t\t\t\t<overWriteReleases>true></overWriteReleases>\n\t\t\t\t\t\t\t<overWriteSnapshots>true</overWriteSnapshots>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>copy-old-pubsub</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>copy</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifactItems>\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-pubsub</artifactId>\n\t\t\t\t\t\t\t\t\t<version>2.2.0</version>\n\t\t\t\t\t\t\t\t\t<destFileName>tigase-pubsub-2.2.0.jar.old</destFileName>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t</artifactItem>\n\t\t\t\t\t\t\t</artifactItems>\n\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../../jars</outputDirectory>\n\t\t\t\t\t\t\t<stripVersion>false</stripVersion>\n\t\t\t\t\t\t\t<useBaseVersion>true</useBaseVersion>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>tigase-resources</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>unpack</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifactItems>\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-http-api</artifactId>\n\t\t\t\t\t\t\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>*.xml</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-http-api</artifactId>\n\t\t\t\t\t\t\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.groovy, **/*.html</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-http-api-jetty</artifactId>\n\t\t\t\t\t\t\t\t\t<version>1.1.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>*.xml</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-http-api-jetty</artifactId>\n\t\t\t\t\t\t\t\t\t<version>1.1.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.groovy</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-muc</artifactId>\n\t\t\t\t\t\t\t\t\t<version>2.4.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../../scripts</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.groovy</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-socks5</artifactId>\n\t\t\t\t\t\t\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../../database</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.sql</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-pubsub</artifactId>\n\t\t\t\t\t\t\t\t\t<version>3.2.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.sql,**/*.sh,**/*.cmd,**/*.txt</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t\t<artifactItem>\n\t\t\t\t\t\t\t\t\t<groupId>tigase</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>tigase-pubsub</artifactId>\n\t\t\t\t\t\t\t\t\t<version>3.2.0-SNAPSHOT</version>\n\t\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t\t\t<overWrite>false</overWrite>\n\t\t\t\t\t\t\t\t\t<outputDirectory>${project.basedir}/../..</outputDirectory>\n\t\t\t\t\t\t\t\t\t<includes>**/*.groovy</includes>\n\t\t\t\t\t\t\t\t</artifactItem>\n\n\t\t\t\t\t\t\t</artifactItems>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jarsigner-plugin</artifactId>\n\t\t\t\t<version>1.4</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>sign</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>sign</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archiveDirectory>${project.basedir}/../..</archiveDirectory>\n\t\t\t\t\t<includes>\n\t\t\t\t\t\t<include>target/tigase*.?ar</include>\n\t\t\t\t\t\t<include>jars/tigase*.?ar</include>\n\t\t\t\t\t\t<include>jars/licence-lib.jar</include>\n\t\t\t\t\t</includes>\n\t\t\t\t\t<processMainArtifact>false</processMainArtifact>\n\t\t\t\t\t<processAttachedArtifacts>false</processAttachedArtifacts>\n\t\t\t\t\t<tsa>http://timestamp.comodoca.com/rfc3161</tsa>\n\t\t\t\t\t<skip>${sign-skip}</skip>\n\t\t\t\t\t<removeExistingSignatures>true</removeExistingSignatures>\n\n\t\t\t\t\t<keystore>${sign-keystore}</keystore>\n\t\t\t\t\t<alias>${sign-alias}</alias>\n\t\t\t\t\t<storepass>${sign-storepass}</storepass>\n\t\t\t\t\t<keypass>${sign-keypass}</keypass>\n\t\t\t\t\t<verbose>${verbose-log}</verbose>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<version>2.8.2</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<dependencies>\n\n\t\t<!--tigase dependencies-->\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-server</artifactId>\n\t\t\t<version>7.1.0-SNAPSHOT</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-ext-mailer</artifactId>\n\t\t\t<version>1.0.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.osgi.core</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-muc</artifactId>\n\t\t\t<version>2.4.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-pubsub</artifactId>\n\t\t\t<version>3.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-extras</artifactId>\n\t\t\t<version>1.1.2-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>licence-lib</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-stats-collector-library</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-stats-collector-provider</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-http-api</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase.sure.web</groupId>\n\t\t\t<artifactId>tigase-web-ui</artifactId>\n\t\t\t<version>2.1-SNAPSHOT</version>\n\t\t\t<type>war</type>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-http-api-jetty</artifactId>\n\t\t\t<version>1.1.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\t\t\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-message-archiving</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-unified-archive</artifactId>\n\t\t\t<version>1.0.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-socks5</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-stun</artifactId>\n\t\t\t<version>1.1.2-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-acs</artifactId>\n\t\t\t<version>2.3.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-acs-muc</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-acs-pubsub</artifactId>\n\t\t\t<version>1.2.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-mongodb</artifactId>\n\t\t\t<version>1.1.0-SNAPSHOT</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\n\n\n\t\t<!--databases-->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.derby</groupId>\n\t\t\t<artifactId>derby</artifactId>\n\t\t\t<version>10.12.1.1</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.derby</groupId>\n\t\t\t<artifactId>derbytools</artifactId>\n\t\t\t<version>10.12.1.1</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.11</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.postgresql</groupId>\n\t\t\t<artifactId>postgresql</artifactId>\n\t\t\t<version>9.4.1207</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>net.sourceforge.jtds</groupId>\n\t\t\t<artifactId>jtds</artifactId>\n\t\t\t<version>1.3.1</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mongodb</groupId>\n\t\t\t<artifactId>mongo-java-driver</artifactId>\n\t\t\t<version>2.14.1</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\n\n\t\t<!-- other libraries-->\n\t\t<dependency>\n\t\t\t<groupId>org.codehaus.groovy</groupId>\n\t\t\t<artifactId>groovy-all</artifactId>\n\t\t\t<version>2.4.3</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.hamcrest</groupId>\n\t\t\t<artifactId>hamcrest-core</artifactId>\n\t\t\t<version>1.3</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<version>${slf4j.version}</version>\n\t\t\t<scope>runtime</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>jul-to-slf4j</artifactId>\n\t\t\t<version>${slf4j.version}</version>\n\t\t\t<scope>runtime</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>de.javawi</groupId>\n\t\t\t<artifactId>jstun</artifactId>\n\t\t\t<version>0.7.3</version>\n\t\t</dependency>\n\n\t\t<!--OSGi dependencies-->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.osgi.core</artifactId>\n\t\t\t<version>1.4.0</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.bundlerepository</artifactId>\n\t\t\t<version>1.6.6</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.http.bundle</artifactId>\n\t\t\t<version>2.2.1</version>\n\t\t\t<scope>runtime</scope>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.apache.felix.http.bridge</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.apache.felix.http.cometd</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.apache.felix.http.jetty</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.configadmin</artifactId>\n\t\t\t<version>1.6.0</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.main</artifactId>\n\t\t\t<version>4.4.0</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.shell</artifactId>\n\t\t\t<version>1.4.2</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.apache.felix.shell.remote</artifactId>\n\t\t\t<version>1.0.4</version>\n\t\t\t<scope>runtime</scope>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.osgi.core</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.osgi.compendium</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t\t<artifactId>org.apache.felix.shell</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t<version>1.0.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t<artifactId>logback-core</artifactId>\n\t\t\t<version>1.0.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<version>4.11</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/scripts/genChangeLog.sh",
    "content": "#!/bin/bash\n\ngit log --pretty --numstat --summary tigase-server-5.1.0..master | scripts/git2cl > ChangeLog\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/scripts/git2cl",
    "content": "#!/usr/bin/perl\n\n# Copyright (C) 2007, 2008 Simon Josefsson <simon@josefsson.org>\n# Copyright (C) 2007 Luis Mondesi <lemsx1@gmail.com>\n# * calls git directly. To use it just: \n#   cd ~/Project/my_git_repo; git2cl > ChangeLog\n# * implements strptime()\n# * fixes bugs in $comment parsing\n#   - copy input before we remove leading spaces\n#   - skip \"merge branch\" statements as they don't\n#     have information about files (i.e. we never\n#     go into $state 2)\n#   - behaves like a pipe/filter if input is given from the CLI\n#     else it calls git log by itself\n#\n# The functions mywrap, last_line_len, wrap_log_entry are derived from\n# the cvs2cl tool, see <http://www.red-bean.com/cvs2cl/>:\n# Copyright (C) 2001,2002,2003,2004 Martyn J. Pearce <fluffy@cpan.org>\n# Copyright (C) 1999 Karl Fogel <kfogel@red-bean.com>\n#\n# git2cl is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n#\n# git2cl is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with git2cl; see the file COPYING.  If not, write to the Free\n# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n# 02110-1301 USA.\n\n=head1 NAME\n\ngit2cl        -  tool to convert git logs to GNU ChangeLog\n\n=head1 SYNOPSIS\n\ngit2cl > ChangeLog\n\nIf you don't want git2cl to invoke git log internally, you can use it\nas a pipe.\nIt needs a git log generated with --pretty --numstat and --summary.\nYou can use it as follows:\n\n    git log --pretty --numstat --summary | git2cl > ChangeLog\n\n=head1 DESCRIPTION\n\nThis is a quick'n'dirty tool to convert git logs to GNU ChangeLog\nformat.\n\nThe tool invokes `git log` internally unless you pipe a log to it.\nThus, typically you would use it as follows:\n\n=head1 SEE ALSO\n\nOutput format specification:\n    <http://www.gnu.org/prep/standards/html_node/Change-Logs.html>\n\n=head1 AUTHORS\n\ngit2cl is developed by Simon Josefsson <simon@josefsson.org>\n                   and Luis Mondesi <lemsx1@gmail.com>\n\n=cut\n\nuse strict;\nuse POSIX qw(strftime);\nuse Text::Wrap qw(wrap);\nuse FileHandle;\n\nuse constant EMPTY_LOG_MESSAGE => '*** empty log message ***';\n\n# this is a helper hash for stptime.\n# Assumes you are calling 'git log ...' with LC_ALL=C\nmy %month = (\n    'Jan'=>0,\n    'Feb'=>1,\n    'Mar'=>2,\n    'Apr'=>3,\n    'May'=>4,\n    'Jun'=>5,\n    'Jul'=>6,\n    'Aug'=>7,\n    'Sep'=>8,\n    'Oct'=>9,\n    'Nov'=>10,\n    'Dec'=>11,\n);\n\nmy $fh = new FileHandle;\n\nsub key_ready\n{\n    my ($rin, $nfd);\n    vec($rin, fileno(STDIN), 1) = 1;\n    return $nfd = select($rin, undef, undef, 0);\n}\n\nsub strptime {\n    my $str = shift;\n    return undef if not defined $str;\n\n    # we are parsing this format\n    # Fri Oct 26 00:42:56 2007 -0400\n    # to these fields\n    # sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1\n    # Luis Mondesi <lemsx1@gmail.com>\n    my @date;\n    if ($str =~ /([[:alpha:]]{3})\\s+([[:alpha:]]{3})\\s+([[:digit:]]{1,2})\\s+([[:digit:]]{1,2}):([[:digit:]]{1,2}):([[:digit:]]{1,2})\\s+([[:digit:]]{4})/){\n        push(@date,$6,$5,$4,$3,$month{$2},($7 - 1900),-1,-1,-1);\n    } else {\n        die (\"Cannot parse date '$str'\\n'\");\n    }\n    return @date;\n}\n\nsub mywrap {\n    my ($indent1, $indent2, @text) = @_;\n    # If incoming text looks preformatted, don't get clever\n    my $text = Text::Wrap::wrap($indent1, $indent2, @text);\n    if ( grep /^\\s+/m, @text ) {\n\treturn $text;\n    }\n    my @lines = split /\\n/, $text;\n    $indent2 =~ s!^((?: {8})+)!\"\\t\" x (length($1)/8)!e;\n    $lines[0] =~ s/^$indent1\\s+/$indent1/;\n    s/^$indent2\\s+/$indent2/\n\tfor @lines[1..$#lines];\n    my $newtext = join \"\\n\", @lines;\n    $newtext .= \"\\n\"\n\tif substr($text, -1) eq \"\\n\";\n    return $newtext;\n}\n\nsub last_line_len {\n    my $files_list = shift;\n    my @lines = split (/\\n/, $files_list);\n    my $last_line = pop (@lines);\n    return length ($last_line);\n}\n\n# A custom wrap function, sensitive to some common constructs used in\n# log entries.\nsub wrap_log_entry {\n    my $text = shift;                  # The text to wrap.\n    my $left_pad_str = shift;          # String to pad with on the left.\n\n    # These do NOT take left_pad_str into account:\n    my $length_remaining = shift;      # Amount left on current line.\n    my $max_line_length  = shift;      # Amount left for a blank line.\n\n    my $wrapped_text = '';             # The accumulating wrapped entry.\n    my $user_indent = '';              # Inherited user_indent from prev line.\n\n    my $first_time = 1;                # First iteration of the loop?\n    my $suppress_line_start_match = 0; # Set to disable line start checks.\n\n    my @lines = split (/\\n/, $text);\n    while (@lines)   # Don't use `foreach' here, it won't work.\n    {\n\tmy $this_line = shift (@lines);\n\tchomp $this_line;\n\n\tif ($this_line =~ /^(\\s+)/) {\n\t    $user_indent = $1;\n\t}\n\telse {\n\t    $user_indent = '';\n\t}\n\n\t# If it matches any of the line-start regexps, print a newline now...\n\tif ($suppress_line_start_match)\n\t{\n\t    $suppress_line_start_match = 0;\n\t}\n\telsif (($this_line =~ /^(\\s*)\\*\\s+[a-zA-Z0-9]/)\n\t       || ($this_line =~ /^(\\s*)\\* [a-zA-Z0-9_\\.\\/\\+-]+/)\n\t       || ($this_line =~ /^(\\s*)\\([a-zA-Z0-9_\\.\\/\\+-]+(\\)|,\\s*)/)\n\t       || ($this_line =~ /^(\\s+)(\\S+)/)\n\t       || ($this_line =~ /^(\\s*)- +/)\n\t       || ($this_line =~ /^()\\s*$/)\n\t       || ($this_line =~ /^(\\s*)\\*\\) +/)\n\t       || ($this_line =~ /^(\\s*)[a-zA-Z0-9](\\)|\\.|\\:) +/))\n\t{\n\t    $length_remaining = $max_line_length - (length ($user_indent));\n\t}\n\n\t# Now that any user_indent has been preserved, strip off leading\n\t# whitespace, so up-folding has no ugly side-effects.\n\t$this_line =~ s/^\\s*//;\n\n\t# Accumulate the line, and adjust parameters for next line.\n\tmy $this_len = length ($this_line);\n\tif ($this_len == 0)\n\t{\n\t    # Blank lines should cancel any user_indent level.\n\t    $user_indent = '';\n\t    $length_remaining = $max_line_length;\n\t}\n\telsif ($this_len >= $length_remaining) # Line too long, try breaking it.\n\t{\n\t    # Walk backwards from the end.  At first acceptable spot, break\n\t    # a new line.\n\t    my $idx = $length_remaining - 1;\n\t    if ($idx < 0) { $idx = 0 };\n\t    while ($idx > 0)\n\t    {\n\t\tif (substr ($this_line, $idx, 1) =~ /\\s/)\n\t\t{\n\t\t    my $line_now = substr ($this_line, 0, $idx);\n\t\t    my $next_line = substr ($this_line, $idx);\n\t\t    $this_line = $line_now;\n\n\t\t    # Clean whitespace off the end.\n\t\t    chomp $this_line;\n\n\t\t    # The current line is ready to be printed.\n\t\t    $this_line .= \"\\n${left_pad_str}\";\n\n\t\t    # Make sure the next line is allowed full room.\n\t\t    $length_remaining = $max_line_length - (length ($user_indent));\n\n\t\t    # Strip next_line, but then preserve any user_indent.\n\t\t    $next_line =~ s/^\\s*//;\n\n\t\t    # Sneak a peek at the user_indent of the upcoming line, so\n\t\t    # $next_line (which will now precede it) can inherit that\n\t\t    # indent level.  Otherwise, use whatever user_indent level\n\t\t    # we currently have, which might be none.\n\t\t    my $next_next_line = shift (@lines);\n\t\t    if ((defined ($next_next_line)) && ($next_next_line =~ /^(\\s+)/)) {\n\t\t\t$next_line = $1 . $next_line if (defined ($1));\n\t\t\t# $length_remaining = $max_line_length - (length ($1));\n\t\t\t$next_next_line =~ s/^\\s*//;\n\t\t    }\n\t\t    else {\n\t\t\t$next_line = $user_indent . $next_line;\n\t\t    }\n\t\t    if (defined ($next_next_line)) {\n\t\t\tunshift (@lines, $next_next_line);\n\t\t    }\n\t\t    unshift (@lines, $next_line);\n\n\t\t    # Our new next line might, coincidentally, begin with one of\n\t\t    # the line-start regexps, so we temporarily turn off\n\t\t    # sensitivity to that until we're past the line.\n\t\t    $suppress_line_start_match = 1;\n\n\t\t    last;\n\t\t}\n\t\telse\n\t\t{\n\t\t    $idx--;\n\t\t}\n\t    }\n\n\t    if ($idx == 0)\n\t    {\n\t\t# We bottomed out because the line is longer than the\n\t\t# available space.  But that could be because the space is\n\t\t# small, or because the line is longer than even the maximum\n\t\t# possible space.  Handle both cases below.\n\n\t\tif ($length_remaining == ($max_line_length - (length ($user_indent))))\n\t\t{\n\t\t    # The line is simply too long -- there is no hope of ever\n\t\t    # breaking it nicely, so just insert it verbatim, with\n\t\t    # appropriate padding.\n\t\t    $this_line = \"\\n${left_pad_str}${this_line}\";\n\t\t}\n\t\telse\n\t\t{\n\t\t    # Can't break it here, but may be able to on the next round...\n\t\t    unshift (@lines, $this_line);\n\t\t    $length_remaining = $max_line_length - (length ($user_indent));\n\t\t    $this_line = \"\\n${left_pad_str}\";\n\t\t}\n\t    }\n\t}\n\telse  # $this_len < $length_remaining, so tack on what we can.\n\t{\n\t    # Leave a note for the next iteration.\n\t    $length_remaining = $length_remaining - $this_len;\n\n\t    if ($this_line =~ /\\.$/)\n\t    {\n\t\t$this_line .= \"  \";\n\t\t$length_remaining -= 2;\n\t    }\n\t    else  # not a sentence end\n\t    {\n\t\t$this_line .= \" \";\n\t\t$length_remaining -= 1;\n\t    }\n\t}\n\n\t# Unconditionally indicate that loop has run at least once.\n\t$first_time = 0;\n\n\t$wrapped_text .= \"${user_indent}${this_line}\";\n    }\n\n    # One last bit of padding.\n    $wrapped_text .= \"\\n\";\n\n    return $wrapped_text;\n}\n\n# main\n\nmy @date;\nmy $author;\nmy @files;\nmy $comment;\n\nmy $state; # 0-header 1-comment 2-files\nmy $done = 0;\n\n$state = 0;\n\n# if reading from STDIN, we assume that we are\n# getting git log as input\nif (key_ready())\n{\n\n    #my $dummyfh; # don't care about writing\n    #($fh,$dummyfh) = FileHandle::pipe;\n    $fh->fdopen(*STDIN, 'r');\n}\nelse\n{\n    $fh->open(\"LC_ALL=C git log --pretty --numstat --summary|\")\n\tor die(\"Cannot execute git log...$!\\n\");\n}\n\nwhile (my $_l = <$fh>) {\n    #print STDERR \"debug ($state, \" . (@date ? (strftime \"%Y-%m-%d\", @date) : \"\") . \"): `$_'\\n\";\n    if ($state == 0) {\n\tif ($_l =~ m,^Author: (.*),) {\n\t    $author = $1;\n\t}\n\tif ($_l =~ m,^Date: (.*),) {\n\t    @date = strptime($1);\n\t}\n\t$state = 1 if ($_l =~ m,^$, and $author and (@date+0>0));\n    } elsif ($state == 1) {\n        # * modifying our input text is a bad choice\n        #   let's make a copy of it first, then we remove spaces \n        # * if we meet a \"merge branch\" statement, we need to start\n        #   over and find a real entry\n        # Luis Mondesi <lemsx1@gmail.com>\n        my $_s = $_l;\n\t$_s =~ s/^    //g;\n        if ($_s =~ m/^Merge branch/)\n        {\n            $state=0;\n            next;\n        }\n\t$comment = $comment . $_s;\n\t$state = 2 if ($_l =~ m,^$,);\n    } elsif ($state == 2) {\n\tif ($_l =~ m,^([0-9]+)\\t([0-9]+)\\t(.*)$,) {\n\t    push @files, $3;\n\t}\n\t$done = 1 if ($_l =~ m,^$,);\n    }\n\n    if ($done) {\n\tprint (strftime \"%Y-%m-%d  $author\\n\\n\", @date);\n\n\tmy $files = join (\", \", @files);\n\t$files = mywrap (\"\\t\", \"\\t\", \"* $files\"), \": \";\n\n\tif (index($comment, EMPTY_LOG_MESSAGE) > -1 ) {\n\t    $comment = \"[no log message]\\n\";\n\t}\n\n\tmy $files_last_line_len = 0;\n\t$files_last_line_len = last_line_len($files) + 1;\n\tmy $msg = wrap_log_entry($comment, \"\\t\", 69-$files_last_line_len, 69);\n\n\t$msg =~ s/[ \\t]+\\n/\\n/g;\n\n\tprint \"$files: $msg\\n\";\n\n\t@date = ();\n\t$author = \"\";\n\t@files = ();\n\t$comment = \"\";\n\n\t$state = 0;\n\t$done = 0;\n    }\n}\n\nif (@date + 0)\n{\n    print (strftime \"%Y-%m-%d  $author\\n\\n\", @date);\n    my $msg = wrap_log_entry($comment, \"\\t\", 69, 69);\n    $msg =~ s/[ \\t]+\\n/\\n/g;\n    print \"\\t* $msg\\n\";\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/src/main/assembly/dist-max.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<assembly>\n\t<id>dist-max</id>\n\t<formats>\n\t\t<format>zip</format>\n\t\t<format>tar.gz</format>\n\t</formats>\n\n\t<fileSets>\n\t\t<fileSet>\n\t\t\t<directory>./</directory>\n\t\t\t<outputDirectory>./</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>README</include>\n\t\t\t\t<include>ChangeLog</include>\n\t\t\t\t<include>License.html</include>\n\t\t\t\t<include>package.html</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../certs</directory>\n\t\t\t<outputDirectory>certs</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>dummy.cer</include>\n\t\t\t\t<include>rsa-keystore</include>\n\t\t\t\t<include>truststore</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../database</directory>\n\t\t\t<outputDirectory>database</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../docs</directory>\n\t\t\t<outputDirectory>docs</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>Administration_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Administration_Guide/pdf/**/*</include>\n\t\t\t\t<include>Development_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Development_Guide/pdf/**/*</include>\n\t\t\t\t<include>Properties_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Properties_Guide/pdf/**/*</include>\n\t\t\t\t<include>User_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>User_Guide/pdf/**/*</include>\n\t\t\t\t<include>javadoc/**/*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../win-stuff</directory>\n\t\t\t<outputDirectory>win-stuff</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*/**</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../etc</directory>\n\t\t\t<outputDirectory>etc</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>bosh-extra-headers.txt</include>\n\t\t\t\t<include>cross-domain-policy.xml</include>\n\t\t\t\t<include>client-access-policy.xml</include>\n\t\t\t\t<include>init.properties</include>\n\t\t\t\t<include>tigase.conf</include>\n\t\t\t\t<include>jmx.access</include>\n\t\t\t\t<include>jmx.password</include>\n\t\t\t\t<include>logback.xml</include>\n\t\t\t\t<include>snmp.acl</include>\n\t\t\t\t<include>tigase-http-context.xml</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<!-- OSGi configuration file -->\n\t\t<fileSet>\n\t\t\t<directory>../../conf</directory>\n\t\t\t<outputDirectory>conf</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>config.properties</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../src/main/groovy/tigase/admin</directory>\n\t\t\t<outputDirectory>scripts/admin</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>**/*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../jars</directory>\n\t\t\t<outputDirectory>jars</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>**/*.old</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../scripts</directory>\n\t\t\t<outputDirectory>scripts</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>**/*</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0744</fileMode>\n\t\t\t<directoryMode>0744</directoryMode>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>./</directory>\n\t\t\t<outputDirectory>/logs</outputDirectory>\n\t\t\t<excludes>\n\t\t\t\t<exclude>*/**</exclude>\n\t\t\t</excludes>\n\t\t\t<fileMode>0744</fileMode>\n\t\t\t<directoryMode>0754</directoryMode>\n\t\t</fileSet>\n\t</fileSets>\n\n\t<dependencySets>\n\t\t<dependencySet>\n\t\t\t<outputDirectory>jars</outputDirectory>\n\t\t\t<useProjectArtifact>false</useProjectArtifact>\n\t\t\t<outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>\n\t\t\t<unpack>false</unpack>\n\t\t\t<scope>runtime</scope>\n\t\t\t<!--\t\t\t<excludes>\n\t\t\t\t<exclude>junit:junit</exclude>\n\t\t\t</excludes>-->\n\t\t\t<includes>\n\t\t\t\t<!--tigase libraries-->\n\t\t\t\t<include>tigase:tigase-server</include>\n\t\t\t\t<!--<include>tigase:tigase-utils</include>-->\n\t\t\t\t<!--<include>tigase:tigase-xmltools</include>-->\n\t\t\t\t<include>tigase:tigase-acs</include>\n\t\t\t\t<include>tigase:tigase-acs-muc</include>\n\t\t\t\t<include>tigase:tigase-acs-pubsub</include>\n\t\t\t\t<include>tigase:tigase-muc</include>\n\t\t\t\t<include>tigase:tigase-pubsub</include>\n\t\t\t\t<include>tigase:tigase-extras</include>\n\t\t\t\t<include>tigase:licence-lib</include>\n\t\t\t\t<include>tigase:tigase-stats-collector-library</include>\n\t\t\t\t<include>tigase:tigase-stats-collector-provider</include>\n\t\t\t\t<include>tigase:tigase-http-api</include>\n\t\t\t\t<include>tigase:tigase-http-api-jetty</include>\n\t\t\t\t<include>tigase.sure.web:tigase-web-ui</include>\n\t\t\t\t<include>tigase:tigase-message-archiving</include>\n\t\t\t\t<include>tigase:tigase-unified-archive</include>\n\t\t\t\t<include>tigase:tigase-socks5</include>\n\t\t\t\t<include>tigase:tigase-stun</include>\n\t\t\t\t<include>tigase:tigase-mongodb</include>\n\t\t\t\t<include>tigase:tigase-ext-mailer</include>\n\n\t\t\t\t<!--database libraries-->\n\t\t\t\t<include>org.apache.derby:derby</include>\n\t\t\t\t<include>org.apache.derby:derbytools</include>\n\t\t\t\t<include>mysql:mysql-connector-java</include>\n\t\t\t\t<include>org.postgresql:postgresql</include>\n\t\t\t\t<include>net.sourceforge.jtds:jtds</include>\n\t\t\t\t<include>org.mongodb:mongo-java-driver</include>\n\t\t\t\t\n\t\t\t\t<!-- other libraries-->\n\t\t\t\t<include>org.codehaus.groovy:groovy-all</include>\n\t\t\t\t<include>openDMK:jdmkrt</include>\n\t\t\t\t<include>org.hamcrest:hamcrest-core</include>\n\t\t\t\t<include>org.slf4j:slf4j-api</include>\n\t\t\t\t<include>org.slf4j:jul-to-slf4j</include>\n\t\t\t\t<include>de.javawi:jstun</include>\n\n\t\t\t\t<!--HTTP API component dependencies-->\n\t\t\t\t<include>javax.servlet:javax.servlet-api</include>\n\t\t\t\t<!--<include>org.eclipse.jetty.orbit:javax.servlet</include>-->\n\t\t\t\t<!--<include>org.eclipse.jetty:jetty-continuation</include>-->\n\t\t\t\t<!--<include>org.eclipse.jetty:jetty-deploy</include>-->\n\t\t\t\t<include>org.eclipse.jetty:jetty-http</include>\n\t\t\t\t<include>org.eclipse.jetty:jetty-io</include>\n\t\t\t\t<include>org.eclipse.jetty:jetty-security</include>\n\t\t\t\t<include>org.eclipse.jetty:jetty-server</include>\n\t\t\t\t<include>org.eclipse.jetty:jetty-servlet</include>\n\t\t\t\t<include>org.eclipse.jetty:jetty-util</include>\n\t\t\t\t<!--<include>org.eclipse.jetty:jetty-webapp</include>-->\n\t\t\t\t<!--<include>org.eclipse.jetty:jetty-xml</include>-->\n\t\t\t\t<!--<include>org.eclipse.jetty.osgi:jetty-osgi-boot</include>-->\n\n\t\t\t\t<!--OSGi dependencies-->\n\t\t\t\t<include>org.osgi:org.osgi.core</include>\n\t\t\t\t<include>org.apache.felix:org.apache.felix.bundlerepository</include>\n\t\t\t\t<include>org.apache.felix:org.apache.felix.configadmin</include>\n\t\t\t\t<include>org.apache.felix:org.apache.felix.main</include>\n\t\t\t\t<include>org.apache.felix:org.apache.felix.shell</include>\n\t\t\t\t<include>org.apache.felix:org.apache.felix.shell.remote</include>\n\t\t\t\t<include>ch.qos.logback:logback-classic</include>\n\t\t\t\t<include>ch.qos.logback:logback-core</include>\n\n\t\t\t\t<!--Mailer extension-->\n\t\t\t\t<include>javax.activation:activation</include>\n\t\t\t\t<include>com.sun.mail:javax.mail</include>\n\t\t\t\t<include>com.sun.mail:smtp</include>\n\n\t\t\t</includes>\n\t\t</dependencySet>\n\t</dependencySets>\n</assembly>\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/src/main/assembly/dist.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<assembly>\n\t<id>dist</id>\n\t<formats>\n\t\t<format>zip</format>\n\t\t<format>tar.gz</format>\n\t</formats>\n\n\t<fileSets>\n\t\t<fileSet>\n\t\t\t<directory>./</directory>\n\t\t\t<outputDirectory>./</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>README</include>\n\t\t\t\t<include>ChangeLog</include>\n\t\t\t\t<include>License.html</include>\n\t\t\t\t<include>package.html</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../certs</directory>\n\t\t\t<outputDirectory>certs</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>dummy.cer</include>\n\t\t\t\t<include>rsa-keystore</include>\n\t\t\t\t<include>truststore</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../database</directory>\n\t\t\t<outputDirectory>database</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../docs</directory>\n\t\t\t<outputDirectory>docs</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>Administration_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Administration_Guide/pdf/**/*</include>\n\t\t\t\t<include>Development_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Development_Guide/pdf/**/*</include>\n\t\t\t\t<include>Properties_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>Properties_Guide/pdf/**/*</include>\n\t\t\t\t<include>User_Guide/html_chunk/**/*</include>\n\t\t\t\t<include>User_Guide/pdf/**/*</include>\n\t\t\t\t<include>javadoc/**/*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../win-stuff</directory>\n\t\t\t<outputDirectory>win-stuff</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*/**</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../etc</directory>\n\t\t\t<outputDirectory>etc</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>bosh-extra-headers.txt</include>\n\t\t\t\t<include>cross-domain-policy.xml</include>\n\t\t\t\t<include>client-access-policy.xml</include>\n\t\t\t\t<include>init.properties</include>\n\t\t\t\t<include>tigase.conf</include>\n\t\t\t\t<include>jmx.access</include>\n\t\t\t\t<include>jmx.password</include>\n\t\t\t\t<include>logback.xml</include>\n\t\t\t\t<include>snmp.acl</include>\n\t\t\t\t<include>tigase-http-context.xml</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../src/main/groovy/tigase/admin</directory>\n\t\t\t<outputDirectory>scripts/admin</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>**/*</include>\n\t\t\t</includes>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>../../scripts</directory>\n\t\t\t<outputDirectory>scripts</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>**/*</include>\n\t\t\t</includes>\n\t\t\t<excludes>\n\t\t\t\t<exclude></exclude>\n\t\t\t</excludes>\n\t\t\t<fileMode>0744</fileMode>\n\t\t\t<directoryMode>0744</directoryMode>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>./</directory>\n\t\t\t<outputDirectory>/logs</outputDirectory>\n\t\t\t<excludes>\n\t\t\t\t<exclude>*/**</exclude>\n\t\t\t</excludes>\n\t\t\t<fileMode>0644</fileMode>\n\t\t\t<directoryMode>0754</directoryMode>\n\t\t</fileSet>\n\t</fileSets>\n\t<dependencySets>\n\t\t<dependencySet>\n\t\t\t<useProjectArtifact>false</useProjectArtifact>\n\t\t\t<outputDirectory>jars</outputDirectory>\n\t\t\t<outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>\n\t\t\t<unpack>false</unpack>\n\t\t\t<!--<scope>runtime</scope>-->\n\t\t\t<includes>\n\t\t\t\t<!--tigase libraries-->\n\t\t\t\t<include>tigase:tigase-server</include>\n\t\t\t\t<include>tigase:tigase-http-api</include>\n\t\t\t\t<include>tigase.sure.web:tigase-web-ui</include>\n\t\t\t\t<include>javax.servlet:javax.servlet-api</include>\n\n\t\t\t\t<!--database libraries-->\n\t\t\t\t<include>org.apache.derby:derby</include>\n\t\t\t\t<include>org.apache.derby:derbytools</include>\n\t\t\t\t<include>mysql:mysql-connector-java</include>\n\t\t\t\t<include>org.postgresql:postgresql</include>\n\t\t\t\t<!-- other libraries-->\n\t\t\t\t<include>org.codehaus.groovy:groovy-all</include>\n\t\t\t\t<include>openDMK:jdmkrt</include>\n\t\t\t\t<include>net.sourceforge.jtds:jtds</include>\n\n\t\t\t</includes>\n\t\t</dependencySet>\n\t</dependencySets>\n</assembly>\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/distribution/src/main/resources/META-INF/java.security.Provider",
    "content": "# our security providers\ntigase.auth.TigaseSaslProvider"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/.gitignore",
    "content": ".html\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/css/docbook-xsl.css",
    "content": "/*\n  CSS stylesheet for XHTML produced by DocBook XSL stylesheets.\n*/\n\nbody {\n  font-family: Georgia,serif;\n}\n\ncode, pre {\n  font-family: \"Courier New\", Courier, monospace;\n}\n\nspan.strong {\n  font-weight: bold;\n}\n\nbody blockquote {\n  margin-top: .75em;\n  line-height: 1.5;\n  margin-bottom: .75em;\n}\n\nhtml body {\n  margin: 1em 5% 1em 5%;\n  line-height: 1.2;\n}\n\nbody div {\n  margin: 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\n\ndiv.toc p:first-child,\ndiv.list-of-figures p:first-child,\ndiv.list-of-tables p:first-child,\ndiv.list-of-examples p:first-child,\ndiv.example p.title,\ndiv.sidebar p.title\n{\n  font-weight: bold;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n  margin-bottom: 0.2em;\n}\n\nbody h1 {\n  margin: .0em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h2 {\n  margin: 0.5em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h3 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h4 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h5 {\n  margin: .8em 0 0 -2%;\n  line-height: 1.3;\n}\n\nbody h6 {\n  margin: .8em 0 0 -1%;\n  line-height: 1.3;\n}\n\nbody hr {\n  border: none; /* Broken on IE6 */\n}\ndiv.footnotes hr {\n  border: 1px solid silver;\n}\n\ndiv.navheader th, div.navheader td, div.navfooter td {\n  font-family: Arial,Helvetica,sans-serif;\n  font-size: 0.9em;\n  font-weight: bold;\n  color: #527bbd;\n}\ndiv.navheader img, div.navfooter img {\n  border-style: none;\n}\ndiv.navheader a, div.navfooter a {\n  font-weight: normal;\n}\ndiv.navfooter hr {\n  border: 1px solid silver;\n}\n\nbody td {\n  line-height: 1.2\n}\n\nbody th {\n  line-height: 1.2;\n}\n\nol {\n  line-height: 1.2;\n}\n\nul, body dir, body menu {\n  line-height: 1.2;\n}\n\nhtml {\n  margin: 0; \n  padding: 0;\n}\n\nbody h1, body h2, body h3, body h4, body h5, body h6 {\n  margin-left: 0\n} \n\nbody pre {\n  margin: 0.5em 10% 0.5em 1em;\n  line-height: 1.0;\n  color: navy;\n}\n\ntt.literal, code.literal {\n  color: navy;\n}\n\n.programlisting, .screen {\n  border: 1px solid silver;\n  background: #f4f4f4;\n  margin: 0.5em 10% 0.5em 0;\n  padding: 0.5em 1em;\n}\n\ndiv.sidebar {\n  background: #ffffee;\n  margin: 1.0em 10% 0.5em 0;\n  padding: 0.5em 1em;\n  border: 1px solid silver;\n}\ndiv.sidebar * { padding: 0; }\ndiv.sidebar div { margin: 0; }\ndiv.sidebar p.title {\n  margin-top: 0.5em;\n  margin-bottom: 0.2em;\n}\n\ndiv.bibliomixed {\n  margin: 0.5em 5% 0.5em 1em;\n}\n\ndiv.glossary dt {\n  font-weight: bold;\n}\ndiv.glossary dd p {\n  margin-top: 0.2em;\n}\n\ndl {\n  margin: .8em 0;\n  line-height: 1.2;\n}\n\ndt {\n  margin-top: 0.5em;\n}\n\ndt span.term {\n  font-style: normal;\n  color: navy;\n}\n\ndiv.variablelist dd p {\n  margin-top: 0;\n}\n\ndiv.itemizedlist li, div.orderedlist li {\n  margin-left: -0.8em;\n  margin-top: 0.5em;\n}\n\nul, ol {\n    list-style-position: outside;\n}\n\ndiv.sidebar ul, div.sidebar ol {\n    margin-left: 2.8em;\n}\n\ndiv.itemizedlist p.title,\ndiv.orderedlist p.title,\ndiv.variablelist p.title\n{\n  margin-bottom: -0.8em;\n}\n\ndiv.revhistory table {\n  border-collapse: collapse;\n  border: none;\n}\ndiv.revhistory th {\n  border: none;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\ndiv.revhistory td {\n  border: 1px solid silver;\n}\n\n/* Keep TOC and index lines close together. */\ndiv.toc dl, div.toc dt,\ndiv.list-of-figures dl, div.list-of-figures dt,\ndiv.list-of-tables dl, div.list-of-tables dt,\ndiv.indexdiv dl, div.indexdiv dt\n{\n  line-height: normal;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n/*\n  Table styling does not work because of overriding attributes in\n  generated HTML.\n*/\ndiv.table table,\ndiv.informaltable table\n{\n    margin-left: 0;\n    margin-right: 5%;\n    margin-bottom: 0.8em;\n}\ndiv.informaltable table\n{\n    margin-top: 0.4em\n}\ndiv.table thead,\ndiv.table tfoot,\ndiv.table tbody,\ndiv.informaltable thead,\ndiv.informaltable tfoot,\ndiv.informaltable tbody\n{\n    /* No effect in IE6. */\n    border-top: 3px solid #527bbd;\n    border-bottom: 3px solid #527bbd;\n}\ndiv.table thead, div.table tfoot,\ndiv.informaltable thead, div.informaltable tfoot\n{\n    font-weight: bold;\n}\n\ndiv.mediaobject img {\n    margin-bottom: 0.8em;\n}\ndiv.figure p.title,\ndiv.table p.title\n{\n  margin-top: 1em;\n  margin-bottom: 0.4em;\n}\n\ndiv.calloutlist p\n{\n  margin-top: 0em;\n  margin-bottom: 0.4em;\n}\n\na img {\n  border-style: none;\n}\n\n@media print {\n  div.navheader, div.navfooter { display: none; }\n}\n\nspan.aqua { color: aqua; }\nspan.black { color: black; }\nspan.blue { color: blue; }\nspan.fuchsia { color: fuchsia; }\nspan.gray { color: gray; }\nspan.green { color: green; }\nspan.lime { color: lime; }\nspan.maroon { color: maroon; }\nspan.navy { color: navy; }\nspan.olive { color: olive; }\nspan.purple { color: purple; }\nspan.red { color: red; }\nspan.silver { color: silver; }\nspan.teal { color: teal; }\nspan.white { color: white; }\nspan.yellow { color: yellow; }\n\nspan.aqua-background { background: aqua; }\nspan.black-background { background: black; }\nspan.blue-background { background: blue; }\nspan.fuchsia-background { background: fuchsia; }\nspan.gray-background { background: gray; }\nspan.green-background { background: green; }\nspan.lime-background { background: lime; }\nspan.maroon-background { background: maroon; }\nspan.navy-background { background: navy; }\nspan.olive-background { background: olive; }\nspan.purple-background { background: purple; }\nspan.red-background { background: red; }\nspan.silver-background { background: silver; }\nspan.teal-background { background: teal; }\nspan.white-background { background: white; }\nspan.yellow-background { background: yellow; }\n\nspan.big { font-size: 2em; }\nspan.small { font-size: 0.6em; }\n\nspan.underline { text-decoration: underline; }\nspan.overline { text-decoration: overline; }\nspan.line-through { text-decoration: line-through; }\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/files/StatsDumper.groovy",
    "content": "//CLASSPATH=/home/tigase/tigase-server/jars/tigase-server.jar\nimport tigase.stats.JavaJMXProxy\nimport tigase.stats.JMXProxyListener\nimport tigase.stats.StatisticsProviderMBean\n\nif (args.size() > 0) {\n  if (args[0] == \"-h\") {\n    println (\"Parameters are: [hostname] [username] [password] [dir] [port] [delay(ms)] [interval(ms)] [loadhistory(bool)]\")\n    System.exit(0)\n  }\n}\n\n\ndef hostname = args.size() > 0 ? args[0] : \"0.0.0.0\"\ndef username = args.size() > 1 ? args[1] : \"admin\"\ndef password = args.size() > 2 ? args[2] : \"pass\"\ndef dir = args.size() > 3 ? args[3] : \"stats\"\ndef port = args.size() > 4 ? args[4].toInteger() : 9050\ndef delay = args.size() > 5 ? args[5].toLong() : 10000\ndef interval = args.size() > 6 ? args[6].toLong() : 10000\ndef loadHistory = args.size() > 7 ? args[7].toBoolean() : false\n\nif (!new File(dir).exists()) {\n  new File(dir).mkdir()\n}\n\ndef proxy = new JavaJMXProxy(hostname, hostname, port, username, password, delay, interval, loadHistory)\nproxy.start()\n\nsleep delay\n\nwhile (true) {\n  try {\n    def allStats = proxy.getAllStats(0)\n    if (allStats != null) {\n      def timeToken = (int) System.currentTimeMillis() / 1000.toInteger() / 60.toInteger()\n      def file1 = new File(\"${dir}/stats_${new Date().format('yyyy-MM-dd_hh:mm:ss')}.txt\")\n      println \"Saving stats to the file ${file1.path}\"\n      allStats.each { key, value -> file1 << key + \"     \" + value + \"\\n\" }\n    }\n  } catch(all) {\n    println(\"An exception: \" + all)\n  }\n  sleep interval\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/index.asciidoc",
    "content": "= Tigase Administration Guide\nTigase Team <team@tigase.net>\nv7.1.0\n:numbered:\n:website: http://tigase.net\n:Date: 2014-07-10\n\n\nWelcome to the Tigase Administration Guide.\n\n:leveloffset: 1\n\ninclude::text/Tigase_v7.1.0.asciidoc[]\n\ninclude::text/Admin_Guide_01_-_About_Tigase_Jabber_XMPP_Server.asciidoc[]\n\ninclude::text/Admin_Guide_02_-_Quick_Start.asciidoc[]\n\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_03_-_Quick_Start_-_A_-_Installation_Using_GUI_Installer.asciidoc[]\n\ninclude::text/Admin_Guide_04_-_Quick_Start_-_B_-_Installation_Using_Web_Installer.asciidoc[]\n\ninclude::text/Admin_Guide_05_-_Quick_Start_-_C_-_Installing_Using_Console_Installer.asciidoc[]\n\ninclude::text/Admin_Guide_06_-_Quick_Start_-_D_-_Manual_Installation_in_Console_Mode.asciidoc[]\n\ninclude::text/Admin_Guide_07_-_Quick_Start_-_E_-_Windows_Installation.asciidoc[]\n\ninclude::text/Admin_Guide_07_-_Quick_Start_-_F_-_Setting_Up_Server.asciidoc[]\n\n:leveloffset: 1\n\ninclude::text/Admin_Guide_08_-_Latest_and_Nightly_Builds.asciidoc[]\n\ninclude::text/Admin_Guide_09_-_Configuration.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_10_-_Configuration_-_A_-_Tigase_XMPP_Server_init.properties_Configuration.asciidoc[]\n\ninclude::text/Admin_Guide_11_-_Configuration_-_B_-_Startup_Files_tigase.sh_and_tigase.asciidoc[]\n\ninclude::text/Admin_Guide_12_-_Configuration_-_C_-_Linux_Settings_for_High_Load_Systems.asciidoc[]\n\ninclude::text/Admin_Guide_13_-_Configuration_-_D_-_Configuration_Storage_Options.asciidoc[]\n\ninclude::text/Admin_Guide_13_-_Configuration_-_E_-_JVM_settings.asciidoc[]\n\ninclude::text/Admin_Guide_105_-_Configuration_-_F_-_Sess-man.asciidoc[]\n\n:leveloffset: 1\n\ninclude::text/Admin_Guide_14_-_Security.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_15_-_Security_-_A_-_Server_Certificates.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_16_-_Security_-_A_-_Server_Certificates_-_1_-_Creating_and_Loading_the_Server_Certificate_in_PEM_Files.asciidoc[]\n\ninclude::text/Admin_Guide_17_-_Security_-_A_-_Server_Certificates_-_2_-_Installing_StartCom_Certificate_in_your_Linux_System.asciidoc[]\n\n//include::text/Admin_Guide_18_-_Security_-_A_-_Server_Certificates_-_3_-_Server_Certificate_Using_Keytool_and_Keystore.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_19_-_Security_-_B_-_Authentication_Connectors.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_20_-_Security_-_B_-_Authentication_Connectors_-_1_-_Tigase_Auth_Connector.asciidoc[]\n\ninclude::text/Admin_Guide_21_-_Security_-_B_-_Authentication_Connectors_-_2_-_Tigase_Custom_Auth_Connector.asciidoc[]\n\ninclude::text/Admin_Guide_22_-_Security_-_B_-_Authentication_Connectors_-_3_-_Drupal_Authentication_Added.asciidoc[]\n\ninclude::text/Admin_Guide_23_-_Security_-_B_-_Authentication_Connectors_-_4_-_LDAP_Authentication_Connector.asciidoc[]\n\ninclude::text/Admin_Guide_24_-_Security_-_B_-_Authentication_Connectors_-_5_-_Configuration_of_SASL_EXTERNAL.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_25_-_Security_-_C_-_Packet_Filtering.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_26_-_Security_-_C_-_Packet_Filtering_-_1_-_Domain_Based_Packet_Filtering.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_27_-_Security_-_D_-_Access_Control_List.asciidoc[]\n\n:leveloffset: 1\n\ninclude::text/Admin_Guide_28_-_Database_Management.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_29_-_Database_Management_-_A_-_Database_Preparation.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_29_-_Database_Management_-_A_-_Database_Preperation_-_1_-_DbSchemaLoader.asciidoc[]\n\ninclude::text/Admin_Guide_30_-_Database_Management_-_A_-_Database_Preparation_-_1_-_Prepare_the_MySQL_Database_for_Tigase_Server.asciidoc[]\n\ninclude::text/Admin_Guide_31_-_Database_Management_-_A_-_Database_Preparation_-_2_-_Prepare_the_Derby_Database_for_Tigase_Server.asciidoc[]\n\ninclude::text/Admin_Guide_32_-_Database_Management_-_A_-_Database_Preparation_-_3_-_Prepare_the_MS_SQL_Server_Database_for_Tigase_Server.asciidoc[]\n\ninclude::text/Admin_Guide_33_-_Database_Management_-_A_-_Database_Preparation_-_4_-_Prepare_the_PostgreSQL_Database_for_Tigase_Server.asciidoc[]\n\ninclude::text/Admin_Guide_34_-_Database_Management_-_A_-_Database_Preperation_-_5_-_Prepare_Tigase_for_MongoDB.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_35_-_Database_Management_-_B_-_Hashed_User_Passwords_in_Database.asciidoc[]\n\ninclude::text/Admin_Guide_36_-_Database_Management_-_C_-_Tigase_Server_and_Multiple_Databases.asciidoc[]\n\ninclude::text/Admin_Guide_37_-_Database_Management_-_D_-_Importing_User_Data.asciidoc[]\n\ninclude::text/Admin_Guide_38_-_Database_Management_-_E_-_Integrating_Existing_Databases.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_39_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_1_-_Connecting_Tigase_Server_to_MySQL_Database.asciidoc[]\n\ninclude::text/Admin_Guide_40_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_2_-_Integrating_Tigase_Server_with_Drupal.asciidoc[]\n\ninclude::text/Admin_Guide_41_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_3_-_Integrating_Tigase_Server_with_LibreSource.asciidoc[]\n\ninclude::text/Admin_Guide_42_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_4_-_MySQL_Database_Use.asciidoc[]\n\ninclude::text/Admin_Guide_43_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_5_-_PostgreSQL_Database.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_44_-_Database_Management_-_F_-_Schema_Updates.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_45_-_Database_Managament_-_F_-_Schema_Updates_-_A_-_Tigase_Server_7.1.asciidoc[]\n\ninclude::text/Admin_Guide_46_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x.asciidoc[]\n\ninclude::text/Admin_Guide_47_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_1_-_Derby.asciidoc[]\n\ninclude::text/Admin_Guide_48_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_2_-_MySQL_Database_Schema_Upgrade_for_Tigase_5.1.asciidoc[]\n\ninclude::text/Admin_Guide_49_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_3_-_PostgreSQL_Database_Schema_Upgrade_for_Tigase_5.1.asciidoc[]\n\ninclude::text/Admin_Guide_50_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_4_-_Tigase_Database_Minor_but_Useful_Schema_Change_in_Version_5.1.asciidoc[]\n\ninclude::text/Admin_Guide_51_-_Database_Management_-_F_-_Schema_Updates_-_C_-_Tigase_Server_Version_4.x.asciidoc[]\n\ninclude::text/Admin_Guide_52_-_Database_Management_-_F_-_Schema_Updates_-_C_-_Tigase_Server_Version_4.x_-_1_-_MySQL_Database_Schema_Upgrade_for_Tigase_4.0.asciidoc[]\n\n:leveloffset: 1\n\ninclude::text/Admin_Guide_53_-_Components.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_54_-_Components_-_A_-_StanzaSender.asciidoc[]\n\ninclude::text/Admin_Guide_55_-_Components_-_B_-_Tigase_HTTP_API.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_56_-_Components_-_B_-_Tigase_HTTP_API_-_1_-_REST_API_Guide.asciidoc[]\n\ninclude::text/Admin_Guide_57_-_Components_-_B_-_Tigase_HTTP_API_-_2_-_Admin_UI.asciidoc[]\n\ninclude::text/Admin_Guide_58_-_Components_-_B_-_Tigase_HTTP_API_-_3_-_Web_Client.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_59_-_Components_-_C_-_Message_Archiving.asciidoc[]\n\ninclude::text/Admin_Guide_60_-_Components_-_D_-_Advanced_Message_Processing_-_AMP_XEP-0079.asciidoc[]\n\ninclude::text/Admin_Guide_61_-_Components_-_E_-_PubSub.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_62_-_Components_-_E_-_PubSub_-_1_-_Offline_Message_Sink.asciidoc[]\n\ninclude::text/Admin_Guide_63_-_Components_-_E_-_PubSub_-_2_-_PubSub_Schema_Changes.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_64_-_Components_-_F_-_Server_Monitoring.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_65_-_Components_-_F_-_Server_Monitoring_-_1_-_Setting_up_Remote_Monitoring_in_the_Server.asciidoc[]\n\ninclude::text/Admin_Guide_66_-_Components_-_F_-_Server_Monitoring_-_2_-_Retrieving_statistics.asciidoc[]\n\ninclude::text/Admin_Guide_102_-_Statistics_Descriptions.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_67_-_Components_-_F_-_Server_Monitoring_-_3_-_EventBus.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_68_-_Components_-_G_-_Server_to_Server_Protocol.asciidoc[]\n\ninclude::text/Admin_Guide_69_-_Components_-_H_-_MUC.asciidoc[]\n\ninclude::text/Admin_Guide_70_-_Components_-_I_-_Tigase_Load_Balancing.asciidoc[]\n\ninclude::text/Admin_Guide_71_-_Components_-_J_-_External_Component_Configuration.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_72_-_Components_-_J_-_External_Component_Configuration_-_1_-_Basic_Configuration_Options_(external_component).asciidoc[]\n\ninclude::text/Admin_Guide_73_-_Components_-_J_-_External_Component_Configuration_-_2_-_Tigase_as_External_Component.asciidoc[]\n\ninclude::text/Admin_Guide_74_-_Components_-_J_-_External_Component_Configuration_-_3_-_Load_Balancing_External_Components_in_Cluster_Mode.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_103_-_Components_-_K_-_C2S.asciidoc[]\n\ninclude::text/Admin_Guide_106_-_Components_-_L_-_Socks5.asciidoc[]\n\ninclude::text/Admin_Guide_75_-_Virtual_Hosts_in_the_Tigase_Server.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_76_-_Virtual_Hosts_in_the_Tigase_Server_-_A_-_Specification_for_ad-hoc_Commands_Used_to_Manage_Virtual_Domains.asciidoc[]\n\ninclude::text/Admin_Guide_77_-_Virtual_Hosts_in_the_Tigase_Server_-_B_-_Virtual_Components_for_Cluster_Mode.asciidoc[]\n\n:leveloffset: 1\n\ninclude::text/Admin_Guide_78_-_Using_Tigase.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_79_-_Using_Tigase_-_A_-_Log_Guide.asciidoc[]\n\ninclude::text/Admin_Guide_80_-_Using_Tigase_-_B_-_Debugging_Tigase.asciidoc[]\n\ninclude::text/Admin_Guide_81_-_Using_Tigase_-_C_-_Basic_System_Checks.asciidoc[]\n\ninclude::text/Admin_Guide_82_-_Using_Tigase_-_D_-_Add_and_Manage_Virtual_Domains.asciidoc[]\n\ninclude::text/Admin_Guide_83_-_Using_Tigase_-_E_-_Presence_Forwarding.asciidoc[]\n\ninclude::text/Admin_Guide_84_-_Using_Tigase_-_F_-_Register_Own_XMPP_Domain.asciidoc[]\n\ninclude::text/Admin_Guide_85_-_Using_Tigase_-_G_-_Tigase_and_PyMSN-t_Transport.asciidoc[]\n\ninclude::text/Admin_Guide_86_-_Using_Tigase_-_H_-_Two_or_more_SessionManagers.asciidoc[]\n\ninclude::text/Admin_Guide_87_-_Using_Tigase_-_I_-_Watchdog.asciidoc[]\n\ninclude::text/Admin_Guide_88_-_Using_Tigase_-_J_-_Tips_and_Tricks.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_89_-_Using_Tigase_-_J_-_Tips_and_Tricks_-_1_-_Tigase_Tip_Checking_the_Runtime_Environment.asciidoc[]\n\ninclude::text/Admin_Guide_91_-_Using_Tigase_-_J_-_Tips_and_Tricks_-_3_-_Best_Practices_for_Connecting_From_Web_Browser_to_Tigase_XMPP_Server.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_92_-_Using_Tigase_-_K_-_Command_Line_Tools.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_93_-_Using_Tigase_-_K_-_Command_Line_Tools_-_1_-_Configuration_Managament_Tool.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_94_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase.asciidoc[]\n\n:leveloffset: 3\n\ninclude::text/Admin_Guide_95_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_1_-_Scripting_Introduction_-_Hello_World.asciidoc[]\n\ninclude::text/Admin_Guide_96_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_2_-_Tigase_Scripting_Version_4.4.x_Update_for_Administrators.asciidoc[]\n\ninclude::text/Admin_Guide_97_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_3_-_Tigase_and_Python.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Admin_Guide_98_-_Using_Tigase_-_M_-_Configuration_Wizards.asciidoc[]\n\ninclude::text/Admin_Guide_99_-_Using_Tigase_-_N_-_Offline_Messages.asciidoc[]\n\ninclude::text/Admin_Guide_100_-_Using_Tigase_-_O_-_Licensing.asciidoc[]\n\ninclude::text/Admin_Guide_101_-_Using_Tigase_-_P_-_Advanced_Options.asciidoc[]\n\ninclude::text/Admin_Guide_104_-_Using_Tigase_-_Q_-_Clustering.asciidoc[]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_01_-_About_Tigase_Jabber_XMPP_Server.asciidoc",
    "content": "[[about]]\n= About Tigase XMPP Server\n\n:Author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:Version: v2.0, June 2014: reformatted for AsciiDoc\n:Date:  2010-04-06 16:18\n:Revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n*Tigase XMPP Server* is an *Open Source and Free (AGPLv3)* Java based server. The goals behind its design and implementation of the server are:\n\n. Make the server robust and reliable.\n. Make the server a secure communication platform.\n. Make a flexible server which can be applied to different use cases.\n. Make an extensible server which takes full advantage of XMPP protocol extensibility.\n. Make the server easy to setup and maintain.\n\n== Robust and reliable\n\nThis means that the server can handle many concurrent requests/connections and can run for a long time reliably. The server is designed and implemented to handle millions of simultaneous connections.\n\nIt is not enough however to design and implement a high load server and hope it will run well. The main focus of the project is put in into testing. Tests are taken so seriously that a dedicated testing framework has been implemented. All server functions are considered as implemented only when they pass a rigorous testing cycle. The testing cycle consists of 3 fundamental tests:\n\n. *Functional tests* - Checking whether the function works at all.\n. *Performance tests* - Checking whether the function performs well enough.\n. *Stability tests* - Checking whether the function behaves well in long term run. It must handle hundreds of requests a second in a several hour server run.\n\n== Security\n\nThere are a few elements of the security related to XMPP servers: secure data transmissions which is met by the implementation of *SSL* or *TLS* protocol, secure user authorization which is met by the implementation of *DIGEST* or *SASL* user authorization and secure deployment which is met by component architecture.\n\n*Secure deployment* Tigase software installation does not impact network security. Companies usually have their networks divided into 2 parts: *DMZ* which is partially open to the outside world and the *Private network* which is closed to the outside world.\n\nIf the XMPP server is to provide an effective way of communication between company employees regardless if they are in a secure company office or outside (perhaps at a customer site), it needs to accept both internal and external connections. So the natural location for the server deployment is the *DMZ*. However, this solution has some considerations: each company has normally established network users base and integrated authorization mechanisms. However, that information should be stored outside the DMZ to protect internal security, so how to maintain ease of installation and system security?\n\n*Tigase server* offers a solution for such a case. With it's component structure, Tigase can be easily deployed on any number machines and from the user's point of view it is seen as a one logical XMPP server. In this case we can install a Session Manager module in the *private* network, and a Client Connection Manager with Server Connection Manager in the *DMZ*.\n\nSession Manager connects to *DMZ* and receives all packets from external users. Thus is can securely realize users authorization based on company authorization mechanisms.\n\n== Flexibility\n\nThere are many different XMPP server implementations. The most prevolant are:\n\n- Used as a business communication platform in small and medium companies where the server is not under a heavy load. For such deployments security is a key feature.\n- For huge community websites or internet portal servers is, on the other hand, usually under very heavy load and has to support thousands or millions of simultaneous connections. For such a deployment we need a different level of security as most of the service is open to the public.\n- For very small community deployments or for small home networks the key factor is ease to deploy and maintain.\n\nArchitecture based on components provides the ability to run selected modules on separate machines so the server can be easily applied in any scenario.\n\nFor simple installation the server generates a config file which can be used straight away with very few modifications or none at all. For complex deployments though, you can tweak configurations to your needs and setup XMPP server on as many physical machines as you need.\n\n== Extensibility\n\nThe world changes all the time as does user's needs. The XMPP protocol has been designed to be extensible to make it easy to add new features and apply it to those different user's needs. As a result, XMPP is a very effective platform not only for sending messages to other users, it can also be extended for sending instant notifications about events, a useful platform for on-line customer service, voice communication, and other cases where sending information instantly to other people is needed.\n\n*Tigase server* has been designed to be extensible using a modular architecture. You can easily replace components which do not fulfill your requirements with others better fitting your needs. But that is not all, another factor of extensibility is how easy is to replace or add new extensions. A great deal of focus has been put into the server design API to make it easy for other software developers to create extensions and implement new features.\n\n== Ease of Use\n\nComplex computer networks consisting of many servers with different services are hard to maintain. This requires employing professional staff to operate and maintain the network.\n\nNot all networks are so complex however, most small companies have just a few servers for their needs with services like e-mail and a HTTP server. They might want to add an XMPP server to the collection of their services and don't want to dedicate resources on setup and maintenance. For such users our default configuration is exactly what they need. If the operating system on the server is well configured, then Tigase should automatically pickup the correct hostname and be ready to operate immediately.\n\nTigase server is designed and implemented to allow dynamic reconfiguration during runtime so there is no need to restart the server each time you want to change configuration settings.\n\nThere are also interfaces and handlers available to make it easy to implement a web user interface for server monitoring and configuring.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_02_-_Quick_Start.asciidoc",
    "content": "[[QuickStart]]\n= Quick Start Guide\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n== Minimum Requirements\n\nBefore you begin installing Tigase server onto your system, please make sure the minimum requirements are installed first: +\n- *Java Development Kit v8 or later* - We recommend Oracle JDK.  OpenJDK may work, but some features might cause errors. +\n\n- *Administrator access* - We recommend that you install Tigase Server from a user login with administrator access. +\n\n== Contents\n\nThis is a set of documents allowing you to quickly start with our software. Every document provides an introduction to a single topic allowing you to start using/developing or just working on the subject.  Please have a look at the documents list below to find a topic you are looking for. If you don't find a document for the topic you need please link:http://www.tigase.net/contact[let us know].\n\n- xref:guiinstall[Installation using GUI installer]\n- xref:consoleinstall[Installing using console installer]\n- xref:manualinstall[Manual installation in console mode]\n- xref:webinstall[Installation Using Web Installer]\n- xref:TSBupdates[Tigase server binary updates]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_03_-_Quick_Start_-_A_-_Installation_Using_GUI_Installer.asciidoc",
    "content": "[[guiinstall]]\n= Installation Using GUI Installer\n\n:author: Mateusz Fiolka\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nIf you don't want to install Tigase using a manual method, you can use the GUI installer. It not only copies server files to preferred place, but also assists with configuration of the most important parameters and database setup. Therefore we recommend this as the way to install Tigase.\n\n== Prerequisites\n\nBefore you can start the GUI installer you will need to have working Java environment. Although installer only requires *JRE* (Java Runtime Environment), server needs the *JDK* (Java Development Kit). Please do note that *currently minimal JDK version Tigase is capable to run on is 1.6*. If you don't have JDK installed it is the right moment to do it. Visit the link:http://java.sun.com/javase/downloads/index.jsp[Java downloads site] From the list of available packages select newest JDK version (if you don't have a specific need to use J2EE then choose a package without it). After configuring JDK you can download the Tigase GUI installer and start the server installation process.  It is also important to set the +JAVA_HOME+ environment correctly.\n\n== Download the Installer\n\nYou can always find the newest Tigase packages in the link:https://projects.tigase.org/projects/tigase-server/files[download section].  When you enter the page, you will be presented a list of files to choose from.  You may be confused at the beginning as there are lot of choices, but all Tigase binary packages have conventional names, which help to differentiate them easily. They are of form *tigase-server-x.y.z-bv.ext* where 'x', 'y', 'z' and 'v' are version numbers and they change from a release to release. Ext is the file extension which in the case of our GUI installation program is *.jar*. We recommend you to download the latest version (highest version number) of the server as it contains latest functions and improvements\n\n== Run the jar File\n\nOn most systems installing JRE or JDK creates a default association which allows to run the *.jar* file by just double clicking on it. However if nothing happens when you do it there is a way to do it manually. Perform the steps in the following order:\n\n. If you are on *Windows* system you can use the command prompt to run the installer directly using the java command.\n .. Click on the *Start* menu and choose *Run...* (You can also use the *Win+R* shortcut).\n .. You will be presented with a dialog box where you can enter a command. Type \"*cmd*\" (or \"*command*\" in the case of windows version older then 2000) and submit the window.\nIf you are on a *Linux* system, you can use a terminal. It should be easily discoverable as it is a standard tool on this platform. Find and run it.\n. Command prompt / terminal will appear. You will be able to check a whether your *Java* environment is working. To do it type the\n+\n[source,bash]\n-----\njava -version\n-----\n+\ncommand and press Enter. If the message says that the command is not recognized then your *Java* installation may be corrupt or not configured properly. For correctly setting up *JRE/JDK* including setting the *JAVA_HOME* environmental variable please check documentation provided on the JDK download site. Also when the command succeeds please check if the printed version number fulfills Tigase requirements. When many versions of *JDK/JRE* are installed on one machine *java* command will need to be invoked with the full path it is placed on.\n+\n. When you have no doubt that you can run the correct Java launcher, you may start the installer i.e. for the file *tigase-server-4.1.0-b1315.jar* downloaded to the *c:\\download* directory type the following command:\n+\n[source,bash]\n-----\njava -jar c:\\download\\tigase-server-4.1.0-b1315.jar\n-----\n+\nThis command should start the installer or print an error message explaining what is the cause of problem.\n\n== Starting the Installation\n\nPlease note that this tutorial covers only the basic installation mode. Some screens have been omitted because they contain advanced options which are not shown in simple installation mode. Others such as progress of copying files and summary info on the other hand are self explanatory and will also not described.\n\n\n== JDK Selection\n\nimage:images/winInstall2.gif[]\n\nThis screen is only shown when JDK has not been selected automatically. When your JAVA_HOME path is properly set, it will be auto-detected saving you some configuration time. If you are reading this step and still don't have JDK installed, then go back to the xref:prerequisites[prerequisites] section where you can find some info on how to prepare your system for Tigase installation. Sometimes your system will be configured in a way that prevents detection of JDK path. This often happens when you install JRE after installing JDK. You will have to find JDK directory yourself.  It is by default installed in the *Program Files\\Java* directory of your system drive.\n\n== Installation Type Selection\n\nimage:images/winInstall3.gif[]\n\nRecommended practice is to choose both installation and configuration of the server as manual configuration is more complicated, time consuming and error-prone.\n\n== Introduction To the Server\n\nimage:images/winInstall4.gif[]\n\nThis screen shows some information about Tigase which may help you understand what it is and how it can help to take advantage of the *XMPP* protocol. It is important that you read all information's appearing on the installer screens, as they contain valuable hints and most recent information.\n\n== Choice of Base Directory\n\nimage:images/winInstall6.gif[]\n\nThis is the point where you choose where do you want you server to be installed. Recommended path should not contain spaces, as it may be reason of some strange path problems. In the case of installation on Windows it should be installed on a short path because there is a limit of path lengths. Also note that on Windows Vista there may be some problems with making the server work while installed in the Program Files directory, related to the working of UAC mechanism, so better don't install it there.  If you don't want are unsure about where to place the server, you can always leave the default selection.\n\n== Packages selection\n\nimage:images/winInstall7.gif[]\n\nNext important step is package selection. Note that some choices are grayed out and you cannot change them as they are essential. Packages consist of documentation, database drivers, sources of the server and some extras. When you select an item, you will be presented with a short description of it's content.\n\nWe recommend that you install documentation. It contains valuable resources which may be very helpful in administration and general use of the server.\n\nIf you have a working database platform that you want to use for storing all important user information in, just select appropriate db drivers.  If you don't have a database engine, you can use the included derby database along with also included drivers.\n\nIf you are a developer and you want to be able to check how the server is working or if you want to help with the development, you can install also the included source codes.\n\n== Basic Server Configuration\n\nimage:images/winInstall13.gif[]\n\nOn this screen you will find most important basic configuration options. As this guide covers only non-advanced set up - disable the advanced configuration checkbox.\n\nFrom here you can select which components will be installed. For most installations the default selection will be most appropriate. You can expand the list to check if any of the other options will better suit your needs.\n\nIt is very important that you enter your domain name correctly here.\n\n- On *Linux* like system you can use the *hostname* command and extract the domain part from the output. If you use the *-f* parameter then you will get the fully qualified domain name.\n- On *Windows* use the standard *System* control panel applet. You will find your domain (computer name) in the *Computer name* tab.\n\nOn the other hand if you want to use Tigase virtual domain support and you have your *DNS* system configured properly, then you can put your virtual domains list here. Just separate them by comma characters. For example if your server is seen from the outside as *veloci.tigase.org,* *mammoth.tigase.org* and *tigase.org* then you can use Tigase instance as if it were three separate instances.  In reality it will be one server, however *admin@veloci.tigase.org* will be a different user then *admin@tigase.org.* This feature allows to use one server to separate user groups, for example ones from different organizations.\n\nWhen you have your domain name just enter it in the domain text box. Next parameter will be the JID of server administrator. Standard practice is to use *admin*, however you may choose any name you like. For example for domain *tigase.org* the full admin name would be *admin@tigase.org.* Just stick your chosen name and domain together using the @ character as separator.\n\nUsing this information your XMPP admin will be automatically added to the database, so after installation you can just login into the server without registering admin first manually.\n\nYou should also select a database which will be used for storing user info. Default is the *Derby* database, if you don't need anything special just leave it as it is. Just select a new password as the default one is easy for a hacker to guess.\n\n*Important notice: Tigase installer does not contain the actual databases, only drivers allowing db access. The only exception is Derby database, which is included in JDK. It is automatically configured by installer, in case of other databases you will need to configure them by yourself.*\n\n== Verification of Database Connection and Performing DB Tasks\n\nimage:images/winInstall20.gif[]\n\nWhen you switch to this screen an automatic test of database configuration will be started. It consists of few steps which will be executed in order. After testing connection and configuring schema, admin users will be added.\n\nWhat to do if any of the tests will fail?\n\n- If you decided to use your own database, check if you entered correct password and whether your database is running.\n- If you use the embedded *Derby* database then probably your problem is more complicated. An error may indicate a bug in the installer. You may report it to one of Tigase developers.\n\nIf you cannot go beyond this step after trying to resolve database problems you may try xref:manualinstall[manual installation] mode.\n\n== Finishing Installation\n\nWhen you perform all those steps altogether with choosing Start Menu location and other basic actions you will be informed that installation process is complete. You can now use your Tigase server. There are some post installation actions you may want to perform. They are briefly presented below.\n\n== Running the Server\n\nPart of the installation process is the selection of Tigase base directory. This is where you can find all important server files. The installer will create some configurable shortcuts in the *Start Menu*. You can navigate to the menu and use it to start the server.   To run the server manually:\n\n- On a *Linux* system you may start the server using the *tigase* file found in the *scripts* sub-directory of Tigase server base directory.\nYou will need to select the type of linux you have, debian, gentoo, mandirva, or redhat, and use the script located in the init.d folder.\nIn the root server directory type the following command:\n\n[source,bash]\n-----\n./scripts/{OS}/init.d/tigase start etc/tigase.conf\n-----\nOf course if you have a custom config file then change last command appropriately.\n\n- On a *Windows* platform you can use a *bat* file to run the server. There is a *run.bat* file in the Tigase root directory. Just double click it in *Explorer* or run it from command line to start the server. A window with server log output will pop-up.\n\nimage:images/winRun.gif[]\n\n== Installation as a Service\n\nOn *Windows* you can install Tigase as a service. To do it use the *InstallTigaseService.bat* batch file found also in server root directory.\n\nIn this mode service will be running in background and will be controllable from the *Services* management snapshot. To launch the tool right click on the *Computer* icon on the desktop. Choose the *Manage* action. It will run the *Computer management* graphical configuration program. On the left side choose the *Services* item.  You will be shown with a list of services. Here you can find Tigase service when it will be installed.\n\nTo uninstall Tigase service use the *UninstallTigaseService.bat* file from Tigase server root directory.\n\n== How to Check if the Server is Running\n\nChecking if the server is running is quite easy. Just try to connect to it by using one of the many available *XMPP* clients.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_04_-_Quick_Start_-_B_-_Installation_Using_Web_Installer.asciidoc",
    "content": "[[webinstall]]\n= Installation Using Web Installer\n:author: Eric Dziewa\n:version: v1.0, January 2015: New Web Installer!\n:Date: 2015-01-15\n:revision: v1.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nWhen Tigase XMPP Server starts up, it looks for the default configuration file: *etc/init.properties*. If this file has not been modified you can run the web installer. Which will step you through the process of configuring Tigase.\nIf you are installing Tigase in a Windows environment, please see the xref:winWebInstall[Windows Installation] section.\n\n== Download and Extract\n\nFirst download Tigase XMPP Server and extract it. You can download the link:https://projects.tigase.org/projects/tigase-server/files[official binaries], or the latest and greatest link:http://build.xmpp-test.net/nightlies/dists/[nightly builds].\n\n[source,bash]\n-----\n$ wget http://build.xmpp-test.net/nightlies/dists/2015-01-12/tigase-server-7.0.0-SNAPSHOT-b3752-dist-max.tar.gz\n$ tar -xf tigase-server-7.0.0-SNAPSHOT-b3752-dist-max.tar.gz\n$ cd tigase-server-7.0.0-SNAPSHOT-b3752\n-----\n\nPlease do not run as root.\n\n== Start the Server\n\n[source,bash]\n-----\nscripts/tigase.sh start\n-----\n\n== Verify Tigase is Running\n\nYou should see a list of listening ports.\n\n[source,bash]\n-----\n$ lsof -i -P\nCOMMAND   PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME\njava    18387 tigase  141u  IPv6 22185825      0t0  TCP *:8080 (LISTEN)\njava    18387 tigase  148u  IPv6 22185834      0t0  TCP *:5222 (LISTEN)\njava    18387 tigase  149u  IPv6 22185835      0t0  TCP *:5223 (LISTEN)\njava    18387 tigase  150u  IPv6 22185836      0t0  TCP *:5290 (LISTEN)\njava    18387 tigase  151u  IPv6 22185837      0t0  TCP *:5280 (LISTEN)\njava    18387 tigase  152u  IPv6 22185838      0t0  TCP *:5269 (LISTEN)\n-----\n\n[[connecttoWebInstall]]\n== Connect to the Web Installer\n\nSome points before you can connect:\n\nThis setup page is restricted access, however for first setup there is a default account set to setup Tigase:\nUsername: admin\nPassword: tigase\n\nThis combination will only be valid once as it will be removed from init.properties file on compleation of setup process.  After this point the setup page will only be accessable using the following:\n\n. JID accounts listed as administrators in --admins line in init.properties\n. Username and password combinations added to init.properties file manually, or at the last page in this process.\n\nPoint your browser to *http://localhost:8080/setup/* unless you are working remotely. Then you can use the domain name, or IP address. I used http://tpub.xmpp-test.net:8080/setup/ for this guide.\n\nEnter the username and password above to gain access.\n\n== Step Through the Installation Process\n\nYou will be greeted by the following \"About software\" page.\n\nimage:images/web-install-01.png[]\n\nRead it and then click \"Next\"\n\nimage:images/web-install-02.png[]\n\nHere is some information about our commercial products and licensing. Please read though the agreement, type your name or company and click \"Next\".\n\nimage:images/web-install-04.png[]\n\nThis page will look over your default configuration settings, these include the type, Domains you wish to use, and gives you a chance to specify an administrator for the domain.  Also, you will be selecting what type of database Tigase server will be using.\n\nimage:images/web-install-05.png[]\n\nThe Advanced configuration page. Select what components and configurations you need.\n\nimage:images/web-install-06.png[]\n\nPlugins which will be loaded by the server, most plugins are enabled by default.\n\nimage:images/web-install-07.png[]\n\nThis is where the database schema is installed. *BE SURE TO SPECIFY SUPER USER ACCOUNT AND PASSWORD*\n\nimage:images/web-install-08.png[]\n\nYou should see a page like this after a successful database setup.  This page will reveal any issues with your database setup such as invalid URIs, passwords, and schemas.\n\nimage:images/web-install-09.png[]\n\nNext a page asking if you'd like to provide an API Access Key to access HTTP REST commands.  It is highly recommended that you either specify an API key or block access.  Open API keys allow any REST command to be interpreted by the server.\n\nimage:images/web-install-10.png[]\n\nThe Setup Access Page will be locked from the admin/tigase user as specified above.  This is your chance to have the setup pages add a specific user in addition to admin accounts to re-access this setup process later.  If left blank, only JIDs listed in admin will be allowed to access.\n\nimage:images/web-install-11.png[]\n\nThe installation is complete and this is what the *init.properties* file will look like.\nIf you have a custom setup, or would like to put your own settings in, you may copy and past the contents here to edit the current init.properties file.\nClick \"Save\" to write the file to disk.\n\nimage:images/web-install-12.png[]\n\nYou have now finished the installation, proceed to the next step to restart the server.\n\n== Restart the Server\nIt is recommended at this point to stop the server manually and restart it using the proper script for your OS.\nFrom the Tigase base directory enter\n[source,bash]\n-----\n./scripts/tigase.sh stop\n\n./scripts/{OS}/init.d/tigase start etc/tigase.conf\n-----\nwhere {OS} is your type of Linux, gentoo, debian, mandriva, or redhat\n\nTo further fine tune the server you should edit etc/tigase.conf. Ensure *JAVA_HOME* path is correct, and increase memory if needed using *JAVA_OPTIONS* -Xmx (max), and -Xms (initial). You will need to direct Tigase to read settings from this file on startup as follows.\n\nEverything should be running smooth at this point. Check the logfiles in logs/ if you experience any problems.\n\n[[winWebInstall]]\n== Windows Instructions for using Web Installer\n\nThere are a few steps involved with setting up Tigase with the web installer in a Windows environment.  Please follow this guide.\n\nFirst step is to extract the dist-max archive in it's entirety to the intended running directory.  Once there, run the Setup.bat file inside the win-stuff folder.  This will move the necessary files to the correct folders before Tigase begins operation.\n\nFrom here, you have a few options how to run Tigase; run.bat will operate Tigase using a java command, or run.bat which will start Tigase using the wrapper.  You may also install Tigase and run it as a service.\n\nOne this setup is finished, web installer will continue the same from xref:connecttoWebInstall[here].\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_05_-_Quick_Start_-_C_-_Installing_Using_Console_Installer.asciidoc",
    "content": "[[consoleinstall]]\n= Installing Using Console Installer\n:author: Mateusz Fiolka\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n\n== Installation Using the text-mode Installer\n\nWhen you install Tigase server on a desktop machine or a server having a graphical user interface - you can use the xref:guiinstall[GUI Installer]. However servers are often administered using *SSH* text-mode connection because of low bandwidth requirements or user preferences. Due to popular demand, the Tigase development team has decided to implement a console installer for the server.\n\n*Note! The console installer is only available for Tigase server version 4.1.5 and later*.\n\n=== Requirements and Important Notice\n\nBefore trying the installer please keep in mind:\n\n- This is first - alpha rate version of the text-mode installation - meant to install the server and do some basic configuration. We will be very happy to see bug reports and overall feedback about this feature. Please send your remarks to mailto:artur.hefczyc@tigase.net[Artur Hefczyc] or Mateusz Fiolka.\n- You will still need to perform some additional steps before running the installer. The main requirement is to download and install *Java JDK v1.6 or newer*. This guide is aimed at advanced users - thus downloading and configuring JDK is left to the reader. You can find more info at the link:http://java.sun.com/javase/downloads/index.jsp[Java downloads site].\n\n== Download the Installer\n\nYou can always find the newest Tigase packages in the link:https://projects.tigase.org/projects/tigase-server/files/[download section]. When you enter the page, you will be presented a list of files to choose from.   All Tigase binary packages have conventional names, which help to differentiate them easily. They are of form *tigase-server-x.y.z-bv.ext* where 'x', 'y', 'z' and 'v' are version numbers and they change from a release to release. Ext is the file extension which in the case of our console installation program is *.jar*. We recommend you download the latest version (highest version number) of the server as it contains latest functions and improvements.\n\n== Run the jar File\n\nIn terminal (SSH or Windows cmd prompt if you use on) type:\n[source,bash]\n-----\njava -jar nameOfTheDownloadedJarFile.jar -console\n-----\n\n== Installation Steps\n\nNow you are ready to to install the server.\n\nSome tips for working with the console installer:\n\n- Please remember to write down your JDK location because you will need to type it during the installation process.\n- Installer consists of number of screens which relate to  different configuration aspects. Most of the panels end with a question whether you want to redisplay the panel or quit installer. When you make a mistake you will be probably asked later if you want re-enter the data again.\n- To quit the installer use standard termination key specific to your platform. For example on a *Linux* system it is the Ctrl+C key combination. Keep in mind that if you quit the installer after it copied some files - it may leave them in the place and you might have to remove them manually.\n- In current version the installer is of beta quality and using advanced configuration is not recommended. It might work, however it is not much tested and will be improved later.\n\n=== Initial Screen\n\nOn this screen you will find server version info which will be useful if you would to suggest something to Tigase developers.\n\n[source,bash]\n-----\nWelcome to the installation of Tigase XMPP (Jabber) Server X.Y.Z!\n\nThe homepage is at: http://www.tigase.org/\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== JDK Selection\n\nYour system may contain more then one JDK installation, thus you will have to make an explicit decision which one to use. Currently console mode installer doesn't contain any auto-detection code nor validation. You will have to enter the path correctly or you may have problems with running the server. For example on *Ubuntu Linux* you can find the JDK in the /lib/jvm/java-6-sun directory. For the current Tigase server JDK of version at least *1.6* is required.\n\n[source,bash]\n-----\nThe installed application needs a JDK. A java run-time\nenvironment (JRE) will be not sufficient.\n\nEnter path: /lib/jvm/java-6-sun\n-----\n\n=== Actions Selection\n\nChoose whether you want to configure the server in addition to install it.\n\n[source,bash]\n-----\n*** Select what you want to do next:\n\nOn this panel you can specify whether you want to install\nonly or configure already installed server or to do both. If\nyou are just installing a server on your machine it is a\ngood idea to do both steps.\n\n\n\nThe wizards you want to execute\nInstallation of the Tigase Server\n[on, off]\non\nConfiguration of the Tigase Server\n[on, off]\non\n-----\n\n=== Installer Info\n\nIntroduction to the installer.\n\n[source,bash]\n-----\nPlease note!\n\nWhile the Tigase server is quite stable and well tested\napplication the installer itself is a new addition. Take\nprecautions especially if you upgrade the server from\nearlier version. Backup old server files and the database.\n\nIf you notice any problems please report them to address:\nArtur Hefczyc\n\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Server Info\n\nIf you don't know what exactly Tigase server is, you can find some basic introduction on this screen.\n\n[source,bash]\n-----\nTigase XMPP (Jabber) server ver 4.1.5-bDEV\n\n\nAbout\n\nCopyright (C) 2004 Tigase.org. <http://www.tigase.org/>\n\nTigase Jabber/XMPP Server is\nOpen Source and Free  (AGPLv3)\nJava based server. The goals behind the design and\nimplementation of the server are:\n\n\nMake the server robust and reliable.\nMake the server secure communication platform.\nMake flexible server which can be applied to different use\ncases.\nMake extensible server which takes full advantage of XMPP\nprotocol extensibility.\n\n--- Press ENTER to continue ---\n\nMake the server easy to setup and maintain.\n\n\nInstallation, configuration and compilation\n\nThe most recent documentation on all these topics is always\navailable in the project website: www.tigase.org. Please\nrefer to the website for all the details and always up to\ndate guides.\n\nYou would probably want to start with Quick Start:\nhttp://www.tigase.org/content/quick-start documentation.\n\nThe website also contains lots of other useful information\nlike load tests results, user discussions and on-line support\nand help always available to you.\n\nThis is 4.1.5-bDEV release of the server. Please include the\nexact version number in all correspondence regarding the\nserver.\n\n\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Server License\n\nThis is a license that you have to agree to use Tigase server. Please read it carefully. Take note, that in this manual only part is shown in order to decrease guide length.\n\n[source,bash]\n-----\nPlease read the following license agreement carefully:\n\n\n\nGNU General Public License - GNU Project - Free Software\nFoundation (FSF)\n\n\nGNU GENERAL PUBLIC LICENSE\nVersion 3, 29 June 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc.\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\nPreamble\n\n...\n... Fragment cut out\n...\n\n\nYou should also get your employer (if you work as a\nprogrammer) or school, if any, to sign a \"copyright\ndisclaimer\" for the program, if necessary.  For more\ninformation on this, and how to apply and follow the GNU\nGPL, see --- Press ENTER to continue ---\n\n<http://www.gnu.org/licenses/>.\n\nThe GNU General Public License does not permit incorporating\nyour program into proprietary programs.  If your program is\na subroutine library, you may consider it more useful to\npermit linking proprietary applications with the library.\nIf this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please\nread\n\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n\n1. I accept the terms of this license agreement.\n2. I do not accept the terms of this license agreement.\nChoose number (1-2):\n1\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Server Location Selection\n\nEnter where you want the server to be installed. If you have administrator rights you can place it in a standard location where all your applications reside. If you don't have write permissions for this place, you can always install the server in your home directory.\n\n[source,bash]\n-----\nSelect target path\n[/home/user/tigase] /home/user/tigase-server\n\npress 1 to continue, 2 to quit, 3 to redisplay 1\n-----\n\n=== Selection of Packs to be Installed\n\nSome packs are optional and you can disable/enable them. In the following screen they have an [x] option before them. To switch their state enter item number and ENTER. When done press d and ENTER.\n\n[source,bash]\n-----\nSelect the packs you want to install:\n\n1 => Base, The base files\n2 => Unix Files, Files needed to run the server on Unix like systems\n3 => [x] Docs, The documentation\n4 => [x] Extras, Extras libraries, MUC, PubSub...\n5 => [x] Derby Database, Derby database and JDBC driver\n6 => [x] MySQL Database, MySQL JDBC driver (MySQL has to be\ninstalled separately)\n7 => [x] PostgreSQL Database, PostgreSQL JDBC driver\n(PostgreSQL has to be installed separately)\n8 => [x] SQL Server Database, SQL Server JDBC driver (SQL\nServer has to be installed separately)\n9 => [ ] Sources, The server source files, tools and\nlibraries sources are not included\nr => Redisplay menu\nd => Done\n\nChoose action: d\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Installation\n\nDuring extracting and copying server files to their target you will be presented with the process progress.\n\n[source,bash]\n-----\n[ Starting to unpack ]\n[ Processing package: Base (1/9) ]\n[ Processing package: Unix Files (2/9) ]\n[ Processing package: Windows Files (3/9) ]\n[ Processing package: Docs (4/9) ]\n[ Processing package: Extras (5/9) ]\n[ Processing package: Derby Database (6/9) ]\n[ Processing package: MySQL Database (7/9) ]\n[ Processing package: PostgreSQL Database (8/9) ]\n[ Processing package: SQL Server Database (9/9) ]\n[ Unpacking finished ]\n-----\n\n=== Basic Configuration\n\nThis panel contains most important configuration options for the Tigase server. You can choose which components should be configured to be used when running server, add XMPP admin users and enter their password (many admins, comma separated, initially having the same password). Choose different password from the default one. Then select preferred database. If you don't have a standalone DB which you would like to use, you can choose the included Derby DB.\n\n*Important notice: Tigase installer doesn't contain the actual databases, only drivers allowing db access. One exception is Derby database, which is included in JDK. It is automatically configured by installer, in case of other databases you will need to configure them by yourself.*\n\n[source,bash]\n-----\n*** Basic Tigase server configuration\nOn this panel you can specify basic configuration settings\nfor the Tigase server.\n\nBased on your selection here more configuration options\nmight be presented later on. After the configuration is\ncomplete init.properties file will be created.\n\nYou can optionally restart the server at the end of the\nprocess if you like.\n\n\n\n0  [x] Default installation\n1  [ ] Default plus extra components\n2  [ ] Session Manager only\n3  [ ] Network connectivity only\ninput selection:\n0\nYour XMPP (Jabber) domains [my-laptop]\n\nServer administrators [admin@my-laptop]\n\nAdmin password [tigase]\n\n0  [x] Derby (built-in database)\n1  [ ] MySQL\n2  [ ] PostgreSQL\n3  [ ] SQLServer\n4  [ ] Other...\ninput selection:\n1\n-----\n\n=== Advanced Configuration\n\n*Please note: in this version advanced configuration is not supported. Although it may work it has not been tested and thus is not recommended. Please enter off to not use it.*\n\n[source,bash]\n-----\nAdvanced configuration options\n[on, off]\noff\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Database Configuration\n\nDepending on which database you selected, you will be presented with related options to configure its connectivity options. As you will see, the parameters have default values.\n\n[source,bash]\n-----\n*** Database configuration:\n\nYou have selected MySQL database. This database needs\nadditional configuration parameters. Please enter all\nrequired information.\n\n\n\nMySQL super user account will be used only to create and\nconfigure database for the Tigase server. It will not be\nused by the Tigase server later on.\n\nSuper user account name: [root]\n\nWARNING: password will be visible while entering\nSuper user password: mysecretpassword\nWARNING: password will be visible while entering\nRetype password: mysecretpassword\n\n\n\nMySQL database details. It will be created automatically if\nit does not exist.\n\nDatabase account: [tigase]\n\nAccount password: [tigase12]\n\nDatabase name: [tigasedb]\n\nDatabase host or IP: [localhost]\n\nAdditional database parameters: []\n\npress 1 to continue, 2 to quit, 3 to redisplay\n-----\n\n=== Database Checking and Preparation\n\nAfter entering all database information an automatic test of connection and database setup is performed. If everything is ok the installer will try to convert database schema to required version and finally adds XMPP administrators to it.\n\n[source,bash]\n-----\nPerforming DB tasks\n\nChecking connection to the database\nConnection OK\nChecking if the database exists\nExists OK\nChecking the database schema\nNew schema loaded OK\nChecking whether the database needs conversion\nConversion not needed\nAdding XMPP admin accounts\nAdded admins OK\n-----\n\n=== Installation Complete\n\nNow you can run the server and use it!\n\n[source,bash]\n-----\nInstall was successful\napplication installed on /home/user/tigase-server\n[ Console installation done ]\n-----\n\n=== Running the Sever\n\nYou can start the server using the tigase file found in the scripts sub-directory of Tigase server base directory. There, select the type of linux you have, debian, gentoo, mendriva or redhat.  In the root server directory type the following command:\n\n[source,bash]\n-----\n./scripts/{OS}/init.d/tigase start etc/tigase.conf\n-----\nWhere {OS} is your *nix operating system.\n\nOf course if you have a custom config file then change last command appropriately.  On a Windows platform you can use a bat file to run the server. There is a run.bat file in the Tigase root directory. Just double click it in Explorer or run it from command line to start the server. A window with server log output will pop-up.\n\n=== How to Check if the Server is Running\n\nChecking to see if the server is running is quite easy. Just connect to it by using one of mnay available XMPP clients.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_06_-_Quick_Start_-_D_-_Manual_Installation_in_Console_Mode.asciidoc",
    "content": "[[manualinstall]]\n= Manual Installation in Console Mode\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nOur preferred way to install the Tigase server is using xref:guiinstall[GUI installer] and configuration program which comes with one of the binary packages. Please pick up the latest version of the JAR file in our link:http://www.tigase.org/filebrowser/tigase-server[download section].\n\nIn many cases however this is not always possible to use the GUI installer. In many cases you have just an ssh access or even a direct access in console mode only. We are going to provide a text-only installer in one of the next releases but for the time being you can use our binary packages to install the server manually. Please continue reading to learn how to install and setup the server in a few easy steps...\n\nIf you have an old version of the Tigase server running and working and you intend to upgrade it please always backup the old version first.\n\n== Get the Binary Package\n\nHave a look at our link:http://www.tigase.org/filebrowser/tigase-server[download area]. Always pick the latest version of the package available. For manual installation either *zip* or *tar.gz* file is available. Pick one of files with filename looking like: *tigase-server-x.y.z-bv.tar.gz* or *tigase-server-x.y.z-bv.zip* where 'x', 'y', 'z' and 'v' are version numbers and they change from a release to release.\n\n== Unpack the Package\n\nUnpack the file using command for the tar.gz file:\n\n[source,sh]\n-----\n $ tar -xzvf tigase-server-x.y.z-bv.tar.gz\n-----\n\nor for the zip file:\n\n[source,sh]\n-----\n $ unzip tigase-server-x.y.z-bv.zip\n-----\n\nA new directory will be created: *tigase-server-x.y.z-bv/*.\n\nSometimes after unpacking package on unix system startup script doesn't have execution permissions. To fix the problem you have to run following command:\n\n[source,sh]\n-----\n $ chmod u+x ./scripts/tigase.sh\n-----\n\n== Prepare Configuration\n\nIf you look inside the new directory, it should like this output:\n\n[source,sh]\n-----\n $ ls -l\ntotal 316K\n-rw-r--r--  1 265K 2008-12-15 22:24 ChangeLog\n-rw-r--r--  1  37K 2008-12-15 22:24 License.html\n-rw-r--r--  1 1.1K 2008-12-15 22:24 README\ndrwxr-xr-x  6  204 2009-02-03 13:25 certs/\ndrwxr-xr-x 22  748 2009-02-03 13:25 database/\ndrwxr-xr-x  3  102 2008-12-15 22:24 docs/\ndrwxr-xr-x  4  136 2009-02-03 13:25 etc/\ndrwxr-xr-x  3  102 2009-02-03 13:25 jars/\ndrwxr-xr-x 12  408 2009-02-03 13:25 libs/\ndrwxr-xr-x  2   68 2008-12-15 22:24 logs/\n-rw-r--r--  1 1.5K 2008-12-15 22:24 package.html\ndrwxr-xr-x  7  238 2009-02-03 13:25 scripts/\n-----\n\nAt the moment the most important is the etc/ directory with 2 files:\n\n[source,sh]\n-----\n $ ls -l etc/\ntotal 8.0K\n-rw-r--r-- 1  97 2008-12-15 22:24 init.properties\n-rw-r--r-- 1 333 2008-12-15 22:24 tigase.conf\n-----\n\nA Small change in the tigase.conf file is needed. Find the line setting for *JAVA_HOME*:\n\n[source,sh]\n-----\nJAVA_HOME=\"${JDKPath}\"\n-----\n\nand replace *$\\{JDKPath}* with a path to Java installation on your system.\n\nYou need also to edit the init.properties file. It contains initial parameters normally set by the configuration program. As this is a manual installation, you will have to edit this document yourself. It contains already a few lines:\n\n[source,sh]\n-----\n $ cat etc/init.properties\nconfig-type=--gen-config-def\n--admins=admin@$HOST_NAME\n--virt-hosts = $HOST_NAME\n--debug=server\n-----\n\nYou have to replace *$HOST_NAME* with a domain name used for your XMPP installation. Let's say this is \\'*jabber.your-great.net*'. Your init.properties should look like this then:\n\n[source,sh]\n-----\n $ cat etc/init.properties\nconfig-type=--gen-config-def\n--admins=admin@jabber.your-great.net\n--virt-hosts = jabber.your-great.net\n--debug=server\n-----\n\nYou can also use multiple virtual domains if you want. Please have a look at the detailed description for *--virt-hosts* property in the init.properties guide and also more detailed information in the Virtual Hosts section of the Tigase Server guide.\n\nYou will also need to configure connection to the database. First you have to decide what database you want to use: *Derby*, *MySQL* or *PostgreSQL*. Then there are to more properties you have to add to the *init.properties:* *--user-db* and *--user-db-uri.* The first property specifies the database type you use and the second the database connection string. For simplicity let's assume you want to use *Derby* database with files located in directory */var/lib/tigase/derby*. 2 more lines need to be added to the *init.properties* file:\n\n[source,sh]\n-----\n $ cat etc/init.properties\nconfig-type=--gen-config-def\n--admins=admin@jabber.your-great.net\n--virt-hosts = jabber.your-great.net\n--debug=server\n--user-db=derby\n--user-db-uri=jdbc:derby:/var/lib/tigase/derby\n-----\n\nThis is enough basic configuration to have your Tigase server installation running.\n\n== Prepare Database\n\nNormally the database is prepared for you during the installation process. Now you are on your own. As in section above we prepare your first installation to run with the *Derby* database. Creating and preparing the Derby database is actually quite easy if you use a helper script: link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/scripts/db-create-derby.sh[./scripts/db-create-derby.sh]. The file might not be in your *scripts/* directory if you have an earlier version of the package. Simply download it from the link provided if it is missing and put it in the *scripts/* directory and execute it with the database location as the parameter:\n\n[source,sh]\n-----\n $ ./scripts/db-create-derby.sh /var/lib/tigase/derby\n-----\n\nThere will be lots of output but if there is no error at the end of the output it means your database has been created and it is ready to use.\n\n*NOTE:* There might be filesystem access restrictions for the directory: */var/lib/* and you might want/need to select a different location.\n\n== Start the Server\n\nYou can start the server using the tigase file found in the scripts sub-directory of Tigase server base directory. There, select the type of linux you have, debian, gentoo, mendriva or redhat.  In the root server directory type the following command:\n\n[source,bash]\n-----\n./scripts/{OS}/init.d/tigase start etc/tigase.conf\n-----\nWhere {OS} is your *nix operating system.\n\nand you should get the output like this:\n\n[source,sh]\n-----\nStarting Tigase:\nnohup: redirecting stderr to stdout\nTigase running pid=18103\n-----\n\n== Check if it is Working\n\nThe server is started already but how do you know if it is really working and there were no problems. Have a look in the *logs/* directory. There should be a few files in there:\n\n[source,sh]\n-----\n $ ls -l logs/\ntotal 40K\n-rw-r--r-- 1 20K 2009-02-03 21:48 tigase-console.log\n-rw-r--r-- 1 16K 2009-02-03 21:48 tigase.log.0\n-rw-r--r-- 1   0 2009-02-03 21:48 tigase.log.0.lck\n-rw-r--r-- 1   6 2009-02-03 21:48 tigase.pid\n-----\n\nThe first 2 files are the most interesting for us: *tigase-console.log* and *tigase.log.0*. The first one contains very limited information and only the most important entries. Have a look inside and check if there are any *WARNING* or *SEVERE* entries. If not everything should be fine.\n\nNow you can connect with an XMPP client of your choice. The first thing to do would be registering the first account - the admin account from your init.properties file: admin@jabber.your-great.net. Refer to your client documentation how to register a new account.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_07_-_Quick_Start_-_E_-_Windows_Installation.asciidoc",
    "content": "[[windowsInstallation]]\n= Windows Installation\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase server installation should be started with downloading the Tigase installer server from our link:https://projects.tigase.org/attachments/download/273/tigase-server-3.3.2-b889.exe[download area]. This guide describes installation procedure for the branch 3.x of the server so please pick up the latest version of the Tigase 3.x.\n\nThe Windows binary package is an executable file containing an installer. Run the file and the server will be installed and icons will be added to your Windows start menu. Locate the Tigase group in your menu and execute: \"Install Tigase service\" which will install the Tigase server as the system service and it will be automatically started whenever your system starts.\n\nIf you are going to use the Tigase server with MySQL database have a look now in the directory where the Tigase server is installed. There is a directory +etc/+. Have a look inside and find file called +init.properties+. Open the file with a text editor and make sure you added there 2 following lines:\n\n[source,bash]\n-----\n--user-db=mysql\n--user-db-uri=jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass\n-----\n\nThe content of the file should look like the example screenshot below:\n\nimage:images/init_properties1.jpg[]\n\n== MySQL Database Installation\n\nThe section describes installation and configuration of the MySQL database to work with Tigase server.\n\nDownload the binary package from MySQL download area at link:http://dev.mysql.com/downloads/mysql/5.0.html#win32[mysql.com]. Make sure you select executable proper for your operating system.\n\nRun the installation program and follow default installation steps. When the installation is complete find the MySQL elements in the Windows Start menu and run the MySQL Configuration Wizard. Follow the wizard and make sure to check settings against the screenshots in the guide below.\n\nIn Welcome window just press 'Next'.(pic.1)\n\nimage:images/sql1.JPG[]\n\nIn the next window select option: 'Detailed Configuration' and press 'Next' (pic. 2)\n\nimage:images/sql2.JPG[]\n\nOn the next screen select option: 'Server Machine' and press 'Next' (pic. 3)\n\nimage:images/sql3.JPG[]\n\nOn the forth windows leave the default\" 'Multifunctional Database' and press 'Next' (pic. 4)\n\nimage:images/sql4.JPG[]\n\nOn the step number five just press 'Next' using defaults. (pic. 5)\n\nimage:images/sql5.JPG[]\n\nAgain, on window 6 select the default - 'Decision Support (DSS)/OLAP' and press 'Next' (pic.6)\n\nimage:images/sql6.JPG[]\n\nMake sure you switch OFF the 'Strict mode' and and press 'Next' (pic. 7)\n\nimage:images/sql7.JPG[]\n\nOn the character encoding page select: 'Manual Selected Default Character set/ Collation' and  'utf8', press 'Next' (pic.8)\n\nimage:images/sql8.JPG[]\n\nOn next window select 'Include Bin Directory in Windows PATH' and press 'Next' (pic.9)\n\nimage:images/sql9.JPG[]\n\nOn this window just enter the database super user password and make sure you remember it. When ready press 'Next' (pic. 10)\n\nimage:images/sql10.JPG[]\n\nThis is the last screen. Press 'Execute' to save the configuration parameters. (pic. 11)\n\nimage:images/sql11.JPG[]\n\nWhen the configuration is saved you can repeat all the steps and change settings at any time by running: *START => Programs => MYSQL=> MYSQL serwer machine=>  MySQL Server Instance Config Wizard*\n\nNow we have to setup Tigase database. From the Start menu run the MySQL console and enter all commands below finishing them with *<ENTER>*:\n\n. Create the database:\n+\n[source,sql]\n-----\nmysql>create database tigasedb;\n-----\n. Add database user:\n+\n[source,bash]\n-----\nmysql> GRANT ALL ON tigasedb.* TO tigase_user@'%' IDENTIFIED BY 'tigase_passwd';\nmysql> GRANT ALL ON tigasedb.* TO tigase_user@'localhost' IDENTIFIED BY 'tigase_passwd';\nmysql> GRANT ALL ON tigasedb.* TO tigase_user IDENTIFIED BY 'tigase_passwd';\nmysql> FLUSH PRIVILEGES;\n-----\n. Load Tigase database schema:\n+\n[source,bash]\n-----\nmysql> use tigasedb;\nmysql> source c:/Program Files/Tigase/database/mysql-schema.sql;\n-----\n\nThere is a small configuration bug in the installation of Tigase version 3.x. If you look in the *run.bat* file in the Tigase directory you have to replace string *inital.propereties* with *init.properties*.\n\nYou can now restart your machine and all services including the MySQL database and the Tigase server should be running. Alternatively if you don't want to restart your computer you can start both services manually if you know how to do it.\n\nWhen the system is up and running you can connect with any XMPP client (Psi for example) to your server to see if it is working.\n\nNow, you can tweak the server configuration further. Use the guide describing init.properties file for configuration details.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_07_-_Quick_Start_-_F_-_Setting_Up_Server.asciidoc",
    "content": "[[setupTigaseServer]]\n= Tigase Server Network Instructions\n:author: Daniel Wisnewski <daniel@mail.tigase.org>\n:version: v1.0, May 2016: Reformatted for AsciiDoc.\n:date: 2016-05-13 10:30\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nOne you have installed Tigase XMPP Server on a machine, you're going to want to use it.  If you are just using for local communications on a network behind a router, you're all set.  Enjoy and use!\n\nHowever, if you want to have people from other computers outside your network connect to your server, you're going to have to go through a few more steps to show your server out to the public.\n\nNOTE: This guide is merely a recommendation of how to get a local server to be open to incoming communications.  Any time you open ports, or take other security measures you risk compromising your network security.  These are only recommendations, and may not be appropriate for all installations.  Please consult your IT Security expert for securing your own installation.\n\nXMPP, being a decentralized communication method, relies on proper DNS records to figure out where and how an XMPP server is setup.  Operating an XMPP Server will require you to properly setup DNS routing so not only can clients connect to you, but if you decide to run a federated server and enable server to server communication, you will need to do the same.  If you already have a DNS server already, you should have little issue adding these records.\nIf you do not have a DNS setup pointing to your server, you may use a free dynamic name service such as dynu.com.\n\n== A Records\nYou will not be able to use an IP Address or a CNAME record to setup an XMPP Server.  While it's not required, an A record can provide some other benefits such serving as a backup in case the SRV record is not configured right.\n\n== SRV Records\nYou will need to set SRV records both for client-to-server (c2s) communication and, if you plan to use it, server to server (s2s) communication.  We recommend both records are entered for every server as some resources or clients will check for both records.\nFor this example we will use tigase.org is our domain, and xmpp as the xmpp server subdomain.\n\nSRV records have the following form:\n\n_service._protocol.name. TTL class SRV Priority weight port target.\n\nThe key is as follows:\n\n* *service*: is the symbolic name of the desired service, in this case it would be _xmpp-client_ or _xmpp-server_.\n* *protocol*: is the transport protocol, either TCP or UDP, XMPP traffic will take place over _TCP_.\n* *name*: the domain name where the server resides, in this case _tigase.org_.\n* *TTL*: a numeric value for DNS time to live in milliseconds, by default use _86400_.\n* *class*: DNS class field, this is always _IN_.\n* *priority*: the priority of the target host with lower numbers being higher priority.  Since we are not setting up multiple SRV records, we can use _0_.\n* *weight*: the relative weight for records with the same priority. We can use _5_.\n* *port*: the specific TCP or UDP port where the service can be found. In this case it will be _5222_ or _5269_.\n* *target*: the hostname of the machine providing the service, here we will use _xmpp.tigase.org_.\n\nFor our example server, the SRV records will then look like this:\n\n*_xmpp-client._TCP.tigase.org 86400 IN SRV 0 5 5222 xmpp.tigase.org*\n\n*_xmpp-server._TCP.tigase.org 86400 IN SRV 0 5 5269 xmpp.tigase.org*\n\n=== Tigase and Vhosts\nIf you are running multiple vhosts or subdomains that you wish to separate, you will need another record.  In this case an A record will be all you need if you are using default ports.  If you are using custom ports, you will need to have a new SRV record for each subdomain.\n\n== Port Forwarding\nOnce your server is setup, you may need to open at least two ports.  XMPP communication handling and SRV records occur on two ports; 5222 and 5269.  SRV records may result in an error if these ports cannot be contacted by the SRV records service, and you will be unable to connect from outside your network.\nBoth ports should be setup to use TCP only.  Remember, if you set custom ports for your servers communications, you may need to forward them as well.\n\n. If you are using TURN or STUN, you will need to forward 3478 under TCP and UDP.\n. If you are planning to use STUN or TURN over TLS, forward 5349 under TCP.\n\nIf you have a cell phone on a separate network with an XMPP client, you can now try to login to test the server.  If that is not handy, you can use an online tool to check proper DNS records such as kingant's: link:https://kingant.net/check_xmpp_dns/[https://kingant.net/check_xmpp_dns/] and it will tell you if anything is missing.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_08_-_Latest_and_Nightly_Builds.asciidoc",
    "content": "[[TSBupdates]]\n= Tigase Server Binary Updates\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n\nMost open source projects try to make sure that the nightly builds compile correctly so that these builds can be used. However, we at Tigase believe that these builds should be seperated until they are thoroughly tested and released. Although lots of installations out there we know of just run from our nightly builds, this puts an extra responsibility to make sure all code is functional and will constantly work. Therefore, our general approach is to run all basic functionality tests before each code commit to make sure it works correctly. This does not guarantee that there will never be a problem, but it is a precaution from preventing bad builds from arriving in the hands of our customers.\n\nSome users on the other hand, like to be on the bleeding edge and regularly use our nightly builds exploring new code changes and playing with new features before they are put to a full release. Others prefer to stick to stable and fully tested public releases. Others however, want something from the middle, the most recent features, but bug fixes, something like a beta or a release-candidate state.\n\nShould you choose to use the nighly builds, a few things you should consider:\n- Changes may be made to the code that can negatively affect performance.\n- Changes may be made to the code that can negatively affect security.\nWe *highly* recommend testing these builds in your environments before upgrading.\n\nWith these considerations in mind, we provide nightly builds at link:http://build.xmpp-test.net/nightlies/dists/[this link] which provides directories by date.\n\nStandard naming format is tigase-server-x.x.x-SNAPSHOT-byyyy.*\nx.x.x is the major version the builds are working towards, with yyyy being the specific build.\n*Note individual days may have the same builds as noted by the byyyy section of the file.*\n\nJust like the standard distributions, the builds are available with the following extensions:\n. .jar - Java installer version\n. .exe - Windows binary installer version\n. -javadoc.jar - Java installer for javadoc only\n. -dist.zip - Compressed binaries with no dependencies.\n. -dist.tar.gz - tarball compressed binaries with no dependencies.\n. -dist-max.zip - Compressed binaries with all dependencies.\n. -dist-max.tar.gz - tarball compressed binaries with all dependencies.\n\nWe also provide automated testing of each of our nightly builds for each supported databases.  Tests are done with both functional and low memory parameters in mind, and are available link:http://build.xmpp-test.net/nightlies/tests/[at this link].  These tests can provide a quick examination of function before upgrading your current build.\n\nThe latest Cluster tests are available at link:http://graph.cluster-c.xmpp-test.net/latest/[this link] which shows performance and traffic use under strain using the latest available build of Tigase.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_09_-_Configuration.asciidoc",
    "content": "[[configuration]]\n= Configuration\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 12:28\n:revision: 2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n\nWhen the user tries to setup the client for the first time he comes across 2 configuration files: *tigase.conf* and *init.properties* in the /etc folder. Here is a brief explanation what all those files are about and in other sections you can learn all the details needed to configure the server.\n\n. xref:initPropertiesGuide[init.properties] file is a simple text file with server parameters in form: *key* = *value*. When the XML configuration file is missing the Tigase server reads *init.properties* file and uses parameters found there as defaults for generation of the XML file. Therefore if you change the *init.properties* file you normally have to stop the server, remove the XML file and start the server again. All the settings from the *init.properties* are read and applied to the XML configuration. The properties file is easy to read and very safe to modify. At the moment this is the recommended way change the server configuration.\n. xref:manualconfig[tigase.conf] is the Tigase server startup configuration. It is actually not used by the server itself. It rather contains operating system settings and environment parameters to correctly run the link:http://java.sun.com/[Java Virtual Machine]. It is only useful on the unix-like systems with Bash shell. If you run the server on MS Windows systems *tigase.bat* and *wrapper.conf* files are used instead. The *tigase.conf* file is read and loaded by the *scripts/tigase.sh* shell script which also scans the operating system environment for Java VM and other tools needed.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_100_-_Using_Tigase_-_O_-_Licensing.asciidoc",
    "content": "[[licenseserver]]\n= Licensing\n:author: Daniel Wisnewski\n:version: v1.0, March 2016\n:date: 2016-03-15 11:00\n\n:numbered:\n:website: http://tigase.net\n:toc:\n\nFrom release of v7.1.0, users and commercial clients alike may now be able to register and request a license file from our servers on their own.\nThis process helps us maintain licenses, and can allow for client installations of new servers without the need to wait for a license file.\nUsers who do not wish to register will not be required to register.  However, If you are using Tigase ACS or other commercial pieces of software, you will be required to register.\n\n*Again, Tigase XMPP Server will still be available free under AGPLv3, and free users will not need to register.*\n\n== Registering for a License\nTo obtain a license from our licensing servers, you will first need to register with us.  This may be done in a few methods.  The easiest method, and recommended is VIA use of our web portal.\n\n=== Web Portal\nPointing your browser to link:http://license.tigase.net:8080/rest/licence/register[license.tigase.net:8080/rest/licence/register] will give you the following page:\n\nimage::images/Licwebregform.png[Registation form]\n\nFill out the three required forms, your name, an E-mail where you will receive the license, and answer the math problem, to prove you are a human.\n\nOnce filled out, you will be greeted with the following screen:\n\nimage::images/Licwebregok.png[Confirmation page]\n\nYou will receive an E-mail shortly from tigase@tigase.net and will look like this:\n[source,bash]\n-----\nHi!\n\nWelcome User Name!\nYour CustomerID is 9s82stmw2tasc4h6q05n69azxs\n\nPlease add this line yo your init.properties:\n--customer-id=9s82stmw2tasc4h6q05n69azxs\n\n--\nTigase Team\n\n-----\n\nOnce you have this E-mail, proceed to xref:licenseconfig[License Configuration].\n\n=== AdHoc Commands\nThe new license server can now accept adHoc commands to be sent and received using XMPP stanzas.  This is more complicated, but it may help you use scripts or automate the server registration process:\n\nThese Ad-Hoc commands may be used to manually start the following operations:\n\n==== +create-customer-id+\nCreates a new customer-id.\n\nReturns a blank form containing the following fields to be filled:\n- +name+ - full name of the user\n- +email+ - the email address user\n\n\n[source,xml]\n----\n<iq type=\"set\" to=\"licenceserver@coffeebean.local\" id=\"aad3a\">\n    <command xmlns=\"http://jabber.org/protocol/commands\" node=\"create-customer-id\"/>\n</iq>\n----\n\nThe server sends in response:\n\nRegistration Form\n[source,xml]\n----\n<iq from=\"licenceserver@coffeebean.local\" type=\"result\" id=\"aad3a\" to=\"bob@coffeebean.local/Psi+\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\"\n\t\tstatus=\"executing\" node=\"create-customer-id\" sessionid=\"87ed39f9-d29c-405c-b1fa-a541958968aa\">\n        <x xmlns=\"jabber:x:data\" type=\"form\">\n\t\t\t<title>Customer Registration</title>\n\t\t\t<instructions>Please fill all fields</instructions>\n\t\t\t<field type=\"text-single\" label=\"Name\" var=\"name\">\n\t\t\t\t<required/>\n\t\t\t\t<value/>\n\t\t\t</field>\n\t\t\t<field type=\"text-single\" label=\"e-mail\" var=\"email\">\n\t\t\t\t<required/>\n\t\t\t\t<value/>\n\t\t\t</field>\n        </x>\n\t</command>\n</iq>\n----\n\nThe user now sends the completed form:\n\nRegistration form response\n[source,xml]\n----\n<iq type=\"set\" to=\"licenceserver@coffeebean.local\" id=\"aad4a\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\" node=\"create-customer-id\"\n\t\tsessionid=\"87ed39f9-d29c-405c-b1fa-a541958968aa\">\n\t\t<x xmlns=\"jabber:x:data\" type=\"submit\">\n\t\t\t<field type=\"text-single\" var=\"name\">\n\t\t\t\t<value>Bob Bobowsky</value>\n\t\t\t</field>\n\t\t\t<field type=\"text-single\" var=\"email\">\n\t\t\t\t<value>bob@somewhere.gov</value>\n\t\t\t</field>\n\t\t</x>\n\t</command>\n</iq>\n----\n\nAfter sending the filled form, a new +customer-id+ will be generated and sent to the E-mail listed in the form.\nIf you are already registered, it will be sent to the following address existing +customer-id+\n\n==== +retrieve-license+\n\nTo obtain a license from the server must send a form containing a +customer-id+:\n\nStart-up Command +retrieve-license+\n[source,xml]\n----\n<iq type=\"set\" to=\"licenceserver@coffeebean.local\" id=\"aad8a\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\" node=\"retrieve-licence\"/>\n</iq>\n----\n\nIn response, the server will send a form asking for +customer-id+.\nIf the server's found his JabberID, it sent the form will automatically be filled in:\n\nAsking for +customer-id+\n[source,xml]\n----\n<iq from=\"licenceserver@coffeebean.local\" type=\"result\" id=\"aad8a\" to=\"bob@coffeebean.local/Psi+\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\" status=\"executing\"\n\t\tnode=\"retrieve-licence\" sessionid=\"b7aa7ffb-5cda-4c67-aeb4-04094764ec9e\">\n\t\t<x xmlns=\"jabber:x:data\" type=\"form\">\n\t\t\t<title>Retrieve licence</title>\n\t\t\t<instructions>Please fill all fields</instructions>\n\t\t\t<field type=\"text-single\" label=\"customer-id\" var=\"customer-id\">\n\t\t\t\t<value></value>\n\t\t\t</field>\n\t</x>\n\t</command>\n</iq>\n----\n\nThe user sends the completed form:\n\nFilled Form license generation\n[source,xml]\n----\n<iq type=\"set\" to=\"licenceserver@coffeebean.local\" id=\"aad9a\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\" node=\"retrieve-licence\"\n\t\tsessionid=\"b7aa7ffb-5cda-4c67-aeb4-04094764ec9e\">\n\t\t<x xmlns=\"jabber:x:data\" type=\"submit\">\n\t\t\t<field type=\"text-single\" var=\"customer-id\">\n\t\t\t\t<value>6if49ogdd9qbenat2t1461f1kf</value>\n\t\t\t</field>\n\t\t\t<field type=\"list-single\" var=\"component\">\n\t\t\t\t<value>acs</value>\n\t\t\t</field>\n\t\t</x>\n\t</command>\n</iq>\n----\n\nThe server sends a form containing the license.\n\nNOTE: Warning! The license may be in plain-text or Base64 encoded!\n\n.Generated license\n[source,xml]\n----\n<iq from=\"licenceserver@coffeebean.local\" type=\"result\" id=\"aad9a\" to=\"bob@coffeebean.local/Psi+\">\n\t<command xmlns=\"http://jabber.org/protocol/commands\" status=\"completed\" node=\"retrieve-licence\"\n\t\tsessionid=\"b7aa7ffb-5cda-4c67-aeb4-04094764ec9e\">\n\t\t<x xmlns=\"jabber:x:data\" type=\"result\">\n\t\t\t<field type=\"text-multi\" label=\"Licence\" var=\"licence\">\n\t\t\t\t<value>max-costam=9</value>\n\t\t\t\t<value>comment=Licencja całkowicie domyślna</value>\n\t\t\t\t<value>licence-nr=1</value>\n\t\t\t\t<value>licence-id=de54488e-13d0-38a4-8614-1b624cc73ac0</value>\n\t\t\t\t<value>customer-name=Bob Bobowsky</value>\n\t\t\t\t<value>customer-jid=bob@coffeebean.local</value>\n\t\t\t\t<value>template-id=fb9971738214b50c5700673956ade0fa0b8169d0</value>\n\t\t\t\t<value>valid-since=2015-07-17</value>\n\t\t\t\t<value>valid-until=2015-10-17</value>\n\t\t\t\t<value>signature=2bca48ad20b63dd76be08b1a6…374dab308</value>\n\t\t\t</field>\n\t\t</x>\n\t</command>\n</iq>\n----\n\n[[licenseconfig]]\n== Configuring Tigase XMPP Server License Registration\nAs seen earlier, you will need to include your +customer-id+ into the init.properties file on your installation by adding the line:\n[source,properties]\n-----\n--customer-id=9s82stmw2tasc4h6q05n69azxs\n-----\nEverything should be automated from there.\n\n== Statistics Sent\nIf you are using Tigase without a customer ID, you will be given a warning that statistics will be sent to Tigase.  Below is a breakdown of what is sent to the server.\n\nNOTE: The text below has been better formatted for readability, but does not reflect the actual text being sent to Tigase.\n\n[source,output]\n-----\n<statistics version=\"1\">\n\t<domain>xmppserver</domain>\n\t<timestamp>2016-06-23T17:16:24.777-0700</timestamp>\n\t<vhosts>\n    <item>vhost1.xmppserver.com</item>\n  </vhosts>\n\t<uptime>308833</uptime>\n\t<heap>\n    <used>30924376</used>\n    <max>1426063360</max>\n  </heap>\n\t<cluster>\n    <nodes_count>1</nodes_count>\n  </cluster>\n\t<users>\n    <online>0</online>\n    <active>0</active>\n    <max_today>1</max_today>\n    <max_yesterday>0</max_yesterday>\n  </users>\n\t<additional_data>\n\t\t<components>\n\t\t\t<cmpInfo>\n\t\t\t\t<name>amp</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.AmpComponentClustered</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>bosh</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.BoshConnectionClustered</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>c2s</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.ClientConnectionClustered</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>cl-comp</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.ClusterConnectionManager</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>eventbus</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.disteventbus.component.EventBusComponent</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>http</name>\n\t\t\t\t<title>Tigase HTTP API component: Tigase HTTP API component</title>\n\t\t\t\t<version>1.2.0-SNAPSHOT-b135/27310f9b-7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.http.HttpMessageReceiver</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>monitor</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.monitor.MonitorComponent</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>muc</name>\n\t\t\t\t<title>Tigase ACS - MUC Component</title>\n\t\t\t\t<version>1.2.0-SNAPSHOT-b62/74afbb91-2.4.0-SNAPSHOT-b425/d2e26014</version>\n\t\t\t\t<class>tigase.muc.cluster.MUCComponentClustered</class>\n\t\t\t\t<cmpData>\n\t\t\t\t\t<MUCClusteringStrategy>class tigase.muc.cluster.ShardingStrategy</MUCClusteringStrategy>\n\t\t\t\t</cmpData>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>pubsub</name>\n\t\t\t\t<title>Tigase ACS - PubSub Component</title>\n\t\t\t\t<version>1.2.0-SNAPSHOT-b65/1c802a4c-3.2.0-SNAPSHOT-b524/892f867f</version>\n\t\t\t\t<class>tigase.pubsub.cluster.PubSubComponentClustered</class>\n\t\t\t\t<cmpData>\n\t\t\t\t\t<PubSubClusteringStrategy>class tigase.pubsub.cluster.PartitionedStrategy</PubSubClusteringStrategy>\n\t\t\t\t</cmpData>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>s2s</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.server.xmppserver.S2SConnectionManager</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>sess-man</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.SessionManagerClustered</class>\n\t\t\t\t<cmpData>\n\t\t\t\t\t<ClusteringStrategy>class tigase.server.cluster.strategy.OnlineUsersCachingStrategy</ClusteringStrategy>\n\t\t\t\t</cmpData>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>ws2s</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.WebSocketClientConnectionClustered</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>vhost-man</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.vhosts.VHostManager</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>stats</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.stats.StatisticsCollector</class>\n\t\t\t</cmpInfo>\n\n\t\t\t<cmpInfo>\n\t\t\t\t<name>cluster-contr</name>\n\t\t\t\t<title>Tigase XMPP Server</title>\n\t\t\t\t<version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>\n\t\t\t\t<class>tigase.cluster.ClusterController</class>\n\t\t\t</cmpInfo>\n\t\t</components>\n\n\t\t<unlicencedComponenents>\n\t\t\t<ComponentAdditionalInfo name=&quot;acs&quot;/>\n\t\t</unlicencedComponenents>\n\t</additional_data>\n</statistics>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_101_-_Using_Tigase_-_P_-_Advanced_Options.asciidoc",
    "content": "[[tigaseAdvancedOptions]]\n= Tigase Advanced Options\n:author: Daniel Wisnewski\n:date: 2016-03-28 14:55\n:version: v1.0 March 2016\n\n:toc:\n:numbered:\n:website: http://www.tigase.net\n\nThis section is designed to include a number of advanced configuration options available within Tigase, but may not have a relevant section yet to house them.\n\n== Enabling Support for storing offline messages without body content\n\nTigase now supports the full implementation or XEP-0334, See link:http://xmpp.org/extensions/xep-0334.html[XEP-0334] for protocol details.\n\nThis can be customized by setting a list of paths and xmlns to trigger and place storage of offline messages using the following settings in init.properties:\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=/message/received[urn:xmpp:receipts],/message/store-offline\n-----\n\nThis will require the enabling of AMP plugin, so be sure +--sm-plugins=+amp+ is enabled.\n\n[[emptyNicks]]\n== Enabling Empty Nicknames\n\nTigase can now support users with empty nicknames.  This can be enabled by adding the following code is in init.properties.\n------\nsess-man/plugins-conf/jabber\\:iq\\:roster/empty_name_enabled=true\n------\n\n[[accountRegLimit]]\n== Account Registration Limits\n\nIn order to protect Tigase servers from DOS attacks, a limit on number of account registrations per second has been implemented.  This may be configured by adding the following line in the init.properties file:\n-----\nsess-man/plugins-conf/jabber\\:iq\\:register/registrations-per-second=10\n-----\nThis setting allows for 10 registrations from a single IP per second.  If the limit is exceeded, a +NOT_ALLOWED+ error will be returned.\n\n[[silentIgnore]]\n== Enable Silent Ignore on Packets Delivered to Unavailable Resources\n\nYou can now have Tigase ignore packets delivered to unavailable resources to avoid having a packet bounce around and create unnecessary traffic.  You may set this globally, within standard message handling only, or within the AMP component using the following settings:\n\nGlobally:\n[source]\n-----\nsess-man/plugins-conf/silently-ignore-message=true\n-----\nMessage Processing Only:\n[source]\n-----\nsess-man/plugins-conf/message/silently-ignore-message=true\n-----\nAMP Component:\n[source]\n-----\nsess-man/plugins-conf/amp/silently-ignore-message=true\n-----\n\n[[errorCounting]]\n== Mechanism to count errors within Tigase\n\nA new processor within statistics has been added to count the number of errors that Tigase returns. This processor, named +error-counter+, will count all errors returned by Tigase, however by default the number is always zero if it is not enabled.  It can be found as an MBean object in JMX under +ErrorStatistics+ and contains values for packets with +ERROR+ and grouped by type.\nTo enable counting of these errors, you must ensure the processor is included in your --sm-plugins:\n[source,properties]\n-----\n--sm-plugins=error-counter\n-----\n\n=== Including stream errors\n\nStream +ERROR+ packets are not included in the above counter by default as they are processed separately.\nTo enable this to be added to the counter, the following line must be in your init.properties file.\n[source,properties]\n-----\nc2s/processors[s]=stream-error-counter\n-----\n\n[[streamResumptiontimeout]]\n=== Stream resumption default & max-timeout\n\n+SteamManagementIOProcessor+ now has a setting that can be used to change the maximum timeout time it will wait for reconnection if a client does not send a time to wait.  Two settings are now available:\n\n[source,properties]\n-----\nc2s/processors/urn\\:xmpp\\:sm\\:3/resumption-timeout[I]=90\n-----\nThe above setting in init.properties file will change the default timeout period to 90 seconds.\n\n[source,properties]\n-----\nc2s/processors/urn\\:xmpp\\:sm\\:3/max-resumption-timeout[I]=900\n-----\nThis setting will set the maximum time allowed for stream resumption to 900 seconds.  This can be handy if you expect a number of mobile phones to connect to your server and want to avoid duplicate messages being sent back and forth.\n\n[[autoSub]]\nYou may setup a server to automatically approve presence subscriptions or roster authorizations for all users.  Say you were hosting bots and wanted to automate the process.  This can be done with the following settings:\n[source,properties]\n-----\nsess-man/plugins-conf/jabber\\:iq\\:roster/auto-authorize=true\nsess-man/plugins-conf/presence/auto-authorize=true\n-----\nBoth of these settings are false by default, and you may use them together or separately.\nThe following behavior is followed when they are both activated:\n\n- Upon sending a subscription request - Both contacts will each others' subscription and be added to each others' roster.  Presence information will immediately be exchanged between both parties.\n- Upon sending presence with type either unsubscribe or unsubscribed follows the rules defined in RFC regarding processing of these stanzas (i.e. adjusting subscription type of user/contact), but without forwarding those stanzas to the receiving entity to avoid any notifications to the client. However, a roster push is generated to reflect changes to presence in user roster in a seamless manner.\n- Simply adding an item to the roster (i.e. with <iq/> stanza with correct semantics) will also cause an automatic subscription between the user and the contact in a matter explained above.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_102_-_Statistics_Descriptions.asciidoc",
    "content": "[[statsticsDescription]]\n= Statistics description\n:author: Daniel Wisnewski (daniel@tigase.org)\n:date: 2016-04-22 10:40\n:version: v1.0 April 2016\n\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nStatistics are divided between components and processors.  You may see the same statistics collected for multiple components which are defined in common components section.\nNote that statistics are defined by {$component}/statistic so if you wanted Max queue size on pubsub, you would look for +pubsub/Max queue size+.\nStatistics will not be provided by components that are not enabled.\n\n== *Statistics common to components*\n\nThese statistics may be found in multiple components and may be seen multiple times.\nFor example both s2s and c2s will have Bytes sent statistic, so each can be found the following way:\n[source,properties]\n-----\ns2s/Bytes received\nc2s/Bytes received\n-----\n\n=== add-script last {interval}\n\nThe number of times that +add-script+ adhoc command has been run within the last interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+add-script/Average processing time+: The average time in ms, returned as an integer, it takes for +add-script+ to execute.\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/adhoc-command/add-script last hour\n{compname}/adhoc-command/add-script last minute\n{compname}/adhoc-command/add-script last second\n{compname}/adhoc-command/add-script/Average processing time\n-----\n\n=== Average processing time on last 100 runs [ms]\n\nThe average processing time in milliseconds for all commands and scripts for this component over the last 100 times component is called.  This number will populate with less than 100 runs, and will continue averaging until 100 runs happens, at that point, it's the most recent 100 instances.\nThis statistic will reset every time the server shuts down or restarts.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Average processing time on last 100 runs [ms]\n-----\n\n=== Bytes received\n\nThe total number of bytes that the component has received during the current server instance. This statistic resets at server shutdown or restart.\n\n*Statistics Level*: FINE|FINEST\n\nc2s is FINE, all others are FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, proxy, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Bytes received\n-----\n\n=== Bytes sent\n\nThe total number of bytes that the component has sent during the current server instance. This statistic resets at server shutdown or restart.\n\n*Statistics Level*: FINE|FINEST\n\nc2s is FINE, all others are FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, proxy, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Bytes sent\n-----\n\n=== del-script last {interval}\n\nThe number of times that +del-script+ adhoc command has been run within the last interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+del-script/Average processing time+: The average time in ms, returned as an integer, it takes for +del-script+ to execute.\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/adhoc-command/del-script last hour\n{compname}/adhoc-command/del-script last minute\n{compname}/adhoc-command/del-script last second\n{compname}/adhoc-command/del-script/Average processing time\n-----\n\n=== Last {interval} packets\n\nThe number of packets that have been handled by this component in the last interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/last hour packets\n{compname}/last minute packets\n{compname}/last second packets\n-----\n\n=== list-commands last {interval}\n\nThe number of +list-commands+ requests sent to the component in the last interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+list-commands/Average processing time+: The average time in ms, returned as an integer, it takes for +list-commands+ to execute.\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/list-commands last hour\n{compname}/list-commands last minute\n{compname}/list-commands last second\n{compname}/list-commands/Average processing time\n-----\n\n=== {IN|OUT|Total} queue overflow\n\nThe number of times the in or out queue has overflown for this component.  That is there are more packets queues than the max queue size.\nA total statistic is also available that combines both results.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/IN queue overflow\n{compname}/OUT queue overflow\n{compname}/Total queue overflow\n-----\n\n=== {in|out} queue wait: {priority}\n\nThe number of packets with {priority} priority currently in the incoming or outgoing queue.\n\n*Available {priority}*: SYSTEM|CLUSTER|HIGH|NORMAL|LOW|PRESENCE|LOWEST\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/In queue wait: SYSTEM\n{compname}/In queue wait: CLUSTER\n{compname}/In queue wait: HIGH\n{compname}/In queue wait: NORMAL\n{compname}/In queue wait: LOW\n{compname}/In queue wait: PRESENCE\n{compname}/In queue wait: LOWEST\n{compname}/Out queue wait: SYSTEM\n{compname}/Out queue wait: CLUSTER\n{compname}/Out queue wait: HIGH\n{compname}/Out queue wait: NORMAL\n{compname}/Out queue wait: LOW\n{compname}/Out queue wait: PRESENCE\n{compname}/Out queue wait: LOWEST\n-----\n\n=== {IN|OUT}_QUEUE processed {type}\n\nThe number of stanzas of different types that have been processed VIA the In or Out Queue of this component.  This number will reset at the end of the server instance.\nEach component will have a list of the different types of stanzas it can process.\n\n*Available {type}*:\n[source,list]\n-----\nmessages\npresences\ncluster\nother\nIQ no XMLNS\nIQ http://jabber.org/protocol/disco#items\nIQ bind\nIQ jabber:iq:roster\nIQ session\nIQ vCard\nIQ command\nIQ jabber:iq:private\nIQ http://jabber.org/protocol/disco#info\ntotal IQ\n-----\n\nNOTE: Several statistics are only available from statistics component, shutdown thread will ONLY print the following: messages, presences, cluster, other, IQ no XLMNS, total IQ.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/IN_QUEUE processed messages\n{compname}/IN_QUEUE processed presences\n{compname}/IN_QUEUE processed cluster\n{compname}/IN_QUEUE processed other\n{compname}/IN_QUEUE processed IQ no XMLNS\n{compname}/IN_QUEUE processed IQ http://jabber.org/protocol/disco#items\n{compname}/IN_QUEUE processed IQ http://jabber.org/protocol/disco#info\n{compname}/IN_QUEUE processed IQ bind\n{compname}/IN_QUEUE processed IQ jabber:iq:roster\n{compname}/IN_QUEUE processed IQ jabber:iq:private\n{compname}/IN_QUEUE processed IQ session\n{compname}/IN_QUEUE processed IQ vCard\n{compname}/IN_QUEUE processed IQ command\n{compname}/IN_QUEUE processed total IQ\n{compname}/OUT_QUEUE processed messages\n{compname}/OUT_QUEUE processed presences\n{compname}/OUT_QUEUE processed cluster\n{compname}/OUT_QUEUE processed other\n{compname}/OUT_QUEUE processed IQ no XMLNS\n{compname}/OUT_QUEUE processed IQ http://jabber.org/protocol/disco#items\n{compname}/OUT_QUEUE processed IQ http://jabber.org/protocol/disco#info\n{compname}/OUT_QUEUE processed IQ bind\n{compname}/OUT_QUEUE processed IQ jabber:iq:roster\n{compname}/OUT_QUEUE processed IQ jabber:iq:private\n{compname}/OUT_QUEUE processed IQ session\n{compname}/OUT_QUEUE processed IQ vCard\n{compname}/OUT_QUEUE processed IQ command\n{compname}/OUT_QUEUE processed total IQ\n-----\n\n=== max queue size\n\nThe maximum number of items allowed in the packet queue for this component.\n\n*Statistics Level*:\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, muc, monitor, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/max queue size\n-----\n\n=== Open Connections\n\nThe number of open connections to the component.\n\n*Statistics Level*: INFO|FINEST\n\nc2s is INFO, all other components are FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, proxy, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Open connections\n-----\n\n=== Packets received\n\nThe total number of packets received by the component from external sources in the current instance.  This number resets at server shutdown or restart.\n\n*Statistics Level*: FINE\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Packets received\n-----\n\n=== Packets sent\n\nThe total number of packets sent by the component in the current instance.  This number resets at server shutdown or restart.\n\n*Statistics Level*: FINE\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Packets sent\n-----\n\n=== Processed packets thread: {in|out}_{#}\n\nHow many packets have been processed in and out by each processing thread.  Statistics will provide a list with each processing thread, and each thread having an in and an out counter.\nLet's say that we have 4 threads set for ws2s, a list will be seen like this:\n[source,list]\n-----\nws2s/Processed packets thread: in_0-ws2s\nws2s/Processed packets thread: in_2-ws2s\nws2s/Processed packets thread: in_3-ws2s\nws2s/Processed packets thread: in_4-ws2s\nws2s/Processed packets thread: out_0-ws2s\nws2s/Processed packets thread: out_1-ws2s\nws2s/Processed packets thread: out_2-ws2s\nws2s/Processed packets thread: out_3-ws2s\n-----\nNote that the processor counter starts with 0 and will count for as many threads as the component has as defined in xref:processingthreadsstat[{compname}/Processing threads].\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, pubsub, proxy, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Processed packets thread: in_0-{compname}\n{compname}/Processed packets thread: out_0-{compname}\n{compname}/Processed packets thread: in_1-{compname}\n{compname}/Processed packets thread: out_1-{compname}\n{compname}/Processed packets thread: in_2-{compname}\n{compname}/Processed packets thread: out_2-{compname}\n{compname}/Processed packets thread: in_3-{compname}\n{compname}/Processed packets thread: out_3-{compname}\n{compname}/Processed packets thread: in_4-{compname}\n{compname}/Processed packets thread: out_4-{compname}\n{compname}/Processed packets thread: in_5-{compname}\n{compname}/Processed packets thread: out_5-{compname}\n...\n-----\n\n[[processingthreadsstat]]\n=== processing threads\n\nThe number of threads provided for the particular component.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/processing threads\n-----\n\n=== Socket overflow\n\nThe number of times that this component has experienced socket overflow and had to drop packets.  This does not include the number of dropped packets.\n\n*Statistics Level*: FINEST\n\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, proxy, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Socket overflow\n-----\n\n=== Total {in|out} queues wait\n\nThe number of packets in the inbound or outbound queue that are currently waiting to be sent.  This includes packets of all types. This is an instant statistics, in that the number in queue is only as many in the queue the moment statistics are gathered.\n\n*Related Statistics*:\n+{compname}/Total queue wait+: A combined total of +Total in queue wait+ and +Total out queue wait+ statistics for this component.\n+Total queues wait+: A combined total of all component queue wait statistics.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, muc, monitor, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Total in queues wait\n{compname}/Total out queues wait\n{compname}/Total queues wait\nTotal queues wait\n-----\n\n=== Total queues overflow\n\nThe number of times the component packet wait queue has overflown and had to drop packets.  This statistic does not keep track of the number of dropped packets.\n\n*Related Statistics*:\n+total/Total queues overflow+: The combined total of all queue overflow statistics for all components.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\namp, bosh, c2s, cl-comp, eventbus, message-archive, message-router, monitor, muc, proxy, pubsub, rest, s2s, sess-man, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Total queues overflow\ntotal/Total queues overflow\n-----\n\n=== Waiting to send\n\nThe number of packets in the component's queue that are waiting to be sent.  This number will usually be 0 however it will grow if a large number of packets are jamming up your system, or your queue sizes are set too low.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, proxy, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Waiting to send\n-----\n\n=== Watchdog runs\n\nThe number of times watchdog has been run on this component to check for stale connections.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, c2s, cl-comp, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Watchdog runs\n-----\n\n=== Watchdog stopped\n\nThe number of times watchdog identified and closed a connection it has found to be stale according to the settings in init.properties or by the defaults defined xref:watchdog[in this section].\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, cl-comp, c2s, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Watchdog stopped\n-----\n\n=== Watchdog tests\n\nThe number of times watchdog has found a potential stale connection and has conducted a test to determine whether or not to close the connection.  This is per component in the current server instance.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*Available from the following components*:\n[source,list]\n-----\nbosh, cl-comp, c2s, s2s, ws2s\n-----\n\n*List of possible statistics*:\n[source,list]\n-----\n{compname}/Watchdog tests\n-----\n\n== *AMP*\n\nNo exclusive amp specific statistics\n\n== *bosh*\n\n=== Bosh sessions\n\nThe number of currently open and running BOSH sessions to the server.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nbosh/Bosh sessions\n-----\n\n=== pre-bind-session last {interval}\n\nThe number of times the pre-bind-session command has been executed within the last specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+bosh/pre-bind-session/Average processing time+: The average time in ms, returned as an integer, it takes for +pre-bind-session+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nbosh/adhoc-command/pre-bind-session last hour\nbosh/adhoc-command/pre-bind-session last minute\nbosh/adhoc-command/pre-bind-session last second\nbosh/adhoc-command/pre-bind-session/Average processing time\n-----\n\n== *c2s*\n\nNo exclusive c2s specific statistics\n\n== *cl-comp*\n\n=== adhoc-command/cluster-nodes-list last {interval}\n\nThe number of times per interval that the cluster-nodes-list command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+cl-comp/Adhoc-command/cluster-nodes-list/Average processing time+: The average time in ms, returned as an integer, it takes for +cluster-nodes-list+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/adhoc-command/cluster-nodes-list last hour\ncl-comp/adhoc-command/cluster-nodes-list last minute\ncl-comp/adhoc-command/cluster-nodes-list last second\ncl-comp/adhoc-command/cluster-nodes-list/Average processing time\n-----\n\n=== adhoc-command/force-stop-service last {interval}\n\nThe number of times per interval that the force-stop-service command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+cl-comp/Adhoc-command/force-stop-service/Average processing time+: The average time in ms, returned as an integer, it takes for +force-stop-service+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/adhoc-command/force-stop-service last hour\ncl-comp/adhoc-command/force-stop-service last minute\ncl-comp/adhoc-command/force-stop-service last second\ncl-comp/adhoc-command/force-stop-service/Average processing time\n-----\n\n=== adhoc-command/service-keys last {interval}\n\nThe number of times per interval that the service-keys command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+cl-comp/Adhoc-command/service-keys/Average processing time+: The average time in ms, returned as an integer, it takes for +service-keys+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/adhoc-command/service-keys last hour\ncl-comp/adhoc-command/service-keys last minute\ncl-comp/adhoc-command/service-keys last second\ncl-comp/adhoc-command/service-keys/Average processing time\n-----\n\n=== adhoc-command/sim-serv-stopped {interval}\n\nThe number of times per interval that the sim-serv-stopped command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+cl-comp/Adhoc-command/sim-serv-stopped/Average processing time+: The average time in ms, returned as an integer, it takes for +sim-serv-stopped+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/adhoc-command/sim-serv-stopped last hour\ncl-comp/adhoc-command/sim-serv-stopped last minute\ncl-comp/adhoc-command/sim-serv-stopped last second\ncl-comp/adhoc-command/sim-serv-stopped/Average processing time\n-----\n\n=== Average compression ratio\n\nThe average compression ratio of data sent to other clusters during the session.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Average compression ratio\n-----\n\n=== Average decompression ratio\n\nThe average compression ratio of data received from other clusters during the session.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Average decompression ratio\n-----\n\n=== Known cluster nodes\n\nThe number of cluster nodes currently connected to the server.\n\n*Statistics Level*: INFO\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Known cluster nodes\n-----\n\n=== Last {interval} disconnects\n\nThe number of cluster disconnections within the specified interval.\n\n*Available {interval}*: day|hour\n\n*Statistics Level*: FINE\n\n*Result Format*: Comma separated Array.  For day, each array is the number of disconnections each hour, most recent first. For hour each array is the number of disconnections each minute, most recent first.\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Last day disconnects\ncl-comp/Last hour disconnects\n-----\n\n=== Service connected time-outs\n\nThe number of time-outs during connection initialization of cluster nodes.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Service connected time-outs\n-----\n\n=== Total disconnects\n\nThe number of clusters that have disconnected during the current session.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ncl-comp/Total disconnects\n-----\n\n== *eventbus*\n\nNo exclusive eventbus specific statistics\n\n== *message-archive*\n\n=== Removal time of expired messages (avg)\n\nThe average amount of time in milliseconds it takes to remove expired messages from the repository. This includes manual and automatic removal of messages.\n\n*Statistics Level*: FINE\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-archive/Removal time of expired messages (avg)\n-----\n\n== *message-router*\n\n=== CPUs no\n\nThe number of CPUs available on the host machine.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/CPUs no\n-----\n\n=== CPU usage\n\n% of available CPU power used by Tigase Server at the moment statistics are taken.\nTwo formats are available for CPU usage: A float integer which expresses a long decimal available from +CPU Usage [%]+, and a string which provides a rounded number with a % sign from +CPU usage+.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float|String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/CPU usage [%]\nmessage-router/CPU usage\n-----\n\n=== Free Heap\n\nThe amount of heap memory that is available for use, expressed in KB\n\n*Statistics Level*: FINE\n\n*Result Format* String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Free Heap\n-----\n\n=== Free NonHeap\n\nThe amount of non-heap memory that is available for use, expressed in KB\n\n*Statistics Level*: FINE\n\n*Result Format* String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Free NonHeap\n-----\n\n=== HEAP usage [%]\n\nTotal percent of HEAP memory in use by Tigase.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/HEAP usage [%]\n-----\n\n=== Local hostname\n\nThe local hostname of the physical server.\n\n*Statistics Level*: INFO\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Local hostname\n-----\n\n=== Load average\n\nThe average system load for the previous minute.  The way in which the load average is calculated is operating system specific but is typically a damped time-dependent average.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Load average\n-----\n\n=== Max Heap mem\n\nMaximum amount of heap memory available as defined by JAVA_OPTIONS in tigase.conf, in Kb.\n\n*Statistics Level*: INFO\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Max Heap mem\n-----\n\n=== Max NonHeap mem\n\nMaximum amount of non-heap memory available as defined by JAVA_OPTIONS in tigase.conf, in Kb.\n\n*Statistics Level*: FINE\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Max NonHeap mem\n-----\n\n=== NONHEAP usage [%]\n\nTotal amount of NONHEAP memory in use expressed as a percentage.\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-archive/NONHEAP usage [%]\n-----\n\n=== Threads count\n\nThe total number of processing threads available across all components.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Threads count\n-----\n\n=== Uptime\n\nThe total amount of time the server has been online for this session.\n\n*Statistics Level*: INFO\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Uptime\n-----\n\n=== Used Heap\n\nThe amount of heap memory in use in KB.\n\n*Statistics Level*: INFO\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Used Heap\n-----\n\n=== Used NonHeap\n\nThe amount of non-heap memory in use shown in KB.\n\n*Statistics Level*: FINE\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\nmessage-router/Used NonHeap\n-----\n\n== *monitor*\n\n=== adhoc-command/load-errors last {interval}\n\nThe number of times per interval that the load-errors command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+monitor/Adhoc-command/load-errors/Average processing time+: The average time in ms, returned as an integer, it takes for +load-errors+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nmonitor/adhoc-command/load-errors last hour\nmonitor/adhoc-command/load-errors last minute\nmonitor/adhoc-command/load-errors last second\nmonitor/adhoc-command/load-errors/Average processing time\n-----\n\n== *muc*\n\n=== adhoc-command/remove-room last {interval}\n\nThe number of times per interval that the remove-room command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+muc/Adhoc-command/remove-room/Average processing time+: The average time in ms, returned as an integer, it takes for +remove-room+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nmonitor/adhoc-command/remove-room last hour\nmonitor/adhoc-command/remove-room last minute\nmonitor/adhoc-command/remove-room last second\nmonitor/adhoc-command/remove-room/Average processing time\n-----\n\n=== adhoc-command/default-room-config last {interval}\n\nThe number of times per interval that the default-room-command command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+muc/Adhoc-command/default-room-config/Average processing time+: The average time in ms, returned as an integer, it takes for +default-room-config+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nmuc/adhoc-command/default-room-config last hour\nmuc/adhoc-command/default-room-config last minute\nmuc/adhoc-command/default-room-config last second\nmuc/adhoc-command/default-room-config/Average processing time\n-----\n\n== *proxy*\n\n=== Average transfer size in KB\n\nAverage size of packets sent through the proxy component during the current session.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nproxy/Average transfer size in KB\n-----\n\n=== KBytes transferred\n\nTotal number of Kb transferred through the proxy component.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nproxy/KBytes transferred\n-----\n\n=== Open streams\n\nNumber of currently open proxy streams.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nproxy/Open streams\n-----\n\n=== Transfers completed\n\nNumber of specific transfers completed through proxy component.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nproxy/Transfers completed\n-----\n\n== *pubsub*\n\n=== Added new nodes\n\nThe total number of new nodes that has been added in the current server instance.  This statistic is reset when the server resets.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Added new nodes\n-----\n\n=== adhoc-command/delete-item last {interval}\n\nThe number of times per interval that the delete-item command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/delete-item/Average processing time+: The average time in ms, returned as an integer, it takes for +delete-item+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/delete-item last hour\npubsub/adhoc-command/delete-item last minute\npubsub/adhoc-command/delete-item last second\npubsub/adhoc-command/delete-item/Average processing time\n-----\n\n=== adhoc-command/delete-node last {interval}\n\nThe number of times per interval that the delete-node command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/delete-node/Average processing time+: The average time in ms, returned as an integer, it takes for +delete-item+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/delete-node last hour\npubsub/adhoc-command/delete-node last minute\npubsub/adhoc-command/delete-node last second\npubsub/adhoc-command/delete-node/Average processing time\n-----\n\n=== adhoc-command/list-items last {interval}\n\nThe number of times per interval that the list-items command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/list-items/Average processing time+: The average time in ms, returned as an integer, it takes for +list-items+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/list-items last hour\npubsub/adhoc-command/list-items last minute\npubsub/adhoc-command/list-items last second\npubsub/adhoc-command/list-items/Average processing time\n-----\n\n=== adhoc-command/list-nodes last {interval}\n\nThe number of times per interval that the list-nodes command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/list-nodes/Average processing time+: The average time in ms, returned as an integer, it takes for +list-nodes+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/list-nodes last hour\npubsub/adhoc-command/list-nodes last minute\npubsub/adhoc-command/list-nodes last second\npubsub/adhoc-command/list-nodes/Average processing time\n-----\n\n=== adhoc-command/publish-item last {interval}\n\nThe number of times per interval that the publish-item command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/publish-item/Average processing time+: The average time in ms, returned as an integer, it takes for +publish-item+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/publish-item last hour\npubsub/adhoc-command/publish-item last minute\npubsub/adhoc-command/publish-item last second\npubsub/adhoc-command/publish-item/Average processing time\n-----\n\n=== adhoc-command/retrieve-item last {interval}\n\nThe number of times per interval that the retrieve-item command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/adhoc-command/retrieve-item/Average processing time+: The average time in ms, returned as an integer, it takes for +retrieve-item+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/adhoc-command/retrieve-item last hour\npubsub/adhoc-command/retrieve-item last minute\npubsub/adhoc-command/retrieve-item last second\npubsub/adhoc-command/retrieve-item/Average processing time\n-----\n\n=== AdHocConfigCommandModule last {interval}\n\nThe number of times per interval that the AdHocConfigCommandModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/AdHocConfigCommandModule/Average processing time+: The average time in ms, returned as an integer, it takes for +AdHocConfigCommandModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/AdHocConfigCommandModule last hour\npubsub/AdHocConfigCommandModule last minute\npubsub/AdHocConfigCommandModule last second\npubsub/AdHocConfigCommandModule/Average processing time\n-----\n\n=== Affiliations count (in cache)\n\nThe total number of pubsub affiliations that are resident in cache memory.  Affiliations include JIDs that are one of the following; Owner, Publisher, Publish-Only, Member, None, Outcast.  This may not reflect total pubsub affiliations in repository.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Affiliations count (in cache)\n-----\n\n\n=== Average DB write time [ms]\n\nThe average time of all DB writes from PubSub component.  Average is calculated using two other statistics: (Total writing time / Database writes)\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Average DB write time [ms]\n-----\n\n=== cache/hits last {interval}\n\nThe number of times the cache has achieved a hit within the last interval.  A hit is when a request for information is matched to data that is inside the cache memory.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/cache/hits last hour\npubsub/cache/hits last minute\npubsub/cache/hits last second\n-----\n\n=== cache/hit-miss ratio per {interval}\n\nThe ratio of cache hits to cache misses over the specified period.  A cache hit is when a request for information from the cache is matched with information in the cache.  A miss is when that information request cannot find a match in cache.  A miss only indicates that that information was not found in the cache, not that it is not in the repository.\n\n*Available {interval}*: hour|minute\n\n*Statistics Level*: FINE\n\n*Result Format*: Float\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/cache/hit-miss ratio per hour\npubsub/cache/hit-miss ratio per minute\n-----\n\n=== cache/requests last {interval}\n\nThe number of memory cache requests made within the last interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/cache/Requests last hour\npubsub/cache/Requests last minute\npubsub/cache/Requests last second\n-----\n\n=== Cached nodes\n\nThe number of nodes that is currently in memory cache.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Cached nodes\n-----\n\n=== CapsModule\n\nThe number of times per interval that the CapsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/CapsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +CapsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/CapsModule last hour\npubsub/CapsModule last minute\npubsub/CapsModule last second\npubsub/CapsModule/Average processing time\n-----\n\n=== db/GetNodeItems requests last {interval}\n\nThe number of times +GetNodeItems+ command has been run within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/db/GetNodeItems/Average processing time+: The average time in ms, returned as an integer, it takes for +GetNodeItems+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/db/GetNodeItems last hour\npubsub/db/GetNodeItems last minute\npubsub/db/GetNodeItems last second\npubsub/db/GetNodeItems/Average processing time\n-----\n\n=== DefaultConfigModule last {interval}\n\nThe number of times per interval that the DefaultConfigModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/DefaultConfigModule/Average processing time+: The average time in ms, returned as an integer, it takes for +DefaultConfigModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/DefaultConfigModule last hour\npubsub/DefaultConfigModule last minute\npubsub/DefaultConfigModule last second\npubsub/DefaultConfigModule/Average processing time\n-----\n\n=== DiscoverInfoModule last {interval}\n\nThe number of times per interval that the DiscoverInfoModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/DiscoverInfoModule/Average processing time+: The average time in ms, returned as an integer, it takes for +DiscoverInfoModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/DiscoverInfoModule last hour\npubsub/DiscoverInfoModule last minute\npubsub/DiscoverInfoModule last second\npubsub/DiscoverInfoModule/Average processing time\n-----\n\n=== DiscoverItemsModule last {interval}\n\nThe number of times per interval that the DiscoverItemsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/DiscoverItemsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +DiscoverItemsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/DiscoverItemsModule last hour\npubsub/DiscoverItemsModule last minute\npubsub/DiscoverItemsModule last second\npubsub/DiscoverItemsModule/Average processing time\n-----\n\n=== JabberVersionModule last {interval}\n\nThe number of times per interval that the JabberVersionModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/JabberVersionModule/Average processing time+: The average time in ms, returned as an integer, it takes for +JabberVersionModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/JabberVersionModule last hour\npubsub/JabberVersionModule last minute\npubsub/JabberVersionModule last second\npubsub/JabberVersionModule/Average processing time\n-----\n\n=== ManageAffiiationsModule last {interval}\n\nThe number of times per interval that the ManageAffiliationsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/ManageAffiliationsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +ManageAffiliationsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/ManageAffiliationsModule last hour\npubsub/ManageAffiliationsModule last minute\npubsub/ManageAffiliationsModule last second\npubsub/ManageAffiliationsModule/Average processing time\n-----\n\n=== ManageSubscriptionModule last {interval}\n\nThe number of times per interval that the ManageSubscriptionModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/ManageSubscriptionModule/Average processing time+: The average time in ms, returned as an integer, it takes for +ManageSubscriptionModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/ManageSubscriptionModule last hour\npubsub/ManageSubscriptionModule last minute\npubsub/ManageSubscriptionModule last second\npubsub/ManageSubscriptionModule/Average processing time\n-----\n\n=== NodeConfigModule last {interval}\n\nThe number of times per interval that the NodeConfigModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/NodeConfigModule/Average processing time+: The average time in ms, returned as an integer, it takes for +NodeConfigModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/NodeConfigModule last hour\npubsub/NodeConfigModule last minute\npubsub/NodeConfigModule last second\npubsub/NodeConfigModule/Average processing time\n-----\n\n=== NodeCreateModule last {interval}\n\nThe number of times per interval that the NodeCreateModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/NodeCreateModule/Average processing time+: The average time in ms, returned as an integer, it takes for +NodeCreateModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/NodeCreateModule last hour\npubsub/NodeCreateModule last minute\npubsub/NodeCreateModule last second\npubsub/NodeCreateModule/Average processing time\n-----\n\n=== NodeDeleteModule last {interval}\n\nThe number of times per interval that the NodeDeleteModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/NodeDeleteModule/Average processing time+: The average time in ms, returned as an integer, it takes for +NodeDeleteModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/NodeDeleteModule last hour\npubsub/NodeDeleteModule last minute\npubsub/NodeDeleteModule last second\npubsub/NodeDeleteModule/Average processing time\n-----\n\n=== PresenceCollectorModule last {interval}\n\nThe number of times per interval that the PresenceCollectorModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/PresenceCollectorModule/Average processing time+: The average time in ms, returned as an integer, it takes for +PresenceCollectorModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/PresenceCollectorModule last hour\npubsub/PresenceCollectorModule last minute\npubsub/PresenceCollectorModule last second\npubsub/PresenceCollectorModule/Average processing time\n-----\n\n=== PendingSubscriptionModule last {interval}\n\nThe number of times per interval that the PendingSubscriptionModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/PendingSubscriptionModule/Average processing time+: The average time in ms, returned as an integer, it takes for +PendingSubscriptionModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/PendingSubscriptionModule last hour\npubsub/PendingSubscriptionModule last minute\npubsub/PendingSubscriptionModule last second\npubsub/PendingSubscriptionModule/Average processing time\n-----\n\n=== PresenceNotifierModule last {interval}\n\nThe number of times per interval that the PresenceNotifierModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/PresenceNotifierModule/Average processing time+: The average time in ms, returned as an integer, it takes for +PresenceNotifierModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/PresenceNotifierModule last hour\npubsub/PresenceNotifierModule last minute\npubsub/PresenceNotifierModule last second\npubsub/PresenceNotifierModule/Average processing time\n-----\n\n=== PublishItemModule last {interval}\n\nThe number of times per interval that the PublishItemModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/PublishItemModule/Average processing time+: The average time in ms, returned as an integer, it takes for +PublishItemModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/PublishItemModule last hour\npubsub/PublishItemModule last minute\npubsub/PublishItemModule last second\npubsub/PublishItemModule/Average processing time\n-----\n\n=== PurgeItemsModule last {interval}\n\nThe number of times per interval that the PurgeItemsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/PurgeItemsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +PurgeItemsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/PurgeItemsModule last hour\npubsub/PurgeItemsModule last minute\npubsub/PurgeItemsModule last second\npubsub/PurgeItemsModule/Average processing time\n-----\n\n=== Repository writes\n\nNumber of individual writes to Repository from the pubsub component since startup.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n[source,list]\n-----\npubsub/Repository writes\n-----\n\n=== RetractItemModule last {interval}\n\nThe number of times per interval that the RetractItemModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/RetractItemModule/Average processing time+: The average time in ms, returned as an integer, it takes for +RetractItemModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/RetractItemModule last hour\npubsub/RetractItemModule last minute\npubsub/RetractItemModule last second\npubsub/RetractItemModule/Average processing time\n-----\n\n=== RetrieveAffiliationsModule last {interval}\n\nThe number of times per interval that the RetrieveAffiliationsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/RetrieveAffiliationsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +RetrieveAffiliationsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/RetrieveAffiliationsModule last hour\npubsub/RetrieveAffiliationsModule last minute\npubsub/RetrieveAffiliationsModule last second\npubsub/RetrieveAffiliationsModule/Average processing time\n-----\n\n=== RetrieveItemsModule last {interval}\n\nThe number of times per interval that the RetrieveItemsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/RetrieveItemsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +RetrieveItemsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/RetrieveItemsModule last hour\npubsub/RetrieveItemsModule last minute\npubsub/RetrieveItemsModule last second\npubsub/RetrieveItemsModule/Average processing time\n-----\n\n=== RetrieveSubscriptionsModule last {interval}\n\nThe number of times per interval that the RetrieveSubscriptionsModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/RetrieveSubscriptionsModule/Average processing time+: The average time in ms, returned as an integer, it takes for +RetrieveSubscriptionsModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/RetrieveSubscriptionsModule last hour\npubsub/RetrieveSubscriptionsModule last minute\npubsub/RetrieveSubscriptionsModule last second\npubsub/RetrieveSubscriptionsModule/Average processing time\n-----\n\n=== SubscribeNodeModule last {interval}\n\nThe number of times per interval that the SubscribeNodeModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/SubscribeNodeModule/Average processing time+: The average time in ms, returned as an integer, it takes for +SubscribeNodeModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/SubscribeNodeModule last hour\npubsub/SubscribeNodeModule last minute\npubsub/SubscribeNodeModule last second\npubsub/SubscribeNodeModule/Average processing time\n-----\n\n=== Subscription count (in cache)\n\nThe total number of pubsub subscriptions that are resident in cache memory.  This may not reflect total pubsub subscriptions in repository.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Subscription count (in cache)\n-----\n\n=== Total writing time\n\nThe cumulative total of time pubsub component has written to the database expressed in milliseconds.\n\n*Statistics Level*: FINEST\n\n*Result Format*: String (###ms)\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Total writing time\n-----\n\n=== UnsubscribeNodeModule last {interval}\n\nThe number of times per interval that the UnsubscribeNodeModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/UnsubscribeNodeModule/Average processing time+: The average time in ms, returned as an integer, it takes for +UnsubscribeNodeModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/UnsubscribeNodeModule last hour\npubsub/UnsubscribeNodeModule last minute\npubsub/UnsubscribeNodeModule last second\npubsub/UnsubscribeNodeModule/Average processing time\n-----\n\n=== Update subscription calls\n\nNumber of times Subscriptions have been updated (this includes new, deleted, and edited).\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/Update subscriptions calls\n-----\n\n=== XmppPingModule last {interval}\n\nThe number of times per interval that the XmppPingModule command has been executed.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+pubsub/XmppPingModule/Average processing time+: The average time in ms, returned as an integer, it takes for +XmppPingModule+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\npubsub/XmppPingModule last hour\npubsub/XmppPingModule last minute\npubsub/XmppPingModule last second\npubsub/XmppPingModule/Average processing time\n-----\n\n[[repo-factoryStatistics]]\n== *repo-factory*\n\n=== repo-factory/Number of data repositories\n\nThe number of data repositories setup for this XMPP server.\n\n*Statistics Level*: FINE\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nrepo-factory/Number of data repositories\n-----\n\n=== repo-factory/repository {jdbclocation} connections count\n\nThe number of connections made to this database.\n\n*Statistics Level*: FINE\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nrepo-factory/repository {jdbclocation} connections count\n-----\n\n=== repo-factory/repository {jdbclocation} reconnections\n\nThe number of reconnections made to this database.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nrepo-factory/repository {jdbclocation} reconnections\n-----\n\n=== repo-factory/repository {jdbclocation} failed reconnections\n\nThe number of reconnections that have failed to connect to this database.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nrepo-factory/repository {jdbclocation} failed reconnections\n-----\n\n== *rest*\n\nNo exclusive rest specific statistics\n\n== *s2s*\n\n=== adhoc-command/get-cid-connection last {interval}\n\nThe number of times get-cid-connection command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+s2s/adhoc-command/get-cid-connection/Average processing time+: The average time in ms, returned as an integer, it takes for +get-cid-connection+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/adhoc-command/get-cid-connection last hour\ns2s/adhoc-command/get-cid-connection last minute\ns2s/adhoc-command/get-cid-connection last second\ns2s/adhoc-command/get-cid-connection/Average processing time\n-----\n\n=== adhoc-command/s2s-bad-state-conns last {interval}\n\nThe number of times s2s-bad-state-conns command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/s2s-bad-state-conns/Average processing time+: The average time in ms, returned as an integer, it takes for +s2s-bad-state-conns+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/adhoc-command/s2s-bad-state-conns last hour\ns2s/adhoc-command/s2s-bad-state-conns last minute\ns2s/adhoc-command/s2s-bad-state-conns last second\ns2s/adhoc-command/s2s-bad-state-conns/Average processing time\n-----\n\n=== adhoc-command/reset-bad-state-conns last {interval}\n\nThe number of times reset-bad-state-conns command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/reset-bad-state-conns/Average processing time+: The average time in ms, returned as an integer, it takes for +reset-bad-state-conns+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/adhoc-command/reset-bad-state-conns last hour\ns2s/adhoc-command/reset-bad-state-conns last minute\ns2s/adhoc-command/reset-bad-state-conns last second\ns2s/adhoc-command/reset-bad-state-conns/Average processing time\n-----\n\n=== CIDs number\n\nConnectionID for the server.  This may include multiple CIDs if server is running multiple vhosts.\n\n*Statistics Level*: FINEST\n\n*Result Format*: String\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/CIDs number\n-----\n\n=== Total DB keys\n\nTotal number of database keys.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total DB keys\n-----\n\n=== Total {incoming|outgoing}\n\nThe total number of server-to-server connections, outgoing is local server connecting to other servers, and incoming is connections from other servers.  The results may or may not be the same.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total incoming\ns2s/Total outgoing\n-----\n\n=== Total {incoming|outgoing} TLS\n\nThe total number of server-to-server connections using TLS, outgoing is local server connecting to other servers, and incoming is connections from other servers.  The results may or may not be the same.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total incoming TLS\ns2s/Total outgoing TLS\n-----\n\n=== Total outgoing handshaking\n\nTotal number of outgoing connections that are currently handshaking to other servers.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total outgoing handshaking\n-----\n\n=== Total control waiting\n\nTotal number of connections that were manually told to wait.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total control waiting\n-----\n\n=== Total waiting\n\nTotal number of connections that are currently waiting for response from other server.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\ns2s/Total waiting\n-----\n\n== *sess-man*\n\n=== Active user connections\n\nNumber of user connections that are considered active.  An active user is a user that has sent stanzas to the server or through the server within the last 5 minutes.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*list of possible statistics*:\n[source,list]\n-----\nsess-man/Active user connections\n-----\n\n=== adhoc-command/connection-time last {interval}\n\nThe number of times connection-time command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/connection-time/Average processing time+: The average time in ms, returned as an integer, it takes for +connection-time+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/connection-time last hour\nsess-man/adhoc-command/connection-time last minute\nsess-man/adhoc-command/connection-time last second\nsess-man/adhoc-command/connection-time/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#add-user last {interval}\n\nThe number of times admin#add-user command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#add-user/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#add-user+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#add-user-tracker last {interval}\n\nThe number of times admin#add-user-tracker command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#add-user-tracker/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#add-user-tracker+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user-tracker last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user-tracker last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user-tracker last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#add-user-tracker/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#announce last {interval}\n\nThe number of times admin#announce command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#announce/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#announce+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#announce last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#announce last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#announce last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#announce/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#change-user-password last {interval}\n\nThe number of times admin#change-user-password command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#change-user-password/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#change-user-password+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#change-user-password last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#change-user-password last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#change-user-password last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#change-user-password/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#delete-user last {interval}\n\nThe number of times admin#delete-user command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#delete-user/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#delete-user+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#delete-user last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#delete-user last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#delete-user last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#delete-user/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#end-user-session last {interval}\n\nThe number of times admin#end-user-session command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#end-user-session/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#end-user-session+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#end-user-session last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#end-user-session last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#end-user-session last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#end-user-session/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-active-users last {interval}\n\nThe number of times admin#get-active-users command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-active-users/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-active-users+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-users last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-users last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-users last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-users/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-active-user-num last {interval}\n\nThe number of times admin#get-active-user-num command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-active-user-num/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-active-user-num+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-user-num last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-user-num last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-user-num last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-active-user-num/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-idle-users last {interval}\n\nThe number of times admin#get-idle-users command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-idle-users/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-idle-users+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num last {interval}\n\nThe number of times admin#get-idle-users-num command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-idle-users-num+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-idle-users-num/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-online-users-list last {interval}\n\nThe number of times admin#get-online-users-list command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-online-users-list/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-online-users-list+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-online-users-list last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-online-users-list last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-online-users-list last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-online-users-list/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-top-active-users last {interval}\n\nThe number of times admin#get-top-active-users command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-top-active-users/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-top-active-users+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-top-active-users last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-top-active-users last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-top-active-users last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-top-active-users/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list last {interval}\n\nThe number of times admin#get-registered-users-list command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-registered-users-list+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-registered-users-list/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#get-user-roster last {interval}\n\nThe number of times admin#get-user-roster command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#get-user-roster/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#get-user-roster+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-user-roster last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-user-roster last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-user-roster last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#get-user-roster/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#remove-user last {interval}\n\nThe number of times admin#remove-user command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#remove-user/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#remove-user+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#remove-user last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#remove-user last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#remove-user last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#remove-user/Average processing time\n-----\n\n=== adhoc-command/http://jabber.org/protocol/admin#user-stats last {interval}\n\nThe number of times admin#user-stats command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/http://jabber.org/protocol/admin#user-stats/Average processing time+: The average time in ms, returned as an integer, it takes for +admin#user-stats+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/http://jabber.org/protocol/admin#user-stats last hour\nsess-man/adhoc-command/http://jabber.org/protocol/admin#user-stats last minute\nsess-man/adhoc-command/http://jabber.org/protocol/admin#user-stats last second\nsess-man/adhoc-command/http://jabber.org/protocol/admin#user-stats/Average processing time\n-----\n\n=== adhoc-command/get-user-info last {interval}\n\nThe number of times get-user-info command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/get-user-info/Average processing time+: The average time in ms, returned as an integer, it takes for +get-user-info+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/get-user-info last hour\nsess-man/adhoc-command/get-user-info last minute\nsess-man/adhoc-command/get-user-info last second\nsess-man/adhoc-command/get-user-info/Average processing time\n-----\n\n=== adhoc-command/modify-user last {interval}\n\nThe number of times modify-user command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/modify-user/Average processing time+: The average time in ms, returned as an integer, it takes for +modify-user+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/modify-user last hour\nsess-man/adhoc-command/modify-user last minute\nsess-man/adhoc-command/modify-user last second\nsess-man/adhoc-command/modify-user/Average processing time\n-----\n\n=== adhoc-command/oauth-credentials last {interval}\n\nThe number of times oauth-credentials command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/oauth-credentials/Average processing time+: The average time in ms, returned as an integer, it takes for +oauth-credentials+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/oauth-credentials last hour\nsess-man/adhoc-command/oauth-credentials last minute\nsess-man/adhoc-command/oauth-credentials last second\nsess-man/adhoc-command/oauth-credentials/Average processing time\n-----\n\n=== adhoc-command/roster-fixer last {interval}\n\nThe number of times roster-fixer command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/roster-fixer/Average processing time+: The average time in ms, returned as an integer, it takes for +roster-fixer+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/roster-fixer last hour\nsess-man/adhoc-command/roster-fixer last minute\nsess-man/adhoc-command/roster-fixer last second\nsess-man/adhoc-command/roster-fixer/Average processing time\n-----\n\n=== adhoc-command/roster-fixer-cluster last {interval}\n\nThe number of times roster-fixer-cluster command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/roster-fixer-cluster/Average processing time+: The average time in ms, returned as an integer, it takes for +roster-fixer-cluster+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/roster-fixer-cluster last hour\nsess-man/adhoc-command/roster-fixer-cluster last minute\nsess-man/adhoc-command/roster-fixer-cluster last second\nsess-man/adhoc-command/roster-fixer-cluster/Average processing time\n-----\n\n=== adhoc-command/user-domain-perm last {interval}\n\nThe number of times user-domain-perm command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/user-domain-perm/Average processing time+: The average time in ms, returned as an integer, it takes for +user-domain-perm+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/user-domain-perm last hour\nsess-man/adhoc-command/user-domain-perm last minute\nsess-man/adhoc-command/user-domain-perm last second\nsess-man/adhoc-command/user-domain-perm/Average processing time\n-----\n\n=== adhoc-command/user-roster-management last {interval}\n\nThe number of times user-roster-management command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/user-roster-management/Average processing time+: The average time in ms, returned as an integer, it takes for +user-roster-management+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/user-roster-management last hour\nsess-man/adhoc-command/user-roster-management last minute\nsess-man/adhoc-command/user-roster-management last second\nsess-man/adhoc-command/user-roster-management/Average processing time\n-----\n\n=== adhoc-command/user-roster-management-ext last {interval}\n\nThe number of times user-roster-management-ext command has been executed within the specified interval.\n\n*Available {interval}*: hour|minute|second\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*Sub-level Statistics Available*:\n\n+adhoc-command/user-roster-management-ext/Average processing time+: The average time in ms, returned as an integer, it takes for +user-roster-management-ext+ to execute.\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/adhoc-command/user-roster-management-ext last hour\nsess-man/adhoc-command/user-roster-management-ext last minute\nsess-man/adhoc-command/user-roster-management-ext last second\nsess-man/adhoc-command/user-roster-management-ext/Average processing time\n-----\n\n=== Authentication timeouts\n\nThe number of connections that have timed out during the authentication process.  Default timeout is 2 minutes.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of available statistics*:\n[source,list]\n-----\nsess-man/Authentication timeouts\n-----\n\n=== Closed user connections\n\nUser connections that have been terminated by the user (as opposed to the server).\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of available statistics*:\n[source,list]\n-----\nsess-man/Closed user connections\n-----\n\n=== default-handler/Invalid registrations\n\nNumber of invalid registrations attempted with the server\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of available statistics*:\n[source,list]\n-----\nsess-man/default-handler/Invalid registrations\n-----\n\n=== default-handler/Registered users\n\nNumber of registered users for this server.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of available statistics*:\n[source,list]\n-----\nsess-man/default-handler/Registered users\n-----\n\n=== Maximum user connections\n\nMaximum number of connections that have been made during server instance, this number includes users connecting multiple times.\n\n*Statistics Level*: INFO\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Maximum user connections\n-----\n\n=== Maximum user sessions {today|yesterday}\n\nThe number of most simultaneous sessions within the specified interval.  Today = previous 24 hours, Yesterday = 24 hours after previous 24 hours (does not go by calendar date).\n\n*Statistics Level*: INFO|FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Maximum user sessions today\nsess-man/Maximum user sessions yesterday\n-----\n\n=== Registered accounts\n\nSum total of registered accounts for the server.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Registered accounts\n-----\n\n=== Open user connections\n\nThe current number of open user connections.  This may be interpreted as number of connections from users, however a user can have more than one connection (connection from mobile and PC for example).\n\n*Statistics Level*: INFO\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Open user connections\n-----\n\n=== Open user sessions\n\nThe current number of open user sessions.\n\n*Statistics Level*: INFO\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Open user sessions\n-----\n\n=== Total user connections\n\nThe cumulative number of connections that have been made to the server during the current instance.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Total user connections\n-----\n\n=== Total user sessions\n\nThe cumulative number of sessions that this server has negotiated during the current instance.\n\n*Statistics Level*: FINER\n\n*result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Total user sessions\n-----\n\n=== presence/Users status changes\n\nThe number of presence changes for all users that have been conducted during the server instance.\n\n*Stastics Level*: INFO\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/presence/Users status changes\nsess-man/presence-state/Users status changes\n-----\n\n=== sess-man/Processor\n\nProcessor statistics will result in a field of labels and values exclusive to that processor.\nThe field shows as follows:\n[source,properties]\n-----\n, Queue: 0, AvTime: 0, Runs: 0, Lost: 0\n-----\nWhere:\nQueue: Number of packets in process queue\nAvTime: Average time in ms processor takes to conduct it's operation.\nRuns: Number of times Processor has been run.\nLost: Number of packets lost during processing.\n\n*Statistics Level*: FINEST\n\n*List of possible statistics*:\n[source,list]\n-----\nsess-man/Processor: message carbons\n\nsess-man/Processor: http://jabber.org/protocol/stats\n\nsess-man/Processor: jabber:iq:auth\n\nsess-man/Processor: vcard-temp\n\nsess-man/Processor: amp\n\nsess-man/Processor: presence-subscription\n\nsess-man/Processor: disco\n\nsess-man/Processor: msgoffline\n\nsess-man/Processor: urn:xmpp:blocking\n\nsess-man/Processor: urn:xmpp:ping\n\nsess-man/Processor: jabber:iq:register\n\nsess-man/Processor: urn:ietf:params:xml:ns:xmpp-sasl\n\nsess-man/Processor: prp\n\nsess-man/Processor: presence\n\nsess-man/Processor: message-archive-xep-0136\n\nsess-man/Processor: default-handler\n\nsess-man/Processor: jabber:iq:roster\n\nsess-man/Processor: starttls\n\nsess-man/Processor: presence-state\n\nsess-man/Processor: jabber:iq:version\n\nsess-man/Processor: urn:xmpp:time\n\nsess-man/Processor: session-open\n\nsess-man/Processor: jabber:iq:privacy\n\nsess-man/Processor: urn:ietf:params:xml:ns:xmpp-bind\n\nsess-man/Processor: http://jabber.org/protocol/commands\n\nsess-man/Processor: vcard-xep0292\n\nsess-man/Processor: session-close\n\nsess-man/Processor: urn:ietf:params:xml:ns:xmpp-session\n\nsess-man/Processor: jabber:iq:private\n\nsess-man/Processor: Average amp on last 100 runs [ms]\n\nsess-man/Processor: Average msgoffline on last 100 runs[ms]\n\nThese are example scripts included with Tigase for demonstration purposes, it is likely you will not encounter or need them.\n\nsess-man/groovy-example last hour\n\nsess-man/groovy-example last minute\n\nsess-man/groovy-example last second\n\nsess-man/groovy-example/Average processing time\n\nsess-man/hello last hour\n\nsess-man/hello last minute\n\nsess-man/hello last second\n\nsess-man/hello/Average processing time\n-----\n\n== *vhost-man*\n\n=== Checks is anonymous domain\n\nNumber of anonymous domain checks that have been run within vhost-man.\n\n*Statistics Level*: FINEST\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nvhost-man/Checks is anonymous domain\n-----\n\n=== Checks: is local domain\n\nNumber of local domain checks that have been run within vhost-man.\n\n*Statistics Level*: FINER\n\n*Result Format*: Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nvhost-man/Checks: is local domain\n-----\n\n=== Get components for local domain\n\nNumber of components loaded within local domain.\n\n*Statistics Level*: FINER\n\n*Result Format* Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nvhost-man/Get components for local domain\n-----\n\n=== Get components for non-local domain\n\nNumber of components loaded outside local domain.\n\n*Statistics Level*: FINEST\n\n*Result Format* Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nvhost-man/Get components for non-local domain\n-----\n\n=== Number of Vhosts\n\nNumber of configured and running Virtual Hosts.\n\n*Statistics Level*: FINE\n\n*Result Format* Integer\n\n*List of possible statistics*:\n[source,list]\n-----\nvhost-man/Number of VHosts\n-----\n\n== *ws2s*\n\nNo exclusive ws2s specific statistics\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_103_-_Components_-_K_-_C2S.asciidoc",
    "content": "[[c2scomponent]]\n= Client to Server Communication\n:author: Daniel Wisnewski (daniel@tigase.org)\n:date: 2016-06-23 08:20\n:version: v1.0 June 2016\n\nClient to server communication is an integral part of XMPP communication.  C2S handles all client communication to the server, and is responsible for filtering and handling remote communications.\nC2S CAN be disabled, however doing so will only allow communication of internal components, and S2S communications.\n\n= Configuration\n\n== Resumption timeout\nIt is now possible to set a default stream resumption timeout that the server uses.  This allows control of how long a server will wait for a reconnection from a client.  This can be particularly helpful to manage mobile clients connecting to your server as they may not have complete coverage, and you do not want to close the stream right away.\nBy default, Tigase sets this value to 60 seconds.\n\n[source,properties]\n-----\nc2s/processors/urn\\:xmpp\\:sm\\:3/resumption-timeout[I]=90\n-----\nThis sets the default timeout to 90 seconds.  You may, if you choose, specify a maximum timout time, which will allow the server to wait between the default and maximum before a connection is closed.\n[source,properties]\n-----\nc2s/processors/urn\\:xmpp\\:sm\\:3/max-resumption-timeout[I]=900\n-----\n\nNOTE: If the max-resumption-timeout is not set, it will always equal the resumption-timeout number, or default is none is set.\n\nAvailable since v7.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_104_-_Using_Tigase_-_Q_-_Clustering.asciidoc",
    "content": "[[tigaseClustering]]\n= Tigase Clustering\n:author: Daniel Wisnewski\n:version: v1.0 June 2016\n:date: 24-06-2016 11:00\n\nTigase Clustering allows the use of a number of servers to be unified in delivering, from what a client or user sees, a single unified platform.\nThere are two typical reasons why clustering should be employed:\n\n- High Availability\n\n  By using clustering, services can be provided with a high reliability and redundancy.  By using a network of multiple servers, content or services can be served on any of the clustered servers maintaining a consistent uptime without relying on one machine.\n\n- Load Balancing\n\n  This type of cluster helps to distribute a workload over a number of servers to reduce bottlenecking from heavy resource loads on a particular server.\n\nWith Tigase, you don't have to choose between either/or!\n\n*Tigase Clustering* offers *Full Redundancy* and *Automatic Load Balancing* allowing addition of new nodes at runtime with a simple configuration.  All without a severe tax on resource consumption.\n\nAll basic components support clustering configuration, and some may be turned on or off.\n\n== Configuration\nTo enable Clustering on Tigase servers, use the following line in your init.properties file:\n[source,properties]\n-----\n--cluster-mode=true\n-----\n\nThat's it!\n\n=== Custom Ports\nYou can customize ports for the cluster component, just be sure that each clustered server also has the same settings so they can communicate.\n[source,properties]\n-----\n--cl-comp-ports=4250,3540\n-----\nYou can fine tune each port configuration, however this is not typically needed.\n\n==== Custom Port Configuration\nEach port has it's own details that can be manipulated VIA the following ports.  Again *THIS IS OPTIONAL*\n[source,properties]\n-----\ncl-comp/connections/4250/type[S]=accept\ncl-comp/connections/4250/socket[S]=plain\ncl-comp/connections/4250/ifc[s]=*\ncl-comp/connections/4250/remote-host[S]=localhost\ncl-comp/connections/4250/connections/tls/required[B]=false\n-----\n\n=== Multi-node configuration\nEach node should have +--cluster-mode=true+ enabled that you wish to connect to the cluster.  They will automatically discover other nodes to connect to VIA Server to Server traffic.\nNodes that are added or removed will be periodically updated.\n\n=== Traffic Control\nYou can customize the traffic going between clustered servers with a few options.\n\n==== cm-ht-traffic-throttling\nThis setting will control the number of bytes sent over non-user connections.  Namely, Server to Server or S2S connections.\n[source,properties]\n-----\n--cm-ht-traffic-throttling=xmpp:25k:0:disc,bin:200m:0:disc\n-----\nThe format is as follows: {traffic-type}:{maximum-traffic}:{max-lifespan-traffic}:{action}\n- *traffic-type* Specifies the type of traffic controlled.  This can either be *XMPP* or *bin*.  XMPP limits the number of packets transferred, whereas bin limits the number of bytes transferred.\n- *maximum-traffic* Specifies how many bytes or packets may be sent within one minute.\n- *max-lifespan-traffic* Specifies how many bytes or packets may be sent within the lifetime of the connection. 0 means unlimited.\n- *action* Specifies the action to be taken which can be *disc* which disconnects the connection, or *drop* which will drop any data exceeding the thresholds.\n\n==== cm-see-other-host\nThis allows the specific use of a load balancing mechanism by selecting +SeeOtherHostIfc+ implementation.\nFor more details, see xref:loadBalanding[Tigase Load Balancing] documentation.\n\n== Old configuration method\n\nWhile these options are still available these settings CAN be less reliable.  *Use ONLY if you need specific setups that cannot be accommodated by the automatic cluster mode*.\n\n=== Specifying Specific nodes\nYou can still use the old method of specifying every node on each server.\nServer 3 needs the following set\n[source,properties]\n-----\n--cluster-nodes=serv1.xmpp-test.org,serv2.xmpp-test.org\n-----\nServer 2 needs\n[source,properties]\n-----\n--cluster-nodes=serv1.xmpp-test.org,serv3.xmpp-test.org\n-----\nand so on...\n\n==== Password and Port configuration\nYou may specify a password and port to specific cluster servers if that is required.  To do so, you will need to add {password}:{port} to the domain, like this example:\n[source,properties]\n-----\n--cluster-nodes=serv1.xmpp-test.org:domainpass:5600\n-----\n\n== Checking Cluster Connections\n\nAfter setting up clustering you may want to verify that the clusters are operational. Right now it can be done in two manners - first by checking that there are actual network connections established between cluster nodes. The other is to check internal status of the server.\n\n=== Established connections\nThere are number of ways to check for opened connections, simplest one use command line. (Tigase uses port _5277_ for cluster connections)\n\n* Linux\n[source,sh]\n-----\n$ lsof -iTCP:5277 -sTCP:ESTABLISHED -P -n\n-----\n\n* Windows\n[source,sh]\n-----\nC:\\WINNT>netstat -anp tcp | find \":5277 \"\n-----\n\n=== Cluster nodes connected (using XMPP)\nVerifying clustering connectivity over XMPP protocol requires any XMPP client capable of http://xmpp.org/extensions/xep-0030.html[XEP-0030: Service Discovery]. It's essential to remember that only an administrator (a user whose JID is configured as administrative) has access.\n\n==== Psi XMPP Client\nFor the purpose of this guide a http://psi-im.org/[Psi] client will be used. After successfully configuring and connecting to account with administrative privileges we need to access _Service Discovery_, either from application menu or from context menu of the particular account account:\n\nimage:images/monitoring_xmpp_1.png[caption=\"Figure 1: \", title=\"Access service discovery\", alt=\"roster-discovery\", width=\"233\"]\n\nIn the _Service Discovery_ window we need to find _Cluster Connection Manager_ component. After expanding the tree node for the component a list of all cluster nodes will be presented with the current status (either _connected_ or _disconnected_). Node column will contain actual hostname of the cluster node:\n\nimage:images/monitoring_clustering.png[caption=\"Figure 2: \", title=\"List of cluster nodes\", alt=\"discovery-nodes\", width=\"558\"]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_105_-_Configuration_-_F_-_Sess-man.asciidoc",
    "content": "[[sessMan]]\n= Session Manager\n:author: Daniel Wisnewski\n:version: v1.0 June 2016\n:date: 24-06-2016 11:00\n\nTigase Session Manager is where most of Tigase basic options can be configured, and where many operations are controlled from.\nChanges to session manager can effect operations throughout an entire XMPP installation, so care must be made when changing settings here.\n\n[[sessManMobileOpts]]\n== Mobile Optimizations\nBy default, Tigase employs XEP-0352 Client State Indication which allows for a more streamlined mobile experiencing by allowing the XMPP server to suppress or reduce the number of updates sent to a client thereby reducing the number of stanzas sent to a mobile client that is inactive.\nThis employment is contained within the processor +ClientStateIndication+ and is independent from the MobileV1, MobileV2, MobileV3 settings.\n\nHowever, this can be fine tuned by using mobile plugins from Tigase which can be used at the same time by adding the following line to the init.properties file:\n[source,properties]\n-----\nsess-man/plugins-conf/urn\\:xmpp\\:csi\\:0/logic=tigase.xmpp.impl.MobileV1\n-----\nOptions are:\n\n=== MobileV1\nKeeps all presence stanzas in queue until client is active.\n\n=== MobileV2\nThis setting delays delivery of presences while client is in inactive state, but only keeps the last presence for each full jid.\n*This is the default setting for CSI logic*.\n\n=== MobileV3\nKeeps the same presence logic as MobileV2, but also queues Message Carbons.\n*Currently not supported by CSI processor, will cause issues*.\n\n=== Disabling CSI\nIf you wish to not use the +ClientStateIndication+ processor, set the following in your init.properties file:\n[source,properties]\n-----\n--sm-plugins=-urn:xmpp:csi:0\n-----\n\n=== A note about Mobile Plugins\nPreviously, you could enable Mobile optimization logic using +--sm-plugins=+Mobile_V1+.\n\nIf you have used these in the past, it is recommended you change your system to use the CSI processor with the appropriate mobile processing logic.\n\nIf you require v3 logic, or do not wish to use CSI, be sure to disable it using the above option.\n\n== Thread Pool Counts\nSession manager can control the number of available thread pools for each processor.  By adding the following line to the init.properties file, the global thread pool can be increased by a specified factor:\n[source,properties]\n-----\nsess-man/sm-threads-factor[I]=3\n-----\nIn this case, the global thread pools is increased by a factor or 3.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_106_-_Components_-_L_-_Socks5.asciidoc",
    "content": "[[socks5]]\n= Socks 5 Component\n:author: Daniel Wisnewski\n:date: 2016-07-26 10:35\n:version: v1.0 July 2016\n\n\nTigase SOCKS5 component allows for file transfers to be made over a SOCKS5 proxy in accordance with link:http://xmpp.org/extensions/xep-0065.html[XEP-0065 SOCKS5 Bytestreams].  This allows for some useful features such as:\n- transfer limits per user, domain, or global\n- recording transfers between users\n- quotas and credits system implementation\n\n== Installation\nTigase SOCKS5 component comes built into the dist-max archives for Tigase XMPP server, and requires the component to be listed in init.properties file:\n[source,properties]\n-----\n--comp-name-3=proxy\n--comp-class-3=tigase.socks5.Socks5ProxyComponent\n-----\n\nYou will also need to decide if you wish to use database-based features or not.  If you wish to simply run the socks5 proxy without features such as quotas, limits add the following line:\n[source,properties]\n-----\nproxy/verifier-class=tigase.socks5.verifiers.DummyVerifier\n-----\n\nThis will enable the SOCKS5 Proxy without any advanced features.  If you wish to use those features, see the configuration section below.\n\n== Database Preparation\nIn order to use the more advanced features of the SOCKS5 Proxy Component, your database needs to be prepared with the proper schema prior to running the server.\n\nYou may either edit an existing database, or create a new database for specific use with the Proxy.\n\n=== Edit Existing Database\nYou can add the proper schema to your existing database using the DBSchemaLoader utility included with Tigase.  The database folder contains the schema file for your type of database.\n\nFirst, backup your database before performing any actions and shut down Tigase XMPP Server.\n\nThen from the Tigase installation directory run the following command:\n[source,bash]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbType {derby,mysql,postgresql,sqlserver} - dbHostname {db address} -dbName {dbname} -rootUser root -rootPass root -file database/{dbtype}-socks5-schema.sql\n-----\nYou should see the following dialogue\n-----\nLogLevel: CONFIG\ntigase.util.DBSchemaLoader     \t <init>          \t CONFIG     Properties: [{dbHostname=localhost, logLevel=CONFIG, dbType=derby, file=database/derby-socks5-schema.sql, rootUser=root, dbPass=tigase_pass, dbName=tigasedb, schemaVersion=7-1, rootPass=root, dbUser=tigase_user}]\ntigase.util.DBSchemaLoader     \t validateDBConnection \t INFO       Validating DBConnection, URI: jdbc:derby:tigasedb;create=true\ntigase.util.DBSchemaLoader     \t validateDBConnection \t CONFIG     DriverManager (available drivers): [[jTDS 1.3.1, org.apache.derby.jdbc.AutoloadedDriver@34a245ab, com.mysql.jdbc.Driver@3941a79c, org.postgresql.Driver@6e2c634b]]\ntigase.util.DBSchemaLoader     \t validateDBConnection \t INFO       Connection OK\ntigase.util.DBSchemaLoader     \t validateDBExists \t INFO       Validating whether DB Exists, URI: jdbc:derby:tigasedb;create=true\ntigase.util.DBSchemaLoader     \t validateDBExists \t INFO       Exists OK\ntigase.util.DBSchemaLoader     \t loadSchemaFile  \t INFO       Loading schema from file: database/derby-socks5-schema.sql, URI: jdbc:derby:tigasedb;create=true\ntigase.util.DBSchemaLoader     \t loadSchemaFile  \t INFO        completed OK\ntigase.util.DBSchemaLoader     \t shutdownDerby   \t INFO       Validating DBConnection, URI: jdbc:derby:tigasedb;create=true\ntigase.util.DBSchemaLoader     \t shutdownDerby   \t WARNING    Database 'tigasedb' shutdown.\ntigase.util.DBSchemaLoader     \t printInfo       \t INFO\n\nDatabase init.properties configuration:\n\n--user-db=derby\n--user-db-uri=jdbc:derby:tigasedb;create=true\n-----\n\nOne this process is complete, you may begin using SOCKS5 proxy component.\n\n=== Create New Database\n\nIf you want to create a new database for the proxy component and use it as a separate socks5 database, create the database using the appropriate schema file in the database folder.\nOnce this is created, add the following line to your init.properties folder.\n[source,properties]\n-----\nproxy/repo-url=driver:address\n-----\n\nFor example, a mysql database will have this type of URL: jdbc:mysql://localhost/SOCKS?user=root&password=root to replace {database URL}.  For more options, check the database section of xref:databasePreperation[this documentation].\n\n== Configuration\n\n=== *+verifier-class+*\n[source,properties]\n-----\nproxy/verifier-class=\n-----\nSpecifies the class used to verify transfer limits.  The following options are available:\n\n==== +LimitsVerifier+\n- Class Name: +tigase.socks5.verifiers.LimitsVerifier+\n\nUses the database to store limits and record the amount of data transferred VIA the proxy. It accepts one parameter, +transfer-update-quantization+ which is used to create a value to check if the value of transferred bytes should be updated in the database or not.  By default, this value is 1MB.\n\nNOTE: Low values can slow down file transfers, while high values can allow for users to exceed quotas.\n\n==== +DummyVerifier+\n- Class Name: tigase.socks5.verifiers.DummyVerifier\n\nThis accepts file transfers VIA SOCKS5 proxy from any user and does not check limitations against the database.\n\n=== *+socks5-repo-cls+*\n[source,properties]\n-----\nproxy/socks5-repo-cls=\n-----\n\nSpecifies implementation of repository used to store usage statistics.  Two options are available for this setting:\n- tigase.socks5.verirepository.JDBCSocks5Repository - Uses the database implementation.\n- tigase.socks5.repository.DummySocks5Repository - ignores data storage, and is the default implementation.\n\n\n=== *+repo-url+*\n[source,properties]\n-----\nproxy/repo-url=\n-----\nThe database connection URL for the socks5 repository.\n\n=== *+verifier-params+*\n[source,properties]\n-----\nproxy/repo-params=\n-----\n\nComma separated parameters for +LimitsVerifier+ which will override the defaults.  All of these limits are on a per calendar month basis.\nFor example, a user is limited to 10MB for all transfers.  If he transfers 8MB between the 1st and the 22nd, he only has 2MB left in his limit.  On the 1st of the following month, his limit is reset to 10MB.\n\nAvailable parameters:\n\n- +global-limit+ - Transfer limit for all domains in MB per month.\n- +instance-limit+ - Transfer limit for server instance in MB per month.\n- +default-domain-limit+ - The Default transfer limit per domain in MB per month.\n- +default-user-limit+ - The default transfer limit per user in MB per month.\n- +default-file-limit+ - The default transfer limit per file in MB per month.\n\n=== *+remote-addresses+*\n[source,properties]\n-----\nproxy/remote-addresses=\n-----\n\nA comma separated list of IP addresses that will be accessible VIA the Socks5 Proxy.  This can be useful if you want to specify a specific router address to allow external traffic to transfer files using the proxy to users on an internal network.\n\n== Database usage for specific settings\nThe above configuration allows for global settings, however you may also define specifics for users and the scopes of those limitations by editing the database information directly.\n\nThe +user_id+ field denotes the scope of the limitation.\n\n. Using a +domain_name+ defines limits for all users whose JIDs are within that domain.\n. Using a +JID+ of a user defines limit for this exact user.\n\nIf the value set is larger than 0, that is the specific limit.\nIf value is equal to 0 the limit is not overridden and the global limit is used.\nIf value equals -1 proxy will forbid any transfer for this user.\nIt there is no value for user in this table, a new row will be created during first transfer and limits for domain or global limits will be used.\n\nSocks5 database is setup in this manner:\n\n[width=\"100%\",frame=\"topbot\",options=\"header\"]\n|=================================\n|uid  |user_id              |sha1_user_id                              |domain     |sha1_domain                              |filesize_limit |transfer_limit_per_user  |transfer_limit_per_domain\n|1    |user@domain.com      |c35f2956d804e01ef2dec392ef3adae36289123f  |domain.com |e1000db219f3268b0f02735342fe8005fd5a257a |0              |3000                     |0\n|2    |domain.com           |e1000db219f3268b0f02735342fe8005fd5a257a  |domain.com |e1000db219f3268b0f02735342fe8005fd5a257a |500            |0                        |0\n|=================================\n\nThis example table shows that user@domain.com is limited to 3000MB per transfer whereas all users of domain.com are limited to a max file size of 500MB.\nThis table will populate as users transfer files using the SOCKS5 proxy, once it begins population, you may edit it as necessary.\nA second database is setup tig_socks5_connections that records the connections and transmissions being made, however it does not need to be edited.\n\n\n\n== Example init.properties block\nCombined, your init.properties should look like the below excerpt to run socks5 transfers using a separate database.\n\n[source,properties]\n-----\nproxy/repo-url=jdbc:mysql://localhost/SOCKS?user=root&password=root\nproxy/verifier-class=tigase.socks5.verifiers.LimitsVerifier\nproxy/socks5-repo-cls=tigase.socks5.verirepository.JDBCSocks5Repository\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_10_-_Configuration_-_A_-_Tigase_XMPP_Server_init.properties_Configuration.asciidoc",
    "content": "[[initPropertiesGuide]]\n= Tigase XMPP Server init.properties Configuration\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 03:54\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\ninit.properties is a slightly extended version of the Java properties file with (key, value) pairs.\n\nComment lines will have as it's first non-white space ASCII character either '#' or '!'.\n\nThe key starts with first non-white space ASCII character and ends on either first white space ASCII character or either of '=' or ':'. Therefore if your key contains any of '=', ':' or white space characters you have to escape them with backslash \\'\\': \\: or \\=.\n\nAll examples below specify 'vhosts' as a key and 'test-a, test-b, test-c' as a value:\n\n[source,bash]\n-----\nvhosts=test-a, test-b, test-c\nvhosts : test-a, test-b, test-c\n    vhosts     =     test-a, test-b, test-c\n-----\n\nPossible types are:\n\n- *[S]* (or nothing) - Characters string: 'abcdef'\n- *[s]* - String array: 'abcdef, ghaijk, lmnopq'\n- *[B]* - Boolean: 'true' or 'false'\n- *[b]* - Boolean array: 'true, true, false'\n- *[L]* - Long number: 1234567890\n- *[l]* - Long array: '12334, 45435, 45645'\n- *[I]* - Integer number: 123456\n- *[i]* - Integer array: '123, 456, 678'\n\nThere are lots of parameters which have broader meaning than just one property. Some of them affect many configuration settings or can generate whole sections in the XML file. Most of them starts with \\'--' double hyphen. Please note, each property put in the init.properties file starting with \\'--' becomes a JVM system property (without \\'--' at the beginning).\n\n//example init.properties goes here\n\nReference the property guide for a description of properties.\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#admins[--admins]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#authDb[--auth-db]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#authDbUri[--auth-db-uri]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#authDomainRepoPool[--auth-domain-repo-pool]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#authRepoPool[--auth-repo-pool]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#authRepoPoolSize[--auth-repo-pool-size]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#bindExtHostnames[--bind-ext-hostnames]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#boshCloseConnection[--bosh-close-connection]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#boshExtraHeadersFile[--bosh-extra-headers-file]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#clConnRepoClass[--cl-conn-repo-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#clientAccessPolicyFile[--client-access-policy-file]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#clusterConnectAll[--cluster-connect-all]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#clusterMode[--cluster-mode]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#clusterNodes[--cluster-nodes]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#cmHtTrafficThrottling[--cm-ht-traffic-throttling]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#cmSeeOtherHost[--cm-see-other-host]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#cmTrafficThrottling[--cm-traffic-throttling]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#cmpnamePorts[--cmpname-ports]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#compClass[--comp-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#compName[--comp-name]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#crossDomainPolicyFile[--cross-domain-policy-file]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#dataRepoPoolSize[--data-repo-pool-size]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#debug[--debug]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#debugPackages[--debug-packages]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#domainFilterPolicy[--domain-filter-policy]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#elementsNumberLimit[--elements-number-limit]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#extComp[--ext-comp]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#extcompRepoClass[--extcomp-repo-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#external[--external]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#hardenedMode[--hardened-mode]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#maxQueueSize[--max-queue-size]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#monitoring[--monitoring]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#netBuffHighThroughput[--net-buff-high-throughput]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#netBuffStandard[--net-buff-standard]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#newConnectionsThrottling[--new-connections-throttling]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#nonpriorityQueue[--nonpriority-queue]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#queueImplementation[--queue-implementation]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#rosterImplementation[--roster-implementation]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#s2sEjabberdBugWorkaroundActive[--s2s-ejabberd-bug-workaround-active]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#s2sSecret[--s2s-secret]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#s2sSkipTlsHostnames[--s2s-skip-tls-hostnames]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#scriptDir[--script-dir]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#smClusterStrategyClass[--sm-cluster-strategy-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#smPlugins[--sm-plugins]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#smThreadsPool[--sm-threads-pool]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#sslCertsLocation[--ssl-certs-location]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#sslContainerClass[--ssl-container-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#sslDefCertDomain[--ssl-def-cert-domain]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#statsHistory[--stats-history]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#stringprepProcessor[--stringprep-processor]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#test[--test]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#tigaseConfigRepoClass[--tigase-config-repo-class]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#tigaseConfigRepoUri[--tigase-config-repo-uri]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#tlsJdkNssBugWorkaroundActive[--tls-jdk-nss-bug-workaround-active]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#trusted[--trusted]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#userDb[--user-db]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#userDbUri[--user-db-uri]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#userDomainRepoPool[--user-domain-repo-pool]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#userRepoPool[--user-repo-pool]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#userRepoPoolSize[--user-repo-pool-size]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostAnonymousEnabled[--vhost-anonymous-enabled]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostMaxUsers[--vhost-max-users]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostMessageForwardJid[--vhost-message-forward-jid]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostPresenceForwardJid[--vhost-presence-forward-jid]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostRegisterEnabled[--vhost-register-enabled]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#vhostTlsRequired[--vhost-tls-required]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#virtHosts[--virt-hosts]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#watchdogDelay[--watchdog_delay]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#watchdogPingType[--watchdog_ping_type]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#watchdogTimeout[--watchdog_timeout]\n\n*Property name:* link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html/#configType[config-type]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_11_-_Configuration_-_B_-_Startup_Files_tigase.sh_and_tigase.asciidoc",
    "content": "[[manualconfig]]\n= Startup File for tigase.sh - tigase.conf\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nProperty file names for +tigase.sh+ startup script is a second parameter for the startup script. It can be skipped if environmental variables are set in different location or in different way.\n\nConfig file for startup script simply sets number of environment variables with the location of required components. Possible variables to set in this file are:\n\n- *JAVA_HOME* - location of Java installation home directory. *Must be set*.\n- *TIGASE_HOME* - location of Tigase installation home directory. _By default script try to find this location by searching directories from the location where the script has been run._\n- *TIGASE_CONSOLE_LOG* - file to which all console messages will be redirected if server is run in background. By default it will be: _TIGASE_HOME/logs/tigase-console.log_. *_If this file/directory is not writable by Tigase process all console messages will be redirected to /dev/null_*\n- *TIGASE_PID* location of the file with server PID number. By default it will be _TIGASE_HOME/logs/tigase.pid_.\n- *JAVA_OPTIONS* - options for JVM like size of RAM allocated for the JVM, properties and so on.\n- *TIGASE_OPTIONS* - additional options for Tigase server program. You can tweak initial parameters for your environment here.\n\nSample file to run *Tigase* with *PostgreSQL* database may look like:\n\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=org.postgresql.Driver\"\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\nCLASSPATH=\"\"\nTIGASE_CONFIG=\"tigase-pgsql.xml\"\nTIGASE_OPTIONS=\" --property-file etc/init.properties \"\n-----\n\nPlease note encoding settings. JVM by default uses encoding set in operating system environment. XMPP protocol, however uses +UTF-8+ for all data processing. So the ENC settings enforces +UTF-8+ encoding for all operations.\n\nAnother significant setting is \\'*CLASSPATH*'. It is intentionally set to an empty string. The *tigase.sh* startup script builds the *CLASSPATH* on it's own from files found in *jars/* and *libs/* directories. It is advised to set the *CLASSPATH* to the empty string because the Tigase server scans all available classes to find all components and plugins implementation. If the *CLASSPATH* contains lots of libraries which are not used anyway it can cause a long startup time and high system loads.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_12_-_Configuration_-_C_-_Linux_Settings_for_High_Load_Systems.asciidoc",
    "content": "[[linuxhighload]]\n= Linux Settings for High Load Systems\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThere are a few basic settings you have to adjust for high load systems to make sure the server has enough resources to handle a big number of network connections.\n\nThe main parameter is a maximum number of opened files allowed for the process to keep at the same time. Each network connection uses a file handler, therefore if the limit is too low you can quickly run out of handlers and the server can not accept any more connections.\n\nThis limit is set on 2 levels - on the kernel level (*fs.file-max*) and on the system level (*nofile*).\n\nAnother kernel property which can be important in certain configurations (like transports installations or when you use proxy for Bosh connections) is: *net.ipv4.ip_local_port_range*. This parameter can be set the same way as the +fs.file-max+ property.\n\n== fs.file-max\n\nThe *fs.file-max* kernel property is set via sysctl command. You can see current settings by executing the command:\n\n[source,sh]\n-----\n# sysctl fs.file-max\nfs.file-max = 358920\n-----\n\nIf you plan to run high load service with large number of server connections, then this parameter should be at least as twice big as the number of network connections you expect to support. You can change this setting by executing the command:\n\n[source,java]\n-----\n# sysctl -w fs.file-max=360000\nfs.file-max = 360000\n-----\n\n== net.ipv4.ip_local_port_range\n\nYou can see current settings by executing the command:\n\n[source,sh]\n-----\n# sysctl net.ipv4.ip_local_port_range\nnet.ipv4.ip_local_port_range = 32768\t61000\n-----\n\nYou can change this setting by executing the command:\n\n[source,sh]\n-----\n# sysctl -w net.ipv4.ip_local_port_range=\"1024 65000\"\nnet.ipv4.ip_local_port_range = 1024 65000\n-----\n\n== TCP_keepalive\n\nAccording to link:http://blog.kolargol.eu/2006/06/tcpkeepalive.html[blog.kolargol.eu] or link:http://www.gnugk.org/keepalive.html[www.gnugk.org/] some keepalive settings should be changed to improve reliability.\n\n[source,sh]\n-----\n# sysctl -w net.ipv4.tcp_keepalive_time=\"60\"\nnet.ipv4.tcp_keepalive_time = 60\n# sysctl -w net.ipv4.tcp_keepalive_probes=\"3\"\nnet.ipv4.tcp_keepalive_probes = 3\n# sysctl -w net.ipv4.tcp_keepalive_intvl=\"90\"\nnet.ipv4.tcp_keepalive_intvl = 90\n-----\n\n== /etc/sysctl.conf\n\nThe above commands let the system remember new settings until the next system restart. If you want to make the change permanent you have to edit the file: */etc/sysctl.conf* and add the property at the end of the file:\n\n[source,sh]\n-----\nfs.file-max=360000\nnet.ipv4.ip_local_port_range=1024 65000net.ipv4.tcp_keepalive_time=60\nnet.ipv4.tcp_keepalive_probes=3\nnet.ipv4.tcp_keepalive_intvl=90\n-----\n\nIt will be automatically loaded next time you start the server.\n\nCommand:\n\n[source,sh]\n-----\n# sysctl -p\n-----\n\nCauses the +/etc/systcl.conf+ to be reloaded which is useful when you have added more parameters to the file and don't want to restart the server.\n\n== nofile\n\nThis is the property used by the system limits. For example running the command +ulimit -a+ shows you all limits set for the current user:\n\n[source,sh]\n-----\n# ulimit -a\ncore file size          (blocks, -c) 0\ndata seg size           (kbytes, -d) unlimited\nfile size               (blocks, -f) unlimited\npending signals                 (-i) 38912\nmax locked memory       (kbytes, -l) 32\nmax memory size         (kbytes, -m) unlimited\nopen files                      (-n) 40960\npipe size            (512 bytes, -p) 8\nPOSIX message queues     (bytes, -q) 819200\nstack size              (kbytes, -s) 8192\ncpu time               (seconds, -t) unlimited\nmax user processes              (-u) 38912\nvirtual memory          (kbytes, -v) unlimited\nfile locks                      (-x) unlimited\n-----\n\nTo make it even more interesting and more complex, there are 2 types of system limits:\n*soft limit* which can be temporarily exceeded by the user and\n*hard limit* which can not be exceeded.\nTo see your *hard limit* execute command:\n\n[source,sh]\n-----\n# ulimit -a -H\ncore file size          (blocks, -c) unlimited\ndata seg size           (kbytes, -d) unlimited\nfile size               (blocks, -f) unlimited\npending signals                 (-i) 38912\nmax locked memory       (kbytes, -l) 32\nmax memory size         (kbytes, -m) unlimited\nopen files                      (-n) 40960\npipe size            (512 bytes, -p) 8\nPOSIX message queues     (bytes, -q) 819200\nstack size              (kbytes, -s) unlimited\ncpu time               (seconds, -t) unlimited\nmax user processes              (-u) 38912\nvirtual memory          (kbytes, -v) unlimited\nfile locks                      (-x) unlimited\n-----\n\nThe hard limits are usually bigger then the soft limits or sometimes the same.\n\nFor us the most important parameter is: *open files*. You can change the property in file: +/etc/security/limits.conf+. You have to append 2 following lines to the end of the file:\n\n[source,sh]\n-----\njabber               soft    nofile         350000\njabber               hard    nofile         350000\n-----\n\nWhere the *jabber* is the user name of the account running you IM service. You can also set the limits for all users on the machine in a following way:\n\n[source,sh]\n-----\n*               soft    nofile         350000\n*               hard    nofile         350000\n-----\n\nFor those changes to make an effect you have to logout from the modified account and login again. New limits should be applied.\n\n== su and init script\n\nIf one intends to use init scripts for startup purposes (or simply wants to be able to start the server utilizing su command) it's necessary to adjust PAM configuration by modifying /etc/pam.d/su file and uncomment following line:\n\n[source,sh]\n-----\nsession    required   pam_limits.so\n-----\n\nAfterwards the init scripts will respect configured limits.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_13_-_Configuration_-_D_-_Configuration_Storage_Options.asciidoc",
    "content": "[[confChanges5x]]\n= Configuration Storage Options in Tigase\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe whole configuration framework for the Tigase server has been redesigned and rewritten for v5.1. This was done to cleanup all the configuration code and logic as well as extend the current functionality to allow for configuration storage in different kinds of repositories - memory, file, database, ...\n\nAlthough this article is titled configuration changes, version 5.x still follows our policy about backward compatibility. So the changes could be considered extensions rather than complete overhauls.\n\nThere is however one change which can affect a few users. Those who use the server and worked with it's configuration remember the mess and confusion related to duality in the server configuration - the +init.properties+ file and +tigase.xml+ file. This is now over.\n\n== Default Behavior\n\nBy default Tigase server loads tigase.conf.ConfigurationCache class which stores the whole configuration in memory. Please note that the +init.properties+ file with initial settings is always loaded if it is available at the given location and all settings in this file work exactly as before. For more details, please refer to the online documentation.\n\nA couple of times 'initial configuration' and 'whole configuration' were mentioned. What is this about, what is the difference?\n\nThe 'initial configuration' are startup settings provided by the user in the +init.properties+ file. Most of the server elements use far more configuration parameters which are set to sensible default values if they are not provided by the user. The configuration framework in Tigase server always keeps the complete configuration of all active elements. This is implemented in such a way to make it possible to present currently used settings to the end-users or administrators and allow them to change the server parameters during runtime.\n\n== Storing Configuration in SQL Database\n\nThere is one more configuration storage implemented right now. It allows you to store the server settings in the SQL database. In most cases this is not quite useful, just opposite, very inconvenient.\nHowever. there is at least one case where you really want to keep the server configuration in the SQL database. This is in the cluster mode. If you have a Tigase cluster system of 10 or more nodes it is much easier to keep the configuration in a single central location and manage it from there, rather then go to every single machine every time you want to change some settings.\nYou can even change any settings for all cluster nodes with a single database query.\n\nYou set the SQL storage the same way as you set it for XML file. However, there is one more parameter as you have to provide also database connection string for the server so it knows where to connect to for the settings:\n\n. Parameters in init.properties file:\n+\n[source,bash]\n-----\n--tigase-config-repo-class=tigase.conf.ConfigSQLRepository\n--tigase-config-repo-uri=connection-uri\n-----\n. Alternatively you can provide system properties to the JVM:\n+\n[source,bash]\n-----\n-Dtigase-config-repo-class=tigase.conf.ConfigSQLRepository\n-Dtigase-config-repo-uri=connection-uri\n-----\n\nPlease note, the current implementation for the SQL storage automatically creates the tables necessary to operate if it does not exist. So you don't have to worry about the schema, but you should make sure that the database user used by the Tigase has permissions to create a table.\n\nConfiguration is stored in table with following schema:\n\n[source,sql]\n-----\ncreate table tigase_configuration (\n-- The component name by which the configuration parameter\n-- is used.\n  component_name varchar(127) NOT NULL,\n\n-- The configuration property key name or identifier.\n  key_name varchar(127) NOT NULL,\n\n-- The configuration property value\n  value varchar(8191) NOT NULL,\n\n-- The cluster node by which the configuration property is read,\n-- if empty it will be read by all cluster nodes.\n  cluster_node varchar(255) NOT NULL DEFAULT '',\n\n-- Additional, secondary identifier for the configuration property.\n-- The configuration can be organized in a hierarchical way to allow\n-- multiple occurrences of the same property name for a single\n-- component, for example you can have the same property for\n-- different tcp/ip ports set to a different value:\n-- c2s/5222/port_type=plain\n-- c2s/5223/port_type=ssl\n-- the port number is a secondary identifier.\n  key_node varchar(127) NOT NULL DEFAULT '',\n\n--  Not currently used. In future it will be used to distinguish between\n-- different kind of properties (initial settings, defaults, updated by\n-- user, etc...)\n  flag varchar(32) NOT NULL DEFAULT 'DEFAULT',\n\n-- The system detects basic Java types and stores information about\n-- the property type, when the property is read the original property\n-- type is restored and provided to the component without need for\n-- a parsing or conversion.\n  value_type varchar(8) NOT NULL DEFAULT 'S',\n\n-- It is not currently used. In the future it will be used to reload\n-- settings changed in last, defined period of time. Basically, the\n-- system can automatically check the configuration database to\n-- see whether some properties have been updated, then reload\n-- them and apply automatically.\n  last_update           timestamp,\n\nprimary key(cluster_node, component_name, key_node,\n                  key_node, flag));\n-----\n\n== Reverting To the Old Behavior\n\nWhile using the +tigase.xml+ file is still possible and the old behavior can be preserved, it is now disabled by default. By default the Tigase server reads only +init.properties+ file with initial settings and stores all the complete configuration in memory only.\n\nThe +init.properties+ works exactly as before and all old parameters are still working exactly as before. The only difference is the lack of the tigase.xml which is not created or read by default if it is present. The main advantage is that you don't have to remove it each time you change something in the +init.properties+ to pick up new settings.\n\nFirstly we will go into how to re-enable the server to check and use the +tigase.xml+ file to retain functionality with older settings. This is actually very simple to accomplish. The Tigase server now, offers pluggable repository support. This means that you can easily extend current functionality with a different configuration storage by writing own class which reads and writes configuration parameters.\n\nBy default class +tigase.conf.ConfigurationCache+ is loaded which stores configuration in memory only.\n\nPlease note, the +init.properties+ file is always read if it exists at a given location.\n\nTo revert to the old behavior you just need to pass a parameter to Tigase server with a class name which is responsible for keeping server parameters in the old XML file. You can do it in two ways:\n\n. Add a parameter to init.properties file:\n+\n[source,bash]\n-----\n--tigase-config-repo-class=tigase.conf.ConfigXMLRepository\n-----\n. Or you can pass a system property to the JVM at the startup time:\n+\n[source,bash]\n-----\n-Dtigase-config-repo-class=tigase.conf.ConfigXMLRepository\n-----\n\n== Going Further\n\nAs the configuration mechanism in the Tigase server offers pluggable storage engines, you can easily write your own engine by implementing the interface: +tigase.conf.ConfigRepositoryIfc+ or by extending one of current implementations.\n\nThe whole configuration framework is pluggable and you can replace it completely if it does not suit you well enough. Your implementation has to extend +tigase.conf.ConfiguratorAbstract+ class and can be set using JVM system property (as this is configuration framework you can't do this via any configuration system):\n\n[source,sh]\n-----\n-Dtigase-configurator=tigase.conf.Configurator\n-----\n\nThe example above shows the parameter set to the default configuration framework.\n\n== Message Router Implementation is Configurable Too\n\nThe Message router component was the only component which was fixed to the Tigase instance. In theory it could always have been replaced but in practice there was no way of doing it as that was the first element loaded at startup.\n\nNow Tigase message router implementation can be easily replaced to and it can be made a configurable option if needed.\n\nAt the server startup time the code creates configurator and calls method: +getMessageRouterClassName()+ which by default returns class: +tigase.server.MessageRouter+. You can extend the configurator and provide any different class name instead which implements required interfaces. You can even make it configureable as it is no longer tied to the server instance.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_13_-_Configuration_-_E_-_JVM_settings.asciidoc",
    "content": "[[jvm_settings]]\n= JVM settings and recommendations\n:author: Daniel Wisnewski <wojte@tigase.org>\n:version: v1.0, June 2016.\n:date: 2016-06-02\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase configuration file `tigase.conf` (described in more detail in <<manualconfig>>) mentioned a couple of environmental variables which are related to the operation of the JVM. In this guide we would like to expound on those configuration options and provide hints for the optimal settings.\n\nSettings included in the `etc/tigase.conf` are as follows:\n\n[source, bash]\n----\n#GC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly\"\n#EX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n\n#GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"\n\n#PRODUCTION_HEAP_SETTINGS=\" -Xms5G -Xmx5G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m \"\n----\n\nAnd while this file utilizes bash variables, JVM configuration options can be used in the same manner on all operating systems.\n\nThe guide will consists of two main parts - memory settings and Garbage Collector tweaks descriptions and hints.\n\nWe recommend using `-server` JVM parameter in all cases.\n\n== Heap Sizing\n\nFor the non-production deployments (development or stating environments) we recommend using default memory settings of the JVM (which depends on the underlaying operating system), which result i automatic memory allocation and, by the rule of thumb - are the safest in such environments.\n\nFor the production environments we recommend a fixed size HEAP - both initial and maximum size, which can be set with (respectively)`-Xms` and `-Xmx` JVM flags - ideally to the same value (which should be roughtly 95% of the available memory, if Tigase will be the only service on the machine) to avoid allocation and deallocation.\n\nFor convenience it's possible to uncomment line with `PRODUCTION_HEAP_SETTINGS` and adjust parameters accordingly.\n\n== GC settings\n\nLet's start with stating that there is no \"one to rule them all\" - each deployment and use-case is different, however we will try to give a couple of pointers and recommendations proceed with short introduction to GC itself.\n\nXMPP is quite specific in terms of memory allocation - short-lived objects (various types of stanzas) usually exceed number of long-lived objects (user connections and related data). This is important bit of information in the context of how usually JVM HEAP is organised and how Garbage Collector works. On the most basic level Heap is separated into couple of regions:\n\n=== Generations\n\n* *Young Generation*, which is further divided in to:\n** *Eden* - the region when the objects are usually allocated when they are created;\n** *Survivor Spaces* - (_to_ and _from_ - one of which is always empty) - responsible for storing all live object remaining after collecting *Young Generation* (process is repeated several times until objects are finally considered _old enough_);\n* *Old Generation* - (_Tenured Space_) - responsible for live objects remaining after running GC on *Survivor Spaces* - those would be _long-lived_ objects (usually user connections and associated data);\n\n=== Minor, Major and Full GC - optimizing\n\nGeneral thinking suggests that:\n* *Minor GC* cleans Young generation;\n* *Major GC* cleans Tenured space;\n* *Full GC* cleans all heap.\n\nHowever, while we can certainly state that Minor GC cleans Young generation it's a bit more difficult to differentiate Major and Full GC, especially considering that Major GC can be quite often triggered by Minor GC and some garbage collectors can perform cleaning concurrently. Instead of focusing of distinguishing phases one should pay closer attention to actual operations of Garbage Collector itself - uncommenting the line `GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"` in `etc/tigase.conf` (or adding same properties to the java commandline) and subsequently analyzing the results should prove more helpful. In addition monitoring GC operation using for example VisualVM (with VisualGC plugin) will also be helpful.\n\n=== Settings for XMPP\n\nIdeally we should limit both number of GC pauses as well as their duration. After running rather tests following conclusions were made:\n\n* Garbage Collection is the faster the more dead objects occupies given space, therefore on high-traffic installation it’s better to have rather large YoungGen resulting in lower promotion of the objects to the OldGen;\n* with JVM8 default sizing of Young / Old generation changed, even tho NewRatio is still defaulting to “2” - setting it explicitly to \"2\" brought back previous sizing;\n* Concurrent Mark and Sweep (CMS) enabled (applies to Tenured space only) with explicit configuration of NewRatio set to default value of 2 (i.e. `-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2`) in general behaves best;\n* For small installations (few core CPU, less memory) with low traffic default Parallel collector may be a better solution;\n* Using Heap size adjusted to the actual usage is better as the larger the heap the larger are spaces over which collection needs to be performed thus resulting in longer pauses; in case of huge heaps G1 collector may be better solution to avoid longer pauses;\n\nConsidering all of the above using following options should be a good starting point toward further optimizing of Garbage Collection:\n\n`GC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly\"`\n\n=== GC settings worth considering\n\nIn addition to the general recommendation to use CMS collector, following options (or changes to the options) may be worth considering:\n\n* `-XX:NewRatio=2` - defines the ratio between the young and tenured generation is 1:2. In other words, the combined size of the eden and survivor spaces will be one-third of the total heap size. The parameters NewSize and MaxNewSize bound the young generation size from below and above. Setting these to the same value fixes the young generation, just as setting -Xms and -Xmx to the same value fixes the total heap size.\n* `-XX:CMSInitiatingOccupancyFraction=percent` - sets the percentage of the old generation occupancy (0 to 100) at which to start a CMS collection cycle.\n* `-XX:+UseCMSInitiatingOccupancyOnly` - instructs the JVM not to base its decision when to start a CMS cycle on run time statistics but instead it uses the value of CMSInitiatingOccupancyFraction for every CMS cycle.\n* `-XX:ParallelGCThreads=x` - sets the number of threads used for parallel garbage collection in the young and old generations. The default value depends on the number of CPUs available to the JVM. If the Tigase JMV is the only one running on the installation default value is recommended.\n* `-XX:ConcGCThreads=x` - sets the number of threads used for concurrent GC. The default value depends on the number of CPUs available to the JVM. If the Tigase JMV is the only one running on the installation default value is recommended.\n* `-XX:+UseBiasedLocking` and `-XX:+DoEscapeAnalysis` - designed to eliminate locking overhead, however their effect on performance is unpredictable therefore testing is required; reduced locking should improve concurrency and, on current multi-core hardware, improve throughput.\n* `-XX:+OptimizeStringConcat` - enables the optimization of String concatenation operations. This option is enabled by default.\n* `-XX:+UseNUMA` - enables performance optimization of an application on a machine with nonuniform memory architecture (NUMA - most modern computers are based on NUMA architecture) by increasing the application's use of lower latency memory. By default, this option is disabled and no optimization for NUMA is made. The option is only available when the parallel garbage collector is used (-XX:+UseParallelGC).\n* `-XX:-UseCompressedOops` -- disables the use of compressed pointers. By default, this option is enabled, and compressed pointers are used when Java heap sizes are less than 32 GB. When this option is enabled, object references are represented as 32-bit offsets instead of 64-bit pointers, which typically increases performance when running the application with Java heap sizes less than 32 GB. This option works only for 64-bit JVMs.\n\n== What to use with Machine x, y, z?\n\n=== Server class machine (non-VM), > 16GB, >= 8 core CPU\n\nFor such setup enabling CMS garbage collector is recommended. Depending on the traffic usage and particular use-case adjusting NewRatio may be needed. Adjusting Xms and Xms sizes for actual available memory is needed (or better yet, for the actual traffic!). Following should be used:\n[source, bash]\n----\nGC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly\"\nEX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n\n#GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"\n\nPRODUCTION_HEAP_SETTINGS=\" -Xms15G -Xmx15G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m \"\n----\n\nFor installation with lot of available memory and intention to utilize it all, using G1GC collector may be a better idea :\n[source, bash]\n----\nGC=\"-XX:+UseG1GC -XX:ConcGCThreads=4 -XX:G1HeapRegionSize=2 -XX:InitiatingHeapOccupancyPercent=35 -XX:MaxGCPauseMillis=100\"\nEX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n\n#GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"\n\nPRODUCTION_HEAP_SETTINGS=\" -Xms60G -Xmx60G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m \"\n----\n\n=== VM machine, 8GB of RAM, 4 core CPU equivalent\n\nFor such setup enabling CMS garbage collector is also recommended. Depending on the traffic usage and particular use-case adjusting NewRatio may be needed (and configuring NewRatio is a must!). Adjusting Xms and Xms sizes for actual available memory is needed (or better yet, for the actual traffic!). Following should be used:\n[source, bash]\n----\nGC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly\"\nEX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n\n#GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"\n\nPRODUCTION_HEAP_SETTINGS=\" -Xms7G -Xmx7G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m \"\n----\n\n=== VM machine with 4GB or less of RAM, and less than 4 core CPU equivalent\n\nSmall installations with limited resources could operate better with default (for JVM versions up to 8, which is the most current at the moment of the writing). Again - depending on the traffic usage and particular use-case adjusting NewRatio may be needed. Adjusting Xms and Xms sizes for actual available memory is recommended (or better yet, for the actual traffic!). Following should be used (i.e. `GC` line should be commented so the defaults will be used):\n[source, bash]\n----\n#GC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly\"\nEX=\"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA\"\n\n#GC_DEBUG=\" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc \"\n\nPRODUCTION_HEAP_SETTINGS=\" -Xms3G -Xmx3G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m \"\n----\n\n== Additional resources\n\n* https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html[Sizing the Generations]\n* http://www.c0t0d0s0.org/archives/6617-About-Java,-parallel-garbage-collection-and-processor-sets.html[About Java, parallel garbage collection and processor sets]\n* http://hiroshiyamauchi.blogspot.cl/2009/12/gc-threads.html[GC Threads]\n* https://github.com/chewiebug/GCViewer#readme[GCViewer readme]\n* http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html[Java HotSpot™ Virtual Machine Performance Enhancements]\n* https://plumbr.eu/java-garbage-collection-handbook[Java Garbage Collection handbook]\n* Useful JVM Flags\n** https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-1-jvm-types-and-compiler-modes/[Part 1 - JVM Types and Compiler Modes]\n** https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-2-flag-categories-and-jit-compiler-diagnostics/[Part 2 - Flag Categories and JIT Compiler Diagnostics)]\n** https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-3-printing-all-xx-flags-and-their-values/[Part 3 - Printing all XX Flags and their Values]\n** https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-4-heap-tuning/[Part 4 - Heap Tuning]\n** https://blog.codecentric.de/en/2012/08/useful-jvm-flags-part-5-young-generation-garbage-collection/[Part 5 - Young Generation Garbage Collection]\n** https://blog.codecentric.de/en/2013/01/useful-jvm-flags-part-6-throughput-collector/[Part 6 - Throughput Collector]\n** https://blog.codecentric.de/en/2013/10/useful-jvm-flags-part-7-cms-collector/[Part 7 - CMS Collector]\n** https://blog.codecentric.de/en/2014/01/useful-jvm-flags-part-8-gc-logging/[Part 8 - GC Logging]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_14_-_Security.asciidoc",
    "content": "= Security\n:author: Daniel Wisnewski\n:version: v1.0 October, 2015\n:date: 2015-05-10 13:31\n\nThe articles here cover advanced security features built into to Tigase Server, and some options for adding your own levels of security.\n\n[[blockingCommand]]\n== XEP-0191 Support\n\nThe simplest security feature, however, inside an XMPP server is the ability to block users and JIDS. link:http://xmpp.org/extensions/xep-0191[XEP-0191] specifies the parameters of simple blocking without using privacy lists. Below is a breakdown and some sample commands you may find helpful.\nTo enable this feature, be sure the following is in your init.properties file:\n----\n--sm-plugins +urn:xmpp:blocking\n----\nIf you have other plugins running, then just add ++urn:blocking+ to the list to activate this feature.\n\n\nTo confirm if your installation of Tigase supports this feature, a quick disco#info of your server should reveal the following feature:\n-----\n<feature var='urn:xmpp:blocking'/>\n-----\n\nBlocked users are stored on the server on a per-JID basis, so one user may only see his or her blocked JIDs.  Lists of blocked JIDs will return as an IQ stanza with a list of <item> fields.  To retrieve the blocklist, the following command is issued:\n[source,xml]\n-----\n<iq type='get' id='blockedjids'>\n  <blocklist xmlns='urn:xmpp:blocking'/>\n</iq>\n-----\nThe server responds:\n[source,xml]\n-----\n<iq type='result' id='blockedjids'>\n  <blocklist xmlns='urn:xmpp:blocking'>\n    <item jid='user1@domain.net'/>\n    <item jid='admin@example.com'/>\n  </blocklist>\n</iq>\n-----\n\nTo block a JID, a similar stanza to the one above is sent to the server with the items of the blocked JIDs you wish to add:\n[source,xml]\n-----\n<iq from='admin@domain.net' type='set' id='block'>\n  <block xmlns='urn:xmpp:blocking'>\n    <item jid='user2@domain.net'/>\n  </block>\n</iq>\n-----\nThe server will then push an unavailable presence to blocked contacts.  Communication between a contact that is blocked, and an entity that blocked it will result in a <not-acceptable> error:\n[source,xml]\n-----\n<message type='error' from='user2@domain.net' to='admin@domain.net'>\n  <body>Hello, are you online?</body>\n  <error type='cancel'>\n    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>\n    <blocked xmlns='urn:xmpp:blocking:errors'/>\n  </error>\n</message>\n-----\n\nUnblocking a contact is just as easy as blocking, send an unblock stanza to the server:\n[source,xml]\n-----\n<iq from='admin@domain.net' type='set' id='unblock'>\n  <unblock xmlns='urn:xmpp:blocking'>\n    <item jid='user2@domain.net'/>\n  </unblock>\n</iq>\n-----\nThe server will begin pushing presence information to unblocked contacts and resources so long as permissions have not changed between.\n\nYou may also opt to unblock all contacts and essentially clear out your blocked list using the following command:\n[source,xml]\n-----\n<iq type='set' id='unblockall'>\n  <unblock xmlns='urn:xmpp:blocking'/>\n</iq>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_15_-_Security_-_A_-_Server_Certificates.asciidoc",
    "content": "[[ServerCertificates]]\n= Server Certificates\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n\n- xref:certspem[Creating and Loading the Server Certificate in pem Files]\n- xref:startcomCertificate[Installing StartCom Certificate in Your Linux System]\n//- xref:keytoolKeystore[Server Certificate Using Keytool and Keystore]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_16_-_Security_-_A_-_Server_Certificates_-_1_-_Creating_and_Loading_the_Server_Certificate_in_PEM_Files.asciidoc",
    "content": "[[certspem]]\n= Creating and Loading the Server Certificate in pem Files\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:Revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n== Server Certificates\n\nServer certificates are needed when you use secure socket connections - SSL/TLS.\n\nFor secure socket connection a proper certificate is needed. You can either generate your own self-signed certificate or obtain certificate from trusted third party organization.\n\nHere are steps how to obtain certificate from a trusted organization.\n\n=== Generating your Own Certificates\n\nSelf-signed certificates can be generated easily on a Linux system.  Although it may not be considered a 'trusted' certificate authority, it can be useful to test server installations.  *We do not recommend regular use of self-signed certificates*.\n\nNote that Tigase v5.0 and later can automatically create self signed PEM files if needed.  However we will cover doing this process by hand.\n\nThis tutorial assumes you are running a Linux-based operating system with access to command shell, and the 'Openssl' package is installed on the system.\n\nThe process takes the following steps: +\n1. Create a local private key.  This file ends with .key extension.  It is recommended to create a new private key for the process. +\n2. Generate a certificate request.  This file ends with the .csr extension and is the file sent to the Certificate Authority to be signed. +\n3. CA signs private key.  This can be done by your own computer, but can also be done by private CAs for a fee. +\n4. Results are obtained from the CA.  This is a .crt file which contains a separate public certificate. +\n5. Combine the .csr and .crt file into a unified .pem file.  Tigase requires keys to be non-password protected PEM files. +\n\n.Generate local private key\n[source,sh]\n-----\nopenssl genrsa -out[domain.com.key] 1024\n-----\nThis command generates a private key using a 1024 bit RSA algorithm.  -out designates the name of the file, in this case it will be *domain.com.key*. The exact name is not important, and the file will be created in whatever directory you are currently in.\n\n.Generate a certificate request:\n[source,sh]\n-----\nopenssl req -nodes -key domain.com.key -out domain.com.csr\n-----\nThis command generates a certificate request using the file specified after -key, and the result file will be domain.com.csr.  You will be asked a series of questions to generate the request.\n\n[source,sh]\n-----\nCountry Name (2 letter code) [AU]:AU\nState or Province Name (full name) [Some-State]:Somestate\nLocality Name (eg, city) []:Your city name\nOrganization Name (eg, company) [Internet Widgits Pty Ltd]:Company name\nOrganizational Unit Name (eg, section) []:Department or any unit\nCommon Name (eg, YOUR name) []:*.yourdomain.com\nEmail Address []:your_email_address@somedomain.com\n\nPlease enter the following 'extra' attributes\nto be sent with your certificate request\nA challenge password []:\nAn optional company name []:\n-----\n\n.Sign the Certificate Request:\nNow the .csr file will be signed by a Certificate Authority.  In this tutorial, we will be self-signging our certificate.  This practice however is generally not recommended, and you will receive notifications that your certificate is not trusted.  There are commercial offers from companies to sign your certificate from trusted sources.  Please see the xref:OtherSources[Certificate From Other Providers] section for more information.\n[source,bash]\n-----\nopenssl x509 -req -days 365 -in domain.com.csr -signkey domain.com.key -out domain.com.crt\n-----\nThis command signs the certificate for 365 days and generates the domain.com.crt file. You can, of course use any number of days you like.\n\n.Generate PEM file\nYou should now have the following files in the working directory:\n..\\\ndomain.com.key\ndomain.com.csr\ndomain.com.crt\n\n[source,sh]\n-----\ncat yourdomain.com.crt yourdomain.com.key > yourdomain.com.pem\n-----\n\nIf the certificate is issued by third-party authority you will have to attach the certificate chain, that being certificate of the authority who has generated your certificate. You normally need to obtain certificates for your chain from the authority who has generated your certificate. For example, if you have a certificate from XMPP federation you need to download link:http://www.startssl.com/certs/ca.pem[StartCom root certificate] *and* link:http://www.startssl.com/certs/sub.class1.server.ca.pem[intermediate ICA certificate]. In such cases the pem file is created using following command:\n\n[source,sh]\n-----\ncat yourdomain.com.crt yourdomain.com.key sub.class1.xmpp.ca.crt ca.crt > yourdomain.com.pem\n-----\n\nThe result file should looks similar to:\n\n[source,sh]\n------\n-----BEGIN CERTIFICATE-----\nMIIG/TCCBeWgAwIBAgIDAOwZMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ\n.\n.\n.\npSLqw/PmSLSmUNIr8yQnhy4=\n-----END CERTIFICATE-----\n-----BEGIN RSA PRIVATE KEY-----\nWW91J3JlIGtpZGRpbmchISEKSSBkb24ndCBzaG93IHlvdSBvdXIgcHJpdmF0ZSBr\n.\n.\n.\nZXkhISEhCkNyZWF0ZSB5b3VyIG93biA7KSA7KSA7KQo=\n-----END RSA PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW\n.\n.\n.\nxV/stleh\n-----END CERTIFICATE-----\n------\n\nFor Tigase server as well as many other servers (Apache 2.x), the order is following; your domain certificate, your private key, authority issuing your certificate, root certificate.\n\n*Note! Tigase requires full certificate chain in PEM file (described above)! Different applications may require pem file with certificates and private key in different order. So the same file may not be necessarily used by other services like Web server or e-mail server. Currently, Tigase can automatically sort certificates in PEM file while loading it.*\n\n== Installing/Loading Certificate To the Tigase Server\n\nFrom version *3.1.0-b802* of Tigase server, installing and loading certificates is very easy. The server can load all certificates directly from *pem* files. You just need to create a separate pem file for each of your virtual domains and put the file in a directory accessible by the server. Tigase server can automatically load all *pem* files found in given directory.  By default, and to make things easy, we recommend the +Tigase/certs+ directory.\n\n[[OtherSources]]\n== Certificate From Other Providers\n\nThere is number of certificate providers offering certificates either for free or for money. You can use any of them, however you have to be aware that sometimes certificates might not be recognized by all XMPP servers, especially if it's one from a new provider. Here is an example list of providers:\n\n- link:https://www.cacert.org/[CAcert] - free certificates with an excellent Web GUI for managing generated certificates and identities.\n- link:https://www.startssl.com/[StartCom] - both free and paid certificates, class 1, 2 and 3. Very good GUI for managing certificates and identities.\n- link:https://www.verisign.com/[Verisign] - very expensive certificates comparing to above provides but the provider is recognized by everybody. If you have a certificate from Verisign you can be sure it is identified as a valid certificate.\n- link:http://www.comodo.com/business-security/digital-certificates/ssl-certificates.php[Comodo Certificate Authority] offers different kind of commercial certificates\n\nTo obtain certificate from a third party authority you have to go to its website and request the certificate using certificate request generated above. I cannot provide any instructions for this as each of the providers listed have different requirements and interfaces.\n\n[[onecertmultipledomain]]\n== Using one certificate for multiple domains\nBy default, each virtual hosts will require it's own certificate.  However, if you choose to use one certificate for all virtual hosts, Tigase supports that option.\nFor example, if you have host1.example.net, host2.example.net, and host3.example.net each vhost will need some configuration:\n[source,properties]\n-----\nbasic-conf/virtual-hosts-cert-host1.example.net=/home/tigase/certs/host1.pem\nbasic-conf/virtual-hosts-cert-host2.example.net=/home/tigase/certs/host2.pem\nbasic-conf/virtual-hosts-cert-host3.example.net=/home/tigase/certs/host3.pem\n-----\nThis may be time consuming if you have many Vhosts, or expect to generate many more.  The good news is, now one certificate can be used for ALL Vhosts using the following configuration line:\n[source,properties]\n-----\nbasic-conf/virt-hosts-cert-*.example.net=/home/tigase/certs/certificate.pem\n-----\n\nNow any Vhosts created will use the same certificate located at /home/tigase/certs/certificate.pem. *NOTE:* This is an all or nothing option, if you wish to customize each Vhost, you will need to do so individually.\n\n\n== Tigase Server Configuration for 5.1.0 and older\n\nStarting from version 5.1.0 and newer it's not needed to use external libraries nor extra configuration in the init.properties file. With this version Tigase uses, loaded by default thus no need to configure it, following class:\n\n[source,bash]\n-----\n--ssl-container-class=tigase.io.SSLContextContainer\n-----\n\nOlder versions require different configurations. In order to be able to load server certificates directly from *pem* files you need to have *tigase-extras* package installed in your server *libs/* directory in version at least *0.1.0*. If you use a Tigase server binary package other than *mini*, this library is included by default. If you haven't changed anything in your XML configuration file, put following line in your +initial.properties+ file:\n\n[source,bash]\n-----\n--ssl-container-class=tigase.extras.io.PEMSSLContextContainer\n-----\n\nCopy all your *pem* files with certificates into certs/ subdirectory in Tigase server installation, stop the server, remove XML configuration file and start the server. XML configuration will be automatically regenerated with the new SSLContainer used by all components and all certificates will be automatically loaded.\n\nIf you have changed your XML configuration file, and do not want to lose those changes, you will now have to manually change the existing SSLContainer class with the new one. Just replace all occurrences of the default SSLContainer - tigase.io.SSLContextContainer with the new - tigase.extras.io.PEMSSLContextContainer, copy all your *pem* files with certificates into certs/ subdirectory in Tigase server installation and restart the server.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_17_-_Security_-_A_-_Server_Certificates_-_2_-_Installing_StartCom_Certificate_in_your_Linux_System.asciidoc",
    "content": "[[startcomCertificate]]\n= Installing StartCom Certificate in Your Linux System\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe third party authority for free XMPP server certificates is link:http://cert.startcom.org/[Startcom]. Startcom root certificates are not normally known to your system as a valid a certificate and appear as a self-signed certificate.\n\nTo make it known to your system as valid you will have to install it in your system.\n\nIn any case on any operating system, you have to download the certificate from the issuer link:http://cert.startcom.org/?lang=en&app=110[web site].\n\n== Gentoo Linux\n\n. Copy downloaded ca.crt file to /etc/ssl/certs/starcom_ca.crt file.\n. Run command:\n+\n[source,sh]\n-----\nupdate-ca-certificates\n-----\n\nAll done. To test it, run following command:\n\n[source,sh]\n-----\nopenssl s_client -connect tigase.org:5223 -CApath /etc/ssl/certs\n-----\n\nScroll the output up and look for something like:\n\n[source,bash]\n-----\nverify return:1\n-----\n\nWhich means certificate verification was successful. If you find however:\n\n[source,bash]\n-----\nverify return:0\n-----\n\nLook one line up for an error message which may look like this:\n\n[source,bash]\n-----\nverify error:num=19:self signed certificate in certificate chain\n-----\n\nWhich means the root certificate is still not recognized in your system.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_18_-_Security_-_A_-_Server_Certificates_-_3_-_Server_Certificate_Using_Keytool_and_Keystore.asciidoc",
    "content": "[[keytoolKeystore]]\n= Server Certificate Using Keytool and Keystore\n:author: Bartosz Malkowski <bmalkowski@tigase.pl>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTo allow secure connections through SSL or TLS channel you need a SSL certificate.\n\nThe main purpose of SSL certificate is to provide connecting entity with proof of identity of your server. A Significant role in proving the identity of your server is played by a trusted third party - usually the issuer of the certificate.\n\nCertificate issued by trusted third parties usually come with a cost. However, you can also use self signed certificate which works just as well. The downside is it gives an authentication warning on client software upon connection.\n\nTigase server binary package and source repositories contain so-called \"dummy\" certificates which do not refer to any real site name. This certificate is temporary and should be used only for initial testing of your server. It should be replaced with either a self signed certificate or one issued by trusted third party organization as soon as possible.\n\nHere are instructions how to install certificates for Tigase server.\n\n_Please note! You must use the *keytool* program included in JDK-1.6 or later. The utility included in earlier versions can not import third party signed certificates correctly._\n\n== Self Signed Certificate\n\nIf you don't have a third party signed certificate, you should generate a self-signed certificate.\n\nSome XMPP clients don't work correctly with DSA keys, so we need to use RSA algorithm for generation. To generate private and public keypair, you should use keytool with the following commands:\n\n[source,sh]\n-----\nkeytool -genkey -alias yourdomain -keystore rsa-keystore \\\n    -keyalg RSA -sigalg MD5withRSA\n-----\n\nWhere +yourdomain+ is a domain part of _JIDs_ on your _XMPP_ server. If you want to have TLS support for virtual domains, you have to create certificate for each virtual domain. If you have just one domain, or for some reason you have to use one certificate for all domains, use +default+ as an alias.\n\nNow, enter the password to protect the keystore:\n\n[source,sh]\n-----\nEnter keystore password: 123456\n-----\n\nThe keytool will ask several questions about the certificate data. First question is very important! You must enter the hostname of your XMPP server!!\n\n[source,sh]\n-----\nWhat is your first and last name?\n  [Unknown]: jabber.myserver.org\nWhat is the name of your organizational unit?\n  [Unknown]:\nWhat is the name of your organization?\n  [Unknown]:\nWhat is the name of your City or Locality?\n  [Unknown]:\nWhat is the name of your State or Province?\n  [Unknown]:\nWhat is the two-letter country code for this unit?\n  [Unknown]:\nIs CN=jabber.myserver.org, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?\n  [no]: yes\n-----\n\nIn last step you can enter a new password for the certificate key. At the moment different passwords for both keystore and keys are not supported so you must have the same passwords for each.\n\n[source,sh]\n-----\nEnter key password for <mykey>\n             (RETURN if same as keystore password):\n-----\n\nNow you have to copy the rsa-keystore file to directory certs/ in your tigase server installation directory. The file may be installed in different location, but then corrections to config file are required. Refer to xref:manualconfig[manual configuration] for details.\n\n== Certificate from Certificate Authority\n\nIf you don't have third-party signed certificate yet but you want to have one, you could obtain it from link:http://www.cacert.org/[cacert.org] for free.\n\nFirst, you have to generate a Certificate Request using keytool:\n\n[source,sh]\n-----\nkeytool -certreq -alias yourdomain -keystore rsa-keystore\n-----\n\nWhere +yourdomain+ is a domain name for which this certificate is generated. If you need support for multiple virtual domains, you need to have certificate for each domain separately and assign proper alias to the certificates. If you have just one domain or for some reason you want to use one certificate use +default+ as an alias for all domains.\n\nKeytool generates the request:\n\n[source,bash]\n------\n-----BEGIN NEW CERTIFICATE REQUEST-----\nMIIBrzCCARgCAQAwbzEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UE\nBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjETMBEGA1UEAxMK\nc2VydmVyLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs73Y70725OcG0j4kpCfDX59e\nqhz2gdGOO0LyMO7rm4m+ZCenq8E88M0RJ8/LV/7q0mtOAzbI8dtXZnmJ74xihCH8ZTFpVDMyFWgk\nWCj2kz+IUD9vWt6i1UepSkr1a/jYmVMN3RSaoS+j+QLBsJ4rWeOHgIdbiF5tnMhoZMXU//0CAwEA\nAaAAMA0GCSqGSIb3DQEBBAUAA4GBAHY5r9rftqiKESbbkCcfVhvnUqN4aMTC8/zXWwzBX8guC0kd\nH46+p6eizwJg6p+h6rqShG2OqXCPrJzO3buHr1jEWRTlB8l5CM53L/xq61nYuaSf5R7Vv/RX2+aD\nJyoBqYIoSUED0+Sjhej0SUPTOdpA/bfnqdfdtckday4vsLPC\n-----END NEW CERTIFICATE REQUEST-----\n------\n\nNow send the request to your Certificate Authority. The CA issues a signed certificate and sends it to you. It may may look like:\n\n[source,bash]\n------\n-----BEGIN CERTIFICATE-----\nMIICUDCCAbkCBEUqAK0wDQYJKoZIhvcNAQEEBQAwbzEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UE\nCBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMH\nVW5rbm93bjETMBEGA1UEAxMKc2VydmVyLm9yZzAeFw0wNjEwMDkwNzU2MjlaFw0wNzAxMDcwNzU2\nMjlaMG8xEDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vua25v\nd24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xEzARBgNVBAMTCnNlcnZlci5v\ncmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALO92O9O9uTnBtI+JKQnw1+fXqoc9oHRjjtC\n8jDu65uJvmQnp6vBPPDNESfPy1f+6tJrTgM2yPHbV2Z5ie+MYoQh/GUxaVQzMhVoJFgo9pM/iFA/\nb1reotVHqUpK9Wv42JlTDd0UmqEvo/kCwbCeK1njh4CHW4hebZzIaGTF1P/9AgMBAAEwDQYJKoZI\nhvcNAQEEBQADgYEAQqRPdkbc/pdDcPIWOThn2XPp0gitPkXq89ZM1mb0Pib1OISj9ekjqhEZz0UA\ncI6g1XttpY6hKi6Gg+mRbwiHNVebkDLamE2UIcVJ1wBtowYeOcV1CcLnlj91ScMKNhfD5ebQL+be\ntWWrJX3ep+80kF/NdVkc7htGOhLebopp8SQ=\n-----END CERTIFICATE-----\n------\n\nSave the Certificate to a disk file.\n\nNow that you have third-party signed certificate, you have to import it with *keytool* program to server certificate storage.\n\n_Note! You must have a root CA certificate!!! You can download the cert from CA (ie.: root.crt) and import:_\n\n[source,sh]\n-----\nkeytool -import -keystore rsa-keystore -file root.crt \\\n    -alias root\n-----\n\nLast step is import the Certificate to your keystore:\n\n[source,sh]\n-----\nkeytool -import -alias yourdomain -keystore rsa-keystore \\\n    -file your-certificate.cer\n-----\n\nWhere +yourdomain+ is a domain name for which this certificate has been generated. If you need support for multiple virtual domains you have to import certificate for each domain separately and assign proper alias to each certificate. If you have just one domain or for some reason you want to use one certificate use +default+ as an alias for all domains.\n\nIt's also good to import root CA certificate to this keystore. //You must find it on CA website.\n\n[source,sh]\n-----\nkeytool -import -keystore rsa-keystore -file rootCA.cer\n-----\n\nIt may also generate certreq using +openssl+ for use in other services like WWW. In such a case you may have your private key and certificate in separate files. Let's say private key is in ssl.key file and certificate is in +ssl.crt+ file. To merge them into a single file together use following command:\n\n[source,sh]\n-----\nopenssl pkcs12 -export -inkey ssl.key -in ssl.crt \\\n    -out mycert.pfx -name \"default\"\n-----\n\nNow you can load certificate with a private key to your keystore:\n\n[source,sh]\n-----\nkeytool -importkeystore -srckeystore mycert.pfx \\\n    -srcstoretype pkcs12 -destkeystore rsa-keystore \\\n    -srcalias default -destalias yourdomain \\\n    -destkeypass your_keystore_pass\n-----\n\n*Note!* _Please note -destkeypass parametr. Your keys password must be the same as keystore password. Otherwise it won't work._\n\nNow you have to copy file +rsa-keystore+ to directory +certs/+ in your tigase server installation. The file could also be installed in different location but then corrections to the config file are required. Refer to configuration documentation for details.\n\nFinally, don't forget to modify tigase server configuration file and set proper password for your keystore.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_19_-_Security_-_B_-_Authentication_Connectors.asciidoc",
    "content": "[[customAuthentication]]\n= Custom Authentication Connectors\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis article presents configuration options available to the administrator and describe how to set Tigase server up to use user accounts data from a different database.\n\nThe first thing to know is that Tigase server always opens 2 separate connections to the database. One connection is used for user login data and the other is for all other user data like the user roster, vCard, private data storage, privacy lists and so on...\n\nIn this article we still assume that Tigase server keeps user data in it's own database and only login data is retrieved from the external database.\n\nAt the moment Tigase offers following authentication connectors:\n\n- 'mysql', 'pgsql', 'derby' - standard authentication connector used to load user login data from the main user database used by the Tigase server. In fact the same physical implementation is used for all JDBC databases.\n- 'drupal' - is the authentication connector used to integrate the Tigase server with link:http://drupal.org/[Drupal CMS].\n- 'libresource' - is the authentication connector used to integrate the Tigase server with link:http://dev.libresource.org/[Libresource Collaboration platform].\n- 'tigase-auth' - is the authentication connector which can be used with any database. It executes stored procedures to perform all actions. Therefore it is a very convenient way to integrate the server with an external database if you don't want to expose the database structure. You just have to provide a set of stored procedures in the database. While implementing all stored procedures expected by the server might be a bit of work it allows you to hide the database structure and change the SP implementation at any time. You can add more actions on user login/logout without restarting or touching the server. And the configuration on the server side is very simple. For detailed description of this implementation please refer to xref:tigaseAuthConnector[Tigase Auth documentation].\n- 'tigase-custom' - is the authentication connector which can be used with any database. Unlike the 'tigase-auth' connector it allows you to define SQL queries in the configuration file. The advantage of this implementation is that you don't have to touch your database. You can use either simple plain SQL queries or stored procedures. The configuration is more difficult as you have to enter carefully all SQL queries in the config file and changing the query usually involves restarting the server. For more details about this implementation and all configuration parameters please refer to xref:custonAuthConnector[Tigase Custom Auth documentation].\n\nAs always the simplest way to configure the server is through the +init.properties file+. In the article describing this file you can find long list with all available options and all details how to handle it. For the authentication connector setup however we only need 2 options:\n\n- '--auth-db = connector'\n- '--auth-db-uri = database connection url'\n\nIf you happen to keep the user data in the same database as user authentication data you can even skip the second parameter as Tigase automatically assumes settings from the '--user-db-uri' it '--auth-db-uri' is missing.\n\n'--auth-db-uri' stored a standard JDBC connection URL and is exactly the same as for all other settings. For example if you store authentication data in a 'drupal' database on 'localhost' the URL might look like:\n\n[source,bash]\n-----\n--auth-db-uri = jdbc:mysql://localhost/drupal?user=user&password=passwd\n-----\n\n'--auth-db' stored just a connector name or connector implementation class. For convenience Tigase has predefined short names for the most common connectors but you can always use the class name if you know it. You have to use a class name if you want to attach your own authentication connector. The following 2 settings are equal:\n\n[source,bash]\n-----\n--auth-db = tigase-auth\n-----\n\n[source,bash]\n-----\n--auth-db = tigase.db.jdbc.TigaseAuth\n-----\n\nIn the same exact way you can setup connector for any different database type:\n\n[source,bash]\n-----\n--auth-db = drupal\n-----\n\n[source,bash]\n-----\n--auth-db = tigase-custom\n-----\n\nYou can normally skip configuring connectors for the default Tigase database format: 'mysql', 'pgsql' and 'derby' as they are applied automatically if the parameter is missing.\n\nOne more important thing to know is that you will have to modify '--user-db-uri' if you use a custom authentication connector. This is because if you retrieve user login data from the external database this external database is usually managed by an external system. User accounts are added without notifying Tigase server. Then, when the user logs in and tries to retrieve the user roster, the server can not find such a user in the roster database.\n\nTo keep user accounts in sync between the authentication database and the main user database you have to add following option to the end of the database connection URL: 'autoCreateUser=true'.\n\nFor example:\n\n[source,bash]\n-----\n--user-db-uri=jdbc:mysql://localhost/tigasedb?user=nobody&password=pass&autoCreateUser=true\n-----\n\nIf you are interested in even further customizing your authentication connector by writing your own queries or stored procedures, please have a look at 2 following guides:\n\n- xref:tigaseAuthConnector[Tigase Auth guide]\n- xref:custonAuthConnector[Tigase Custom Auth guide]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_20_-_Security_-_B_-_Authentication_Connectors_-_1_-_Tigase_Auth_Connector.asciidoc",
    "content": "[[tigaseAuthConnector]]\n= Tigase Auth Connector\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe Tigase Auth connector with shortcut name: *tigase-auth* is implemented in the class: link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/db/jdbc/TigaseAuth.java[tigase.db.jdbc.TigaseAuth]. It allows you to connect to any external database to perform user authentication.\nYou can find more details how to setup a custom connector in the xref:customAuthConnector[Custom Authentication Connectors] guide.\n\nTo make this connector working you have to prepare your database to offer set of stored procedures for Tigase server to perform all the authentication actions. The best description is the example schema with all the stored procedures defined. Please refer to the Tigase link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/database[SVN repository] for the schema definition files.\n\nFiles with the stored procedures implementations are located in link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/database[postgresql-schema-4.sql] file for PostgreSQL database.\n\nThe absolute minimum of stored procedures you have to implement is:\n\n- *TigUserLoginPlainPw* - to perform user authentication. The procedure is always called when the user tries to login to the XMPP server. This is the only procedure which must be implemented and actually must work.\n- *TigUserLogout* - to perform user logout. The procedure is always called when the user logouts or disconnects from the server. This procedure must be implemented but it can be empty and can do nothing. It just needs to exist because Tigase expect it to exist and attempts to call it.\n\nWith these 2 above stored procedures you can only perform user login/logouts on the external database. You can't register a user account, change user password or remove the user. In many cases this is fine as all the user management is handled by the external system.\n\nIf you however want to allow for account management via XMPP you have to implement also following procedures:\n\n- *TigAddUserPlainPw* - to add a new user account\n- *TigRemoveUser* - to remove existing user account\n- *TigUpdatePasswordPlainPw* - to change a user password for existing account\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_21_-_Security_-_B_-_Authentication_Connectors_-_2_-_Tigase_Custom_Auth_Connector.asciidoc",
    "content": "[[custonAuthConnector]]\n= Tigase Custom Auth Connector\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe Tigase Custom Auth connector with shortcut name: *tigase-custom* is implemented in the class: link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/db/jdbc/TigaseCustomAuth.java[tigase.db.jdbc.TigaseCustomAuth]. It allows you to connect to any external database to perform user authentication and use a custom queries for all actions.\n\nYou can find more details how to setup a custom connector in the Custom Authentication Connectors guide.\n\nThe basic configuration is very simple:\n\n[source,bash]\n-----\n--auth-db = tigase-custom\n--auth-db-uri = jdbc:mysql://localhost/drupal?user=user&password=passwd\n-----\n\nThat's it.\n\nThe connector loads correctly and starts working using predefined, default list of queries. In most cases you also might want to define your own queries in the configuration file. The shortest possible description is the following example of the content from the +init.properties+ file:\n\n[source,bash]\n-----\n# This query is used to check connection to the database, whether it is still alive or not\nbasic-conf/auth-repo-params/conn-valid-query=select 1\n\n# This is database initialization query, normally we do not use it, especially in\n# clustered environment\nbasic-conf/auth-repo-params/init-db-query=update tig_users set online_status = 0\n\n# Below query performs user authentication on the database level.\n# The Tigase server does not need to know authentication algorithm or password\n# encoding type, it simply passes user id (BareJID) and password in form\n# which was received from the client, to the stored procedure. If the\n# authentication was successful the procedure returns user bare JID or null otherwise.\n# The Tigase checks whether the JID returned from the query matches\n# JID passed as a parameter. If they match, the authentication is successful.\nbasic-conf/auth-repo-params/user-login-query={ call TigUserLoginPlainPw(?, ?) }\n\n# Below query returns number of user accounts in the database, this is mainly used\n# for the server metrics and monitoring components.\nbasic-conf/auth-repo-params/users-count-query={ call TigAllUsersCount() }\n\n# Below query is used to add a new user account to the database\nbasic-conf/auth-repo-params/add-user-query={ call TigAddUserPlainPw(?, ?) }\n\n# Below query is used to remove existing account with all user's data from the database\nbasic-conf/auth-repo-params/del-user-query={ call TigRemoveUser(?) }\n\n# This query is used for the user authentication if \"user-login-query\" is not defined,\n# that is if there is no database level user authentication algorithm available. In such\n# a case the Tigase server loads user's password from the database and compares it\n# with data received from the client.\nbasic-conf/auth-repo-params/get-password-query=select user_pw from tig_users where user_id = ?\n\n# Below query is used for user password update in case user decides to change his password\nbasic-conf/auth-repo-params/update-password-query=update tig_users set user_pw = ? where user_id = ?\n\n# Below query is called on user logout event. Usually we use a stored procedure which\n# records user logout time and marks user as offline in the database\nbasic-conf/auth-repo-params/user-logout-query=update tig_users, set online_status = online_status - 1 where user_id = ?\n\n# This is configuration setting to specify what non-sasl authentication mechanisms\n# expose to the client\nbasic-conf/auth-repo-params/non-sasl-mechs=password,digest\n\n# This is configuration setting to specify what sasl authentication mechanisms expose to the client\nbasic-conf/auth-repo-params/sasl-mechs=PLAIN,DIGEST-MD5\n-----\n\nQueries are defined in the configuration file and they can be either plain SQL queries or stored procedures. If the query starts with characters: '\\{ call' then the server assumes this is a stored procedure call, otherwise it is executed as a plain SQL query. Each configuration value is stripped from white characters on both ends before processing.\n\nPlease don't use semicolon ';' at the end of the query as many JDBC drivers get confused and the query may not work.\n\nSome queries can take arguments. Arguments are marked by question marks '?' in the query. Refer to the configuration parameters description for more details about what parameters are expected in each query.\n\nThe first example shows how to put a stored procedure as a query with 2 required parameters.\n\n[source,java]\n-----\nadd-user-query={ call TigAddUserPlainPw(?, ?) }\n-----\n\nThe same query with plain SQL parameters instead:\n\n[source,java]\n-----\nadd-user-query=insert into users (user_id, password) values (?, ?)\n-----\n\nThe order of the query arguments is important and must be exactly as described in specification for each parameter.\n\n- 'conn-valid-query' - Query executing periodically to ensure active connection with the database.\n+\nTakes no arguments.\n+\nExample query: 'select 1'\n\n- 'init-db-query' - Database initialization query which is run after the server is started.\n+\nTakes no arguments.\n+\nExample query: 'update tig_users set online_status = 0'\n\n- 'add-user-query' - Query adding a new user to the database.\n+\nTakes 2 arguments: +(user_id (JID), password)+\n+\nExample query: 'insert into tig_users (user_id, user_pw) values (?, ?)'\n\n- 'del-user-query' - Removes a user from the database.\n+\nTakes 1 argument: +(user_id (JID))+\n+\nExample query: 'delete from tig_users where user_id = ?'\n\n- 'get-password-query' - Retrieves user password from the database for given user_id (JID).\n+\nTakes 1 argument: +(user_id (JID))+\n+\nExample query: 'select user_pw from tig_users where user_id = ?'\n\n- 'update-password-query' - Updates (changes) password for a given user_id (JID).\n+\nTakes 2 arguments: +(password, user_id (JID))+\n+\nExample query: 'update tig_users set user_pw = ? where user_id = ?'\n\n- 'user-login-query' - Performs user login. Normally used when there is a special SP used for this purpose. This is an alternative way to a method requiring retrieving user password. Therefore at least one of those queries must be defined: +user-login-query+ or +get-password-query.+\n+\nIf both queries are defined then user-login-query is used. Normally this method should be only used with plain text password authentication or sasl-plain.\n+\nTigase expects a result set with user_id to be returned from the query if login is successful and empty results set if the login is unsuccessful.\n+\nTakes 2 arguments: +(user_id (JID), password)+\n+\nExample query: 'select user_id from tig_users where (user_id = ?) AND (user_pw = ?)'\n\n- 'user-logout-query' - This query is called when user logs out or disconnects. It can record that event in the database.\n+\nTakes 1 argument: +(user_id (JID))+\n+\nExample query: 'update tig_users, set online_status = online_status - 1 where user_id = ?'\n\n- 'non-sasl-mechs' - Comma separated list of NON-SASL authentication mechanisms. Possible mechanisms are: +password+ and +digest+. The digest mechanism can work only with +get-password-query+ active and only when password are stored in plain text format in the database.\n\n- 'sasl-mechs' - Comma separated list of SASL authentication mechanisms. Possible mechanisms are all mechanisms supported by Java implementation. The most common are: +PLAIN, DIGEST-MD5, CRAM-MD5+.\n+\n\"Non-PLAIN\" mechanisms will work only with the +get-password-query+ active and only when passwords are stored in plain text format in the database.   Application: Tigase Server\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_22_-_Security_-_B_-_Authentication_Connectors_-_3_-_Drupal_Authentication_Added.asciidoc",
    "content": "[[drupalAuthentication]]\n= Drupal Authentication\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nCurrently, we can only check authentication against a *Drupal* database at the moment. Full *Drupal* authentication is not implemented as of yet.\n\nAs *Drupal* keeps encrypted passwords in database the only possible authorization protocols are those based on PLAIN passwords.\n\nTo protect your passwords *Tigase* server must be used with SSL or TLS encryption.\n\nImplementation of a *Drupal* database based authorization is located in +tigase.db.jdbc.DrupalAuth+ class. Although this class is capable of adding new users to the repository I recommend to switch in-band registration off due to the caching problems in *Drupal.* Changes in database are not synchronized with *Drupal* yet. Functionality for adding new users is implemented only to ease user accounts migration from different repository types from earlier *Tigase* server installations.\n\nThe purpose of that implementation was to allow all accounts administration tasks from *Drupal* like: account creation, all accounts settings, like e-mail, full name, password changes and so on.\n\n*Tigase* server uses following fields from *Drupal* database: name (user account name), pass (user account password), status (status of the account). Server picks up all changes instantly. If user status is not 1 then server won't allow user to login trough XMPP even if user provides valid password.\n\nThere is no _Roster_ management in *Drupal* yet. So Roster management have to be done from the XMPP client.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_23_-_Security_-_B_-_Authentication_Connectors_-_4_-_LDAP_Authentication_Connector.asciidoc",
    "content": "[[LDAPauth]]\n= LDAP Authentication Connector\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-03-30 21:56\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nFrom version 5.1.0, rev. (build) 2881 Tigase XMPP Server offers support for authenticating users against an LDAP server in *Bind* *Authentication* mode.\n\nConfiguration for the LDAP support is really simple you just have to add a few lines to your +init.properties+ file.\n\n[source,bash]\n-----\n# LDAP Authentication connector\n--auth-db = tigase.db.ldap.LdapAuthProvider\n# LDAP connection URI\n--auth-db-uri=ldap://ldap.tigase.com:389\n# LDAP access parameters\nbasic-conf/auth-repo-params/user-dn-pattern=cn=USER_ID,ou=people,dc=tigase,dc=org\n-----\n\nPlease note the *USER_ID* element, this is a special element of the configuration which is used to authenticate particular user. Tigase LDAP connector replaces it with appropriate data during authentication. You can control what Tigase should put into this part. In your configuration you must replace this string with one of the following:\n\n. *%1$s* - use user name only for authentication (JabberID's localpart)\n. *%2$s* - use domain name only for authentication (JabberID's domain part)\n. *%3$s* - use the whole Jabber ID (JID) for authentication\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_24_-_Security_-_B_-_Authentication_Connectors_-_5_-_Configuration_of_SASL_EXTERNAL.asciidoc",
    "content": "[[saslExternal]]\n= Configuration of SASL EXTERNAL\n:author: Bartosz Malkowski <bmalkowski@tigase.pl>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-11-27 13:34\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nIn order to enable SASL External add following line to the  +init.properties+ file\n\n[source,bash]\n-----\nc2s/clientCertCA=/path/to/cacert.pem\n-----\n\nFile +cacert.pem+ contains Certificate Authority certificate which is used to sign clients certificate.\n\nClient certificate must include user's Jabber ID as +XmppAddr+ in +subjectAltName+:\n__________________________\nAs specified in RFC 3920 and updated in RFC 6120, during the stream negotiation process an XMPP client can present a certificate (a “client certificate”). If a JabberID is included in a client certificate, it is encapsulated as an id-on-xmppAddr Object Identifier (“xmppAddr”), i.e., a subjectAltName entry of type otherName with an ASN.1 Object Identifier of “id-on-xmppAddr” as specified in Section 13.7.1.4 of RFC 6120.footnote:[http://xmpp.org/extensions/xep-0178.html#c2s[XEP-0178]]\n__________________________\n\nIt is possible to make client certificate required:\n\n[source,bash]\n-----\nc2s/clientCertRequired[B]=true\n-----\n\nIf this option will be enabled, then client must provide certificate. This certificate will be verified against +c2s/clientCertCA+. If client does not provide certificate or certificate will be invalid, TLS handshake will be interrupted and client will be disconnected.\n\nUsing this options does not force client to use SASL EXTERNAL. Client still may authenticate with other SASL mechanisms.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_25_-_Security_-_C_-_Packet_Filtering.asciidoc",
    "content": "[[tigase41packetFiltering]]\n= Packet Filtering\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-13 16:39\n\n:toc:\n\nTigase offers different ways to filter XMPP packets flying through the server. The most common use for packet filtering is to restrict users from sending or receiving packets based on the sender or received address.\n\nThere are also different possible scenarios: time based filtering, content filtering, volume filtering and so on.\n\nAll pages in this section describe different filtering strategies.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_26_-_Security_-_C_-_Packet_Filtering_-_1_-_Domain_Based_Packet_Filtering.asciidoc",
    "content": "[[domainBasedPacketFiltering]]\n= Domain Based Packet Filtering\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-13 16:43\n\nDomain based packet filtering is a simple filter allowing to restrict user communication based on the source/destination domain name. This is especially useful if we want to limit user communication within a single - own domain only or a list of domains.\n\nA company might not wish to allow employers to chat during work hours with anybody in the world. A company may also have a few different domains used by different branches or departments. An administrator may restrict communication to a list of domains.\n\n== Introduction\n\nThe restriction is on a per-user basis. So the administrator can set a different filtering rules for each user. There is also a per-domain configuration and global-installation setting (applied from most general to most specific, i.e. from installation to user).\n\nRegular users can not change the settings. So this is not like a privacy list where the user control the filter. Domain filter can not be changed or controlled by the user. The system administrator can change the settings based on the company policy.\n\nThere are predefined rules for packet filtering:\n\n. `ALL` - user can send and receive packets from anybody.\n. `LOCAL` - user can send and receive packets within the server installation only and all it's virtual domains.\n. `OWN` - user can send and receive packets within his own domains only\n. `BLOCK` - user can't communicate with anyone. This could be used as a means to temporarily disable account or domain.\n. `LIST` - user can send and receive packets within listed domains only (i.e. _whitelist_).\n. `BLACKLIST` - user can communicate with everybody (like `ALL`), except contacts on listed domains.\n. `CUSTOM` - user can communicate only within custom created rules set.\n\nWhitelist (`LIST`) and blacklist (`BLACKLIST`) settings are mutually exclusive, i.e. at any given point of time only one of them can be used.\n\nThose rules applicable to particular users are stored in the user repository and are loaded for each user session. If there are no rules stored for a particular user server tries to apply rules for a VHost of particular user, and if there is no VHost filtering policy server uses global server configuration. If there is no filtering policy altogether server applies defaults based on following criteria:\n\n. If this is *Anonymous* user then *LOCAL* rule is applied\n. For all *other* users *ALL* rule is applied.\n\n== Configuration\n\nFiltering is performed by the domain filter plugin which must be loaded at startup time. It is loaded by default if the plugins list is not set in the configuration file. However if you have a list of loaded plugins in the configuration file make sure *domain-filter* is on the list.\n\nThere is no other configuration required for the plugin to work.\n\n== Administration, Rules Management\n\nAlthough controlling domain filtering rules is possible for each user separately, it is not practical for large installations. In most cases users are stored in the database and a third-party system keeps all the user information.\n\nTo change the rule for a single user you can use loadable administration scripts feature and load link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/groovy/tigase/admin/UserDomainFilter.groovy[UserDomainFilter.groovy] script. It enables modifying rules for a given user JID.\n\n== Implementation\n\nIf you have a third party system which keeps and manages all user information than you probably have your own UserRepository implementation which allows the Tigase server to access user data. Filtering rules are loaded from user repository using following command:\n\n[source,java]\n-----\nrepo.getData(user_id, null, DomainFilter.ALLOWED_DOMAINS_KEY, null)\nrepo.getData(user_id, null, DomainFilter.ALLOWED_DOMAINS_LIST_KEY, null)\n-----\n\nWhere *user_id* is user Jabber ID without resource part, *DomainFilter.ALLOWED_DOMAINS_KEY* is a property key: \"allowed-domains\". The user repository MUST return one of following only:\n\n. `ALL` - if the user is allowed to communicate with anybody\n. `LOCAL` - if the user is allowed to communicate with users on the same server installation.\n. `OWN` - if the user is allowed to communicate with users within his own domain only.\n. `LIST` - list of domains within which the user is allowed to communicate with other users. No wild-cards are supported. User's own domain should be included too.\n. `BLACKLIST` - list of domains within which the user is NOT allowed to communicate with other users. No wild-cards are supported. User's own domain should NOT be included.\n. `CUSTOM` - list of rules defining custom communication permissions (server processes stanza according to first matched rule, similar to XEP-0016) in the following format:\n\n[source]\n-----\nruleSet = rule1;rule2;ruleX;\n\nrule = order_number|policy|UID_type[|UID]\n\norder_number = any integer;\npolicy = (allow|deny);\nUID_type = [jid|domain|all];\nUID = user JID or domain, for example pubsub@test.com; if UID_type is ALL then this is ignored.\n-----\n\nFor example:\n\n[source]\n-----\n1|allow|self;\n2|allow|jid|admin@test2.com;\n3|allow|jid|pubsub@test.com;\n4|deny|all;\n-----\n. `null` - a java null if there are no settings for the user.\n\nIn case of `LIST` and `BLACKLIST` filtering options, it's essential to provide list of domains for the whitelisting/blacklisting. *DomainFilter.ALLOWED_DOMAINS_LIST_KEY* is a property key: \"allowed-domains-list\". The user repository MUST return semicolon separated list of domains: `domain1.com;domain2.com,domain3.org`\n\nThe filtering is performed by the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/xmpp/impl/DomainFilter.java[`tigase.xmpp.impl.DomainFilter`] plugin. Please refer to source code for more implementation details.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_27_-_Security_-_D_-_Access_Control_List.asciidoc",
    "content": "[[accessControlList]]\n= Access Control Lists in Tigase\n:author: Artur Hefczyc\n:version: v1.0 October 2015\n:date: 2015-10-26 08:51\n\n:toc:\n:numbered:\n:website: http://www.tigase.net\n\nTigase offers support for *Access Control List (ACL)* to allow for fine grained access to administration commands on the server.\n\nBy default, all administration commands are only accessible (visible through service discovery and can be executed) by the service administrators.  Service administrators are existing accounts with JIDs (*BareJIDs*) listed in the +init.properties+ file under --admins.\n\nAdditionally, other XMPP users and entities can be assigned permissions to execute a command or commands using Tigase's ACL capabilities.\n\nThe following is a list of possible ACL modifiers for administrator command accessibility:\n\n- *ALL* - Everybody can execute the command, even users from different federated servers.\n- *ADMIN* - Local server administrators can execute the command, this is a default setting if no ACL is set for a command.\n- *LOCAL* - All users with accounts on the local server can execute the command. Users from other, federated servers will not be able to execute the command.\n- *DOMAIN* - Only users with accounts on the selected domain will be able to execute the command.  It may be useful to setup a domain specifically for admin accounts, and automatically all users within that domain would be able to run the command.\n- *JID* - Comma separated list of JIDs of users who can execute the command.\n\nIn any case, regardless of ACL settings, any command can be executed and accessed by the designated service wide administrators, that is accounts listed as admins in the init.properties file.\n\nMultiple ACL modifiers can be combined and applied for any command. This may not always makes sense. For example ALL supersedes all other settings, so it does not make sense to combine it with any other modifier. However, most others can be combined with JID to broaden access to specific accounts.\n\nOn Tigase server the Access Control List is checked for the first matching modifier. Therefore if you combine ALL with any other modifier, anybody from a local or remote service will always be able to execute the command, no matter what other modifiers are added.\n\nPlease note, the ACL lists work on the command framework level. Access is verified before the command is actually executed. There might be additional access restrictions within a command itself. In many cases, even if all local users are permitted to execute a command (LOCAL modifier), some commands allow only to be executed by a domain owner or a domain administrator (and of course by the service-wide administrators as well). All the commands related to a user management such as adding a new user, removing a user, password changes, etc… belong to this category.\nWhen conducting domain (vhost) management, creation/registration of a new domain can be done by any local user (if LOCAL ACL modifier is set) but then all subsequent domain management tasks such as removing the vhost, updating its configuration, setting SSL certificate can be done by the domain owner or administrator only.\n\nThe ACL list is set for a specific Tigase component and a specific command. Therefore the configuration property must specify all the details. So the general format for configuring ACL for a command is this:\n\n+comp-id/command/command-id=ACL_modifier,ACL_modifier,ACL_modifier+\n\nThe breakdown is as such:\n\n- *comp-id* is the Tigase server component ID such as: +sess-man+, +vhost-man+, +c2s+, etc..\n- *command* is a static text which indicates that the property is for component's command settings.\n- *command-id* is a command ID for which we set the ACL such as +query-dns+, +http://jabber.org/protocol/admin#add-user+, +user-roster-management+, etc…\n\nHere are a few examples:\n\n_Allowing local users to create and manage their own domains_\n[source,bash]\n-----\nvhost-man/command/comp-repo-item-add=LOCAL\nvhost-man/command/comp-repo-item-remove=LOCAL\nvhost-man/command/comp-repo-item-update=LOCAL\nvhost-man/command/ssl-certificate-add=LOCAL\n-----\n\nIn fact all the commands except +item-add+ can be executed by the domain owner or administrator.\n\n_Allowing local users to execute user management commands:_\n[source,bash]\n-----\nsess-man/command/http\\://jabber.org/protocol/admin#add-user=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#change-user-password=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#delete-user=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#get-online-users-list=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#get-registered-user-list=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#user-stats=LOCAL\nsess-man/command/http\\://jabber.org/protocol/admin#get-online-users-list=LOCAL\n-----\n\nAs in the previous example, the commands will by executed only by local users who are the specific domain administrators.\n\n_Allowing users from a specific domain to execute +query-dns+ command and some other users for given JIDs from other domains:_\n-----\nvhost-man/command/query-dns=DOMAIN:tigase.com,admin@tigase.org,frank@example.com\n-----\n\nTo be able to set a correct ACL property you need to know component names and command IDs. Component IDs can be found in the service discovery information on running server or in the server logs during startup. A command ID can be found in the command script source code. Each script contains a list of metadata at the very beginning of it's code. One of them is +AS:CommandId+ which is what you have to use for the ACL setting.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_28_-_Database_Management.asciidoc",
    "content": "[[databasemgnt]]\n= Database Management\n:author: daniel wisnewski\n:version: v1.0 July 2015\n:date: 2015-07-16 12:49\n\n:website: http://tigase.net\n\nTigase is coded to perform with multiple database types and numbers.\nOwing to it's versatile nature, there are some tools and procedures that may be of use to certain administrators.\n\n== Recommended database versions\nAs of v7.1.0 here are the minimum and recommended versions of databases for use with Tigase:\n\n\n[width=\"100%\",frame=\"topbot\",options=\"header\"]\n|=================================\n|Database   |Recommended Version  |Minimum Version  |Additional Information\n|DerbyDB    |10.12.1.1            |10.12.1.1        |Included with Tigase XMPP Server\n|MySQL      |5.6                  |5.5              |\n|SQLServer  |2012                 |2008 R2          |\n|MongoDB    |2.6                  |2.6              |Driver not working with mongoDB 3.0 or newer.\n|=================================\n\nAlthough Tigase may support other versions of databases, these are the ones we are most familiar with in offering support and advice.  Use of databases outside these guidelines may result in unforeseen errors.\n\n== xref:databasePreperation[Database Preparation]\nPreparing new databases in case installer setup is not an option.\n\n== xref:hashedPasswords[Hashed Passwords in User Database]\nProviding more secure password storage.\n\n== xref:multidb[Multiple Databases in Tigase]\nOptions for using multiple databases for different purposes in Tigase.\n\n== xref:dbImportingData[Importing User Data]\nTips to move data repositories from one to another database.\n\n== xref:existingData[Import Existing Database]\nThis section has some depreciated information, however it may be handy to upgrade, or manually connect databases.\n\n== xref:oldVerSchemas[Old Version Schemas and Updates]\nContains our old Schema updates, if you have an old installation of Tigase and want to move to a more current version, see the guides revelant to you.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_29_-_Database_Management_-_A_-_Database_Preparation.asciidoc",
    "content": "[[databasePreperation]]\n= Database Preparation\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:author: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-07-15 06:42\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase uses generally the same database schema and the same set of stored procedures and functions on every database. However, the schema creation scripts and code for stored procedures is different for each database. Therefore the manual process to prepare database is different for each database system.\n\nOf course the simplest and easiest way to prepare database is to use Tigase installer or webinstaller which automates the whole process. Sometimes this is not possible. A second option is to use the +DBSchemaLoader+ utility in Tigase. If either of those won't work, or won't suit your needs,  provided are set of guides describing initialization and preparation process for each supported database.\n\n-xref:dbSchemaLoader[The DBSchemaLoader Utility]\n- xref:prepareMysql[Prepare the MySQL Database for the Tigase Server]\n- xref:hashedPasswords[Hashed User Passwords in Database]\n- xref:prepareDerby[Prepare the Derby Database for the Tigase Server]\n- xref:prepareMssql[Prepare the MS SQL Server Database for the Tigase Server]\n- xref:preparePostgresql[Prepare the PostgreSQL Database for the Tigase Server]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_29_-_Database_Management_-_A_-_Database_Preperation_-_1_-_DbSchemaLoader.asciidoc",
    "content": "[[dbSchemaLoader]]\n= +dbSchemaLoader+ Utility\n:author: Daniel Wisnewski\n:author: v1.0, March 2016: Reformatted for AsciiDoc.\n:date: 2016-03-14 14:30\n\n:numbered:\n:toc:\n:website: http://www.tigase.net\n\nIncluded with Tigase is the +dbSchemaLoader+ Utility, which can be used to apply schema files to databases. It is able to operate with Derby, MySQL, SQLServer, and PostgreSQL databases.\nIn order to use this utility with any of the databases, you will need to first have the database environment up and running, and have established user credentials. You may use root or an account with administrator write privileges.\n\nIMPORTANT: All commands in this guide are required to be running from the Tigase installation directory.\n\n== Operation & Variables\n\nFirst, lets cover the DBSchemaLoader operation and variables:\n\n*Operation*\nThe utility is run using the java -cp command from the Tigase installation directory.  Be sure that you have JDK v1.8 or later installed.\nLinux\n[source,command]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader\n-----\nor from a Windows environment\n-----\njava -cp jars/* tigase.util.DBSchemaLoader\n-----\nThese commands will be followed by a combination of the following variables\n\n*Variables*\n\nUse the following options to customize. Options in bold are required, {potential options are in brackets}.::\n* *-dbType database_type {derby, mysql, postgresql, sqlserver}*\n* -schemaVersion schema version {4, 5, 5-1}\n* *-dbName database name*\n* -dbHostname database hostname (default is localhost)\n* -dbUser tigase username\n* -dbPass tigase user password\n* -rootUser database root username\n* -rootPass database root password\n* *-file path to sql schema file* {database/derby-schema-7-1.sql}\n* -query sql query to execute\n* -logLevel java logger Level\n* -adminJID comma separated list of admin JIDs\n* -adminJIDpass password (one for all entered JIDs)\n\nWith that out of the way, lets look at some examples.\nLets say you have a new mysql database server with root user root and password rood (to keep things simple, we do not recommend this).  The MySQL database is hosted locally, your command would be as follows:\n[source,cmd]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbType mysql -dbName tigasedb -rootUser root -rootPass root -schemaVersion -adminJID admin@example.com -adminJIDpass password 7.1 -file database/mysql-schema-7-1.sql\n-----\nThis will create the tigasedb database, add an Admin user as admin@example.com with password 'password', and apply the v7.1 schema files. Output will look like this:\n[source,cmd]\n-----\nLogLevel: CONFIG\n\ntigase.util.DBSchemaLoader     \t <init>          \t CONFIG     Properties: [{dbHostname=localhost, logLevel=CONFIG, adminJID=admin@example.com, dbType=mysql, file=database/mysql-schema-7-1.sql, rootUser=root, adminJIDpass=password, dbPass=tigase_pass, dbName=tigasedb, schemaVersion=7.1, rootPass=root, dbUser=tigase_user}]\n\ntigase.util.DBSchemaLoader     \t validateDBConnection \t INFO       Validating DBConnection, URI: jdbc:mysql://localhost/?user=root&password=root\n\ntigase.util.DBSchemaLoader     \t validateDBConnection \t CONFIG     DriverManager (available drivers): [[org.apache.derby.jdbc.AutoloadedDriver@10f87f48, org.postgresql.Driver@1b2c6ec2, com.mysql.jdbc.Driver@50040f0c, jTDS 1.3.1]]\n\ntigase.util.DBSchemaLoader     \t validateDBConnection \t INFO       Connection OK\ntigase.util.DBSchemaLoader     \t validateDBExists \t INFO       Validating whether DB Exists, URI: jdbc:mysql://localhost/tigasedb?user=tigase_user&password=tigase_pass\n\ntigase.util.DBSchemaLoader     \t validateDBExists \t INFO       Doesn't exist, creating...\n\ntigase.util.DBSchemaLoader     \t validateDBExists \t INFO        OK\n\ntigase.util.DBSchemaLoader     \t loadSchemaFile  \t INFO       Loading schema from file: database/mysql-schema-7-1.sql, URI: jdbc:mysql://localhost/tigasedb?user=root&password=root\ntigase.util.DBSchemaLoader     \t loadSchemaFile  \t INFO        completed OK\n\ntigase.util.DBSchemaLoader     \t printInfo       \t INFO\n\nDatabase init.properties configuration:\n\n--user-db=mysql\n--user-db-uri=jdbc:mysql://localhost/tigasedb user=tigase_user&password=tigase_pass&useUnicode=true&characterEncoding=UTF-8\n-----\n\nTIP: The utility will automatically generate the lines you need to add to your init.properties file to use this database!\n\nAt this time, it is suggested to load the PubSub schema since you will have to change very little of the command:\n\n[source,cmd]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbType mysql -dbName tigasedb -rootUser root -rootPass root -file database/mysql-pubsub-schema-3.2.0.sql\n-----\n\nShould you wish to use the Socks5 Proxy component, you will need to load that schema as well\n[source,cmd]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbType mysql -dbName tigasedb -rootUser root -rootPass root -file database/mysql-socks5-schema.sql\n-----\n\nAt this time you're finished setting up a database for use with Tigase!\nFor other databases that are supported, the operations will be very similar with only the -dbType and perhaps the -dbHostname being different.\n\n== -Query function\n\nShould you decide to customize your own functions, or have specific information you want to put into the database, you can use the -query function to perform a single query step.\n[source,cmd]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dpType mysql -dbName tigasedb -rootUser root -rootPass root -query \"CREATE TABLE tigasedb.EXTRA_TABLE (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(10) NOT NULL)\"\n-----\nOf course this would break the schema for tigasedb by adding an unexpected table,  you will receive the following message:\n-----\ntigase.util.DBSchemaLoader       printInfo          WARNING       Database schema is invalid\n-----\n\nBut this is a demonstration how you may run a query through the database without the need to use another tool.  Note that you will need to select the specific database for each query.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_30_-_Database_Management_-_A_-_Database_Preparation_-_1_-_Prepare_the_MySQL_Database_for_Tigase_Server.asciidoc",
    "content": "[[prepareMysql]]\n= Prepare the MySQL Database for the Tigase Server\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to prepare MySQL database for connecting Tigase server.\n\n== Basic Setup\n\nThe MySQL database can be prepared in many ways. Most Linux distributions contain tools which allow you to go through all steps from the shell command line. To make sure it works on all platforms in the same way, we will first show how to do it under MySQL command line client.\n\n=== Configuring from MySQL command line tool\n\nRun the MySQL command line client in either Linux or MS Windows environment and enter following instructions:\n\n. Create the database for the Tigase server:\n+\n[source,sql]\n-----\nmysql> create database tigasedb;\n-----\n. Add the +tigase_user+ user and grant him access to the +tigasedb+ database. Depending on how you plan to connect to the database (locally or over the network) use one of following commands or all if you are not sure:\n+\n*Grant access to tigase_user connecting from any network address.*\n+\n[source,sql]\n-----\nmysql> GRANT ALL ON tigasedb.* TO tigase_user@'%'\n            IDENTIFIED BY 'tigase_passwd';\n-----\n+\n*Grant access to tigase_user connecting from localhost.*\n+\n[source,sql]\n-----\nmysql> GRANT ALL ON tigasedb.* TO tigase_user@'localhost'\n            IDENTIFIED BY 'tigase_passwd';\n-----\n+\n*Grant access to tigase_user connecting from local machine only.*\n+\n[source,sql]\n-----\nmysql> GRANT ALL ON tigasedb.* TO tigase_user\n            IDENTIFIED BY 'tigase_passwd';\n-----\n+\nFor the Tigase server version 4.x additional permissions must be granted for the database user:\n+\n[source,sql]\n-----\nmysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user'@'localhost';\nmysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user'@'%';\nmysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user';\n-----\n+\nAnd now you can update user permission changes in the database:\n+\n[source,sql]\n-----\nmysql> FLUSH PRIVILEGES;\n-----\n. Load the proper mysql schema into the database.  Full installations of Tigase will have all the SQL file you need to create and update the database. First, switch to the database you have just created:\n+\n[source,sql]\n-----\nmysql> use tigasedb;\n-----\n+\nWe are assuming you run the mysql client in Linux from the Tigase installation directory.\n+\n[source,sql]\n-----\nmysql> source database/mysql-7-1-schema.sql;\n-----\n+\nFor the Tigase server version v7.1.0 you have to use proper schema version which is 5.1.  You will also need to manually load the PubSub schema as well, current version is v3.2.0.  All modern versions will load previous schemas first so no need to do a manual upgrade.\n+\n[source,sql]\n-----\nmysql> source database/mysql-pubsub-schema-3.2.0.sql;\n-----\n+\nIf you plan to use the Socks5 component, you will also need to add that schema as well.\n+\n[source,sql]\n-----\nmysql> source database/mysql-socks5-schema.sql;\n-----\n+\nOn Windows you have probably to enter the full path, assuming Tigase is installed in C:\\Program Files\\Tigase:\n+\n[source,sql]\n-----\nmysql> source c:/Program Files/Tigase/database/mysql-7-1-schema.sql;\nmysql> source c:/Program Files/Tigase/database/mysql-pubsub-schema-3.2.0.sql;\nmysql> source c:/Program Files/Tigase/database/mysql-socks5-schema.sql;\n-----\n+\n\n\n== Configuring From the Linux Shell Command Line\n\nFollow steps below to prepare the MySQL database:\n\n. Create the database space for the Tigase server:\n[source,sql]\n-----\nmysqladmin -p create tigasedb\n-----\n. Add the +tigase_user+ user and grant access to the tigasedb database. Depending on how you plan to connect to the database (locally or over the network) use one of following commands or all if you are not sure:\n*Grant access to tigase_user connecting from any network address.*\n[source,sql]\n-----\necho \"GRANT ALL ON tigasedb.* TO tigase_user@'%' \\\n            IDENTIFIED BY 'tigase_passwd'; \\\n            FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n-----\n*Grant access to tigase_user connecting from localhost.*\n[source,sql]\n-----\necho \"GRANT ALL ON tigasedb.* TO tigase_user@'localhost' \\\n            IDENTIFIED BY 'tigase_passwd'; \\\n            FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n-----\n*Grant access to tigase_user connecting from local machine only.*\n[source,sql]\n-----\necho \"GRANT ALL ON tigasedb.* TO tigase_user \\\n            IDENTIFIED BY 'tigase_passwd'; \\\n            FLUSH PRIVILEGES;\" | mysql -u root -pdbpass mysql\n-----\n. Load the proper mysql schema into the database.  Full installations of Tigase will have all the SQL file you need to create and update the database.\n[source,sql]\n-----\nmysql -u dbuser -p tigasedb < mysql-schema-7-1.sql\nmysql -u dbuser -p tigasedb < mysql-pubsub-schema-3.2.0.sql\n-----\n\nIf you want to use the socks5 component, then oyu will need to include the following line as well:\n[source,sql]\n-----\nmysql -u dbuser -p tigasedb < mysql-socks5-schema.sql\n-----\n\n== Configuring MySQL for UTF-8 Support\n\nIn my.conf put following lines:\n\n[source,bash]\n-----\n[mysql]\ndefault-character-SET=utf8\n\n[client]\ndefault-character-SET=utf8\n\n[mysqld]\ninit_connect='SET collation_connection = utf8_general_ci; SET NAMES utf8;'\ncharacter-set-server=utf8\ndefault-character-SET=utf8\ncollation-server=utf8_general_ci\nskip-character-set-client-handshake\n-----\n\nThen connect to the database from the command line shell check settings:\n\n[source,sql]\n-----\nSHOW VARIABLES LIKE 'character_set_database';\nSHOW VARIABLES LIKE 'character_set_client';\n-----\n\nIf any of these shows something else then 'utf8' then you need to fix it using the command:\n\n[source,sql]\n-----\nALTER DATABASE tigasedb DEFAULT CHARACTER SET utf8;\n-----\n\nYou can now also test your database installation if it accepts UTF-8 data. The easiest way to ensure this is to just to create an account with UTF-8 characters:\n\n[source,sql]\n-----\ncall TigAddUserPlainPw('żółw@some.domain.com', 'żółw');\n-----\n\nAnd then check that the account has been created:\n\n[source,sql]\n-----\nSELECT * FROM tig_users WHERE user_id = 'żółw@some.domain.com';\n-----\n\nIf the last command gives you no results it means there is still something wrong with your settings. You might also want to check your shell settings to make sure your command line shell supports UTF-8 characters and passes them correctly to MySQL:\n\n[source,sh]\n-----\nexport LANG=en_US.UTF-8\nexport LOCALE=UTF-8\nexport LESSCHARSET='utf-8'\n-----\n\nIt seems that MySQL 5.0.x also needs extra parameters in the connection string: '&amp;useUnicode=true&amp;characterEncoding=UTF-8' while MySQL 5.1.x seems to not need it but it doesn't hurt to have it for both versions. You have to edit 'etc/init.properties' file and append this to the database connection string.\n\nFor MySQL 5.1.x, however, you need to also update code for all database stored procedures and functions used by the Tigase. They are updated for Tigase version 4.4.x and up, however if you use an older version of the Tigase server, you can reload stored procedures using the file from SVN.\n\n== Other MySQL Settings Worth Considering\n\nThere are a number of other useful options, especially for performance improvements. Please note, you will have to review them as some of them may impact data reliability and are useful for performance or load tests installations only.\n\n[source,bash]\n-----\n# InnoDB seems to be a better choice\n# so lets make it a default DB engine\ndefault-storage-engine = innodb\n-----\n\nSome the general MySQL settings which mainly affect performance:\n\n[source,bash]\n-----\nkey_buffer = 64M\nmax_allowed_packet = 32M\nsort_buffer_size = 64M\nnet_buffer_length = 64K\nread_buffer_size = 16M\nread_rnd_buffer_size = 16M\nthread_stack = 192K\nthread_cache_size = 8\nquery_cache_limit = 10M\nquery_cache_size = 64M\n-----\n\nInnoDB specific settings:\n\n[source,bash]\n-----\n# Keep data in a separate file for each table\ninnodb_file_per_table = 1\n# Allocate memory for data buffers\ninnodb_buffer_pool_size = 1000M\ninnodb_additional_mem_pool_size = 100M\n# A location of the MySQL database\ninnodb_data_home_dir = /home/databases/mysql/\ninnodb_log_group_home_dir = /home/databases/mysql/\n# The main thing here is the 'autoextend' property\n# without it your data file may reach maximum size and\n# no more records can be added to the table.\ninnodb_data_file_path = ibdata1:10M:autoextend\ninnodb_log_file_size = 10M\ninnodb_log_buffer_size = 32M\n# Some other performance affecting settings\ninnodb_flush_log_at_trx_commit = 2\ninnodb_lock_wait_timeout = 50\ninnodb_thread_concurrency = 16\n-----\n\nThese settings may not be fully optimized for your system, and have been only tested on our systems. If you have found better settings for your systems, feel free to link:http://tigase.net/contact[let us know].\n//I am certainly not a database expert nor MySQL expert and I do not pretend to be one. So any comments or suggestions you may have are very welcome and appreciated.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_31_-_Database_Management_-_A_-_Database_Preparation_-_2_-_Prepare_the_Derby_Database_for_Tigase_Server.asciidoc",
    "content": "[[prepareDerby]]\n= Prepare the Derby Database for the Tigase Server\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-06-21 13:28\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to prepare Derby database for connecting the Tigase server.\n\n== Basic Setup\n\nPreparation of Derby database is quite simple, but the following assumptions are made\n\n- +DerbyDB+ - Derby database name\n- +database/+ directory contains all necessary schema files\n- +jars/+ and +libs/+ directories contains Tigase and Derby binaries\n\n=== General Approach\n\nFrom the main Tigase directory execute following commands (Linux and Windows accordingly)\n\n*Linux*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar org.apache.derby.tools.ij database/derby-schema-7.1.sql\n-----\n\n*Windows*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs\\derby.jar;libs\\derbytools.jar;jars\\tigase-server.jar org.apache.derby.tools.ij \"database\\derby-schema-7-1.sql\"\n-----\n\nThis will create Derby database named DerbyDB in the main Tigase directory and load Tigase schema for version 7.1.\n\nYou will need to repeat this process again to add the PubSub schema into the database.\n\n*Linux*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar org.apache.derby.tools.ij database/derby-pubsub-schema-3.2.0.sql\n-----\n\n*Windows*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs\\derby.jar;libs\\derbytools.jar;jars\\tigase-server.jar org.apache.derby.tools.ij \"database\\derby-pubsub-schema-3.2.0.sql\"\n-----\n\nIf you wish to use the Sock5 Proxy Component, you will need to add that schema as well:\n\n*Linux*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar org.apache.derby.tools.ij database/derby-socks5-schema.sql\n-----\n\n*Windows*\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"DerbyDB;create=true\" -cp libs\\derby.jar;libs\\derbytools.jar;jars\\tigase-server.jar org.apache.derby.tools.ij \"database\\derby-socks5-schema.sql\"\n-----\n\n== Connecting Tigase to database\n\nOnce the database is setup, configure the init.properties file in Tigase and add the following configuration:\n[source,properties]\n-----\njdbc:derby:{location of derby database};\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_32_-_Database_Management_-_A_-_Database_Preparation_-_3_-_Prepare_the_MS_SQL_Server_Database_for_Tigase_Server.asciidoc",
    "content": "[[prepareMssql]]\n= Prepare the MS SQL Server Database for the Tigase Server\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-09-04 14:57\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to prepare the MS SQL Server database for connecting the Tigase server to it.\n\n== Basic Setup\n\nIt's expected that a working installation of Microsoft SQL Server is present. The following guide will describe the necessary configurations required for using MS SQL Server with Tigase XMPP Server.\n\n== Preparing MS SQL Server Instance\n\nAfter installation of MS SQL Server an instance needs to be configure to handle incoming JDBC connections. For that purpose it's required to open _SQL Server Configuration Manager_. In the left-hand side panel navigate to _SQL Server Configuration Manager_, then _SQL Server Network Configuration -> Protocols for $\\{INSTANCE_NAME}_. After selecting instance in the right-hand side panel select TCP/IP and open _Properties_, in the Protocol tab in General section select Yes for Enabled property. In the IP Addresses tab select Yes for Active and Enabled properties of all IP Addresses that you want MS SQL Server to handle. Subsequently set the TCP Port property (if missing) to the default value - 1433. A restart of the instance may be required afterwards.\n\n== Configuration using MS SQL Server Management Studio\n\nIn order to prepare the database you can use either a wizard or execute queries directly in the Query Editor. Firstly you need to establish a connection to the MS SQL Server instance. From Object Explorer select Connect and in the Connect to Server dialog enter administrator credentials.\n\n=== Using Wizards\n\n- Create Login\n+\nIn the left-hand side panel select Security -> Logins and from context menu choose New Login, in the Wizard window enter desired Login name, select SQL Server authentication and enter desired password subsequently confirming action with OK\n\n- Create Database\n+\nFrom the Object Explorer select Databases node and from context menu select New Database; in the Wizard window enter desired Database name and enter previously created Login name into Owner field; subsequently confirming action with OK.\n\n=== Using Queries\n\nFrom the Object Explorer root node's context menu select New Query. In the Query windows execute following statements adjusting details to your liking:\n\n\n[source,sql]\n-----\nUSE [master]\nGO\n\nCREATE DATABASE [tigasedb];\nGO\n\nCREATE LOGIN [tigase] WITH PASSWORD=N'tigase12', DEFAULT_DATABASE=[tigasedb]\nGO\n\nALTER AUTHORIZATION ON DATABASE::tigasedb TO tigase;\nGO\n-----\n\n== Import Schema\n\nFrom the File menu Select Open -> File (or use Ctrl+O) and then open following files:\n\n- sqlserver-schema-7-1-schema.sql\n- sqlserver-schema-7-1-sp.sql\n- sqlserver-schema-7-1-props.sql\n- sqlserver-pubsub-schema-3.2.0.sql\n\nSubsequently select created database from the list of Available Databases (Ctrl+U) available on the toolbar and execute each of the opened files in the order listed above.\n\n== Configuring from command line tool\n\nCreation of the database and import of schema can be done from command line as well. In order to do that, execute following commands from the directory where Tigase XMPP Server is installed otherwise paths to the schema need to be adjusted accordingly:\n\n[source,bash]\n-----\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -Q \"CREATE DATABASE [%database%]\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -Q \"CREATE LOGIN [%user%] WITH PASSWORD=N'%password%', DEFAULT_DATABASE=[%database%]\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -Q \"ALTER AUTHORIZATION ON DATABASE::%database% TO %user%;\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-7-1-schema.sql\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-7-1-sp.sql\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-7-1-props.sql\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-pubsub-schema-3.2.0.sql\n-----\n\nAbove can be automatized with provided script %tigase-server%\\scripts\\db-create-sqlserver.cmd (note: it needs to be executed from main Tigase XMPP Server directory due to maintain correct paths):\n\n[source,sh]\n-----\n$ scripts\\db-create-sqlserver.cmd %database_servername% %database_name% %tigase_username% %tigase_password% %root_username% %root_password%\n-----\n\nIf no parameters are provided then the following defaults are used:\n\n[source,bash]\n-----\n%database_servername%=localhost\n%database_name%=tigasedb\n%tigase_username%=tigase\n%tigase_password%=tigase12\n%root_username%=root\n%root_password%=root\n-----\n\n== Tigase configuration - init.properties\n\nConfiguration of the MS SQL Server follows general database convention. For MS SQL Support --user-db needs to be set to sqlserver:\n\n[source,bash]\n-----\n--user-db=sqlserver\n-----\n\nand the --user-db-uri needs to point to the configured database:\n\n[source,bash]\n-----\n--user-db-uri=jdbc:[jtds:]sqlserver://db_hostname:port[;property=val]\n-----\n\nwhere any number of additional parameters can (and should) consist of:\n\n- databaseName - name of the database\n- user - username configured to access database\n- password - password for the above username\n- schema - name of the database schema\n- lastUpdateCount - 'false' value causes all update counts to be returned, including those returned by server triggers\n\nExample:\n\n[source,sh]\n-----\n--user-db-uri=jdbc:sqlserver://hostname:1433;databaseName=tigasedb;user=tigase;password=tigase12;schema=dbo;lastUpdateCount=false\n-----\n\n== JDBC: jTDS vs MS JDBC driver\n\nTigase XMPP Server supports two JDBC drivers intended to be used with Microsoft SQL Server - one created and provided by Microsoft itself and the alternative implementation - jTDS. Tigase is shipped with the latter in the distribution packages. Starting with the version 7.1.0 we recommend using jDTS driver that is shipped with Tigase as JDBC driver created by Microsoft can cause problems with some components in cluster installations. MS driver can be downloaded form the website: link:http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=11774[JDBC Drivers 4.0, 4.1 for SQL Server] then unpack the archive. Copy sqljdbc_4.0/enu/sqljdbc4.jar file to $\\{tigase-server}/jars directory.\n\nDepending on the driver used --user-db-uri needs to be configured accordingly.\n\n- Microsoft driver:\n+\n[source,bash]\n-----\n--user-db-uri=jdbc:sqlserver://...\n-----\n- jDTS driver\n+\n[source,bash]\n-----\n--user-db-uri=jdbc:jdts:sqlserver://...\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_33_-_Database_Management_-_A_-_Database_Preparation_-_4_-_Prepare_the_PostgreSQL_Database_for_Tigase_Server.asciidoc",
    "content": "[[preparePostgresql]]\n= Prepare the PostgreSQL Database for the Tigase Server\n:author: Andrzej Wojcik <andrzejw@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-06-16 09:38\n:Revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to prepare PostgreSQL database for connecting to Tigase server.\n\n== Basic Setup\n\nThe PostgreSQL database can be prepared in many ways. Below are presented two possible ways. The following assumptions apply to both methods:\n\n- +admin_db_user+ - database user with admin rights\n- +tigase_user+ - database user for Tigase\n- +tigasedb+ - database for Tigase\n\n=== Configuring from PostgreSQL Command Line Tool\n\nRun the PostgreSQL command line client and enter following instructions:\n\n. Add the +tigase_user+:\n+\n[source,sql]\n-----\npsql=# create role tigase_user with login password 'tigase123';\n-----\n. Create the database for the Tigase server with +tigase_user+ as owner of database:\n+\n[source,sql]\n-----\npsql=# create database tigasedb owner tigase_user;\n-----\n. Load database schema to initialize the Tigase server from the file that corresponds to the version of Tigase you want to use. First you need to switch to +tigasedb+.\n+\n[source,sql]\n-----\npsql=# \\connect tigasedb\n-----\n+\nBegin by applying the basic Schema\n+\n[source,sql]\n-----\npsql=# \\i database/postgresql-schema-7-1.sql\n-----\n+\nContinue by adding the PubSub Schema\n+\n[source,sql]\n-----\npsql=# \\i database/postgresql-pubsub-schema-3.2.0.sql\n-----\n+\nAnd finally if you wish to use Socks5 Proxy component, add that schema:\n[source,sql]\n-----\npsql=# \\i database/postgresql-socks5-schema.sql\n-----\n\n=== Configuring From the Linux Shell Command Line\n\nFollow steps below to prepare the PostgreSQL database:\n\n. Add the +tigase_user+:\n+\n[source,sql]\n-----\ncreateuser -U admin_db_user -W -D -R -S -P tigase_user\n-----\n+\nYou will be asked for credentials for admin_db_user and password for new database user.\n. Create the database for the Tigase server with tigase_user as owner of database:\n+\n[source,sql]\n-----\ncreatedb -U admin_db_user -W -O tigase_user tigasedb\n-----\n. Load database schema to initialize the Tigase server from the file that corresponds to the Tigase version you want to use.\n+\n[source,sql]\n-----\npsql -q -U tigase_user -W tigasedb -f database/postgresql-schema-7-1.sql\npsql -q -U tigase_user -W tigasedb -f database/postgresql-pubsub-schema-3.2.0.sql\n-----\n+\nIf you want to use the socks5 proxy component, then add the following line:\n+\n[source,sql]\n-----\npsql -q -U tigase_user -W tigasedb -f database/postgresql-socks5-schema.sql\n-----\nThe above commands should be executed from the main Tigase directory. The initialization schema file should be also available locally in database/ directory of your Tigase installation.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_34_-_Database_Management_-_A_-_Database_Preperation_-_5_-_Prepare_Tigase_for_MongoDB.asciidoc",
    "content": "[[mongoDBSupport]]\n= Preparing Tigase for MongoDB\n:author: not known\n:version: v1.0 October, 2015\n:date: 2015-01-10 12:22\n\n:toc:\n:numbered:\n:website: http://www.tiagse.org\n\nTigase now supports MongoDB for auth, settings, and storage repositories. If you wish to use MongoDB for Tigase, please use this guide to help you.\n\n== Dependencies\n\nTo run Tigase MongoDB support library requires drivers for MongoDB for Java which can be downloaded from link:https://github.com/mongodb/mongo-java-driver/releases[here]. This driver needs to be placed in +/jars+ directory located in Tigase XMPP Server installation directory.\n\n== Configuration\n\n=== Configuration of user repository for Tigase XMPP Server\n\nTo configure Tigase XMPP Server to use MongoDB you need to set +--user-db-uri=+ in etc/init.properties file to proper MongoDB URI pointing to which MongoDB database should be used (it will be created by MongoDB if it does not exist).\n+--user-db+ property should not be set to let Tigase XMPP Server autodetect proper implementation of +UserRepository+. Tigase XMPP Server will create proper collections in MongoDB if they do not exist so no schema files are necessary.\n\nExample configuration of XMPP Server pointing to MongoDB database +tigase_test+ in a local instance:\n[source,bash]\n-----\n--user-db-uri=mongodb://localhost/tigase_test\n-----\nIf Tigase Server is not able to detect a proper storage layer implementation, it can be forced to use one provided by Tigase using the following lines in +etc/init.properties+ file:\n-----\n--user-db=tigase.mongodb.MongoRepository\n--auth-db=tigase.mongodb.MongoRepository\n-----\nEvery component should be able to use proper implementation to support MongoDB using this URI. Also MongoDB URI can be passed as any URI in configuration of any component.\n\n=== Configuration for MUC\nBy default, MUC component will use MongoDB to store data if Tigase is configured to use it as a default store. However, if you would like to use a different MongoDB database to store MUC message archive, you can do this by adding the following line to +etc/init.properties+ file:\n[source]\n-----\nmuc/history-db-uri=mongodb://localhost/tigase_test\n-----\nIf MUC components fails to detect and use a proper storage layer for MongoDB, you can force it to use one provided by Tigase by using the following line in the +init.properties+ file:\n-----\nmuc/history-db=tigase.mongodb.muc.MongoHistoryProvider\n-----\n\n=== Configuration for PubSub\nBy default, PubSub component will use MongoDB to store data if Tigase is configured to use it as a default store. However, if you would like to use a different MongoDB database to store PubSub component data, you can do this by adding the following line to +etc/init.properties+ file:\n[source]\n-----\npubsub/pubsub-repo-url=mongodb://localhost/tigase_test\n-----\nIf the PubSub components fails to detect and use a proper storage layer for MongoDB, you can force it to use one provided by Tigase by using the following line in the +init.properties+ file:\n-----\npubsub/pubsub-repo-class=tigase.mongodb.pubsub.PubSubDAOMongo\n-----\n\n=== Configuration for Message Archiving\nBy default, the Message Archiving component will use MongoDB to store data if Tigase is configured to use it as a default store. However, if you would like to use a different MongoDB database to store message archives, you can do this by adding the following line to +etc/init.properties+ file:\n[source]\n-----\nmessage-archive/archive-repo-uri=mongodb://localhost/tigase_test\n-----\nIf Message Archiving component fails to detect and use a proper storage layer for MongoDB, you can force it to use one provided by Tigase by using the following line in the +init.properties+ file:\n-----\nmessage-archive/archive-repo-class=tigase.mongodb.archive.MongoMessageArchiveRepository\n-----\n\n== Schema Description\nThis description contains only basic description of schema and only basic part of it. More collections may be created if additional components of Tigase XMPP Server are loaded and configured to use MongoDB.\n\n=== Tigase XMPP Server Schema\nBasic schema for UserRespository and AuthRepository consists of two collections:\n. tig_users - contains list of users\n. tig_nodes - contains data related to users in tree-like way\n\n+tig_users+ collection contains the following fields:\n\n.tig_users\n[width=\"50%\",options=\"header\"]\n|=====================================================================\n|Name\t      |Description\n|_id\t      |id of user which is SHA256 hash of users jid (raw byte array)\n|user_id\t  |contains full user jid\n|domain\t    |domain to which user belongs for easier lookup of users by domain\n|password\t  |password of user (or hash of password)\n|=====================================================================\n\n+tig_nodes+ collection contains the following fields\n\n.tig_nodes\n[width=\"50%\",options=\"header\"]\n|=====================================================================\n|Name\t    |Description\n|_id\t    |id of row autogenerated by MongoDB\n|uid\t    |id of user which is SHA256 hash of users jid (raw byte array)\n|node\t    |full path of node in tree-like structure separated by / (may not exist)\n|key\t    |key for which value for node is set\n|value\t  |value which is set for node key\n|=====================================================================\n\nTigase XMPP Server also uses additional collections for storage of Offline Messages\n\n.msg_history collection\n[width=\"50%\",options=\"header\"]\n|=====================================================================\n|Name\t    |Description\n|from\t    |full user jid of message sender\n|from_hash\t|SHA256 hash of message sender jid as raw byte array\n|to\t      |full users jid of message recipient\n|to_hash\t|SHA256 hash of message recipient full jid as raw byte array\n|ts\t      |timestamp of message as date\n|message\t|serialized XML stanza containing message\n|expire-at\t|timestamp of expiration of message (if message contains AMP expire-at set)\n|=====================================================================\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_35_-_Database_Management_-_B_-_Hashed_User_Passwords_in_Database.asciidoc",
    "content": "[[hashedPasswords]]\n= Hashed User Passwords in Database\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-10-09 03:13\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nBy default, user passwords are stored in plain-text in the Tigase's database. However, there is an easy way to have them encoded in either one of already supported ways or to even add a new encoding algorithm on your own.\n\nStoring passwords in hashed format in the database makes it possible to avoid using a plain-text password authentication mechanism. You cannot have hashed passwords in the database and non-plain-text password authentication. On the other hand, the connection between the server and the client is almost always secured by SSL/TLS so the plain-text password authentication method is perhaps less of a problem than storing plain-text passwords in the database.\n\nNevertheless, it is simple enough to adjust this in Tigase's database and we will add an option in the Tigase installer to allow you to make the decision on install.\n\n== Shortcut\nConnect to your database from a command line and execute following statement for MySQL database:\n\n[source,sql]\n-----\ncall TigPutDBProperty('password-encoding', 'encoding-mode');\n-----\n\nWhere encoding mode is one of the following:\n\n- *MD5-PASSWORD* the database stores MD5 hash code from the user's password.\n- *MD5-USERID-PASSWORD* the database stores MD5 hash code from concatenated user's bare JID and password.\n- *MD5-USERNAME-PASSWORD* the database stores MD5 hash code from concatenated user's name (localpart) and password.\n\nFor example:\n\n[source,sql]\n-----\ncall TigPutDBProperty('password-encoding', 'MD5-PASSWORD');\n-----\n\n== Full Route\nThe way passwords are stored in the DB is controlled by Tigase database schema property. Properties in the database schema can be set by a stored procedure called: +TigPutDBProperty(key, value)+. Properties from the DB schema can be retrieved using another stored function called: +TigGetDBProperty(key)+.\n\nThe simplest way to call them is via command-line interface to the database.\n\nFor the purpose of this guide let's say we have a MySQL database and a test account: *test@example.com* with password *test77*.\n\nBy default, most of DB actions for Tigase, are performed using stored procedures including user authentication. So, the first thing to do is to make sure the stored procedures are working correctly.\n\n=== Create a Test User Account\nTo add a new user account we use a stored procedure: +TigAddUserPlainPw(bareJid, password)+. As you can see there is this strange appendix to the procedure name: *PlainPw*. This procedure accepts plain passwords regardless how it is stored in the database. So it is safe and easy to use either for plain-text passwords or hashed in the DB. There are also versions of procedures without this appendix but they are sensitive on the data format and always have to pass password in the exact format it is stored in the database.\n\nSo, let's add a new user account:\n\n[source,sql]\n-----\ncall TigAddUserPlainPw('test@example.com', 'test77');\n-----\n\nIf the result was 'Query OK', then it means the user account has been successfully created.\n\n=== Test User Authentication\nWe can now test user authentication:\n\n[source,sql]\n-----\ncall TigUserLoginPlainPw('test@example.com', 'test77');\n-----\n\nIf authentication was successful the result looks like this:\n\n[source,sql]\n---------------------\n+--------------------+\n| user_id            |\n+--------------------+\n| 'test@example.com' |\n+--------------------+\n1 row in set (0.01 sec)\n\nQuery OK, 0 rows affected (0.01 sec)\n---------------------\n\nIf authentication was unsuccessful, the result looks like this:\n\n[source,sql]\n----------\n+---------+\n| user_id |\n+---------+\n|    NULL |\n+---------+\n1 row in set (0.01 sec)\n\nQuery OK, 0 rows affected (0.01 sec)\n----------\n\n=== Password Encoding Check\n+TigGetDBProperty+ is a function, not a procedure in MySQL database so we have to use select to call it:\n\n[source,sql]\n-----\nselect TigGetDBProperty('password-encoding');\n-----\n\nMost likely output is this:\n\n[source,sql]\n----------------------------------------\n+---------------------------------------+\n| TigGetDBProperty('password-encoding') |\n+---------------------------------------+\n| NULL                                  |\n+---------------------------------------+\n1 row in set, 1 warning (0.00 sec)\n----------------------------------------\n\nWhich means a default password encoding is used, in plain-text and thus no encoding. And we can actually check this in the database directly:\n\n[source,sql]\n-----\nselect uid, user_id, user_pw from tig_users where user_id = 'test@example.com';\n-----\n\nAnd expected result with plain-text password format would be:\n\n[source,sql]\n-------------------------------------\n+-----+--------------------+---------+\n| uid | user_id            | user_pw |\n+-----+--------------------+---------+\n|  41 | 'test@example.com' | test77  |\n+-----+--------------------+---------+\n1 row in set (0.00 sec)\n-------------------------------------\n\n=== Password Encoding Change\nNow let's set password encoding to MD5 hash:\n\n[source,sql]\n-----\ncall TigPutDBProperty('password-encoding', 'MD5-PASSWORD');\n-----\n\n'Query OK', means the password encoding has been successfully changed. Of course we changed the property only. All the existing passwords in the database are still in plain-text format. Therefore we expect that attempt to authenticate the user would fail:\n\n[source,sql]\n----------\ncall TigUserLoginPlainPw('test@example.com', 'test777');\n+---------+\n| user_id |\n+---------+\n|    NULL |\n+---------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n----------\n\nWe can fix this by updating the user's password in the database:\n\n[source,sql]\n---------------------\n\ncall TigUpdatePasswordPlainPw('test@example.com', 'test777');\nQuery OK, 1 row affected (0.01 sec)\n\nmysql> call TigUserLoginPlainPw('test@example.com', 'test777');\n+--------------------+\n| user_id            |\n+--------------------+\n| 'test@example.com' |\n+--------------------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n---------------------\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_36_-_Database_Management_-_C_-_Tigase_Server_and_Multiple_Databases.asciidoc",
    "content": "[[multidb]]\n= Tigase Server and Multiple Databases\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-10-02 04:23\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nSplitting user authentication data from all other XMPP information such as roster, vcards, etc... was almost always possible in Tigase XMPP Server. Possible and quite simple thing to configure. Also it has been always possible and easy to assign a different database for each Tigase component (MUC, PubSub, AMP), for recording the server statistics. Almost every data type or component can store information in a different location, simple and easy to setup through the configuration file.\n\nHowever it is much less known that it is also possible to have a different database for each virtual domain. This applies to both the user repository and authentication repository. This allows for very interesting configuration such as user database sharding where each shard keeps users for a specific domain, or physically split data based on virtual domain if each domain refers to a different customer or group of people.\n\nHow can we do that then?\n\nThis is very easy to do through the Tigase's configuration file.\n\nTypically the well known lines:\n\n[source,sh]\n-----\n--auth-db=tigase-custom\n--auth-db-uri=jdbc:mysql://db1.tigase/dbname?user&password\n--user-db=mysql\n--user-db-uri=jdbc:mysql://db2.tigase/dbname?user&password\n-----\n\nDefine just a default databases for both user repository and authentication repository. Default means it is used when there is no repository specified for a particular virtual domain. However, you can have a separate, both user and authentication repository for each virtual domain.\n\nHere is, how it works:\n\n[source,sh]\n-----\n# First, let's define our default database for all VHosts\n--auth-db=tigase-custom\n--auth-db-uri=jdbc:mysql://db1.tigase/dbname?user&password\n--user-db=mysql\n--user-db-uri=jdbc:mysql://db2.tigase/dbname?user&password\n\n# Now, we have VHost: domain1.com\n# User authentication data for this VHost is stored in Drupal database\n--auth-db[domain1.com]=drupal\n--auth-db-uri[domain1.com]=jdbc:mysql://db7.tigase/dbname?user&password\n# All other user data is stored in Tigase's standard database in MySQL\n--user-db[domain1.com]=mysql\n--user-db-uri[domain1.com]=jdbc:mysql://db4.tigase/dbname?user&password\n\n# Next VHost: domain2.com\n# User authentication is in LDAP server\n--auth-db[domain2.com]=tigase.db.ldap.LdapAuthProvider\n# Pretty standard Tigase's definition for the database (repository)\n#  connection string\n--auth-db-uri[domain2.com]=ldap://ldap.domain2.com:389\n# Now is something new, we have a custom authentication repository\n# settings for a single domain.\n# Please note how we define the VHost for which we set custom parameters\nbasic-conf/auth-repo-params/domain2.com/user-dn-pattern=cn=,ou=,dc=,dc=\n# All other user data is stored in the same as default repository\n--user-db[domain2.com]=mysql\n--user-db-uri[domain2.com]=jdbc:mysql://db2.tigase/dbname?user&password\n\n# Next VHost: domain3.com\n# Again user authentication is in LDAP server but pointing to\n# a different LDAP server with different access credentials\n--auth-db[domain3.com]=tigase.db.ldap.LdapAuthProvider\n# Pretty standard Tigase's definition for the database\n# (repository) connection string\n--auth-db-uri[domain3.com]=ldap://ldap.domain3.com:389\n# Now is something new, we have a custom authentication\n# repository settings for a single domain\n# Please note how we define the VHost for which we set custom parameters\nbasic-conf/auth-repo-params/domain3.com/user-dn-pattern=cn=,ou=,dc=,dc=\n# All other user data is stored on the domain3 server in PostgreSQL database\n--user-db[domain3.com]=pgsql\n--user-db-uri[domain3.com]=jdbc:pgsql://db.domain3.com/dbname?user&password\n\n# For VHost: domain4.com all the data, both authentication and\n# user XMPP data are stored on a separate\n# MySQL server with custom stored procedures for both user\n# login and user logout processing.\n--auth-db[domain4.com]=tigase-custom\n--auth-db-uri[domain4.com]=jdbc:mysql://db14.domain4.com/dbname?user&password\nbasic-conf/auth-repo-params/domain4.com/user-login-query={ call UserLogin(?, ?) }\nbasic-conf/auth-repo-params/domain4.com/user-logout-query={ call UserLogout(?) }\nbasic-conf/auth-repo-params/domain4.com/sasl-mechs=PLAIN,DIGEST-MD5\n--user-db[domain4.com]=mysql\n--user-db-uri[domain4.com]=jdbc:mysql://db14.domain4.com/dbname?user&password\n-----\n\nAs you can see, it requires some writing but flexibility is very extensive and you can setup as many separate databases as you need or want. If one database (recognized by the database connection string) is shared among different VHosts, Tigase still uses a single connection pool, so it won't create an excessive number of connections to the database.\n\nI hope this helps with more complex setups and configuration cases.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_37_-_Database_Management_-_D_-_Importing_User_Data.asciidoc",
    "content": "[[dbImportingData]]\n= Importing User Data\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nYou can easily copy data between Tigase compatible repositories that is repositories for which there is a database connector. However, it is not that easy to import data from an external source. Therefore a simple data import functionality has been added to repository utilities package.\n\nYou can access repository utilities through command +./bin/repo.sh+ or +./scripts/repo.sh+ depending on whether you use a binary package or source distribution.\n\n+-h+ parameter gives you a list of all possible parameters:\n\n[source,sh]\n-------------\n./scripts/repo.sh -h\n\nParameters:\n -h          this help message\n -sc class   source repository class name\n -su uri     source repository init string\n -dc class   destination repository class name\n -du uri     destination repository init string\n -dt string  data content to set/remove in repository\n -u user     user ID, if given all operations are only for that ID\n             if you want to add user to AuthRepository parameter must\n             in form: \"user:password\"\n -st         perform simple test on repository\n -at         simple test for adding and removing user\n -cp         copy content from source to destination repository\n -pr         print content of the repository\n -n          data content string is a node string\n -kv         data content string is node/key=value string\n -add        add data content to repository\n -del        delete data content from repository\n ------------\n -roster     check the user roster\n -aeg [true|false]  Allow empty group list for the contact\n -import file  import user data from the file of following format:\n         user_jid, password, roser_jid, roster_nick, subscription, group\n\n\n\nNote! If you put UserAuthRepository implementation as a class name\n      some operation are not allowed and will be silently skipped.\n      Have a look at UserAuthRepository to see what operations are\n      possible or what operation does make sense.\n      Alternatively look for admin tools guide on web site.\n-------------\n\nThe most critical parameters are the source repository class name and the initialization string. Therefore there are a few example preset parameters which you can use and adjust for your system. If you look inside the +repo.sh+ script you can find at the end of the script following lines:\n\n[source,sh]\n-----\nXML_REP=\"-sc tigase.db.xml.XMLRepository -su ../testsuite/user-repository.xml_200k_backup\"\nMYSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:mysql://localhost/tigase?user=root&password=mypass\"\nPGSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:postgresql://localhost/tigase?user=tigase\"\n\njava $D -cp $CP tigase.util.RepositoryUtils $MYSQL_REP $*\n-----\n\nYou can see that the source repository has been set to MySQL database with +tigase+ as the database name, +root+ the database user and +mypass+ the user password.\n\nYou can adjust these settings for your system.\n\nNow to import data to your repository simply execute the command:\n\n[source,sh]\n-----\n./bin/repo.sh -import import-file.txt\n-----\n\n_Note, the import function is available from_ *b895*\n\nThe format of the import file is very simple. This is a flat file with comma separated values:\n\n[source,bash]\n-----\njid,password,roster_jid,roster_nick,subscriptio,group\n-----\n\nTo create such a file from MySQL database you will have to execute a command like this one:\n\n[source,sql]\n-----\nSELECT a, b, c, d INTO OUTFILE 'import-file.txt'\nFIELDS TERMINATED BY ','\nLINES TERMINATED BY '\\n'\nFROM test_table;\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_38_-_Database_Management_-_E_-_Integrating_Existing_Databases.asciidoc",
    "content": "[[existingData]]\n= Importing Existing Data\n:author: Daniel Wisnewski\n:version: v1.0 October, 2015\n:date: 2015-05-10 13:35\n\nInformation about importing user data from other databases.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_39_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_1_-_Connecting_Tigase_Server_to_MySQL_Database.asciidoc",
    "content": "[[connectingTigaseToMysql]]\n= Connecting the Tigase Server to MySQL Database\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nPlease before continuing reading of this manual have a look at the xref:prepareMysql[initial MySQL database setup]. It will help you with database preparation for connecting with Tigase server.\n\nThe easiest way to setup Tigase server for connecting with MySQL database is to use the xref:tigase3xconfiguration[configuration wizards] (configuration generators) which release you from manually editing the XML configuration file and allow you quickly regenerate the XML configuration file in case of problems.\n\nThe article describes an older way for using configuration generators which is a bit more difficult and doesn't work on Windows systems. The guide below describes a new way to use them which is simpler and can be applied to Windows systems as well. It is using the +init.properties+ file where you can put all your initial configuration parameters.\n\nThis guide describes MySQL database connection parameters.\n\nThis guide is actually very short as there are example configuration files which can be used and customized for your environment.\n\nUnfortunately these files are not included yet in the server version 3.x binary release and you have to download them from the SVN repository using following links:\n\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/etc/tigase-mysql.conf[tigase-mysql.conf] - the Tigase server startup file. The only difference from the default one is that it points to the file described below to load initial parameters.\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/etc/init-mysql.properties[init-mysql.properties] - the file contains a few initial parameters which can/should be adjusted to your environment. Here is a content of the file with each line described:\n+\n[source,bash]\n-----\n# Load standard set of the server components.\n# Look at the http://www.tigase.org/configuration-wizards\n# document for other possible values. Normally you don't\n# need to change this line.\nconfig-type=--gen-config-def\n# List of administrator accounts, please replace them with\n# administrator accounts in your installation\n--admins=admin@tigase.org,admin@test-d\n# The line says that the database used by the Tigase server is 'mysql'\n# Look at the configuration wizards article for different options\n# You can also put here a Java class name if you have a custom\n# implementation for a database connector.\n--user-db=mysql\n# The line contains the database connection string. This is database\n# specific string and for each kind of database it may look differently.\n# Below string is for MySQL database. Please modify it for your system.\n# MySQL connector requires connection string in the following format:\n# jdbc:mysql://[hostname]/[database name]?user=[user name]&password=[user password]\n--user-db-uri=jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass\n# Virtual domains for your server installation, comma separated list of vhosts\n--virt-hosts=tigase.org,test-d,localhost\n# Select what packages you want to have logging switched for\n# The below setting is recommended for the initail setup and it is required\n# when asking for help with setting the server up\n--debug=server\n-----\n\nDownload both files and put them to your +etc/+ directory.\n\nEdit the +init-mysql.properties+ for your environment.\n\nRemove the XML configuration file.\n\nStart the server using following command:\n\n[source,sh]\n-----\n./bin/tigase.sh start etc/tigase-mysql.conf\n-----\n\n_Ask more questions if you got stuck or need any help with this._\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_40_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_2_-_Integrating_Tigase_Server_with_Drupal.asciidoc",
    "content": "[[integrateWithDrupal]]\n= Integrating Tigase Server with Drupal\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase supports integration with Drupal on many levels. At the moment this guide can work with Drupal version 4.x and 5.x. They may also work with Drupal 6.x but this version hasn't been tested.\n\nFirst of all, Tigase can authenticate users against a Drupal database which means you have the same user account for both Drupal website and the XMPP server. Moreover in such a configuration all account management is done via Drupal web interface like account creation, password change update user details and so on. Administrator can temporarily disable user account and this is followed by Tigase server too.\n\n== Connecting to Drupal Database\nThe best way to setup Tigase with Drupal database is via configuration wizards that is +init.properties+ file where you can put initial setting for Tigase configuration.\n\nIf you look in +etc/+ directory of your Tigase installation you should find a few files there. The one we want to base our configuration on is: +init-mysql.properties+. In some older packages the file might be missing, then you can download it from the link:https://projects.tigase.org/projects/tigase-server/repository/changes/etc/init-mysql.properties[SVN repository].\n\nIf you look inside the file and strip all the comments you would see following lines:\n\n[source,bash]\n-----\nconfig-type=--gen-config-def\n--admins=admin@tigase.org,admin@tigase.net\n--user-db=mysql\n--user-db-uri=jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass\n--virt-hosts=tigase.org,tigase.net\n--debug=server\n-----\n\nAll you need to connect to Drupal database are 2 following lines:\n\n[source,bash]\n-----\n--auth-db=drupal\n--auth-db-uri=jdbc:mysql://localhost/drupal?user=drupalusr&password=drupalpass\n-----\n\nLet's combine it in a single file called +etc/init-drupal.properties+:\n\n[source,bash]\n-----\nconfig-type=--gen-config-def\n--admins=admin@tigase.org,admin@tigase.net\n--auth-db=drupal\n--auth-db-uri=jdbc:mysql://localhost/drupal?user=drupalusr&password=drupalpass\n--user-db=mysql\n--user-db-uri=jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass\n--virt-hosts=tigase.org,tigase.net\n--debug=server\n-----\n\nIn theory you can load Tigase database schema to Drupal database and then both +db-uris+ would have the same database connection string. More details about setting up and connecting to MySQL database can be found in the xref:prepareMysql[MySQL guide].\n\nYou need also to edit +etc/tigase.conf+ file to point to your newly created properties file. The last line which looks like this:\n\n[source,bash]\n-----\nTIGASE_OPTIONS=\" --property-file etc/init.properties \"\n-----\n\nshould be changed to following:\n\n[source,bash]\n-----\nTIGASE_OPTIONS=\" --property-file etc/init-drupal.properties \"\n-----\n\nMake sure you have Java-6 installed and +JAVA_HOME+ is set to the correct location. If +JAVA_HOME+ is not set you can add following line to +etc/tigase.conf+ file:\n\n[source,bash]\n-----\nJAVA_HOME=\"/your/java-6-location\"\n-----\n\nThe best way to check whether the variable is set correctly is with command:\n\n[source,sh]\n-----\n$ ls -l $JAVA_HOME/bin/java\n-----\n\nshould list you the file without error.\n\nCheck also if the +logs/+ directory is created in your Tigase server location as sometimes unpacking application doesn't create empty directories.\n\nNow when you have the configuration file and databases ready to use you can start the Tigase server with the following command:\n\n[source,sh]\n-----\n./bin/tigase.sh start etc/tigase.conf\n-----\n\nIf you run the Tigase server installed from sources the command would be:\n\n[source,sh]\n-----\n./scripts/tigase.sh start etc/tigase.conf\n-----\n\nThere are system startup scripts for Gentoo and Mandriva Linux on +bin/+ or +scripts/+ directory which can be used to automatically start the server when system starts.\n\nNow you can register an account on your Drupal website and connect with an XMPP client using the account details.\n\n*Note!* _You have to enable plain password authentication in your XMPP client to connect to Tigase server with Drupal database_\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_41_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_3_-_Integrating_Tigase_Server_with_LibreSource.asciidoc",
    "content": "[[integrateWithLibreSource]]\n= Integrating Tigase Server With LibreSource\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n*This document is still not finished.*\n\nTaken directly from link:http://dev.libresource.org/[LibreSource] page:\n\n_LibreSource is a collaborative platform dedicated to both software development and community building. Based on Java/J2EE technology, LibreSource is a modular web server that users can customize online by combining resources and rights: wiki pages, forum, trackers, files, download areas, etc. All the tools are included and integrated._\n\n== Short Introduction\nIntegration between *Tigase* server and *LibreSource* is on a database level. It is implemented in the same way as integration with *Drupal* but with slightly more functions available.\n\nBasically LibreSource system maintains own database with all it's data and Tigase connects to LibreSource database to authenticate users. All user data specific to XMPP service are kept in separate tables which can be located in the same database as LibreSource data or in different database.\n\nCurrent list of features included in the integration:\n\n- XMPP users authentication against user data stored in LibreSource database.\n- Recording XMPP user on-line status in LibreSource database. This can be displayed on the Web page as additional user info.\n- Recording user last login time and this information can also be available on Web page.\n- Checking user account status. So if the user account is disabled in LibreSource system then this user will not be able to login to XMPP service too.\n- User account creation. This feature might be useful during testing time or user data transition from an old Tigase installation to LibreSource system. _Please note! This feature should be normally disabled on live system. All user account management should be done from LibreSource system because of data caching._\n- User account deletion. _Please note! This feature should be normally disabled on live system. All user account management should be done from LibreSource system because of data caching._\n\nA few assumptions:\n\n. LibreSource data are kept in PostgreSQL database - +libresource+ and database user is demo.\n. For use in cases where Tigase data are stored in MySQL database name is tigase, database user is dbuser and database user password is +dbpass+\n\n== How to set Tigase up\nNow we will focus on setting things up to have both services up and running together. Below is example of the most complex environment to run where LibreSource is using PostgreSQL database and Tigase is using a MySQL database. All basic user data needed for authentication is kept by LibreSource, so Tigase has to connect to PostgreSQL database also in order to authenticate users.\n\n. First you need LibreSource system up and running. Please refer to LS documentation for details.\n. Install Tigase server in the normal way including loading Tigase database schema. Database tables used by Tigase server use different naming convention so you can simply load Tigase DB schema to the same database as LibreSource data. It is also possible and recommended to keep Tigase data in separate database.\n. Using configuration wizards generate configuration for Tigase server to connect to LibreSource database. Here is the sample file with parameters for configuration wizard assuming following setup:\n  - LibreSource data are kept in PostgreSQL database: +libresource,+ user: +demo+\n  - Tigase data are kept in MySQL database: +tigase+, user: +dbuser+, password: +dbpass+\n  - No external components are connected to Tigase server\n  - Tigase works for domain: +domain.net+\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver\"\n\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\nTIGASE_CONFIG=\"etc/tigase-mysql-libresource.xml\"\nTIGASE_OPTIONS=\"--gen-config-def \\\n  --user-db mysql \\\n  --user-db-uri jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass&autoCreateUser=true \\\n  --auth-db libresource \\\n  --auth-db-uri jdbc:postgresql://localhost/libresource?user=demo \\\n  --virt-hosts domain.net,localhost \"\n-----\n. A simpler example where all data (LibreSource and Tigase) are stored in the same database:\n  - LibreSource data are kept in PostgreSQL database: +libresource+, user: +demo+\n  - Tigase data are kept also in PostgreSQL database: +libresource+, user: +demo+\n  - No external components are connected to Tigase server\n  - Tigase works for domain: +domain.net+\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver\"\n\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\nTIGASE_CONFIG=\"etc/tigase-mysql-libresource.xml\"\nTIGASE_OPTIONS=\"--gen-config-def \\\n  --user-db pgsql \\\n  --user-db-uri jdbc:postgresql://localhost/libresource?user=demo&autoCreateUser=true \\\n  --auth-db libresource \\\n  --auth-db-uri jdbc:postgresql://localhost/libresource?user=demo \\\n  --virt-hosts domain.net,localhost \"\n-----\n\nNow, you can run Tigase as normal and it all works.\n\n*Note!* _You have to load Tigase database schema for user data. Please refer to guide for specific database: xref:mysql2database[MySQL] or xref:postgresDB2[PostgreSQL]._\n\n== Migration From an old Tigase Installation to LibreSource\nTigase package includes additional tools to make it easier to manage and control you installation. One is used to change configuration settings - +config.sh+ and another is used to manipulate user data in repository - +repo.sh+.\n\nDepending on whether you use Tigase version built from sources or binary version these scripts might be available in either +scripts/+ or +bin/+ subdirectories. To make things simpler let's assume they are stored in +scripts/+ directory.\n\nAssuming you have an old Tigase server installation with number of users in MySQL database and you want to migrate all of them to LibreSource there are 2 steps involved:\n\n. User data migration\n. Changing your existing configuration\n\n=== Data Migration\nFirst we need to migrate user data used for authentication. That data will be used by both services: _LibreSource_ and _Tigase_ and they normally stored in _LibreSource_ database. Therefore we have to use _LibreSource_ database connector to handle the data (write or read). _Tigase_ server will be using _LibreSource_ database for reading only but during migration time we need to write user accounts to LS database. Sample command to migrate user accounts looks like this:\n\n[source,sh]\n-----\n./scripts/repo.sh -sc tigase.db.jdbc.JDBCRepository \\\n  -su \"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\" \\\n  -dc tigase.db.jdbc.LibreSourceAuth \\\n  -du \"jdbc:postgresql://localhost/libresource?user=demo\" \\\n  -cp\n-----\n\nThe above command will copy all user accounts from MySQL tigase database to +libresource+ database. Please refer to repository management tool documentation for information how to migrate single or selected user accounts.\n\nIf you want to keep all Tigase server data in the same database you have to copy also all other user data like rosters, vCards and so on.\n\nFirst thing we have to do is load the database schema for Tigase data. Because Tigase tables have distinct names from LibreSource, there is no danger for any conflict. As in the above example let's assume LibreSource's data is stored in libresource database and database user name is +demo+:\n\n[source,sh]\n-----\npsql -q -U demo -d libresource -f database/postgresql-schema.sql\n-----\n\nNow we can load and transfer all user data from MySQL database to LibreSource:\n\n[source,sh]\n-----\n./scripts/repo.sh -sc tigase.db.jdbc.JDBCRepository \\\n  -su \"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\" \\\n  -dc tigase.db.jdbc.JDBCRepository \\\n  -du \"jdbc:postgresql://localhost/libresource?user=demo\" \\\n  -cp\n-----\n\nThis command looks siumilar to the previous one. Just a Java class used for handling destination database is different.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_42_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_4_-_MySQL_Database_Use.asciidoc",
    "content": "[[mysql2database]]\n= MySQL Database Use\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:date: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to configure Tigase server to use link:http://www.mysql.com/[MySQL] database as a user repository.\n\nIf you used an XML based user repository before you can copy all user data to MySQL database using repository management tool. All steps are described below.\n\n== MySQL Database Preparation\nTo load db schema to your MySQL instance first create database:\n\n[source,sh]\n-----\nmysqladmin -p create tigase\n-----\n\nAnd then you can load database schema:\n\n[source,sh]\n-----\nmysql -u dbuser -p tigase < mysql-schema.sql\n-----\n\n== Server Configuration\nNow you have to change configuration to load a jdbc module instead of XML based repository. Using configuration management script, first change class name handling repository.\n\nTo see current settings run command:\n\n[source,sh]\n-----\n$ ./scripts/config.sh -c tigase-config.xml -print -key session_1/user-repo-class\n-----\n\nAs a result you should see something like:\n\n[source,sh]\n-----\nsession_1/user-repo-class = tigase.db.xml.XMLRepository\n-----\n\nYou can see that current setting points to the XML repository implementation. To use jdbc module for connecting to MySQL database you have to set tigase.db.jdbc.JDBCRepository class (enter text below in one line):\n\n[source,sh]\n-----\n$ ./scripts/config.sh -c tigase-config.xml -print -key session_1/user-repo-class -value tigase.db.jdbc.JDBCRepository -set\n-----\n\nAs a result you will see new value set for the parameter:\n\n[source,bash]\n-----\nsession_1/user-repo-class = tigase.db.jdbc.JDBCRepository\n-----\n\nYou have also to set the same value as authorization repository unless you want to use different authorization data source:\n\n[source,sh]\n-----\n $ ./scripts/config.sh -c tigase-config.xml -print -key session_1/auth-repo-class -value tigase.db.jdbc.JDBCRepository -set\n-----\n\nAnd again as a result we can see:\n\n[source,bash]\n-----\nsession_1/auth-repo-class = tigase.db.jdbc.JDBCRepository\n-----\n\nNext step is to set the database connection string. Assuming you have database: *tigase* on *localhost* with database user: *dbuser* and password *dbpass* your connection string will look like this:\n\n[source,bash]\n-----\njdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\n-----\n\nTo set this in your configuration file, you have to the configuration management script 2 times. First for user data repository and second for authorization data repository:\n[source,sh]\n-----\n$ ./scripts/config.sh -c tigase-config.xml -print -key session_1/user-repo-url -value \"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\" -set\n$ ./scripts/config.sh -c tigase-config.xml -print -key session_1/auth-repo-url -value \"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\" -set\n-----\n\n*Note quotes around connection string.* They are needed to make sure the shell won't interpret special characters.\n\nNow the configuration is ready to load the jdbc module and connect to your database.\n\nOne more thing you need to do is to tell JVM which jdbc driver to use to connect to database. Depending on your MySQL and jdbc installation it might be: +com.mysql.jdbc.Driver.+ To set is as database driver you have to set is a jdbc.drivers property value. Usually you do this by adding -D parameter to Java call:\n\n[source,sh]\n-----\n $ java -Djdbc.drivers=com.mysql.jdbc.Driver tigase.server.XMPPServer\n-----\n\nIf you use tigase.sh script to run server you will have to add +-Djdbc.drivers=com.mysql.jdbc.Driver+ to the startup script +init.Properties+ property file to +JAVA_OPTIONS+ values.\n\n== User Data Import\nIf you previously used an XML based user repository, you can import all data into a MySQL database using repository management tool. This is quite long command so let me list all required parameters first with brief explanation:\n\n. *-cp* copy content of the source repository to destination repository.\n. *-sc* *tigase.db.xml.XMLRepository* source repository class.\n. *-su* *user-repository.xml* source repository connection string - assuming your user repository is in +user-repository.xml+ file.\n. *-dc* *tigase.db.jdbc.JDBCRepository* destination repository class.\n. *-du* *\"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\"* destination repository connection string.\n\nAnd now whole command. Enter all in one line:\n\n[source,sh]\n-----\n$ ./scripts/repo.sh -cp -sc tigase.db.xml.XMLRepository -su user-repository.xml -dc tigase.db.jdbc.JDBCRepository -du \"jdbc:mysql://localhost/tigase?user=dbuser&password=dbpass\"\n-----\n\nFor more information how to use command line administration tools refer to xref:commandLineTools2[command line tools guide.]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_43_-_Database_Management_-_E_-_Integrating_Existing_Databases_-_5_-_PostgreSQL_Database.asciidoc",
    "content": "[[postgresDB2]]\n= PostgreSQL Database Use\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis guide describes how to configure Tigase server to use link:http://www.postgresql.org/[PostgreSQL] database as a user repository.\n\nIf you used an XML based user repository before you can copy all user data to PostgreSQL database using repository management tool. All steps are described below.\n\n== PostgreSQL Database Preparation\nCreate new database user account which will be used to connect to your database:\n\n[source,sh]\n-----\n# createuser\nEnter name of user to add: tigase\nShall the new user be allowed to create databases? (y/n) y\nShall the new user be allowed to create more new users? (y/n) y\n-----\n\nNow using new database user account create database for your service:\n\n[source,sh]\n-----\n# createdb -U tigase tigasedb\nCREATE DATABASE\n-----\n\nNow you can load the database schema:\n\n[source,sh]\n-----\n# psql -U tigase -d tigasedb -f postgresql-schema.sql\n-----\n\nNow the database is ready for Tigase server to use.\n\n== Server Configuration\nServer configuration is identical as MySQL database setup. The same jdbc module is used to connect to PostgreSQL database as for MySQL. The only difference is the connection string which usually looks like:\n\n[source,bash]\n-----\njdbc:postgresql://localhost/tigasdb?user=tigase\n-----\n\nSo for more detailed guide how to change configuration refer to xref:mysql2database[MySQL database use guide] or if you look for a more automatic configuration file generation refer to xref:3xconfiguration[configuration wizards] page.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_44_-_Database_Management_-_F_-_Schema_Updates.asciidoc",
    "content": "[[oldVerSchemas]]\n= Schema Updates\n:author: Daniel wisnewski\n:version: v1.0, October 2015\n:date: 2015-10-05 13:41\n\nThis is a repository for Schema updates in case you have to upgrade from older installations.\n\n\n- xref:tigaseServer71[Tigase Server Schema v7.1 Updates] Applies to v7.1.0 and v7.2.0\n- xref:tigase51schemaupgrade[Upgrades to v5.1 of Tigase]\n. xref:derby51upgrade[Derby Database Schema Upgrade for Tigase 5.1]\n. xref:mysql51upgrade[MySQL Database Schema Upgrade for Tigase 5.1]\n. xref:postgresql51upgrade[PostgreSQL Database Schema Upgrade for Tigase 5.1]\n- xref:tigase40schemaUpgrade[MySQL Database Schema Upgrade for Tigase 4.0]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_45_-_Database_Managament_-_F_-_Schema_Updates_-_A_-_Tigase_Server_7.1.asciidoc",
    "content": "[[tigaseServer71]]\n= Tigase Server Schema v7.1 Updates\n:author: Daniel Wisnewski\n:version: v1.0 October 2015\n:Date: 2015-10-12 15:36\n\n:numbered:\n:website: http://www.tigase.org\n\n[[v710notice]]\n== *FOR ALL USERS UPGRADING TO v7.1.0 FROM A v7.0.2 INSTALLATION*\nThe schema has changed for the main database, and the pubsub repository.  In order to upgrade to the new schemas, you will need to do the following: +\n\n1. Upgrade the Main database schema to v7.1 using the database/${DB_TYPE}-schema-upgrade-to-7-1.sql file\n\n2. Upgrade the Pubsub Schema to v3.1.0 using the database/${DB_TYPE}-pubsub-schema-3.1.0.sql file\n\n3. Upgrade the Pubsub Schema to v3.2.0 using the database/${DB_TYPE}-pubsub-schema-3.2.0.sql file\n\nAll three commands may be done at the same time in that order, it is suggested you make a backup of your current database to prevent data loss.\n\n\n== Tigase Schema Change for v7.1\nTigase has made changes to its database to include primary keys in the tig_pairs table to improve performance of the Tigase server.  This is an auto-incremented column for Primary Key items appended to the previous schema.\n\n*You MUST update your database to be compliant with the new v7.1 schema.  If you do not, Tigase will not function properly.*\n\n_This change will affect all users of Tigase using v7.1.0 and newer._\n\nIf you are installing a new version of v7.1.0 on a new database, the schema should automatically be installed.\n\nFirst, shut down any running instances of Tigase to prevent conflicts with database editing.  Then from command line use the DBSchemaLoader class to run the -schema-upgrade-to-7.1.sql file to the database.  The command is as follows:\n\nIn a linux environment\n[source,bash]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbHostname ${HOSTNAME} -dbType ${DB_TYPE} -rootUser ${ROOT_USER} -dbPass ${DB_USER_PASS} -dbName ${DB_NAME} -schemaVersion ${DB_VERSION} -rootPass ${ROOT_USER_PASS} -dbUser ${DB_USER}  -adminJID \"${ADMIN_JID}\" -adminJIDpass ${ADMIN_JID_PASS}  -logLevel ALL -file database/${DB_TYPE}-schema-upgrade-to-7-1.sql\n-----\n\nIn a windows environment\n[source,bash]\n-----\njava -cp jars/* tigase.util.DBSchemaLoader -dbHostname ${HOSTNAME} -dbType ${DB_TYPE} -rootUser ${ROOT_USER} -dbPass ${DB_USER_PASS} -dbName ${DB_NAME} -schemaVersion ${DB_VERSION} -rootPass ${ROOT_USER_PASS} -dbUser ${DB_USER}  -adminJID \"${ADMIN_JID}\" -adminJIDpass ${ADMIN_JID_PASS}  -logLevel ALL -file database/${DB_TYPE}-schema-upgrade-to-7-1.sql\n-----\n\nAll variables will be required, they are as follows: +\n\n* ${HOSTNAME} - Hostname of the database you wish to upgrade. +\n* ${DB_TYPE} - Type of database [derby, mysql, postgresql, sqlserver]. +\n* ${ROOT_USER} - Username of root user. +\n* ${ROOT_USER_PASS} - Password of specified root user. +\n* ${DB_USER} - Login of user that can edit database. +\n* ${DB_USER_PASS} - Password of the specified user. +\n* ${DB_NAME} - Name of the database to be edited. +\n* ${DB_VERSION} - In this case, we want this to be 7.1. +\n* ${ADMIN_JID} - Bare JID of a database user with admin privileges.  Must be contained within quotation marks. +\n* ${ADMIN_JID_PASS} - Password of associated admin JID. +\n\nPlease note that the SQL file for the update will have an associated database with the filename.  i.e. postgresql-update-to-7.1.sql for postgresql database.\n\nA finalized command will look something like this:\n[source,bash]\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbHostname localhost -dbType mysql -rootUser root -rootPass root -dbUser admin -dbPass admin -schemaVersion 7.1 -dbName Tigasedb -adminJID \"admin@local.com\" -adminJIDPass adminpass -logLevel ALL -file database/mysql-schema-upgrade-to-7.1.sql\n-----\n\nOnce this has successfully executed, you may restart you server.  Watch logs for any db errors that may indicate an incomplete schema upgrade.\n\n\n[[pubSub71]]\n== Changes to Pubsub Schema\nTigase has had a change to the PubSub Schema, to upgrade to PubSub Schema v7.1 without having to reform your databases, use this guide to update your databases to be compatible with the new version of Tigase.\n\n*NOTE* Current PubSub Schema is v3.2.0, you will need to repeat these instructions for v3.1.0 and then v3.2.0 before you run Tigase V7.1.0.\n\nThe PubSub Schema has been streamlined for better resource use, this change affects all users of Tigase.\nTo prepare your database for the new schema, first be sure to create a backup!  Then apply the appropriate PubSub schema to your MySQL and it will add the new storage procedure.\n\nAll these files should be in your /database folder within Tigase, however if you are missing the appropriate files, use the links below and place them into that folder.\n\nThe MySQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/revisions/master/entry/database/mysql-pubsub-schema-3.1.0.sql[Here].\n\nThe Derby schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/derby-pubsub-schema-3.1.0.sql[Here].\n\nThe PostGRESQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/postgresql-pubsub-schema-3.1.0.sql[Here].\n\nThe MS SQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/sqlserver-pubsub-schema-3.1.0.sql[Here].\n\nThe same files are also included in all distributions of v7.1.0 in +[tigaseroot]/database/+ . All changes to database schema are meant to be backward compatible.\n\n\nYou can use a utility in Tigase to update the schema using the following command from the Tigase root:\nLinux\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader\n-----\nor from a Windows environment\n-----\njava -cp jars/* tigase.util.DBSchemaLoader\n-----\n*NOTE: Some variation may be necessary depending on how your java build uses -cp option*\n\nUse the following options to customize. Options in bold are required.::\n* *[-dbType database_type {derby, mysql, postgresql, sqlserver}]*\n* [-schemaVersion schema version {4, 5, 5-1} ]\n* *[-dbName database name]*\n* [-dbHostname database hostname] (default is localhost)\n* [-dbUser tigase username]\n* [-dbPass tigase user password]\n* *[-rootUser database root username]*\n* *[-rootPass database root password]*\n* *[-file path to sql schema file]*\n* [-query sql query to execute]\n* [-logLevel java logger Level]\n* [-adminJID comma separated list of admin JIDs]\n* [-adminJIDpass password (one for all entered JIDs]\n\n*Arguments take following precedent: query, file, whole schema*\n\nAs a result your final command should look something like this:\n-----\njava -cp \"jars/*\" tigase.util.DBSchemaLoader -dbType mysql -dbName tigasedb -dbUser root -dbPass password -file database/mysql-pubsub-schema-3.1.0.sql\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_46_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x.asciidoc",
    "content": "[[tigase51schemaupgrade]]\n= Tigase 5.1 Database Schema Upgrade\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-07-16 11:10\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nWe had to make a small change to the database schema for Tigase version 5.1.0.\n\nIt does not affect data or data structure, only the way in which some data is accessed in database. We added one more stored procedure which has to be installed in database if you upgrade your installation from a previous Tigase version\n\nThe schema upgrade is very simple and safe but make sure the current database schema is in version 4.0.\nIf you happen to use ancient version of Tigase earlier than 4.0 and you want to upgrade to 5.1, you have to run xref:tigase40schemaupgrade[4.0 upgrade script] first.\n\nPlease follow detailed guide for the database applicable to your installation: xref:derby51upgrade[Derby], xref:mysql51upgrade[MySQL], xref:postgresql51upgrade[PostgreSQL].\n\n- xref:derby51upgrade[Derby Database Schema Upgrade for Tigase 5.1]\n- xref:mysql51upgrade[MySQL Database Schema Upgrade for Tigase 5.1]\n- xref:postgresql51upgrade[PostgreSQL Database Schema Upgrade for Tigase 5.1]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_47_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_1_-_Derby.asciidoc",
    "content": "[[derby51upgrade]]\n= Derby Database Schema Upgrade for Tigase 5.1\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-06-20 19:12\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe schema upgrade is very simple and safe but make sure the current database schema is in version 4.0.\n\nFirst things first - make a database backup:\n\n[source,sh]\n-----\ntar -czf derbyDB.tar.gz /path/to/derbyDB\n-----\n\nIf you need to restore database for any reason simply extract files from the backup archive:\n\n[source,sh]\n-----\nrm -rf /path/to/derbyDB\ntar -xf derbyDB.tar.gz\n-----\n\nNow we can run schema upgrade script\n\n[source,sh]\n-----\njava -Dij.protocol=jdbc:derby: -Dij.database=\"/path/to/derbyDB\" \\\n\t\t-Dderby.system.home=`pwd` \\\n\t\t-cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar \\\n\t\torg.apache.derby.tools.ij database/postgresql-schema-upgrade-to-5-1.sql\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_48_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_2_-_MySQL_Database_Schema_Upgrade_for_Tigase_5.1.asciidoc",
    "content": "[[mysql51upgrade]]\n= MySQL Database Schema Upgrade for Tigase 5.1\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-04-21 03:58\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe schema upgrade is very simple and safe but make sure the current database schema is in version 4.0.\n\nAssumptions:\n\n. *tigasedb* is a database name\n. *tigase_user* is a database user name\n. *mypass* is database user password\n\nFirst things first - make a database backup:\n\n[source,sh]\n-----\nmysqldump -u tigase_user -pmypass tigasedb > tigasedb_dump.sql\n-----\n\nIf you need to restore database for any reason execute following commands:\n\n[source,sh]\n-----\nmsyqladmin -u tigase_user -pmypass drop tigasedb\nmysqladmin -u tigase_user -pmypass create tigasedb\nmysql -u tigase_user -pmypass tigasedb < tigasedb_dump.sql\n-----\n\n_Note! You may be required to use root user and his password to execute mysqladmin commands._\n\nNow we can run schema upgrade script\n\n[source,sh]\n-----\nmysql -u tigase_user -pmypass tigasedb < database/mysql-schema-upgrade-to-5-1.sql\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_49_-_Database_Management_-_F_-_Schema_Updates_-_B_-_Tigase_Server_Version_5.x_-_3_-_PostgreSQL_Database_Schema_Upgrade_for_Tigase_5.1.asciidoc",
    "content": "[[postgresql51upgrade]]\n= PostgreSQL Database Schema Upgrade for Tigase 5.1\n:author: Andrzej Wojcik <andrzejw@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-06-16 11:03\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe schema upgrade is very simple and safe but make sure the current database schema is in version 4.0.\n\nAssumptions:\n\n- *tigasedb* is a database name\n- *tigase_user* is a database user name\n- *admin_db_user* is database admin user name\n\nFirst things first - make a database backup:\n\n[source,sql]\n-----\npg_dump -U tigase_user -W tigasedb > tigasedb_dump.sql\n-----\n\nIf you need to restore database for any reason execute following commands:\n\n[source,sql]\n-----\ndropdb -U admin_db_user -W tigasedb\ncreatedb -U admin_db_user -W -O tigase_user tigasedb\npsql -U tigase_user -W tigasedb < tigasedb_dump.sql\n-----\n\nNow we can run schema upgrade script\n\n[source,sql]\n-----\npsql -q -U tigase_user -W tigasedb -f database/postgresql-schema-upgrade-to-5-1.sql\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_51_-_Database_Management_-_F_-_Schema_Updates_-_C_-_Tigase_Server_Version_4.x.asciidoc",
    "content": "[[tigasev4x]]\n= Tigase Server Version 4.x\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nSchema Upgrades for Tigase server version 4.x.\n\n- xref:tigase40schemaUpgrade[MySQL Database Schema Upgrade for Tigase 4.0]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_52_-_Database_Management_-_F_-_Schema_Updates_-_C_-_Tigase_Server_Version_4.x_-_1_-_MySQL_Database_Schema_Upgrade_for_Tigase_4.0.asciidoc",
    "content": "[[tigase40schemaupgrade]]\n= MySQL Database Schema Upgrade for Tigase 4.0\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nFor number of reasons the database schema had to be changed for Tigase server version 4.0. The most important are:\n\n- Compliance with the XMPP RFC which says that each part of JID may have up to 1023 characters. We store in the database user JIDs without resource names thus the maximum possible size of the user id is 2047. There aren't really JIDs that long yet, but we experienced quite long JIDs in a few installations already. So it was decided to prepare Tigase to accept any JID allowed by RFC.\n\n- Performance and flexibility -  the Tigase server now accesses database using stored procedures. This allows for any database storage format and it doesn't really matter for Tigase server what is the database schema how data is organized inside. What it needs is just bunch of stored procedures to access the data. This allows for much more flexibility in storing user data as well as much easier integration with third-party systems as well as organize data in more efficient way.\n\nTherefore when you run the Tigase server now it may (depending on what exact SVN revision you use) refuse to start if it detects that the database schema is not updated. If it happens just follow steps below to update the database schema and start the server again.  Updating of the database schema is very easy and almost fully automated process. Just follow the steps below and you should be able to run the new version of Tigase server in a few minutes or even seconds depending on your database size. It took around 7 minutes to update our database with 200k user accounts on an average machine.\n\n*Note. Do not update the database schema before Tigase server tells you to do so. Be sure to do a database backup before starting the schema update.*\n\n_Please note. I have done a few schema upgrades already in a few different configurations and here are a few tips which might be useful if something goes wrong:_\n\n. *You really, REALLY have to do the DB backup (database dump) before upgrading.* _If you don't you might not be able to revert database on your own._\n. _In case of error:_ *ERROR 1419 (HY000) at line 31 in file: 'database/mysql-schema-4-sp.schema': You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)* _Restore the database following description found below and run the update again as MySQL super user._\n. _The following error may manifest itself in many ways from the NullPointerException in Tigase server log file to message like this:_ *User does not have access to metadata required to determine stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.* _The best solution to this is to grant proper permissions to this user. Enter the MySQL command line mode as MySQL super user:_\n+\n[source,sql]\n-----\n$ mysql -u root -proot_passwd mysql\nmysql> GRANT SELECT, INSERT, UPDATE ON \\`mysql\\`.\\`proc\\` TO 'tigase_user'@'localhost';\nmysql> GRANT SELECT, INSERT, UPDATE ON \\`mysql\\`.\\`proc\\` TO 'tigase_user'@'%';\nmysql> GRANT SELECT, INSERT, UPDATE ON \\`mysql\\`.\\`proc\\` TO 'tigase_user';\nmysql> FLUSH PRIVILEGES;\n$\n-----\n\nAssumptions:\n\n. *tigasedb* is a database name\n. *tigase_user* is a database user name\n. *mypass* is database user password\n\nFirst things first - make a database backup:\n\n[source,sh]\n-----\nmysqldump -u tigase_user -pmypass tigasedb > tigasedb_dump.sql\n-----\n\nIf you need to restore database for any reason execute following commands:\n\n[source,sh]\n-----\nmsyqladmin -u tigase_user -pmypass drop tigasedb\nmysqladmin -u tigase_user -pmypass create tigasedb\nmysql -u tigase_user -pmypass tigasedb < tigasedb_dump.sql\n-----\n\n_Note! You may be required to use_ *root* _user and password to execute mysqladmin commands.  Ok we have the database backup and we know how to restore it. Now we can run schema upgrade script:_\n\n[source,sh]\n-----\nmysql -u tigase_user -pmypass tigasedb < database/mysql-schema-upgrade-to-4.sql\n-----\n\n_The script should generate output like this:_\n\n[source,sh]\n-----\nDroping index for user_id column\nResizing user_id column to 2049 characters to comply with RFC\nCreating a new index for user_id column for first 765 bytes of the field\nAdding sha1_user_id column\nAdding user_pw column\nAdding last_login column\nAdding last_logout column\nAdding online_status column\nAdding failed_logins column\nAdding account_status column\nCreating a new index for user_pw column\nCreating a new index for last_login column\nCreating a new index for last_logout column\nCreating a new index for account_status column\nCreating a new index for online_status column\nResizing node column to 255 characters\nChanging pval column type to mediumtext\nLoading stored procedures definitions\nSetting passwords encoding in the database\nConverting database to a new format\nCreating a new index for sha1_user_id column\nSetting schema version to 4.0\nAll done, database ready to use!\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_53_-_Components.asciidoc",
    "content": "[[loadComponent]]\n= Configuring the Tigase Server to Load a Component\n\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nA detailed description of all the configuration options is in the +init.properties+ guide where you can also find information described below and much more. The purpose of this document is to give you a brief introduction on how to load a component into Tigase server without the need to dig through all the details.\n\nI will show how to load 2 components into Tigase server using a configuration in the init.properties file: link:https://projects.tigase.org/projects/tigase-muc[MUC] and link:https://projects.tigase.org/projects/tigase-pubsub[PubSub].\n\nThe only step is to tell the server what components to load, how to name them and optionally give some extra parameters. To do so open the +init.properties+ file you use in your installation.\n\nLet's say you want to just add PubSub for now. All you need to do is add 2 lines to the properties file:\n\n[source,bash]\n-----\n--comp-name-1=pubsub\n--comp-class-1=tigase.pubsub.PubSubComponent\n-----\n\nThe first line contains the component name 'pubsub' and the main class for this component is: 'tigase.pubsub.PubSubClusterComponent'. It doesn't really matter what the component name is, the only requirement is that it must be unique among other components names. Because you can load many components, it helps to provide descriptive names thus 'pubsub' is a good name for a 'PubSub' component.\n\nYou can of course add more components, even PubSub components to the same server. Just remember that each of them would need to have a different name then. For example:\n\n[source,bash]\n-----\n--comp-name-2=pubsub-priv\n--comp-class-2=tigase.pubsub.PubSubComponent\n-----\n\nAlthough this may be rare, it allows for wide compatibility and platform stability.\n\nNormally, however we want to load few different components like PubSub, MUC, MSN Transport and so on.... Therefore instead of the above second PubSub we can load the MUC component:\n\n[source,bash]\n-----\n--comp-name-2=muc\n--comp-class-2=tigase.muc.MUCComponent\n-----\n\nChanges to the init.properties file will take effect upon server restart.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_54_-_Components_-_A_-_StanzaSender.asciidoc",
    "content": "[[stanzaSender]]\n= StanzaSender\n\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nStanzaSender is a component which makes it easier to integrate XMPP server with other third-party tools.\n\nIt simply allows you to send stanzas from your application without implementing any XMPP specific code. The component regularly reads specified data source for XMPP packets to send. The data source can be a SQL database, directory on your filesystem, or anything you might want.\n\nIf you have a Web application for example for which you want to send notifications of an event to selected users you can install link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/src/main/java/tigase/server/ssender[StanzaSender] component on your Tigase server. It will help you to easily distribute your messages to end-users.\n\n== How it Works\n\nThe module itself doesn't do anything, it just schedules tasks and sends stanzas which come from anywhere. To do the actual work of retrieving stanzas from data source the component uses *tasks*.\n\nIn theory the task can retrieve XMPP packets for sending from any location or may just generate stanzas on its own.\n\nIn practice there are 2 *tasks* already implemented and ready to use. You can treat them as a sample code for implementation of your own tasks customised for your specific needs or you can just use these tasks as they are.\n\nThe tasks which are available are:\n\n- +FileTask+ retrieving stanzas from directory in file system.\n- +JDBCTask+ retrieving stanzas from SQL database.\n\n=== FileTask\n\n+FileTask+ implements tasks for cyclic retrieving stanzas from a directory and sending them to the StanzaHandler object.\n\nIt looks for any new stanza to send. Any single file can contain only a single stanza to send and any entry in database table can also contain only a single stanza to send. Files on hard disk and records in databases are deleted after it is read.\n\nAny file in a given directory is treated the same way - Tigase assumes it contains valid XML data with XMPP stanza to send. You can however set in configuration, using wildchars which files contain stanzas. All stanzas must contain complete data including correct \"_from_\" and \"_to_\" attributes.\n\nBy default it is looking for +*.stanza+ files in +/var/spool/jabber/+ folder but you can specify different directory names in the initialization string. Here is a sample initialization strings:\n\n- +/var/spool/jabber/*.stanza+\n- +/var/spool/jabber/*+\n\nThe last is equal to:\n\n- +/var/spool/jabber/+\n\nNote the last forward slash '/' is required in such case if the last element of the path is a directory.\n\n*Please note! Tigase must have writing permissions for this directory, otherwise it may not function properly.*\n\n=== JDBCTask\n\n+JDBCTask+ implements tasks for cyclic retrieving stanzas from database and sending them to the StanzaHandler object.\n\nDatabase table format:\n\n- *id* - numerical unique record identifier.\n- *stanza* - text field containing valid XML data with XMPP stanza to send.\n\nAny record in this table is treated the same way - Tigase assumes it contains valid XML data with XMPP stanza to send. No other data are allowed in this table. All stanzas must be complete including correct \"_from_\" and \"_to_\" attributes.\n\nBy default it is looking for stanzas in +xmpp_stanza+ table, but you can specify a different table name in the connection string. For example:\n\n+jdbc:mysql://localhost/tigasedb?user=tigase&password=pass&table=xmpp_stanza+\n\nPlease note the last parameter which is specific to +JDBCTask+. You can specify the table name which stores stanzas for sending, if omitted default value is: +xmpp_stanza+.\n\n== Configuration\n\nStanzaSender is a Tigase component so the configuration is similar to that of all other components. The simplest way to get the settings for *StanzaSender* is by generating a configuration with all possible components. To do this you have to run Tigase server with +--gen-config-all+ parameter set.\n\nBy default this component name is *ssend* and here is a content of the configuration file for *StanzaSender*:\n\nIt is one of +msg-receivers+:\n\n[source,bash]\n-----\n<entry type=\"String[]\" key=\"id-names\">\n  ...\n  <item value=\"ssend\"/>\n</entry>\n-----\n\nTo activate the component and a specify class name for it following entries has been added:\n\n[source,bash]\n-----\n<entry value=\"true\" type=\"Boolean\" key=\"ssend.active\"/>\n<entry value=\"tigase.server.ssender.StanzaSender\" type=\"String\" key=\"ssend.class\"/>\n-----\n\nAnd the main settings section for the component:\n\n[source,bash]\n-----\n<component name=\"ssend\">\n  <map>\n   <entry value=\"10\" type=\"Long\" key=\"default-interval\"/>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n   <entry type=\"String[]\" key=\"stanza-listeners\">\n    <item value=\"jdbc\"/>\n    <item value=\"file\"/>\n   </entry>\n  </map>\n  <node name=\"file\">\n   <map>\n    <entry value=\"true\" type=\"Boolean\" key=\"active\"/>\n    <entry value=\"tigase.server.ssender.FileTask\" type=\"String\" key=\"class-name\"/>\n    <entry value=\"/var/spool/jabber/*.stanza\" type=\"String\" key=\"init-string\"/>\n    <entry value=\"10\" type=\"Long\" key=\"interval\"/>\n   </map>\n  </node>\n  <node name=\"jdbc\">\n   <map>\n    <entry value=\"true\" type=\"Boolean\" key=\"active\"/>\n    <entry value=\"tigase.server.ssender.JDBCTask\" type=\"String\" key=\"class-name\"/>\n    <entry value=\"jdbc:mysql://localhost/tigase?user=tigase&\n        password=mypass&table=xmpp_stanza\"\n      type=\"String\" key=\"init-string\"/>\n    <entry value=\"10\" type=\"Long\" key=\"interval\"/>\n   </map>\n  </node>\n </component>\n-----\n\nMost parameters should be pretty clear but some may need a little explanation.\n\n=== General +StanzaSender+ parameters:\n\n- *default-interval* number which specifies in seconds how often should the task look in data source for new packets to send.\n- *max-queue-size* is a number which specifies internal packets queue size. This is used to prevent the component from consuming all the memory for data in case the component can not process them.\n- *stanza-listeners* is a list of task names to load. Each task can read XMPP packets to send from different data sources. You can load as many listeners (tasks) as you need. Each task must read stanzas from different data sources.\n\nFor each task from the +stanza-listeners+ list there is a separate section with parameters for each task:\n\n- *active* boolean switch allowing you to turn on/off the task without removing configuration completely.\n- *class-name* Java class name which implements the task. This class must extend +tigase.server.ssender.SenderTask+ and it is loaded at runtime.\n- *init-string* is kind of data source connection string. For database it is just database connection string, for file system this is just a directory name. It may be even different for different tasks. The 2 tasks already implemented have some specific features: +FileTask+ allows you to use wild-chars in directory/ file name specification and +JDBCTask+ allows you to specify additional parameter at the end of JDBC connection string - database table name. For specific examples look at above config sections.\n- *interval* is a number which allows you to specify different interval in seconds for checking data source for each task.\n\n*NOTE:* Each task has own separate parameters list.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_55_-_Components_-_B_-_Tigase_HTTP_API.asciidoc",
    "content": "= Tigase HTTP API\n:author: Daniel Wisnewski & Andrzej Wójcik\n:version: v1.2 August 2015\n:date: 2015-23-08 10:13\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nWelcome to the Tigase HTTP API users guide.  The HTTP API allows you to manage, configure, chat, and send commands to Tigase server using a simple, easy-to-use interface right from your browser!\nWe will guide you through setup, running, and going through some features of the HTTP API.\n\n== Requirements\nThe HTTP API Requires Tigase version v5.0.3 but we recommend using the latest version of Tigase which will give you the easiest setup and functionality.\nCurrent versions of Tigase include most of the required files needed to run the API, however you will need to add one more library: servlet-api-3.1.jar which is available link:https://projects.tigase.org/attachments/download/1504/servlet-api-3.1.jar[Here].\nPlace that file in your /jars directory and you're all setup and good to go.\n\n*Please note, earlier versions of Tigase installer may have not included another required file: javax.servlet-api.jar*\n\nThis file is included in the archive distributions, and may be extracted to the /jars directory from there.\n\nFor older versions of the API, please see link:https://projects.tigase.org/projects/tigase-http-api/wiki/Dependencies[the Tigase HTTP API Wiki].\n\n== Setup & Configuration\nOnce all the requirements in place, all you need to do is add the following lines to Tigase's init.properties file:\n[source,properties]\n----\n--comp-name-3=http\n--comp-class-3=tigase.http.HttpMessageReceiver\n----\nNote that the class and name number is not important, so long as you don't have anything else with the same number.\n\nWith this default configuration Tigase will attempt to start an http server at port 8080 and run the default modules such as RestModule which will add context for the REST API in /rest path.\nRestModule will also load all groovy scripts located in scripts/rest/xxx directories and it will bind it to proper action for the /rest/xxx/ paths.  More than one directory can be used, think of xxx as a wildcard.\n\n=== Advanced Configuration\nThe HTTP component has a variety of configuration options, lets see them in detail here\n\n[[httpCompProp]]\n==== Component Properties\nPlease note, for settings mentioning {compname} replace them with the exact text found as --comp-name, which may be http, rest, or something you have set custom in init.properties.\n\n{compname}/http/ports[i]=8088,8096::\n    Sets a comma separated list of ports on which the HTTP server listens for connections.  8080 is set by default.\n\n{compname}/2222/socket=ssl::\n    Sets the port you wish the HTTP server to listen to for HTTPS connections to 2222\n\n{compname}/4096/domain=example.com::\n    Sets 4096 as the port number you want to listen to HTTPS connections *AND* set the domain name of the SSL certificate from Tigase XMPP server certificate store to be used.\n\n{compname}/server-class=::\n    Sets the name of the class used to manage the HTTP server. The following names may be used\n    * *tigase.http.jetty.JettyStandaloneHttpServer* - starts standalone Jetty HTTP Server instance *(requires Tigase HTTP API - Jetty HTTP Server)*\n    * *tigase.http.jetty.JettyOSGiHttpServer* - uses Jetty HTTP Server instance available as OSGi service (may be used only in OSGi envoirment) *(requires Tigase HTTP API - Jetty HTTP Server)*\n    * *tigase.http.java.JavaStandaloneHttpServer* - uses HttpServer provided by Java JDK to start standalone HTTP server (may not work on JDK from every JDK provider)\n\n{compname}/http/port::\n    An older version of the /ports[i] setting, it is still supported, but expect to be phased out.\n\n{compname}/setup/admin-credentials::\n    Sets a user and password combination that can access the web installer setup pages. By default administrator JIDs listed in --admins property are granted access, however you may specifiy a specific user and password to give access in addition to those JIDs. +\n    Format is [username:password] So for example, _http/setup/admin-credentials=admin:password_ +\n    Note that this stores the information in *plaintext on init.properties file*, and *this is an optional setting*.\n\n==== Modules\nTigase HTTP API component provides functionalities as modules which may be enabled or disabled and configured separately.\nCommon settings for modules which can be passed in component properties in following format component_name/module_id/module_setting:\n\n- active[B]= Values true/false to enable or disable module\n- context-path= Path of HTTP context under which module should be available\n- vhosts[s]= Comma separated list of virtual hosts under which the module should be availble. If this setting is not set, the HTTP module will be available for all virtual hosts.\n\nWith those ideas in mind, lets look at the available modules for the HTTP API.\n\n===== Rest Module\nThis module provides support for the REST API.  enable it by using this line in the init.properties file:\n----\nhttp/RestModule/active[B]=true\n----\nAssuming that comp-name for the class is +http+\n\nrest-scripts-dir=::\n    Path to directory containing scripts processing REST requests.  By default this directory is scripts/rest\napi-keys[s]=::\n    Comma separated list of strings which would be possible to use as keys to pass api-key parameter to request an authorization to execute.\n    If nothing is passed, then no request will be allowed.  To allow any request, this property needs to be set to +open_access+.\n\n===== DNS Webservice Module\n\n+dns-webservice+ module provides support for resolution of DNS names using the HTTP protocol.  This might be useful for web applications that need to resolve DNS address to a specific IP.  For example, discover IP and port of WebSocket service to use to connect to XMPP server.\n\nTo activate this module, use the following line;\n[source,properties]\n----\nhttp/dns-webservice/active[B]=true\n----\nAssuming that comp-name for the class is +http+\n\n== Use of the HTTP API\nTo begin using the HTTP API, point a browser to the following url\nhttp://your.server.domain:8080/ui/ and you will be presented with the following image to login with.\n\nimage:images/http-login.jpg[]\n\nUse your admin-level XMPP id and it's password to login.  Please use bare JID for logins.\n\n*NOTE: Normal users can login here as well to use chat and basic functions, but they will not have admin privileges as shown in this guide*\n\n== Browser interface walk-through\n\n=== Chat\n\nChat is the first window that you will see after logging in.  It's quite bare here since there is no roster to speak of.  If you had a roster, users would be shown.\nLets add a user.  Click the user add icon, and then fill in the fields below.\n\nimage:images/http-add-new.jpg[]\n\nOnce both users have added and authorized each other's roster listing, the users and groups will be shown on the left, with the right side being used for chat functionality.\n\nimage:images/http-chat.jpg[]\n\n=== Discovery\nThe Discovery tab encapsulates the service discovery function of XMPP servers, and will provide a list of available services. Clicking on the service will give you options for executing commands, checking settings, MUC rooms and more.\n\n=== Management\nThe Management tab is your administration and settings tool for the XMPP server.  Here you can change settings, add and remove users, send server-wide notifications, write and execute scripts, and even obtain server statistics at a glance.\n\n*NOTE: some changes to settings may be instant, and others require a server restart*\n\n=== Statistics\nThe statistics tab lists all running components in the server.\n\n== HTTP API Scripting\nScripts in the HTTP API component are used for processing all of requests.\n\nTo add a new action to HTTP API component you need to create a script in Groovy in which there is an implementation of class extending tigase.http.rest.Handler class. The URI of the script will be created from the location of script in scripts folder.\nFor example, if TestHandler script with regular a expression will be set to +/test+ and will be placed in +scripts/rest/tested+, the handler will be called for following URI +/rest/tested/test+.\n\n=== Properties\nIf you are extending classes, you will need to set the following properties:\n\nregex::\n  regular expression which is used to match request URI and parse parameters embedded in URI, example below:\n\n  /\\/([^@\\/]+)@([^@\\/]+)/\n\n\nrequiredRole::\n  Role of the user required to be able to access this URI. Available values: null, \"user\", \"admin\". If requiredRole is not null, authentication will be required.\n\nisAsync::\n  If set to true, it will be possible to wait for results, perhaps waiting for an IQ stanza to send results.\n\n=== Properties Containing Closures\nExtended class should also set closures for one or more of the following properties: +execGet+, +execPut+, +execPost+, and +execDelete+ depending on which HTTP action or actions you need to support for the following URI. Each closure *has dynamic arguments lists*.\nBelow is a list of arguments passed to closure which describes how and when the list of arguments change.\n\nI) *service*:\n  Implementation of Service interface, used to access database or send/recieve XMPP stanzas.\n\nII) *callback*:\n  Closure which needs to be called to return data. Accepts only one argument of type +String,byte[],Map+. If data is type of Map it will be encoded to JSON or XML depending on 'Content-Type' header.\n\nIII) *user*:\n  Will be passed only if +requiredRole+ is not null. *In other cases this argument will not be in arguments list!*\n\nIV) *content*:\n  Parsed content of the request. *Will not be in arguments list if Content-Length of request is empty*. If Content-Type is of XML or JSON type, type returned as Map.  Otherwise it will be an instance of +HttpServletRequest+.\n\nV) *x*:\n  Additional arguments passed to callback are groups from regular expression matching URI. *Groups are not passed as list, but are added to a list of arguments as next arguments*.\n\nIf the property for corresponding HTTP action is not set, the component will return a 404 HTTP error.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_56_-_Components_-_B_-_Tigase_HTTP_API_-_1_-_REST_API_Guide.asciidoc",
    "content": "[[restAPI]]\n= REST API & HTTP Guide\n:author: many people\n:date: 2015-11-09 10:22\n:version: v1.0 September 2015\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nThis component covers both REST API as well as basic HTTP component configuration.\nREST stands for REpresentational State Transfer which is a stateless communication method that in our case passes commands using HTTP GET, PUT, POST, and DELETE commands to resources within the Tigase server.\nAlthough REST uses HTTP to receive commands, REST itself is not intended for use in a browser.\n\n== Setup & Configuration\nTigase's REST component requires the following in classpath\n\n- +servlet-api-3.1.jar+\n\nIf you have installed Tigase v7.1.0 or later, the jar is already installed.  If you are using an older version of Tigase, you may download the file from link:https://projects.tigase.org/attachments/download/1504/servlet-api-3.1.jar[this link].\nOnce this is installed, you will also need to add the following lines in your init.properties file to enable the HTTP component.\n\n[source,bash]\n------\n--comp-name-4=http\n--comp-class-4=tigase.http.HttpMessageReceiver\n------\nIn this default configuration, Tigase will try to start a standalone Jetty HTTP server at port 8080 and start up the default modules, including +RestModule+ which will add context for REST API in the /rest path. +RestModule+ will also load all groovy scripts located in +scripts/rest/*+ directories and will bind them to proper actions for the +/rest/*+ paths.\n\n*NOTE:* Scripts that handle HTTP requests are available in the component repository in +src/scriopts/groovy/tigase/rest/+ directory.\n\n=== Component Properties\nHere are some additional properties for the +HttpMessageReceiver+ component that can be set in the init.properties file.\n\n- +{compname}/http/ports[i]=+ - Sets a comma separated list of ports on which the HTTP server will listen for connections. Default is 8080.\n- +{compname}/*********/socket=ssl+ - Sets the port for SSL connections, replace ### with the port number of your choice.\n- +{compname}/*********/domain=example.com+ - This sets the domain name of the SSL certificate from Tigase XMPP certificate store, also sets the port to ### to listen for HTTPS connections.\n- +{compname}/server-class=+ - Sets the name of the class used to manage the HTTP server. Currently there are the following options:\n. +tigase.http.JettyStandaloneHttpServer+ - Starts standalone Jetty HTTP Server instance *(requires Tigase HTTP API - Jetty HTTP Server)*\n. +tigase.http.jetty.JettyOSGIHttpServer+ - Uses Jetty HTTP Server instance available as OSGi service (may be used only in OSGi envoirment) *(require Tigase HTTP API - Jetty HTTP Server)*\n. +tigase.http.java.JavaStandaloneHttpServer+ - Uses +HttpServer+ provided by Java JDK to start standalone HTTP server (may not work on JDK from every JDK provider).\n. +{compname}/http/threads=+ - Sets the number of threads available for HTTP component. Default is 4.\n. +{compname}/http/request-timeout=+ - Sets the timeout time in ms for threads to close on inactive connections. Default is 60 seconds.\n\n=== Modules\nTigase's REST Component comes with two modules that can be enabled, disabled, and configured separately.\nCommon settings for modules for component properties are used in the following format: +component_name/module_id/module_setting/+\nthe following settings are available for both listed modules:\n\n- +active[B]+ - Boolean values true/false to enable or disable the module.\n- +context-path+ - Path of HTTP context under which the module should be available.\n- +vhosts[s]+ - Comma separated list of virtual hosts for which the module should be available. If not configured, the module will be available for all vhosts.\n\n==== Rest Module\nThis is the Module that provides support for the REST API.\nAvailable properties:\n\n- +rest-scripts-dir+ - Provides ability to specify path to scripts processing REST requests if you do not wish to use default (scripts/rest).\n- +api-keys[s]+ - Comma separated list of strings which would be possible to use as keys to pass +api-key+ parameter to request authorization for request execution. If nothing is passed, then no request will be allowed. To allow any request, this property needs to be set using the following:\n-----\nhttp/rest/api-keys[s]=open_access\n-----\nYou may set api-keys to any string you wish, however, when you make requests of the HTTP API service, the included API key must match *EXACTLY*. Keep the API key to ASCII characters to maintain compatibility. For example, if you were to set the following API key:\n-----\nhttp/rest/api-key[s]=a7D2dm3lps138w\n-----\nRequests made to the HTTP service must conclude with the same key: +http://localhost:8080/rest/adhoc/sess-man@domain.com?api-key=a7D2dm3lps138w+\n\n==== +dns-webservice+\nThis module provides resolution of DNS names using HTTP protocol. This particular module might be useful for web applications that need to resolve the DNS address to a particular IP. For example to help discover the IP and port of WebSocket services used to connect to the XMPP server.\n\n== Usage Examples\nHere are some examples using the HTTP API using available scripts.\n\n=== Retrieving list of available ad-hoc commands\nTo retrieve a list of available commands, REST needs to use the GET method from the following resource: +/rest/adhoc/sess-man@domain.com+. This provides a list of available adhoc commands from the sess-man@domain.com resource. This can be change to any bare JID that you wish to get commands from so it can be a MUC room, monitor component, or in this case, the Session manager.\nWith the server running, lets connect to the address +http://localhost:8080/rest/+ and the following resource +/adhoc/sess-man@domain.com+ which will retrieve a list of all ad-hoc commands available at sess-man@domain.com. This particular action is protected by authentication using HTTP basic authentication so valid credentials are necessary. User credentials are available in the Tigase's user database installation, so use the bare JID and password of an admin-authorized account to conduct this activity.\nThe result will be an XML format output of available commands, similar to an IQ stanza, below an example of that result.\n\n[source,xml]\n-----\n<items>\n  <item>\n    <jid>sess-man@domain.com</jid>\n    <node>http://jabber.org/protocol/admin#get-active-users</node>\n    <name>Get list of active users</name>\n  </item>\n  <item>\n    <jid>sess-man@domain.com</jid>\n    <node>del-script</node>\n    <name>Remove command script</name>\n  </item>\n  <item>\n    <jid>sess-man@domain.com</jid>\n    <node>add-script</node>\n    <name>New command script</name>\n  </item>\n</items>\n-----\n\nThere is also the ability to return a JSON formatted result. To achieve this, you need to pass +Content-Type: application/json+ to the HTTP header of the request, or add the +type+ parameter and set it to +application/json+ setting.  An example of a JSON result is below.\n[source,java]\n-----\n{\n    \"items\": [\n        {\n            \"jid\": \"sess-man@domain.com\",\n            \"node\": \"http://jabber.org/protocol/admin#get-active-users\",\n            \"name\": \"Get list of active users\"\n        },\n        {\n            \"jid\": \"sess-man@domain.com\",\n            \"node\": \"del-script\",\n            \"name\": \"Remove command script\"\n        },\n        {\n            \"jid\": \"sess-man@domain.com\",\n            \"node\": \"add-script\",\n            \"name\": \"New command script\"\n        }\n    ]\n}\n-----\nAgain, either of these methods can be used on any component with available ad-hoc commands. Feel free to experiment and see what options are available for each component.\n\n=== Executing ad-hoc commands\nOnce you have found a command you wish to use, you can send that command using the HTTP POST method. In this example, lets request a list of active users as seen in the previous section. *NOTE:* like the previous example, these commands require basic HTTP authentication.\n\nThe following command is sent to +http://localhost:8080/rest/adhoc/sess-man@domain.com+\n[source,xml]\n-----\n<command>\n  <node>http://jabber.org/protocol/admin#get-active-users</node>\n  <fields>\n    <item>\n      <var>domainjid</var>\n      <value>domain.com</value>\n    </item>\n    <item>\n      <var>max_items</var>\n      <value>25</value>\n    </item>\n  </fields>\n</command>\n-----\nThis particular command reqiures the three fields +<node>+, +domainjid+, and +max_items+. These three values are the node for the command, as returned in available commands, the domain results are to be returned from, and the maximum number of results. Keep in mind that +Content-type: text/xml+ must be passed to the HTTP header to get an XML result. Not doing so may yield errors or incomprehensible results.\nThe result for this command will look like this:\n\n[source,xml]\n-----\n<command>\n  <jid>sess-man@domain.com</jid>\n  <node>http://jabber.org/protocol/admin#get-active-users</node>\n  <fields>\n    <item>\n      <var>Users: 3</var>\n      <label>text-multi</label>\n      <value>admin@domain.com</value>\n      <value>user1@domain.com</value>\n      <value>morbo@domain.com</value>\n    </item>\n  </fields>\n</command>\n-----\n\nSimilar results can be sent and received using JSON in a similar fashion. Again, be sure to set +ContentType: application/json+ in the header or default settings.\n\n[source,java]\n-----\n{\n  \"command\" : {\n    \"node\" : \"http://jabber.org/protocol/admin#get-active-users\",\n    \"fields\" : [\n      {\n        \"var\" : \"domainjid\",\n        \"value\" : \"subdomain.domain.com\"\n      },\n      {\n        \"var\" : \"max_items\",\n        \"value\" : \"25\"\n      }\n    ]\n  }\n}\n-----\n\nThe results will look quite similar to the XML results:\n\n[source,java]\n-----\n{\n    \"command\": {\n        \"jid\": \"sess-man@domain.com\",\n        \"node\": \"http://jabber.org/protocol/admin#get-active-users\",\n        \"fields\": [\n            {\n                \"var\": \"Users: 2\",\n                \"label\": \"text-multi\",\n                \"value\": [\n                  \"minion1@subdomain.domain.com\",\n                  \"overadmin@subdomain.domain.com\"\n                ]\n            }\n        ]\n    }\n}\n-----\n\n[we should take another approach, and use something more permanent, like add or delete a user]\n\n=== Sending any XMPP Stanza\nXMPP messages or any other XMPP stanza can be sent using this API by sending HTTP POST request on http://localhost:8080/rest/stream/api-key=API_KEY with a serialized XMPP stanza as content, where API_KEY is the API key specified in the init.properties file.\nEach request needs to be authorized by sending a valid administrator JID and password as a user/password of BASIC HTTP authorization method.  The content of the HTTP request should be encoded in UTF-8 and +Content-Type+ should be set to application/xml.\n\n==== Handling of request\nIf no +from+ attribute is set in the stanza, the HTTP API component will supplant it's JID instead, however if one is set it will be preserved.  However, in iq stanzas, if no +from+ attribute is set the HTTP response content will be sent back as a response.  Successful requests will return a HTTP response code of 200.\n\n*Examples:*\nAny of these examples must be sent as an HTTP POST request to /rest/stream/?api-key=API_KEY of the HTTP API component.\n\n===== Sending XMPP message with +from+ set to HTTP API component a full JID\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\n\n===== Sending XMPP message with +from+ set to HTTP API component with a bare JID\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" to=\"test@example.com\">\n    <body>Example message 1</body>\n</message>\n-----\n\n===== Sending XMPP message with from set to a specified JID to a full JID\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" from=\"sender@example.com\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\n\n== Sending messages through REST\nYou can also send messages, or really any XMPP stanza to users and components through REST API. Sending XMPP messages or stanzas using HTTP is realized as a groovy script bundled in the installation package from v7.0.2. If you want to be sure your current install supports this feature, check for the presence of +Stream.groovy+ file in the +scripts/rest/stream/+ directory.\n\nAs in other examples, be sure that you have the following line in your init.properties:\n[source,bash]\n-----\nhttp/rest/api-keys[s]=test_key\n-----\nYou may also opt to have +open_access+ set to disable API key parameter.\n\n=== Usage\nUsing the HTTP POST method, XMPP stanzas can be sent using the built in HTTP API. In a local installation, the request can be sent to +http://localhost:8080/rest/stream/?api-key=API_KEY+ with a seralized XMPP stanza as content, where API_KEY is the API key for HTTP API which is set in +etc/init.properties+ as +rest/api-keys[s]+.  In the case we laid out, it would be +test_key+. Because XMPP uses XML for formatting, all content in these requests *MUST* be encoded in UTF-8 and +Content-type+ must be set to +application/xml+.\nLets take a look at some examples.\n\n_In all examples the data is sent as an HTTP POST request to /rest/stream/?api-key=test-key._\n\n==== Send XMPP stanza with from set to HTTP API component to bare JID\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\nOnce this message is sent, the Groovy script adds the remaining information automatically, and the following is what is receieved by test@example.com/resource-1.\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" from:\"http@example.com\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\nAs you can see, the HTTP component is automatically populated as the sender.\n\n==== Send XMPP stanza with from set to HTTP API component to full JID\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" to=\"test@example.com\">\n    <body>Example message 1</body>\n</message>\n-----\nThe syntax and formatting is the same, with the recepiant messaging being exactly the same.\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" from:\"http@example.com\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\n\n==== Send XMPP stanza with from set to specified JID\nYou may specify any JID that is registered in the server to send the stanza, ones that use a name that is not registered will return an error.\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" from=\"sender@example.com\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\nEnds with the result being somewhat customized.\n[source,xml]\n-----\n<message xmlns=\"jabber:client\" type=\"chat\" from:\"sender@example.com\" to=\"test@example.com/resource-1\">\n    <body>Example message 1</body>\n</message>\n-----\n\n[[avatarRetrievalRequests]]\n=== Avatar retrieval requests\nThere are different formats for avatar retrieval depending on how they are stored, see below for the resources for each type of avatar.\n\n- +/rest/avatar/user@domain+ - which returns first avatar found (PEP, VCard4 or VCardTemp in this order)\n- +/rest/avatar/user@domain/avatar+ - which returns PEP avatar\n- +/rest/avatar/user@domain/vcard4+ - which returns avatar from VCard4\n- +/rest/avatar/user@domain/vcard-temp+ - which returns avatar from VCardTemp\n\n== Setting HTTP API Privacy Rules\nThe HTTP API component has settings that allow you to specify who is allowed to use the HTTP API interface, keeping unauthorized users from accessing the feature. This feature is implemented using a Groovy admin ad-hoc stript for the Session Manager component. As a result of this method, it will be avaiulable to execution using the default GTTP API componene capability to execute the script. The actual work of filtering, however, will be conducted by the +DomainFilter+ plugin.\n\n[[getUserInfoREST]]\n== New Rest API added to obtain a JID login time\n+GetUserInfo+ command has been expanded to obtain user login and logout times in addition to standard information. To obtain the information, send a POST request to http://xmpp.domain.net:8080/rest/adhoc/sess-man@xmpp.domain.net?api-key=test-api-key with the following:\n[source,xml]\n-----\n<command>\n  <node>get-user-info</node>\n  <fields>\n    <item>\n      <var>accountjid</var>\n      <value>user@xmpp.domain.net</value>\n    </item>\n    <item>\n      <var>Show connected resources in table</var>\n      <value>true</value>\n    </item>\n  </fields>\n</command>\n-----\n\n=== Configuration\nThe HTTP API privacy scipt is loaded automatically. +DomainFilter+ is a default plugin loaded by Tigase on startup. This means there is very little you need to do to have this running.\nAgain, you may define a custom API key to limit access using the following line in init.properties\n[source,properties]\n------\nhttp/rest/api-keys[s]=test_key\n------\n\n=== Usage\nSetting privacy rules can be done by sending a POST request to the session manager using this address: +http://localhost:8080/rest/sess-man@domain.com?api-key=test_key+\n[source,xml]\n-----\n<command>\n  <node>user-domain-perm</node>\n  <fields>\n    <item>\n      <var>jid</var>\n      <value>user@domain.com</value>\n    </item>\n    <item>\n      <var>fiteringPolicy</var>\n      <value>CUSTOM</value>\n    </item>\n    <item>\n      <var>filteringList</var>\n      <value>\n         1|allow|self;\n         2|allow|jid|admin@test2.com;\n         3|allow|jid|pubsub@test.com;\n         4|deny|all;\n      </value>\n    </item>\n  </fields>\n</command>\n-----\nHere all parameters are passed to be excuted by ad-hot command.  Using the +user-domain-perm+ node we were able to add jids to a +CUSTOM+ filter. Here is a brief breakdown:\n\n- +jid+ denotes which JID the settings will be applied too.\n- +filteringPolicy+ - This uses a +CUSTOM+ type list that allows for multi-item list of custom processing rules.\n- +filteringLise - This is a multi-item list, semi-colon delimited, where each line denotes one item with a rule in this format: +order_number|policy|UID_type[|UID]:+\n  - +order_number+ can be any integer, as long as no numbers repeat.\n  - +policy+ can either +allow+ or +deny+.\n  - +UID_type+ is the User ID Type, can be +jid+, +domain+, or +all+.\n  - +UID+ is the user JID affected. If +UID_type+ is set to +all+ then this will be ignored.\n\nThese ad-hoc commands replicate settings found in xref:domainBasedPacketFiltering[Domain Based Packet Filtering] in the admin guide. They may also be influenced by the link:http://docs.tigase.org/tigase-server-Properties_Guide/html?#domainFilterPolicy[--domain-filter-policy] property of init.properties.\n\n\n== Scripting\nAs you can see from the above commands, Tigase uses pre-defined scripts for processing of all requests in HTTP API.\nAlthough the list may be small for now, this does mean with a little bit of Groovy scripting, you can create your own scripts to interpret REST commands and send them to the server!\n\nAll scripts for this purpose will be an implementation of class extending +tigase.http.rest.Handler+ class. The URI of the scripts will be inside the scripts folder. For example, if the script uses +TestHandler+ with a regular expression set to +/test+ and is placed inside the +scripts/rest/+ the handler will be called with this URI: +scripts/rest/test/+.\n\n=== Properties\nWhen extending classes, you will need to set the following listed properties.\nregex::\n  Regular expression which is used to match request URI and parse parameters embedded in URI, for example:\n\n  -----\n  /\\/([^@\\/]+)@([^@\\/]+)/\n  -----\n\nrequiredRole::\n  Role of user required to be able to access this URI. Available values are +null+, +user+, and +admin+. Authentication for the script will be required if +requiredRole+ is not null.\n\nisAsync::\n  If set to true, it will be possible to wait for results pending the arrival of IQ stanzas for instance.\n\n==== Properties containing closures\nExtended class should also set for closures for one or more of the following properties: +execGet+, +execPut+, +execPost+, +execDelete+, depending on which HTTP action is needed to support the following URI. Each closure has a *dynamic arguments list* generated at runtime. Below is a list of arguments passed to closure which describe how and when the list of arguments change.\n\nservice::\n  Implementation of service interface which is used to access database or send/receove XMPP stanzas.\n\ncallback::\n  Callback closures needs to be called to return data. However they only accept one argument of type +string,byte[],Map+. If data is Map tupe, it will be encoded to JSON or XML depending on Content-Type header.\n\nuser::\n  Is passed only if requiredRole is not null. Otherwise this argument will not be in the argument list.\n\ncontent::\n  Parsed content of the request. *This will not be in the list of arguments if Content-Lengeth of request is empty.* If Content-Type is set to XML or JSON the return result will be as Map, otherwise it will be an instance of +HttpServletRequest+.\n\nx::\n  Additional arguments passed to callback are groups from regular expression matching the URI. Groups are not passed as a list, but are added to the list of arguments and next arguments.\n\nIf a property for corresponding HTTP action is not set, the component will return an HTTP 404 error.\n\n=== Example Script\n\nLets have a look at a script that is included with the install package to get a better idea of how these scripts work.\nThis script will GET a list of all registered account and output them according to an HTML file we will look at later.\n[source,java]\n-----\nimport tigase.http.rest.Service\nimport tigase.xmpp.BareJID\n\n/**\n * Class implements ability to retrieve by service administrator list of registered accounts\n * Handles requests for /rest/users/\n *\n * Example format of content of response:\n * <users><items><item>user1@domain</item><item>user2@domain</item></items><count>2</count></users>\n */\nclass UsersHandler extends tigase.http.rest.Handler {\n\n    public UsersHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/\",\n\t\t\tGET : [ info:'Retrieve list of registered user jids',\n\t\t\t\tdescription: \"\"\"Request do not require any parameters and returns list of all registered user accounts on this server (for all vhosts).\n\nExample response will look like this:\n\\${util.formatData([users:[items:['user1@example.com','user2@example.com','user1@example2.com'],count:3]])}\n\"\"\"]\n\t\t];\n        regex = /\\//\n        requiredRole = \"admin\"\n        isAsync = false\n        execGet = { Service service, callback, jid ->\n            def users = service.getUserRepository().getUsers()\n            callback([users:[items:users, count:users.size()]]);\n        }\n    }\n\n}\n-----\nAs we can see, it's a fairly short code.  First it calls the rest service (required for all of the REST activity), and the BareJID handler.\nNext we extend out custom class to extend +tigase.http.rest.Handler+. Our author has provided a helpful description of the code to better describe it's operation and expected result.\nThe last section is the actual code that defines what will match our query, in this case anything, a requirement that an admin make the command, that the connection will terminate with results, and what commands will be passed.\n\nThe matching HTML, which will shape the output of the code is included here.\n[source,html]\n-----\n${ util.include('header', [title:'All users']) }\n<table style=\"margin: auto;\">\n<tr>\n<th>Avatar</th>\n<th>User JID</th>\n</tr>\n<% result.users.items.each { user -> %>\n<tr>\n<td>\n<img style=\"max-height: 50px; max-width: 50px;\" src=\"${util.link(\"/avatar/\" + user)}\" />\n</td>\n<td>\n<a href=\"${util.link(\"/user/\"+user)}\">${user}</a>\n</td>\n</tr>\n<% } %>\n</table>\n${ util.include('footer') }\n-----\nThis file builds a table using the user fields from the GET request. *NOTE:* Not all scripts need a matching HTML file, basic requests may not need special handling.\n\n== REST API & PubSub\nAll PubSub Scripts are found within the +scripts/rest/pubsub+ directory of Tigase's installation directory.  All examples in this section are prepared for a PubSub component available at pubsub@example.com. To use these examples for your installation, that JID needs to be replaced with with your pubsub JID.\n\nAll parameters passed in the content of HTTP request needs to be wrapped with +<data/>+ tag at the root of the XML document. Returned results will be wrapped within the +<result/>+ tag in the root of the XMl document.\n\n=== Create a Node\nHTTP URL: example.com/rest/pubsub/pubsub@example.com/create-node\n\nAvailable HTTP methods:\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed to the newly created node.\n\n*POST*\n\nCommand requires fields +node+ and +pubsub#node_type+ to be filled with proper values for execution.\n\n- +node+ Field contains id of node to create\n- +owner+ Field may contain JID or JIDS which will be considered owner of the node. If this field is empty, server will use JID of HTTP API Component (rest@example.com)\n- +pubsub#node_type+ Field should contain one of two types:\n  * +leaf+ Node to items that will be published\n  * +collection+ Node to nodes what will contain other nodes\n\nBelow is an example of creating a +leaf+ type node with the owner set to admin@example.com.\n[source,xml]\n-----\n<data>\n  <node>example</node>\n  <owner>admin@example.com</owner>\n  <pubsub prefix=\"true\">\n    <node_type>leaf</node_type>\n  </pubsub>\n</data>\n-----\nServer response:\n[source,xml]\n-----\n<result>\n  <Note type=\"fixed\">\n    <value>Operation successful</value>\n  </Note>\n</result>\n-----\n\n=== Delete a node\nHTTP URL: example.com/rest/pubsub/pubsub@example.com/delete-node\n\nAvailable HTTP methods:\n\n*GET*\n\nCommand returns example content which contains all required and operational parameters that may be passed.\n\n*POST*\n\nCommand requires field +node+ to be filled where +node+ is the id of the node to delete.\n\nBelow is an example of removing a node with an id of +example+\n[source,xml]\n-----\n<data>\n  <node>example</node>\n</data>\n-----\nServer response\n[source,xml]\n-----\n<result>\n  <Note type=\"fixed\">\n    <value>Operation successful</value>\n  </Note>\n</result>\n-----\n\n=== Subscribe to a node\nHTTP URI: example.com/rest/pubsub/pubsub@example.com/subscribe-node\n\nAvailable HTTP methods:\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed.\n\n*POST*\n\nCommand requires +node+ and +jid+ fields to be filled.\n\n- +node+ is the id of the node to subscribe too.\n- +jid+ is the JID or JIDS to be subscribed to the node.\n\nBelow is an example of the XML information passed between client and server with +test1@example.com+ and +test2@example.com+ subscribing to +example+ node.\n[source,xml]\n-----\n<data>\n  <node>example</node>\n  <jids>\n    <value>test1@example.com</value>\n    <value>test2@example.com</value>\n  </jids>\n</data>\n-----\nServer response:\n[source,xml]\n-----\n<result>\n  <Note type=\"fixed\">\n    <value>Operation successful</value>\n  </Note>\n</result>\n-----\n\n=== Unsubscribe from a node\nHTTP URI: example.com/rest/pubsub/pubsub@example.com/unsubscribe-node\n\nAvailable HTTP methods:\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed.\n\n*POST*\n\nLike the Subscribe to a node section, the command requires both the +node+ and +jid+ fields to be filled.\n\n- +node+ is the id of the node to unsubscribe from.\n- +jid+ is the JID or JIDS to be unsubscribed from the node.\n\nBelow is an example of the XML information passed between client and server with +test1@example.com+ and +test2@example.com+ unsubscribing to +example+ node.\n[source,xml]\n-----\n<data>\n  <node>example</node>\n  <jids>\n    <value>test@example.com</value>\n    <value>test2@example.com</value>\n  </jids>\n</data>\n-----\nServer response:\n[source,xml]\n-----\n<result>\n  <Note type=\"fixed\">\n    <value>Operation successful</value>\n  </Note>\n</result>\n-----\n\n=== Publish an item to a node\nHTTP URI: example.com/rest/pubsub/pubsub@example.com/publish-item\n\nAvailable HTTP methods:\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed.\n\n*POST*\n\nCommand requires the +node+ and +entry+ fields to be filled.\nAvailable fields:\n\n- +node+ Field contains the id of the node to be published to.\n- +item-id+ Field to contain the id of the entry to publish.\n- +expire-at+ Field may contain a timestamp after which item should not be delivered to subscribed users.  Timestamp should follow this pattern: YYYY-MM-DDhh:mm:ss with a trailing Z to indicate UTC time in a 24h format.\n- +entry+ Field should contain multi-line entry content which should be valid XML value for an item.\n\nBelow is an example exchange between client and server for publishing an item with id +item-1+ to node +example+ .\n[source,xml]\n-----\n<data>\n  <node>example</node>\n  <item-id>item-1</item-id>\n  <expire-at>2015-05-13T16:05:00+02:00</expire-at>\n  <entry>\n    <item-entry>\n      <title>Example 1</title>\n      <content>Example content</content>\n    </item-entry>\n  </entry>\n</data>\n-----\nServer response:\n[source,xml]\n-----\n<result>\n  <Note type=\"fixed\">\n    <value>Operation successful</value>\n  </Note>\n</result>\n-----\n\n=== List Available Nodes\nHTTP URI: example.com/rest/pubsub/pubsub.example.com/list-nodes\n\nAvailable HTTP methods\n\n*GET*\n\nThis method returns list of available PubSub nodes for the domain passed as part of the URI (+pubsub.example.com+).\n\nBelow is an example exchange between client and server for listing all nodes, the result having +test+, +node_54idf40037+ and +node_3ws5lz0037+\n[source,xml]\n-----\n<result>\n<title>List of available nodes</title>\n<nodes label=\"Nodes\" type=\"text-multi\">\n<value>test</value>\n<value>node_54idf40037</value>\n<value>node_3ws5lz0037</value>\n</nodes>\n</result>\n-----\n\n=== List Published Items on Node\nHTTP URI: example.com/rest/pubsub/pubsub.example.com/list-items\n\nAvailable HTTP methods\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed.\n\n*POST*\n\nThis command requires the +node+ field to be filled.  The +node+ field contains the ID of the node from which we want the list of published items.\n\nBelow is an example exchange between client and server asking for all items published in the example node.\n[source,xml]\n-----\n<data>\n<node>example</node>\n</data>\n-----\n\nServer Response\n[source,xml]\n-----\n<result>\n<title>List of PubSub node items</title>\n<node label=\"Node\" type=\"text-single\">\n<value>example</value>\n</node>\n<items label=\"Items\" type=\"text-multi\">\n<value>item-1</value>\n<value>item-2</value>\n</items>\n</result>\n-----\n\nItems item-1 and item-2 are the listed items.\n\n=== Retrieve Published Item on Node\nHTTP URI: example.com/rest/pubsub/pubsub.example.com/retrieve-item\n\nAvailable HTTP methods\n\n*GET*\n\nMethod returns example content which contains all required and optional parameters that may be passed.\n\n*POST*\n\nCommand requires that fields +node+ and +item-id+ are filled.\nAvailable Fields:\n- +node+ The node the item is published to.\n- +item-id+ The id of the item you wish to retrieve.\n\nExample communication between client and server:\n[source,xml]\n-----\n<data>\n<node>example</node>\n<item-id>item-1</item>\n</data>\n-----\n\nServer response:\n[source,xml]\n-----\n<result>\n<title>Retrive PubSub node item</title>\n<node label=\"Node\" type=\"text-single\">\n<value>example</value>\n</node>\n<item-id label=\"Item ID\" type=\"text-single\">\n<value>item-1</value>\n</item-id>\n<item label=\"Item\" type=\"text-multi\">\n<value>&lt;item expire-at=&quot;2015-05-13T14:05:00Z&quot; id=&quot;item-1&quot;&gt;&lt;item-entry&gt;\n&lt;title&gt;Example 1&lt;/title&gt;\n&lt;content&gt;Example content&lt;/content&gt;\n&lt;/item-entry&gt;&lt;/item&gt;\n</value>\n</item>\n</result>\n-----\n\nNode that inside the item element, there is an XML encoded element, this will be retrieved without any decoding.\n\n== Other Example REST Commands and Documentation\nOther example REST commands, and accompanied documentation can be found at localhost:8080/rest/ on any server running Tigase and the HTTP component.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_57_-_Components_-_B_-_Tigase_HTTP_API_-_2_-_Admin_UI.asciidoc",
    "content": "[[adminUI]]\n= Admin UI Guide\n:author: Daniel Wisnewski\n:version: v2.0 Sept 2015\n:date: 2015-02-09 10:28\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nThe Admin User Interface is an HTTP-based interface that sends REST commands to the server to update configurations, change settings, and retrieve statistics.\n\n== A Note about REST\nREST stands for REpresentational State Transfer which is a stateless communication method that in our case passes commands using HTTP GET, PUT, POST, and DELETE commands to resources within the Tigase server.\nAlthough REST uses HTTP to receive commands, REST itself is not intended for use in a browser.  For more information, please see the REST API guide.\n\n\n== Configuration\nAllows you to list server components and their configurations, as well as manage server components and plugins.\n\nList server/component configuration section covers all the component options including the basic-conf and will allow you to change each setting by changing the values in the field and clicking submit.  All settings are listed by the component name in the dropdown menu either as default, or as defined by --component-name property.\n\nimage:images/admin-componentconfig.jpg[]\n\nManage active server components allows you to do exactly that, but you can also add and disable components from this interface.\n\nimage:images/admin-managecomponent.jpg[]\n\nHere you can List, Add, Edit, and Remove components.\n- *List* provides a list of all running components, each with its name, info, and class.\n- *Add* provides an interface to add a class and a name for components. You will not be able to add invalid component names or classes.\n- *Edit* enables you to edit the specific properties of any running component. Even options for which there are no current values will be listed, you can consider this list a comprehensive list of settings and options for the current component.\n- *Remove* provides a way to remove running components.\n\nManaging server plugins allows you to turn on or off plugins from this window VIA check-boxes. Note that the changes are made in real-time.\n\nimage:images/admin-manageplugins.jpg[]\n\n== Example Scripts\nThis is a list of script examples that can be run and do menial functions for each component.  They may not have particular value themselves, but are present to be used as reference when writing custom scripts.\nGet list of available commands is one script, that is present for every component that is active on the server, and as its title implies, will provide a list of all commands for that component.  Lastly, the two scripts from the xref:scriptingSupport[Scripting section] of this guide.  Generally, there is not much needed to see in this section.\n\n== Notifications\nThis section has one simple command: to be able to send a mass message to all logged in users.\nThere are three types of messages that can be sent from this section:\n- *normal* Messages will show as a pop-up in most clients.\n- *headline* Certain clients will take headline messages and insert them into MUC or chats between users, otherwise it will create a pop-up like normal messages.\n- *chat* Chat messages will open up a chat dialog with users.\n\n== Other\nThis section contains a considerable list of options and settings affecting server functions.\n\n=== Activate log tracker for a user\nThis allows you to set a log file to track a specific user.  Set the bare or full JID of the user you want to log, and a name of the files you wish the log to be written to. The files will be written in the root Tigase directory unless you give a directory like logs/filename. The log files will be named with a .0 extension and will be named .1, .2, .3 and so on as each file reaches 10MB by default. filename.0 will always be the most recent.\nLogging will start once the command has been issued, and cease once the server restarts.\n\n=== Add SSL certificate\nHere you can add SSL certificates from PEM files to specific virtual hosts. Although Tigase can generate its own self-signed certificates, this will override any default certificates.\nThe certificates cannot contain a passphrase, or be encrypted.  Be sure that the contents contain both the certificate and private key data.\nYou also have the option to save the certificate to disk, making the change permanent.\n\n=== Add listener script\nThis section allows you to create a custom function for the eventbus component.  These scripts can have the server conduct certain operations if set criteria are met. You may write the script in either Groovy or EMCAscript. Please see the xref:eventbus[eventbus section] for more details.\n\n=== Add Monitor Task\nYou can write scripts for Groovy or ECMAScript to add to monitor tasks here. This only adds the script to available scripts however, you will need to run it from another prompt.\nNote that these scripts may only work with the monitor component.\n\n=== Add Monitor Timer Task\nThis section allows you to add monitor scripts in Groovy while using a delay setting which will delay the start of the script.\n\n=== Add New Item - ext\nDepending on whether you have any external components loaded or not, this may show.  This allows you to add additional external components to the running instance of Tigase.\n\n=== Add New Item - Vhost\nThis allows you to add new virtual hosts to the XMPP server.  A breakdown of the fields is as follows:\n\n- Domain name: the full domain name of the new vhost.  Tigase will not add anything to this domain, so if it is ti be a subdomain of example.com, you will need to enter sub.domain.com.\n- Enabled: Whether the domain is turned on or off.\n- Anonymous enabled: Allow anonymous logins.\n- In-band registration: Whether or not to allow users to register accounts upon login.\n- TLS required: Require logins to the vhost to conduct a TLS handshake before opening streams.\n- S2S secret: a server-generated code to differentiate traffic between servers, typically there is no need to enter your own, but you may if you need to get into low level code.\n- Domain filter policy: Sets the filter policy for this domain, see xref:domainBasedPacketFiltering[This section] for a description of the rules.\n- Domain filter domains: a specific setting to restrict or control cross domain traffic.\n- Max users: maximum users allowed to be registered to the server.\n- Allowed C2S, BOSH, Websocket ports: Comma separated list of ports that this vhost will check for all of these services.\n- Presence forward address: specific address where presence information is forwarded too.  This may be handy if you are looking to use a single domain for presence processing and handling.\n- Message forward address: Specific address where all messages will be sent too.  This may be useful to you if you have a single server handling AMP or message storage and want to keep the load there.\n- Other Parameters: Other settings you may wish to pass to the server, consider this a section for options after a command.\n- Owner: The owner of the vhost who will also be considered an administrator.\n- Administrators: comma separated list of JIDs who will be considered admins for the vhost.\n- XEP-0136 Message Archiving Enabled: Whether to turn on or off this feature.\n- XEP-0136 Required store method: If XEP-0136 is turned on, you may restrict the portion of message that is saved. This is required for any archiving, if null, any portion of the message may be stored.\n- Client certificate required: Whether the client should submit a certificate to login.\n- Client certificate CA: The Certificate Authority of the client certificate.\n- XEP-0136 retention period: integer of number of days message archives will be set.\n- Trusted JIDs: Comma separated list of JIDs who will be added to the trusted list, these are JIDS that may conduct commands, edit settings, or other secure work without needed secure logins.\n- XEP-0136 retention type: Sets the type of data that retention period will use.  May be User defined (custom number type), Unlimited, or Number of Days.\n- XEP-0136 - store MUC messages: Whether or not to store MUC messages for archiving.  Default is user, which allows users to individually set this setting, otherwise tue/false will override.\n- see-other-host redirection enabled: in servers that have multiple clusters, this feature will help to automatically repopulate the cluster list if one goes down, however if this is unchecked, that list will not change and may attempt to send traffic to a down server.\n- XEP-0136 Default store method: The default section of messages that will be stored in the archive.\n\n=== Change user inter-domain communication permission\nHere you can restrict users to be able to communicate on specific domains, this works similar to the domain filtering policy using the same rule sets. For more details, see xref:domainBasedPacketFiltering[Domain Based Packet Filtering] section for rule details and specifics.\nNote that the changes may be made to mutiple JIDs at the same time.\n\n=== Connections Time\nLists the longest and average connection time from clients to servers.\n\n=== Create Node\nThis section allows you to create a new node for the pubsub component.  Here is a breakdown of the fields:\n\n- The node to create: this is the name of the node that will be created.\n- Owner JID: user JID who will be considered the owner of the node.\n- pubsub#node type: sets the type of node the the new node will be.  Options include:\n  * *leaf* Node that can publish and be published too.\n  * *collection* A collection of other nodes.\n- A friendly name for the node: Allows spaces and other characters to help differentiate it from other nodes.\n- Whether to deliver payloads with event notifications: as it says, to publish events or not.\n- Notify subscribers when the configuration changes: default is false\n- Persist items to storage: whether or not to physically store items in the node.\n- Max # of items to persist: Limit how many items are kept in the node archive.\n- The collection with which the node is affiliated: If the node is to be in a collection, place that node name here.\n- Specify the subscriber model: Choose what type of subscriber model will be used for this node.  Options include:\n  * *authorize* - Requires all subscriptions to be approved by the node owner before items will be published to the user.  Also only subscribers may retrieve items.\n  * *open* - All users may subscribe and retrieve items from the node.\n  * *presence* - Typically used in an instant message environment. Provides a system under which users who are subscribed to the owner JID's presence with a from or both subscription may subscribe from and retrieve items from the node.\n  * *roster* - This is also used in an instant message environments, Users who are both subscribed to the owners presence AND is placed in specific allowed groups by the roster are able to subscribe to the node and retrieve items from it.\n  * *whitelist* - Only explicitly allowed JIDs are allowed to subscribe and retrieve items from the node, this list is set by the owner/administrator.\n- Specify the Publisher model: Choose what type of publisher model will be used for this node.  Options include:\n  * *open* - Any user may publish to this node.\n  * *publishers* - Only users listed as publishers may be able to publish.\n  * *subscribers* - Only subscribers may publish to this node.\n- When to send the last published item: This allows you to decide if and when the last published item to the node may be sent to newly subscribed users.\n  * *never* - Do not send the last published item.\n  * *on_sub* - Send the last published item when a user subscribes to the node.\n  * *on_sub_and_presence* - Send the last published item to the user after a subscription is made, and the user is available.\n- The domains allowed to access this node: Comma separated list of domains for which users can access this node.  By default is is blank, and there is no domain restriction.\n- Whether to deliver items to available users only: Items will only be published to users with available status if this is selected.\n- Whether to subscription expired when subscriber going offline: This will make all subscriptions to the node valid for a single session and will need to be re-subscribed upon reconnect.\n- The XSL transformation which can be applied to payloads in order to generate an appropriate message body element: Since you want a properly formatted <body> element, you can add an XSL transformation here to address any payloads or extra elements to be properly formatted here.\n- The URL of the XSL transformation which can be applied to payloads in order to generate an appropriate message body element: This would be the URL of the XSL Transform, e.g. http://www.w3.org/1999/XSL/Transform.\n- Roster groups allowed to subscribe: a list of groups for whom users will be able to subscribe.  If this is blank, no user restriction will be imposed.\n- Notify subscribers when owner changes their subscription or affiliation state: This will have the node send a message in the case of an owner changing affiliation or subscription state.\n- Allows get list of subscribers for each subscriber: Allows subscribers to produce a list of other subscribers to the node.\n- Whether to sort collection items by creation date or update time: options include\n  * *byCreationDate* - Items will be sorted by the creation date, i.e. when the item was made.\n  * *byUpdateTime* - Items will be sorted by the last update time, i.e. when the item was last edited/published/etc..\n\n=== DNS Query\nA basic DNS Query form.\n\n=== Default config - Pubsub\nHere you may set the default configuration for any new pubsub node.  These changes will be made for all future nodes, but will not affect currently active nodes.\n\n=== Default room config\nThis page allows admins to set the default configuration for any new MUC rooms that may be made on the server.\n\n=== Delete Monitor Task\nThis removes a monitor task from the list of available monitor scripts. This action is not permanent as it will revert to inital settings on server restart.\n\n=== Delete Node\nProvides a space to remove a node from the server.  It must be the full name of the node, and only one node can be removed at a time.\n\n=== Deleting ALL Nodes\nThis page allows the logged in admin to delete all nodes from the associated vhost.  This change is irreversible, be sure to read and check the box before submitting the command.\n\n=== Fix User's Roster\nYou can fix a users roster from this prompt. Fill out the bare JID of the user and the names you wish to add or remove from the roster. This will NOT edit a user's roster, but rather compare client roster to database and fix any errors between them.\n\n=== Fix User's Roster on Tigase Cluster\nThis does the same as the Fix User's Roster, but can apply to users who may not be logged into the local vhost, but are logged into a clustered server.\n\n=== Get User Roster\nAs the title implies this gets a users' roster and displays it on screen. You can use a bare or full JID to get specific rosters.\n\n=== Get any file\nEnables you to see the contents of any file in the tigase directory. By default you are in the root directory, if you wish to go into directory use the following format:\nlogs/tigase.log.0\n\n=== Get Configuration File\nIf you don't want to type in the location of a configuration file, you can use this prompt to bring up the contents of either tigase.conf or init.properties.\n\n=== Get init.properties File\nWill output the current init.properties file, this includes any modifications made during the current server session.\n\n=== Get list available commands\nThis may be listed multiple times for different components, but this will do as the section suggest and list available commands for that particular component.\n\n=== Load test\nHere you can run a test with the pubsub component on any node to test functionality and proper settings for the node.\n\n=== Load Errors\nWill display any errors the server encounters in loading and running. Can be useful if you need to address any issues.\n\n=== New command script\nThis space allows you to create a new command script that will work within the associated component.  Note that under the hyperlinked title, there is a listing of muc.server.org or pubsub.server.org, use these to determine where the new command will operate.\n\n=== OAuth Credentials\nThis allows the setting of new custom OAuth credentials for the server, and you can also require the use of OAuth tokens for users when they login.  This is a setting for the specific host you are logged into.  If you are logged into xmpp1.domain.com, it will not affect settings for xmpp2.domain.com.\n\n=== Pre-Bind BOSH user session\nThis allows a JID to be paired with a BOSH session before that user logs in, can reduce CPU use if you have a user that logs in via BOSH on a regular basis, or a web client that will regularly connect. You may also specify HOLD and WAIT integers to affect how BOSH operates with the associated JID.\n\n=== Publish item to node\nThis window allows you to not only test, but publish an item to the specified node.  All fields must be filled in in order to avoid the server dropping an improperly formatted stanza.\n\n=== Read ALL nodes\nHere you can display all nodes and items from nodes that are currently in storage.\n\n=== Rebuild database\nThis will force Tigase to rebuild databases for the pubsub component, this may be useful for pubsub subscribers who continue to get pushed events after they unsubscribe.\n\n=== Reload component repository\nThis will reload any vhosts that the server is running.  This may be useful if one is disconnected or broken during runtime.\n\n=== Remove an item\nThis will remove a running vhost from the server, you will be presented with a list to pick from.\n\n=== Remove command script\nLike new command script, take a look at the subheading to determine which component you want to remove the script from.  Once there, select the command you wish to remove from the server.  If remove from disk is selected, then the change will be permanent.  Otherwise, the command will be removed until the next server restart.\n\n=== Remove listener script\nSelect from a list the listener script you wish to remove.  This will only affect custom listener scripts added to the eventbus component.\n\n=== Remove room\nThis provides fields to remove a room from the MUC component. you may suggest an alternative room which will move occupants to the alternative room once the current one is removed.\n\n=== Retrieve items\nHere you can retrieve items from PubSub nodes, this simulates the get IQ stanza from the pubsub component.\n- Service name - The address of the pubsub component.\n- Node name - Item node to retrieve items from.\n- Item ID - The item ID of the item you wish to retrieve.\n- Items Since - UTC timestamp to start search from: YYYY-MM-DDTHH:MM:SSZ\n\n=== S2S Bad State Connections\nThis will list any connections to other servers that are considered bad or stale.  This will populate very rarely as Tigase automatically adjusts around clustered servers that go down.  In the event a connection stays bad, it is recommended to reset those connections in the next space.\n\n=== S2S Reset Bad State Connections\nThis will reset the connections with other servers that are considered bad and have shown up in the S2S Bad State Connections page.\n\n=== S2S Get CID Connection State\nFor internal developer use only.\n\n=== Subscribe to a node\nThis provides a space for an administrator to manually have a JID subscribe to a particular node.\n\n=== Unsubscribe from node\nHere you can unsubscribe users from a particular node.  Users can be a comma separated list.\n\n=== Update item configuration\nTypically two entries will be seen for this entry, one for basic-conf and another for vhost-man. They each have their own sections, but provide for a plethora of server options.  Changes to the server are done in realtime, and may not be permanent.\n\n==== basic-conf\nThis will prompt a list of nearly every component setting currently available in the Tigase installation.  They are broken down as follows:\nComponent/catagory or setting/setting\nSo for example, if you wanted to change admins for the eventbus component, you will select 'eventbus/admins'.\nAnother example might be if you wanted to turn on or off a task in monitor component, lets say disk-checker-task, you would find 'monitor/disk-checker-task/enabled'.\nClicking Submit query will show current status and settings, and possible fields to change.  Most changes done in this manner will be reset to default or as written in init.properties file on server restart.\n\n\n==== vhost-man\nYou will be presented with a list of domains that Tigase is currently hosting, you will be able to change settings for one domain at a time using this function.  Once a domain is selected, you will be able to set or change the following settings:\n\n- Domain name: the full domain name of the new vhost.  Tigase will not add anything to this domain, so if it is ti be a subdomain of example.com, you will need to enter sub.domain.com.\n- Enabled: Whether the domain is turned on or off.\n- Anonymous enabled: Allow anonymous logins.\n- In-band registration: Whether or not to allow users to register accounts upon login.\n- TLS required: Require logins to the vhost to conduct a TLS handshake before opening streams.\n- S2S secret: a server-generated code to differentiate traffic between servers, typically there is no need to enter your own, but you may if you need to get into low level code.\n- Domain filter policy: Sets the filter policy for this domain, see xref:domainBasedPacketFiltering[This section] for a description of the rules.\n- Domain filter domains: a specific setting to restrict or control cross domain traffic.\n- Max users: maximum users allowed to be registered to the server.\n- Allowed C2S, BOSH, Websocket ports: Comma separated list of ports that this vhost will check for all of these services.\n- Presence forward address: specific address where presence information is forwarded too.  This may be handy if you are looking to use a single domain for presence processing and handling.\n- Message forward address: Specific address where all messages will be sent too.  This may be useful to you if you have a single server handling AMP or message storage and want to keep the load there.\n- Other Parameters: Other settings you may wish to pass to the server, consider this a section for options after a command.\n- Owner: The owner of the vhost who will also be considered an administrator.\n- Administrators: comma separated list of JIDs who will be considered admins for the vhost.\n- XEP-0136 Message Archiving Enabled: Whether to turn on or off this feature.\n- XEP-0136 Required store method: If XEP-0136 is turned on, you may restrict the portion of message that is saved. This is required for any archiving, if null, any portion of the message may be stored.\n- Client certificate required: Whether the client should submit a certificate to login.\n- Client certificate CA: Client Certificate Authority.\n- XEP-0136 retention period: Integer of number of days message archives will be set.\n- Trusted JIDs: Comma separated list of JIDs who will be added to the trusted list, these are JIDS that may conduct commands, edit settings, or other secure work without needed secure logins.\n- XEP-0136 retention type: Sets the type of data that retention period will use.  May be User defined (custom number type), Unlimited, or Number of Days.\n- XEP-0136 - store MUC messages: Whether or not to store MUC messages for archiving.  Default is user, which allows users to individually set this setting, otherwise true/false will override.\n- see-other-host redirection enabled: in servers that have multiple clusters, this feature will help to automatically repopulate the cluster list if one goes down, however if this is unchecked, that list will not change and may attempt to send traffic to a down server.\n- XEP-0136 Default store method: The default section of messages that will be stored in the archive.\n\n\n=== Update user roster entry\nThis section allows admins to edit individual users rosters, although it provides similar functionality to fix users roster, this is designed for precision editing of a user roster.\n\n- Roster owner JID: The BareJID of the user roster you wish to edit.\n- JID to manipulate: The specific BareJID you want to add/remove/change.\n- Comma separated groups: Groups you wish to add the JID too.\n- Operation Type: What function will be performed?\n  * *Add* - Add the JID to manipulate to the owner JID's roster and groups.\n  * *Remove* - Remove the JID to manipulate from the owner JID's roster and groups.\n- Subscription type: The type of subscription stanza that will be sent to the server, and subsequently between the two users will be employed.\n  * *None* - Select this if neither the owner or the user to be manipulated wishes to receive presence information.\n  * *From* - The Roster Owner will not receive presence information from the JID to manipulate, but the opposite will be true.\n  * *To* - The JID to manipulate will not receive presence information from the Roster Owner, but the opposite will be true.\n  * *Both* - Both JIDs will receive presence information about each other.\n\n=== Update user roster entry extended version\nThis section is an expanded version of the previous one, all fields already specified are the same with these additions:\n\n- Roster owner name: A friendly name or nickname if you wish to change/create one. *not required*\n- Comma separated of owner groups: Groups that the user wants to join/leave. *not required*\n- Roster item JID: The specific JID that needs to be edited.\n- Roster item name: A friendly name or nickname that will be changed/created. *not required*\n- Comma separated list of item groups: A group or list of groups that the roster item JID will be added to/removed from.\n- Action:\n  * *Add/update item* - Will add or update the item JID in the roster owner's roster.\n  * *Remove item* - Will remove the item JID from the roster owner's roster.\n  * *Add/update both rosters* - Will add or update the item in both roster owner and roster item's roster.\n  * *Remove from both rosters* - Will remove the item from both roster owner and roster item's roster.\n\n== Scripts\nThis section will enable administrators to custom write or enter their own scripts for specific components.  Each active component will have an entry for new and remove command scripts and scripts written there will be for that component.\n\n=== New Command Script\n- Description: A friendly name of the script, will be the title of the link in the menu on the left.\n- Command ID: Internal command that Tigase will use when referencing this script.\n- Group: The group for the script, which may be any of the headings on the left (Configuration, Example scripts, Notifications, Other etc..) or your own.  If no group exists, a new one will be created.\n- Language: The language the script is written in.  Currently Tigase supports Groovy and EMCAScript.\n- Script text: the fulltext of the script.\n- Save to disk: Scripts that are saved to disk will be permanently stored in the server's directory /scripts/admin/[Component]/commandID.js *NOTE* Scripts that are NOT saved to disk will not survive a server restart.\n\n=== Remove Command Script\nAs with New Command Script, there is an entry for each component.  This page will provide a space to remove commands for the selected component.\nYou will be provided a list of scripts associated with that component.  You also have the open to remove from disk, which will permanently delete the script from the hard drive the server is on.  If this is unchecked, the script will be unavailable until the next restart.\n\n== Statistics\nThis section is more useful to test statistics scripts and components, as many of them produce very small amounts of information, however these may be collected by other components or scripts for a better information display.\n\n=== Get User Statistics\nProvides a script output of user statistics including how many active sessions are in use, number of packets used, specific connections and their packet usage and location. All resources will return individual stats along with IP addresses.\n\n=== Get Active User List\nProvides a list of active users under the selected domain within the server.  An active user is considered a user currently logged into the XMPP server.\n\n=== Get list of idle users\nProvides a list of users who are idle on the server.\n\n=== Get list of online users\nProvides a list of users who are currently online.\n\n=== Get number of active users\nProvides a list of active users, users who are not idle or away.\n\n=== Get number of idle users\nProvides a number of idle users.\n\n=== Get top active users\nWill produce a list of user-limited users who are considered most active in packets sent.\n\n== Users\n=== Add User\nHere you can add new users to any domain handled by vHosts, users are added to database immediately and are able to login.  *NOTE: You cannot bestow admin status to these users in this section.*\n\n=== Change User Password\nThis enables you to change the password of any user in the database. Although changes will take effect immediately, users currently logged in will not know the password has been changed until they try to log in again.\n\n=== Delete User\nThis removes the user or users (comma separated) from the database. The deleted users will be kicked from the server once submit is clicked.\n\n=== End user session\nDisconnects the current selected user by ending their session with the server.\n\n=== Get User Info\nThis section allows admins to get information about a specific user including current connections as well as offline and online messages awaiting delivery.\n\n=== Get registered user list\nThis will display all registered users for the selected domain up to the number specified.\n\n=== Modify User\nAllows you to modify some user details including E-mail and whether it is an active user.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_58_-_Components_-_B_-_Tigase_HTTP_API_-_3_-_Web_Client.asciidoc",
    "content": "[[webClient]]\n= Tigase Web Client\n:author: Daniel Wisnewski\n:date: 2015-26-08 08:41\n:version: v1.0 August 2015\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nTigase now has a fully featured XMPP client built right into the HTTP interface. Everything you would expect from an XMPP client can now be done from the comfort of your browser window with no software install required!\n\nLets walk through setup.\n\nTigase web client requires the +Http.Message.Receiver+ plugin to be active.  To enable this add the following lines to your init.properties file:\n\n------\n--comp-name-5:http\n--comp-class-5:tigase.HttpMessageReceiver\n------\n*NOTE: If you selected HTTP API to be enabled on setup, you already have everything you need.*\nThis sets up an HTTP server with the default port of 8080.  See the HTTP API guide for component configuration.\n\nTo access the client, point a browser to the following address:\nxmpp.your-server.net:8080/ui/\n\nIt will ask you for a login, any bare JID of users registered with the server will work.\n*NOTE: Use your bare JID for login*\n\nOnce you have logged in successfully, you will be presented with the following screen.\n\nimage:images/WebUI-Home.jpg[]\n\nThe commands are broken into categories shown here.  All changes made in these sections are instant and should be seen the same as if you were using an external XMPP client like Psi.\n\n*NOTE* The BOSH client will automatically translate all requests to the server name.  In some rare cases this may not be resolvable by the browser and you will be unable to login.  Should that happen, you may disable that feature using the following line in your init.properties:\n\nbosh/send-node-hostname[B]=false\n\nYou may have to specifically designate the bosh URL when using the advanced tag in the login screen.\n\n== Chat\nThis is the default window, and your main interface for chatting inside XMPP with this server. *NOTE: you can only communicate to users logged onto the current server, or connected clusters*\nUsers from your roster will be on the left panel, the right all active discussions and MUCs, as well as the currently selected chat will be available.\n\nimage:images/WebUI-Chat.jpg[]\n\nUsers that are logged in and on your roster will be displayed on the left side. Double-clicking will bring up a new chat window with the user. You can Right-click on them to bring up a sub menu with the following;\n\nimage:images/WebUI-Usersubmenu.jpg[]\n\n- *Chat* replicates a double-click and opens a new window for chat.\n- *Modify* brings up a dialogue that allows you to change the JID of the contact, a nickname, and group.\n- *Delete* removes the user from your roster. This will also remove subscription authorization for the selected user to receive presence information effectively removing you from their roster. *NOTE: this will not block user packets from your JID*\n- *Info* brings up the User Info (this is the disco#info command for the selected user)\n\nThe top right section has a few icons with specific functionality, they are;\n\nimage:images/WebUI-Chat-Add-New.jpg[] adds a new user to your roster.\n\nimage:images/WebUI-Chat-NewMUC.jpg[] creates a new Multi-user chatroom.\n\nimage:images/WebUI-Chat-Profile.jpg[] allows you to edit your user information such as picture and nickname.\n\nimage:images/WebUI-Chat-CloseWindow.jpg[] closes the active chat window.\n\nimage:images/WebUI-Chat-settings.jpg[] provides a place to change your password or publish changes to your user info. *NOTE: you are limited to changing the General fields*\n\n== Discovery\nThis is your service discovery panel, which breaks down by component in the sidebar. Each component name and its associated JID is listed to help you find what you need. Most components give you an option to Execute commands with a few exceptions allowing browsing and the ability to join a MUC.\n\n*Browse* allows you to dig deeper into certain components; for example list the chatrooms available in the MUC component. At the top of the page the specific JID of the component are you in will be displayed. This is a text field, and can be edited to reflect the JID of the component (or just the server name) to navigate.\n\nimage:images/WebUI-Browse-Comp.jpg[]\n\n*Join to Room* will join you to a MUC room that is selected. Alternatively, selecting Join to Room while MUC component is selected, you can join and start a new MUC room.\n\n*Execute Command* Provides a hierarchy of commands and options to view and edit settings, run commands and scripts, view contents of files, and see statistics. Since each Component can have a unique structure it is best to explore each to see what options are available.\n\n== Management\nThis is an advanced window for settings and management for the XMPP server.\n\n=== Configuration\n==== List server/component configuration\nFrom a drop-down menu you can view all the active components, or the server configuration (basic-conf). This is a read-only list of the current settings.\n\n==== Manage active server components\nThis section gives you a drop-down menu for components\n- *List* will provide a list of active running components with the following format\n    component name :: componentInfo{Title=Server, Server version/revision (submission date), Class=component class} For example:\n    amp :: componentInfo{Title=Tigase XMPP Server, Version=7.1.0-SNAPSHOT-b3990/574c329f (2015-08-28/10:32:06), Class=tigase.server.amp.AmpComponent}\n\n- *Add* Allows you to activate a component in a similar way you would in the init.properties files. define a name for the component, and the class for the component. Once you click Confirm that component will be active and running.\n\n- *Edit* will allow you to edit details of the selected component. All possible values for the component will be listed, even ones that do not have specific settings. Changes will be immediate, although changes will revert to ones specified in init.properties upon restart.\n\n- *Remove* allows you to remove components from a dropdown list. Components will be removed upon confirmation, however settings will be reverted on server restart.\n\n==== Manage active server plugins\nHere is a list of all available plugins, and you can activate or deactivate them by checking or un-checking each one and clicking confirm. All changes are made in realtime, however changes will be reverted on server restart.\n\n=== Notifications\nThis section has one simple command: to be able to send a mass message to all logged in users.  You may choose to change the type of message to headline or Normal which will show as a pop-up in most XMPP clients.  Chat messages will open up a chat dialog with users.\n\n=== Other\nThis section contains a considerable list of options and settings affecting server functions.\n\n=== Activate log tracker for a user\nThis allows you to set a log file to track a specific user.  Set the bare or full JID of the user you want to log, and a name of the files you wish the log to be written to. The files will be written in the root Tigase directory unless you give a directory like logs/filename. The log files will be named with a .0 extension and will be named .1, .2, .3 and so on as each file reaches 10MB by default. filename.0 will always be the most recent.\nLogging will cease once the server restarts.\n\n=== Add SSL certificate\nHere you can add SSL certificates from PEM files to specific virtual hosts. Although Tigase can generate its own self-signed certificates, this will override those default certificates.\n\n=== Add Monitor Task\nYou can write scripts for Groovy or ECMAScript to add to monitor tasks here. This only adds the script to available scripts however, you will need to run it from another prompt.\n\n=== Add Monitor Timer Task\nThis section allows you to add monitor scripts in Groovy while using a delay setting which will delay the start of the script.\n\n=== Add New Item - ext\nProvides a method to add external components to the server. By default you are considered the owner, and the Tigase load balancer is automatically filled in.\n\n=== Add New Item - Vhost\nThis allows you to add new virtual hosts to the XMPP server\n\n=== Change user inter-domain communication permission\nYou can restrict users to only be able to send and receive packets to and from certain virtual hosts. This may be helpful if you want to lock users to a specific domain, or prevent them from getting information from a statistics component.\n\n=== Connections Time\nLists the longest and average connection time from clients to servers.\n\n=== DNS Query\nA basic DNS Query form.\n\n=== Default room config\nAllows you to set the default configuration for new MUC rooms. This will not be able to modify current in use and persistent rooms.\n\n=== Delete Monitor Task\nThis removes a monitor task from the list of available monitor scripts. This action is not permanent as it will revert to initial settings on server restart.\n\n=== Fix User's Roster\nYou can fix a users roster from this prompt. Fill out the bare JID of the user and the names you wish to add or remove from the roster. You can edit a users roster using this tool, and changes are permanent.\n\n=== Fix User's Roster on Tigase Cluster\nThis does the same as the Fix User's Roster, but can apply to users in clustered servers.\n\n=== Get User Roster\nAs the title implies this gets a users' roster and displays it on screen. You can use a bare or full JID to get specific rosters.\n\n=== Get any file\nEnables you to see the contents of any file in the tigase directory. By default you are in the root directory, if you wish to go into directory use the following format:\nlogs/tigase.log.0\n\n=== Get Configuration File\nIf you don't want to type in the location of a configuration file, you can use this prompt to bring up the contents of either tigase.conf or init.properties.\n\n=== Get init.properties File\nWill output the current init.properties file, this includes any modifications made during the current server session.\n\n=== Load Errors\nWill display any errors the server encounters in loading and running. Can be useful if you need to address any issues.\n\n=== New command script - Monitor\nAllows you to write command scripts in Groovy and store them physically so they can be saved past server restart and run at any time. Scripts written here will only be able to work on the Monitor component.\n\n=== New command script - MUC\nAllows you to write command scripts in Groovy and store them physically so they can be saved past server restart and run at any time. Scripts written here will only be able to work on the MUC component.\n\n=== OAUth credentials\nUses OAuth to set new credentials and enable or disable a registration requirement with a signed form.\n\n=== Pre-Bind BOSH user session\nAllows admins to pre-bind a BOSH session with a full or bare JID (with the resource automatically populated on connection). You may also specify HOLD or WAIT parameters.\n\n=== Reload component repository\nThis will show if you have any external components and will reload them in case of any stuck threads.\n\n=== Scripts\nThis section provides a list of command scripts for all active components. Each component has the following options\n- *Get list available commands* will list script commands for the component divided by either Scripts or Groups.\n- *New command script* provides a method to author new command scripts for specific components written in EMCAScript or Groovy. You do have an option to save the script to disk which will make the script permanent within the server.\n- *Remove command script* allows you to remove the selected script from the repository. If Remove from disk is not checked, the script will be unavailable until server restart. If it is, it will be permanently removed from the server.\n\nYou will be unable to edit or run commands from this section.\n\n=== Statistics\nThese statistics might be more useful as script results yield small bits of data, but you may find them useful when looking for server loads or finding user issues.\n\n==== Get User Statistics\nProvides a script output of user statistics including how many active sessions are in use, number of packets used, specific connections and their packet usage and location. All resources will return individual stats along with IP addresses.\n\n==== Get Active User List\nProvides a list of active users under the selected domain within the server.  An active user is considered a user currently logged into the XMPP server.\n\n==== Get list of idle users\nThis will list all idle users separated by vhost.\n\n==== Get list of online users\nThis will list users separated by the vhost they are connected to. The list will include the bare JID as well as any resources for that JID.\n\n==== Get number of active users\nThis displays the number of current active users.\n\n==== Get number of idle users\nThis section returns the number of active users per specific vhost.\n\n===== Get top active users\nThis will list the top number of active users by packets sent and online time. This list will only be built with users currently online and from all vhosts.\n\n=== Users\n\n==== Add New User\nHere you can add new users to any domain handled by vHosts, users are added to database immediately and are able to login.  *NOTE: You cannot bestow admin status to these users in this section.*\n\n==== Change user password\nAllows for admins to change the password of a specific user without needing to know the original password for the selected bare JID. Users currently logged in will not know password has been changed until they attempt to re-login.\n\n==== Delete user\nProvides a text window for admins to input the bare JID of the user they wish to remove from the server.\n\n==== Get User Info\nThis section allows admins to get information about a specific user including current connections as well as offline and online messages awaiting delivery.\n\n==== Get registered user list\nProvides a list of vhosts to search and a maximum number of users to list. Once run, the script will display a list of registered bare JIDs of users from the selected vhost.\n\n==== Modify User\nAllows you to modify some user details including E-mail and whether it is an active user.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_59_-_Components_-_C_-_Message_Archiving.asciidoc",
    "content": "[[messageArchiving]]\n= Message Archiving Component\n\n:author: Daniel Wisnewski\n:version: v1.0 Sept 2015\n:date: 2015-17-09 13:29\n\n:source: https://projects.tigase.org/projects/message-archiving/wiki/Wiki\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\n*NOTE: This component is incomplete and does not support all methods specified in XEP-0136*\nTigase server supports many of the features in XEP-0136, however it is not yet in full compliance with the XEP. The reason for this is that it uses the archived message date as the thread id of message due to the face that some clients sens messages with no thread id (e.g. Psi, Psi+). Due to this fact it is also possible to query the component about messages without specifying thread ids. For now the component also stores bare JIDs of recipients.\n\n\n== Installation\n\nThe message archiving component is not included with the standard build of Tigase, and thus will need to be compiled or downloaded. Here are the two methods:\n\n=== Download\n\nThe easiest way is to download the link:https://projects.tigase.org/attachments/download/3435/tigase-message-archiving-1.2.0-SNAPSHOT.jar[tigase-message-archiving-1.2.0-SNAPSHOT.jar] file into your /jars directory.\n\n=== Compile\n\nThe Tigase Message Archive component is kept in a separate repository from Tigase-server. It will compile in a similar manner though. Be sure you have Maven 3.0 or later installed. (to check use +mvn version+)\nFirst, obtain a clone of the repository using the following command:\n[source,bash]\n-----\n$ git clone https://repository.tigase.org/git/message-archiving.git\n-----\nThe repository will be downloaded to the /message-archiving/ directory.\n-----\n$cd message-archiving\n/message-archiving$ mvn clean package\n-----\nOnce Maven has finished compiling, go into the /target directory and you will find the required jar there. Move that to Tigase's /jars folder and your component is ready to run.\n\n== Configuration\n\nTo activate message archiving, place the following lines in the init.properties file:\n[source,bash]\n-----\n--comp-name-3=message-archive\n--comp-class-3=tigase.archive.MessageArchiveComponent\n-----\nThese two lines are the component required to be active. As with activating any component, be sure the component name and class match, and that the number is not used by another component.\n-----\nmessage-archive/archive-repo-uri=jdbc:mysql://localhost/messagearchivedb?user=test&password=test\n-----\nThis next line defines that message archives will be stored in a specific database, in this case +messagearchivedb+ hosted on localhost. If this is blank, the archive will be stored in the default user repository.\n-----\n--sm-plugins=message-archive-xep-0136\nsess-man/plugins-conf/message-archive-xep-0136/component-jid=archive@host.com\n-----\nThe next line turns on the message archive plugin, while this is not always necessary, in order to configure extra options, this line is needed.\nFinally, this line specifies the name for the component, if left blank the component's JID will be message-archive@local-machine-name.\n\n*NOTE: Message tagging can take up considerable resources!*\nThere are a high number of prepared statements which are used to process and archive messages as they go through the server, and you may experience an increase in resource use with the archive turned on. It is recommended to drecrease the repository connection pool to help balance server load from this component using the following line in init.properties:\n[source,bash]\n-----\n--data-repo-pool-size=5\n-----\n\n[[nonBodyStore]]\n=== Saving Options\n\nBy default, Tigase Message Archive will only store the message body with some metadata, this can exclude messages that are lacking a body.  If you decide you wish to save non-body elements within Message Archive, you can now can now configure this using the following line from init.properties:\n-----\nsess-man/plugins-conf/unified-archive/msg-archive-paths[s]=/message/body,/message/subject\n-----\nWhere above will set the archive to store messages with <body/> or <subject/> elements.\n\nTIP: Enabling this for elements such as iq, or presence will quickly load the archive.  Configure this setting carefully!\n\n== Usage\n\nNow that we have the archive component running, how do we use it?  Currently, the only way to activate and modify the component is through XMPP stanzas.  Lets first begin by getting our default settings from the component:\n[source,xml]\n----\n<iq type='get' id='prefq'>\n  <pref xmlns='urn:xmpp:archive'/>\n</iq>\n----\nIt's a short stanza, but it will tell us what we need to know, Note that you do not need a from or a to for this stanza. The result is as follows:\n[source,xml]\n----\n<iq type='result' id='prefq' to='admin@domain.com/cpu'>\n<pref xmlns='urn:xmpp:archive'>\n<auto save='false'/>\n<default otr='forbid' muc-save=\"false\" save=\"body\"/>\n<method use=\"prefer\" type=\"auto\"/>\n<method use=\"prefer\" type=\"local\"/>\n<method use=\"prefer\" type=\"manual\"/>\n</prefq>\n</iq>\n----\nSee below for what these settings mean.\n\n=== XEP-0136 Field Values\n\n<auto/>::\n  - *Required Attributes*\n  * +save=+ Boolean turning archiving on or off\n  - *Optional Settings*\n  * +scope=+ Determines scope of archiving, default is +\\'stream'+ which turns off after stream end, or may be +\\'global'+ which keeps auto save permanent,\n\n<default/>::\n  Default element sets default settings for OTR and save modes, includes an option for archive expiration.\n  - *Required Attribures*\n  * +otr=+ Specifies setting for Off The Record mode. Available settings are:\n    ** +approve+ The user MUST explicitly approve OTR communication.\n    ** +concede+ Communications MAY be OTR if requested by another user.\n    ** +forbid+ Communications MUST NOT be OTR.\n    ** +oppose+ Communications SHOULD NOT be OTR.\n    ** +prefer+ Communications SHOULD be OTR.\n    ** +require+ Communications MUST be OTR.\n  * +save=+ Specifies the portion of messages to archive, by default it is set to +body+.\n    ** +body+ Archives only the items within the <body/> elements.\n    ** +message+ Archive the entire XML content of each message.\n    ** +stream+ Archive saves every byte of communication between server and client. (Not recommended, high resource use)\n  - *Optional Settings*\n  * +expire=+ Specifies after how many seconds should the server delete saved messages.\n\n<item/>::\n  The Item element specifies settings for a particular entity. These settings will override default settings for the specified JIDS.\n  - *Required Attributes*\n  * +JID=+ The Jabber ID of the entity that you wish to put these settings on, it may be a full JID, bare JID, or just a domain.\n  * +otr=+ Specifies setting for Off The Record mode. Available settings are:\n    ** +approve+ The user MUST explicitly approve OTR communication.\n    ** +concede+ Communications MAY be OTR if requested by another user.\n    ** +forbid+ Communications MUST NOT be OTR.\n    ** +oppose+ Communications SHOULD NOT be OTR.\n    ** +prefer+ Communications SHOULD be OTR.\n    ** +require+ Communications MUST be OTR.\n  * +save=+ Specifies the portion of messages to archive, by default it is set to +body+.\n    ** +body+ Archives only the items within the <body/> elements.\n    ** +message+ Archive the entire XML content of each message.\n    ** +stream+ Archive saves every byte of communication between server and client. (Not recommended, high resource use)\n  - *Optional Settings*\n  * +expire=+ Specifies after how many seconds should the server delete saved messages.\n\n<method/>::\n  This element specifies the user preference for available archiving methods.\n  - *Required Attributes*\n  * +type=+ The type of archiving to set\n    ** +auto+ Preferences for use of automatic archiving on the user's server.\n    ** +local+ Set to use local archiving on user's machine or device.\n    ** +manual+ Preferences for use of manual archiving to the server.\n  * +use=+ Sets level of use for the type\n    ** +prefer+ The selected method should be used if it is available.\n    ** +concede+ This will be used if no other methods are available.\n    ** +forbid+ The associated method MUST not be used.\n\nNow that we have established settings, lets send a stanza changing a few of them:\n[source,xml]\n-----\n<iq type='set' id='pref2'>\n  <pref xmlns='urn:xmpp:archive'>\n    <auto save='true' scope='global'/>\n    <item jid='domain.com' otr='forbid' save='body'/>\n    <method type='auto' use='prefer'/>\n    <method type='local' use='forbid'/>\n    <method type='manual' use='concede'/>\n  </pref>\n</iq>\n-----\nThis now sets archiving by default for all users on the domain.com server, forbids OTR, and prefers auto save method for archiving.\n\n== Manual Activation\n\nTurning on archiving requires a simple stanza which will turn on archiving for the use sending the stanza and using default settings.\n[source,xml]\n----\n<iq type='set' id='turnon'>\n  <pref xmlns='urn:xmpp:archive'>\n    <auto save='true'/>\n  </pref>\n</iq>\n----\nA sucessful result will yield this response from the server:\n[source,xml]\n----\n<iq type='result' to='user@domain.com' id='turnon'/>\n----\nOnce this is turned on, incoming and outgoing messages from the user will be stored in +tig_ma_msgs+ table in the database.\n\n== Automatic Activation of MUC messages\n\nEnabling this feature allows MUC messages to be stored in the Message Archive repository and are added in the same way as for any other message. For this setting consider the MUC room JID, this will be the \"user\" that the messages will be archived with.  This is the same JID used for retrevial as well as sending to storage.   Archived MUC messages will be in the same format as normal archival messages with one exception, each message will have a +<name>+ attribute attached which will be the room nick for the user that sent the message.\nThis feature is disabled by default.\n\n*NOTE:* It is worth to mention that even if more than on user resources joins the same room and each resource will receive the same messages, then only a single message will be stored in Message Archiving repository.\nIt is also important to note that MUC messages are archived to user messages archive only when user is joined to MUC room. For example, if message was sent to room but it was not sent to particular user, it will not be archived.\n\n=== Configuration\n\nEnabling archiving of MUC messages is done by adding one more line to your init.properties file. Along with defining +comp-name+ and +comp-class+ add this line:\n[source,bash]\n-----\nsess-man/plugins-conf/message-archive-xep-0136/store-muc-messages=value\n-----\n+value+ may be one of the following values:\n- +user+ Allows value to be set on domain level by user if the domain level setting allows that. [what?]\n- +true+ Enables the feature for all users in every hosted domain. This cannot be overridden by settings for individual domains or users.\n- +false+ Disables the feature for all users in every hosted domain. This cannot be overridden by settings for individual domains or users.\n\nTo configure this setting for individual vhosts, you will need to execute a configuration command using one of the following settings:\n- +user+ Allows user to start this feature\n- +true+ Enables feature for users of the configured domain. Users will be unable to disable this feature.\n- +false+ Disables feature for users of the configured domain. Users will be unable to disable this feature.\n\n== Searching for Messages\n\nTigase Message Archiving Component allows users to query for messages or collections that contain a string. A simple stanza sent to the message archive component will begin a search. For example, the following stanza requests a search for messages with \"test failed\" in the <body> element. *NOTE:* Searches can *ONLY* be conducted within <body> elements.\n[source,xml]\n-----\n<query xmlns=\"http://tigase.org/protocol/archive#query\">\n    <contains>test failed</contains>\n</query>\n-----\n\n*This query element must be the child of a +list+ or +retrieve+ element.*\n\nSearch options include:\n\n- +with=+ Specify JID of user sending message\n- +from=+ Search from this time and date, Format: YYYY-MM-DDTHH:MM:SSZ Time is in 24h set to GMT\n- +end=+ Search until this time and date, Format: YYYY-MM-DDTHH:MM:SSZ Time is in 24h set to GMT\n\n\n=== Example queries\n\nRetrieving messages with \"test failed\" string with user juliet@capulet.com between 2014-01-01 00:00:00 and 2014-05-01 00:00:00\n[source,xml]\n-----\n<iq type=\"get\" id=\"query2\">\n    <retrieve xmlns='urn:xmpp:archive'\n        with='juliet@capulet.com'\n        from='2014-01-01T00:00:00Z'\n        end='2014-05-01T00:00:00Z'>\n          <query xmlns=\"http://tigase.org/protocol/archive#query\">\n              <contains>test failed</contains>\n          </query>\n    </retrieve>\n</iq>\n-----\n\nRetrieving collections containing messages with \"test failed\" string with user juliet@capulet.com between 2014-01-01 00:00:00 and 2014-05-01 00:00:00\n[source,xml]\n-----\n<iq type=\"get\" id=\"query2\">\n    <list xmlns='urn:xmpp:archive'\n        with='juliet@capulet.com'\n        from='2014-01-01T00:00:00Z'\n        end='2014-05-01T00:00:00Z'>\n          <query xmlns=\"http://tigase.org/protocol/archive#query\">\n              <contains>test failed</contains>\n          </query>\n    </list>\n</iq>\n-----\n\n== Message Tagging Support\n\nTigase now is able to support querying message archives based on tags created for the query.  Currently, Tigase can support the following tags to help seach through message archives:\n- +hashtag+ Words prefixed by a hash (#) are stored with a prefix and used as a tag, for example #Tigase\n- +mention+ Words prefixed by an at (@) are stored with a prefix and used as a tag, for example @Tigase\n\n*NOTE:* Tags must be written in messages from users, they do not act as wildcards. To search for #Tigase, a message must have #Tigase in the <body> element.\n\nThis feature allows users to query and retrieve messages or collections from the archive that only contain one or more tags.\n\n=== Activating Tagging\n\nTo enable this feature, the following line must be in the init.properties file (or may be added with Admin or Web UI)\n[source,bash]\n-----\nmessage-archiving/tags-support[B]=true\n-----\nWhere +message-archiving+ is the class name of the component.\n\nUsage\n~~~~~\nTo execute a request, the tags must be individual children elements of the +retrieve+ or +list+ element like the following request:\n[source,xml]\n-----\n<query xmlns=\"http://tigase.org/protocol/archive#query\">\n    <tag>#People</tag>\n    <tag>@User1</tag>\n</query>\n-----\n\nYou may also specify specific senders, and limit the time and date that you wish to search through to keep the resulting list smaller.  That can be accomplished by adding more fields to the retrieve element such as +'with'+, +'from+', and +'end'+ . Take a look at the below example:\n[source,xml]\n-----\n<iq type=\"get\" id=\"query2\">\n    <retrieve xmlns='urn:xmpp:archive'\n        with='juliet@capulet.com'\n        from='2014-01-01T00:00:00Z'\n        end='2014-05-01T00:00:00Z'>\n          <query xmlns=\"http://tigase.org/protocol/archive#query\">\n              <tag>#People</tag>\n              <tag>@User1</tag>\n          </query>\n    </retrieve>\n</iq>\n-----\nThis stanza is requesting to retrieve messages tagged with @User1 and #people from chats with the user juliet@capulet.com between January 1st, 2014 at 00:00 to May 1st, 2014 at 00:00.\n\n*NOTE:* All times are in Zulu or GMT on a 24h clock.\n\nYou can add as many tags as you wish, but each one is an *AND* statement; so the more tags you include, the smaller the results.\n\n=== Tag Searching\n\nYou can also retrieve a list of Tags that have already been used and are stored in the message archive. You can search for exact or a partial of the tag or mention.  The following request is searching for tags that are 'like' #test, in this case any tags with #test present will show in a list.\n[source,xml]\n----\n<iq type=\"set\" id=\"tagquery\">\n    <tags xmlns=\"http://tigase.org/protocol/archive#query\" like=\"#test\"/>\n</iq>\n----\n\nThe result will return tags with #test in them:\n[source,xml]\n----\n<iq type=\"result\" id=\"tagquery\">\n    <tags xmlns=\"http://tigase.org/protocol/archive#query\" like=\"#test\">\n        <tag>#test1</tag>\n        <tag>#test123</tag>\n        <tag>#testwin</tag>\n        <set xmlns=\"http://jabber.org/protocol/rsm\">\n             <first index='0'>0</first>\n             <last>2</last>\n             <count>3</count>\n        </set>\n    </tags>\n</iq>\n----\n\nYou may retrieve a list of tags or mentions by using just the # or @ symbols in the +like=+ field.\n\n[[maPurging]]\n== Purging Information from Message Archive\n\nThis feature allows for automatic removal of entries older than a configured number of days from the Message Archive. It is designed to clean up database and keep its size within reasonable boundaries.\n\nThere are 4 settings available for this feature:\nTo enable the feature:\n+message-archive/remove-expired-messages[B]=true+\n\nThis setting changes the initial delay after the server is started to begin removing old entries.  In other words, MA purging will not take place until the specified time after the server starts.  Default setting is PT1H, or one hour.\n+message-archive/remove-expired-messages-delay=PT2H+\n\nThis setting sets how long MA purging will wait between passes to check for and remove old entries. Default setting is P1D which is once a day.\n+message-archive/remove-expired-messages-period=PT2D+\n\n*NOTE* that these commands are also compatible with +unified-archive+ component, just replace +message+ with +unified+.\n\n=== Configuration of number of days in VHost\n\nVHost holds a setting that determines how long a message needs to be in archive for it to be considered old and removed.  This can be set independently per Vhost.  This setting can be modified by either using the HTTP admin, or the update item execution in adhoc command.\n\nCommand-line utility\nSets after how many days message should be removed - by default we use 24 hours. So if entry is older than 24 hours then it will be removed, ie. entry from yesterday from 10:11 will be removed after 10:11 after next execution of purge.\nThis configuration is done by execution of Update item configuration adhoc command of vhost-man component, where you should select domain for which messages should be removed and then in field XEP-0136 - retention type select value Number of days and in field XEP-0136 - retention period (in days) enter number of days after which events should be removed from UA.\n\nIn adhoc select domain for which messages should be removed and then in field XEP-0136 - retention type select value Number of days and in field XEP-0136 - retention period (in days) enter number of days after which events should be removed from UA.\n\nIn HTTP UI select Other, then Update Item Configuration (Vhost-man), select the domain, and from there you can set XEP-0136 retention type, and set number of days at XEP-0136 retention period (in days).\n\nValue of +remove-expired-messages-delay+ and +remove-expired-messages-period+ is in format described at Duration.parse() in Java documentation.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_60_-_Components_-_D_-_Advanced_Message_Processing_-_AMP_XEP-0079.asciidoc",
    "content": "[[amp0079]]\n= Advanced Message Processing - AMP XEP-0079\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-05-13 16:09\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase server *5.1.0* or later offers support for link:http://xmpp.org/extensions/xep-0079.html[Advanced Message Processing], called AMP or XEP-0079.\n\nIt is enabled by default but there are several configuration options that you may tweak.\n\nConfiguration of AMP is not very complex, but as it is implemented as a component in the Tigase server it does needs a few settings to get it right.\n\nHere is a first, brief overview of the AMP configuration and later  detailed explanation of each parameter.\n\n[source,bash]\n-----\n--sm-plugins=amp,-message,-msgoffline\n--amp-repo-uri=jdbc:mysql://localhost/tigasedb?user=db_usr&password=db_pwd\n--amp-security-level=STRICT\nsess-man/plugins-conf/amp/amp-jid=amp@your-domain.tld\n-----\n\n\n== First of all: plugins:\n\nEven though the whole functionality is implemented inside the component you need a way to forward messages with +AMP+ payload to that component. This is what the 'amp' plugin does. The 'amp' plugin intercepts all +<message/>+ packets even without AMP payload, redirecting some of the to the +AMP+ component and others processing in a standard way. Therefore you no longer need 'message' plugin or 'msgoffline' plugin. Those are all functions are offered by the 'amp' plugin now. Hence you have to switch 'message' and 'msgoffline' plugins off (the 'amp' plugin is loaded by default):\n\n[source,bash]\n-----\n--sm-plugins=+amp,-message,-msgoffline\n-----\n\nThe 'amp' plugin needs to know where to forward all the +AMP+ packets. By default plugin uses hostname of the given machine as this is true to the most installations. However, this is configured by the last line of the example configuration, which forwards all packets to the address 'amp@your-domain.tld':\n\n[source,bash]\n-----\nsess-man/plugins-conf/amp/amp-jid=amp@your-domain.tld\n-----\n\n== Secondly: component:\n\nBy default Tigase loads the component with the standard name 'amp'\n\n== Optional parameters:\n\nThere is also one parameter shared between the component and the plugin. Connection to the database where offline messages are stored. The AMP component has a dedicated schema for storing offline messages designed for a high traffic and high load installations. It does not use +UserRepository+ for storing messages.\n\nBy default the same physical database as for +UserRepository+ is used but you can change it and store messages in a completely separate location to reduce performance degradation of rest of the system. You can set a database connection string using following property:\n\n[source,bash]\n-----\n--amp-repo-uri=jdbc:mysql://localhost/tigasedb?user=db_usr&password=db_pwd\n-----\n\nThe link:http://xmpp.org/extensions/xep-0079.html[XEP-0079] specification has a link:http://xmpp.org/extensions/xep-0079.html#security[Section 9. - Security Considerations]. As it describes, in some cases the AMP protocol can be used to reveal user's presence information by other users who are not authorised for presence updates. There are a few possible ways to prevent this.\n\nTigase's implementation offers 3 modes to handle +AMP+ requests to prevent revealing user's status to non-authorized users:\n\n[source,bash]\n-----\n--amp-security-level=STRICT\n-----\n\nIn this mode the server performs strict checking. The +AMP+ specification is fully handled. This however involves roster loading for each offline user, hence it may impact the service performance. It may not be feasible or possible to run in this mode for services under a high load with lots of AMP messages.\n\nIn the XEP this mode is described in the following way:\n\n_Accept the relevant condition only if the sender is authorized to receive the receiver's presence, as a result of which the server MUST reply with a <not-acceptable/> error condition if the sender is not so authorized; this is the RECOMMENDED behavior. This is also the default in Tigase._\n\n[source,bash]\n-----\n--amp-security-level=PERFORMANCE\n-----\n\nDummy checking is performed efficiently by just returning an error response every time there is a chance that the default action may reveal user status without looking into the user's roster. This does not affect performance but it does impact the +AMP+ compliance.\n\nIn the XEP this mode is described in the following way:\n\n_Accept the relevant condition only if the action is \"drop\", as a result of which the server MUST reply with a <not-acceptable/> error condition if the action is \"alert\", \"error\", or \"notify\"; this is slightly less restrictive but still unnecessarily restricts the functionality of the system, so is NOT RECOMMENDED._\n\nIt does not do any checking. It acts like all users are authorized to receive notifications, even if it may reveal user status to unauthorized users. It does not impact the server performance and it offers full AMP compliance.\n\n[source,bash]\n-----\n--amp-security-level=NONE\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_61_-_Components_-_E_-_PubSub.asciidoc",
    "content": "[[PubSubComp]]\n= PubSub Component\n:author: many authors\n:version: v1.0, September 2015\n:date: 2015-09-30 17:25\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\n\n\n== Configuration\nTigase's Publish Subscribe component is an link:http://www.xmpp.org/extensions/xep-0060.html[XEP-0060] compliant plugin handling all publish and subscribe activity within Tigase server.\nTo enable the component the following should be in your init.properties file\n-----\n--comp-name-2 = pubsub\n--comp-class-2 = tigase.pubsub.PubSubComponent\n-----\n\n== Pubsub naming\nWithin Tigase, all pubsub component address MUST be domain-based address and not a JID style address.  This was made to simplify communications structure. Tigase will automatically set component names to pubsub.domain, however any messages send to pubsub@domain will result in a +SERVICE_UNAVAILABLE+ error.\n\nPubsub nodes within Tigase can be found as a combination of JID and node where nodes will be identified akin to service discovery.  For example, to address a friendly node, use the following structure:\n\n[source,xml]\n-----\n<iq to='pubsub.domain'>\n  <query node='friendly node'/>\n</iq>\n-----\n\n[[rosterLimit]]\n== Configure Roster Maxmimum size\nStarting with Tigase v7.1.0, administrators can configure the maximum allowable roster size per user via the init.properties file.\n-----\nsess-man/plugins-conf/jabber\\:iqa\\:roster/max_roster_size=100\n-----\nThis sets the roster limit to 100 entries per user.  It can be set to any integer, however by default no limit is set.\n\n\n== AdHoc Commands\nSimilar to the HTTP API, AdHoc commands based on groovy scripts can be sent to this component to do a number of tasks. All scripts for these Ad-hoc commands are found at +sec/main/groovy/tigase/admin+ in source distrubitions, or at link:https://projects.tigase.org/projects/tigase-pubsub/repository/revisions/master/show/src/main/groovy/tigase/admin[this link]. To use them, the scripts need to be copied into the +scripts/admin/pubsub+ folder in the Tigase installation directory.\nFor all examples, the component address will be +pubsub.example.com+.\n\n=== Create a Node\nAd-hoc command node: +create-node+\nRequired role: Service Administrator\n\nCommand requires fields +node+ and +pubsub#node_type+ to be filled with proper values for execution.\n- +node+ Field containing id of node to create.\n- +pubsub#node_type+ Contains one of two possible values.\n  * +leaf-node+ Node that will be published.\n  * +collection+ Node that will contain other nodes.\n\nOther fields are optional fields that can be set to change configuration of newly create node to different configuration than default.\n\nExample call using TCLMT:\n-----\nbin/tclmt.sh -u admin@example.com -p admin123 remote pubsub.example.com create-node example admin@example.com leaf\n-----\n\n=== Delete a Node\nAd-hoc command node: +delete-node+\nRequired role: Service Administrator\n\nCommand requires +node+ field to be filled.\n- +node+ Field containing id of node to delete.\n\nExample call using TCLMT:\n-----\nbin/tclmt.sh -u admin@example.com -p admin123 remote pubsub.example.com delete-node example\n-----\n\n=== Subscribe to a Node\nAd-hoc command node: +subscribe-node+\nRequired role: Service Administrator\n\nCommand requires +node+ and +jids+ nodes to be filled.\n- +node+ Field containing node to subscribe to.\n- +jids+ Field containing list of JIDs to subscribe to the node.\n\nExample call using TCLMT:\n-----\nbin/tclmt.sh -u admin@example.com -p admin123 remote pubsub.example.com subscribe-node example admin@example.com,test1@example.com\n-----\n\n=== Unsubscribe to a Node\nAd-hoc command node: +unsubscribe-node+\nRequired role: Service Administrator\n\nCommand requires +node+ and +jids+ nodes to be filled.\n- +node+ Field containing node to unsubscribe to.\n- +jids+ Field containing list of JIDs to unsubscribe to the node.\n\nExample call using TCLMT:\n-----\nbin/tclmt.sh -u admin@example.com -p admin123 remote pubsub.example.com unsubscribe-node example admin@example.com,test2@example.com\n-----\n\n=== Publish an item to a Node\nAd-hoc command node: +publish-item+\nRequired role: Service Administrator\n\nCommand requires fields +node+ and +entry+ to be filled.\n- +node+ Field containing id of node to publish to.\n- +item-id+ Field may contain id of entry to publish, can be empty.\n- +entry+ Field should contain multi-line entry content that should be valid XML values for items.\n\nThis command due to it's complexity cannot be easily executed by TCLMT using default remote script which provides support for basic adhoc commands.\nExample call using TCLMT:\n-----\nbin/tclmt.sh -u admin@example.com -p admin123 remote pubsub.example.com publish-item example item-1 '<entry><title>Example 1</title></entry>'\n-----\n\nExample Groovy script to execute create-node command using JAXMPP2\n[source,java]\n-----\nimport tigase.jaxmpp.j2se.Jaxmpp\nimport tigase.jaxmpp.core.client.AsyncCallback\nimport tigase.jaxmpp.core.client.exceptions.JaxmppException\nimport tigase.jaxmpp.core.client.xmpp.stanzas.Stanza\nimport tigase.jaxmpp.core.client.SessionObject\nimport tigase.jaxmpp.j2se.ConnectionConfiguration\nimport tigase.jaxmpp.core.client.xml.Element\nimport tigase.jaxmpp.core.client.xml.DefaultElement\nimport tigase.jaxmpp.core.client.xmpp.forms.JabberDataElement\n\nJaxmpp jaxmpp = new Jaxmpp();\n\njaxmpp.with {\n    getConnectionConfiguration().setConnectionType(ConnectionConfiguration.ConnectionType.socket)\n    getConnectionConfiguration().setUserJID(\"admin@example.com\")\n    getConnectionConfiguration().setUserPassword(\"admin123\")\n}\n\njaxmpp.login(true);\n\ndef packet = IQ.create();\npacket.setAttribute(\"to\", \"pubsub.example.com\");\n\nElement command = new DefaultElement(\"command\");\ncommand.setXMLNS(\"http://jabber.org/protocol/commands\");\ncommand.setAttribute(\"node\", \"create-node\");\npacket.addChild(command);\n\nElement x = new DefaultElement(\"x\");\nx.setXMLNS(\"jabber:x:data\");\n\ncommand.addChild(x);\n\ndef data = new JabberDataElement(x);\ndata.addTextSingleField(\"node\", \"example\");\ndata.addListSingleField(\"pubsub#node_type\", \"leaf\");\n\njaxmpp.send(packet, new AsyncCallback() {\n    void onError(Stanza responseStanza, tigase.jaxmpp.core.client.XMPPException.ErrorCondition error) throws JaxmppException {\n        println \"received error during processing request\";\n    }\n\n    void onSuccess(Stanza responseStanza) throws JaxmppException {\n        x = responseStanza.getFirstChild(\"command\").getFirstChid(\"x\");\n        data = new JabberDataElement(x);\n        def error = data.getField(\"Error\");\n        println \"command executed with result = \" + (error ? \"failure, error = \" + error.getFieldValue() : \"success\");\n    }\n\n    void onTimeout() {\n        println \"command timed out\"\n    }\n});\n\nThread.sleep(30000);\njaxmpp.disconnect();\n-----\n\n== PubSub Node Presence Protocol\n\n*Occupant Use Case*\n=== Log in to Pubsub Node\nTo log in to PubSub Node user must send presence to PubSub component with additional information about node:\n[source,xml]\n-----\n<presence\n    from='hag66@shakespeare.lit/pda'\n    id='n13mt3l'\n    to='pubsub.shakespeare.lit'>\n  <pubsub xmlns='tigase:pubsub:1' node='princely_musings'/>\n</presence>\n-----\n\nComponent will publish this information in node:\n\n[source,xml]\n-----\n<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>\n  <event xmlns='http://jabber.org/protocol/pubsub#event'>\n    <items node='princely_musings'>\n      <item>\n        <presence xmlns='tigase:pubsub:1' node='princely_musings' jid='hag66@shakespeare.lit/pda' type='available'/>\n      </item>\n    </items>\n  </event>\n</message>\n<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>\n  <event xmlns='http://jabber.org/protocol/pubsub#event'>\n    <items node='princely_musings'>\n      <item>\n        <presence xmlns='tigase:pubsub:1' node='princely_musings' jid='hag66@shakespeare.lit/pda' type='available'/>\n      </item>\n    </items>\n  </event>\n</message>\n-----\nAnd then will send notification with presences of all occupants to new occupant.\n\n=== Log out from PubSub Node\nTo logout from single node, user must send presence stanza with type unavailable:\n[source,xml]\n-----\n<presence\n    from='hag66@shakespeare.lit/pda'\n    type='unavailable'\n    to='pubsub.shakespeare.lit'>\n  <pubsub xmlns='tigase:pubsub:1' node='princely_musings'/>\n</presence>\n-----\nComponent will send events to all occupants as described:\n[source,xml]\n-----\n<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>\n  <event xmlns='http://jabber.org/protocol/pubsub#event'>\n    <items node='princely_musings'>\n      <item>\n        <presence xmlns='tigase:pubsub:1' node='princely_musings' jid='hag66@shakespeare.lit/pda' type='unavailable'/>\n      </item>\n    </items>\n  </event>\n</message>\n-----\nIf component receives presence stanza with type unavailable without specified node, then component will log out user from all nodes he logged before and publish events.\n\n=== Retrieving list of all Node Subscribers\nTo retrieve list of node subscribers, node configuration option +tigase#allow_view_subscribers+ must be set to true:\n[source,xml]\n-----\n<iq type='set'\n    from='hamlet@denmark.lit/elsinore'\n    to='pubsub.shakespeare.lit'\n    id='config2'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <configure node='princely_musings'>\n      <x xmlns='jabber:x:data' type='submit'>\n        <field var='FORM_TYPE' type='hidden'>\n          <value>http://jabber.org/protocol/pubsub#node_config</value>\n        </field>\n        <field var='tigase#allow_view_subscribers'><value>1</value></field>\n      </x>\n    </configure>\n  </pubsub>\n</iq>\n-----\nWhen option is enabled, each subscriber may get list of subscribers the same way link:http://xmpp.org/extensions/xep-0060.html#owner-subscriptions-retrieve[as owner].\n[source,xml]\n-----\n<iq type='get'\n    from='hamlet@denmark.lit/elsinore'\n    to='pubsub.shakespeare.lit'\n    id='subman1'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <subscriptions node='princely_musings'/>\n  </pubsub>\n</iq>\n-----\nThere is extension to filter returned list:\n[source,xml]\n-----\n<iq type='get'\n    from='hamlet@denmark.lit/elsinore'\n    to='pubsub.shakespeare.lit'\n    id='subman1'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <subscriptions node='princely_musings'>\n        <filter xmlns='tigase:pubsub:1'>\n            <jid contains='@denmark.lit' />\n        </filter>\n    </subscriptions>\n  </pubsub>\n</iq>\n-----\nIn this example will be returned all subscriptions of users from domain \"denmark.lit\".\n\n[[storeFullXMLLastPresence]]\n== Store Full XML of Last Presence\nA new feature has been implemented in v7.1.0 that allows Tigase to store a more detailed <unavailable/> presence stanza to include timestamps and other information.\n\n=== Requirements\nEnsure that +presence-offline+ plugin is enabled in init.properties.  To do this, add *+presence-offline* to the *--sm-plugins* line.\n\nThe following two lines configure options to broadcast probes to offline users.\n-----\nsess-man/plugins-conf/skip-offline=false\nsess-man/plugins-conf/skip-offline-sys=false\n-----\nWithout these lines, Tigase will not send presence probes to users that the server knows to be offline.\n\nThe full XML presence is stored under the tig_pairs table with a pkey of +last-unavailable-presence+ will look like this:\n[source,xml]\n-----\n<presence from=\"user@example.com\" xmlns=\"jabber:client\" type=\"unavailable\">\n<status>Logged out</status>\n<delay stamp=\"2015-12-29T16:51:50.748Z\" xmlns=\"urn:xmpp:delay\"/></presence>\n-----\nAs you can see, the plugin has added a delay stamp which indicates the last time they were seen online. This may be suppressed by using the following line in your init.properties file.\n-----\nsess-man/plugins-conf/delay-stamp=false\n-----\n\nYou may also limit probe responses only to newly connected resources.\n-----\nsess-man/plugins-conf/probe-full-jid=true\n-----\n\nWhen a user logs on, they will receive the same full unavailable presence statements from contacts not logged in.  Also the repository entry containing their last unavailable presence will be removed.\n\n*NOTE: This will increase traffic with users with many people on their rosters.*\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_62_-_Components_-_E_-_PubSub_-_1_-_Offline_Message_Sink.asciidoc",
    "content": "[[offlineMessageSink]]\n= Offline Message Sink\n:author: Bartosz Malkowski\n:version: v1.0, October 2015\n:date: 2015-10-07 09:36\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\n== Description\n\nMessages sent to offline users is published in PubSub node, from where that message is sent to all the node subscribers as a PubSub notification.\n\n[source,xml]\n-----\n<message from='pubsub.coffeebean.local' to='bard@shakespeare.lit' id='foo'>\n  <event xmlns='http://jabber.org/protocol/pubsub#event'>\n    <items node='message_sink'>\n      <item id='ae890ac52d0df67ed7cfdf51b644e901'>\n        <message type=\"chat\" xmlns=\"jabber:client\" id=\"x2ps6u0004\"\n          to=\"userB_h6x1bt0002@coffeebean.local\"\n          from=\"userA_uyhx8p0001@coffeebean.local/1149352695-tigase-20\">\n          <body>Hello</body>\n        </message>\n      </item>\n    </items>\n  </event>\n</message>\n-----\n\n== Configuration\nThe PubSub node must be created and configured beforehand:\n\n=== Create node\n[source.xml]\n-----\n<iq type='set'\n    to='pubsub.coffeebean.local'\n    id='create1'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub'>\n    <create node='message_sink'/>\n  </pubsub>\n</iq>\n-----\n\nAfter that is done, you need to add SessionManager as a publisher:\n\n=== Add sess-man as publisher\n[source,xml]\n-----\n<iq type='set'\n    to='pubsub.coffeebean.local'\n    id='ent2'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <affiliations node='message_sink'>\n      <affiliation jid='sess-man@coffeebean.local' affiliation='publisher'/>\n    </affiliations>\n  </pubsub>\n</iq>\n-----\n\nFinally, the AMP plugin must be configured as well\n\n=== init.properties configuration\n[source,bash]\n-----\nsess-man/plugins-conf/amp/msg-pubsub-jid=pubsub.coffeebean.local\nsess-man/plugins-conf/amp/msg-pubsub-node=message_sink\nsess-man/plugins-conf/amp/msg-pubsub-publisher=sess-man@coffeebean.local\n-----\n\nOf course be sure that AMP plugin is in your +--sm-plugins+ line.\n\n== Usage\nBecause these sinks use a standard PubSub component, administration of the sink node is identical to any other PubSub node. link:http://www.xmpp.org/extensions/xep-0060[XEP-0060] defines standard PubSub usage and management.\n\n=== Managing Subscriptions\n\n==== Add new Subscriber\n[source,xml]\n-----\n<iq type='set'\n    to='pubsub.coffeebean.local'\n    id='subman2'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <subscriptions node='message_sink'>\n      <subscription jid='bard@shakespeare.lit' subscription='subscribed'/>\n    </subscriptions>\n  </pubsub>\n</iq>\n-----\n\n==== Remove Subscriber\n[source,xml]\n-----\n<iq type='set'\n    to='pubsub.coffeebean.local'\n    id='subman2'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>\n    <subscriptions node='message_sink'>\n      <subscription jid='bard@shakespeare.lit' subscription='none'/>\n    </subscriptions>\n  </pubsub>\n</iq>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_63_-_Components_-_E_-_PubSub_-_2_-_PubSub_Schema_Changes.asciidoc",
    "content": "[[PubsubSchemaChanges]]\n= PubSub Schema Changes\n:author:\n:version: v1.0 September, 2015\n:date: 2015-30-09 17:28\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nTigase PubSub Component is currently version 3.2.0 which is introduced in Tigase server v7.1.0\n\n[[Pubsub3.2.0Changes]]\n== PubSub 3.2.0 Changes\n\nPubSub v 3.2.0 adds a new procedure TigPubSubGetNodeMeta which supports PubSub metadata retrieval while conducting a disco#info query on nodes.\n\nYou will need to upgrade your database if you are not using v3.2.0 schema. Tigase will report being unable to load PubSub component if you do not have this schema version.\n\nThe MySQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/revisions/master/entry/database/mysql-pubsub-schema-3.2.0.sql[Here].\n\nThe Derby schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/derby-pubsub-schema-3.2.0.sql[Here].\n\nThe PostGRESQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/postgresql-pubsub-schema-3.2.0.sql[Here].\n\nThe MS SQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/sqlserver-pubsub-schema-3.2.0.sql[Here].\n\nThe same files are also included in all distributions of v7.1.0 in +[tigaseroot]/database/+ . All changes to database schema are meant to be backward compatible.\n\nFor instructions how to manually upgrade the databases, please refer to xref:tigaseServer71[Tigase v7.1.0 Schema Updates section].\n\n[[Pubsub310change]]\n== PubSub 3.1.0 Changes\nThe PubSub Schema has been streamlined for better resource use, this change affects all users of Tigase.\nTo prepare your database for the new schema, first be sure to create a backup!  Then apply the appropriate pubsub schema to your MySQL and it will add the new storage procedure.\n\nThe MySQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/revisions/master/entry/database/mysql-pubsub-schema-3.1.0.sql[Here].\n\nThe Derby schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/derby-pubsub-schema-3.1.0.sql[Here].\n\nThe PostGRESQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/postgresql-pubsub-schema-3.1.0.sql[Here].\n\nThe MS SQL schema can be found link:https://projects.tigase.org/projects/tigase-pubsub/repository/changes/database/sqlserver-pubsub-schema-3.1.0.sql[Here].\n\nThe same files are also included in all distributions of v7.1.0 in +[tigaseroot]/database/+ . All changes to database schema are meant to be backward compatible.\n\n== PubSub v3.0.0 Changes\nTo update older installations of Tigase to the PubSub Schema v3.0.0 follow these instructions. Note this should be done before upgrading to PubSub v3.1.0.\n\nStep by Step guide.\n\n=== Prepare Old Database for Upgrade\nIn +database+ directory of Tigase installation you will find SQL files which will prepare old database schema for upgrade using following this naming pattern: +<database_type>-pubsub-schema-3.0.0-pre-upgrade.sql+ Where +<database_type>+ can be one of the following: +mysql+, +sqlserver+, ie. for MySQL you will find the file +mysql-pubsub-schema-3.0.0-pre-upgrade.sql+. You need to execute statements from this file on your source database, which will drop old procedures and functions used to access database and also this statements will rename old tables by adding suffix _1 to each of old tables. Example:\n\nMySQL::\n  +mysql -u tigase -p tigase_pubsub < database/mysql-pubsub-schema-3.0.0-pre-upgrade.sql+\n\nMS SQL::\n  +sqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-pubsub-schema-3.0.0-pre-upgrade.sql+\n\n=== Update Tigase PubSub Component\nFor this you need to copy the Tigase PubSub Component jar file to jars directory inside Tigase XMPP Server installation directory. It is also recommended to copy files from database directory of Tigase PubSub Component to database directory in Tigase XMPP Server installation directory.\n\nIf you happen to use one of the the distribution packaged (either installer or -dist-max flavored archive) then all required files are already available - both new schema files will be available in +database/+ directory as well as both versions of PubSub component will be present in +jars/+ directory - PubSub3 as tigase-pubsub.jar and PubSub2 as tigase-pubsub-2.2.0.jar.old (provided for compatibility reasons).\n\n=== Load New Schema\nIn the +database+ directory you will find files containing new schemas for:\n\n- MySQL - +mysql-pubsub-schema-3.0.0.sql+\n- PostgreSQL - +postgresql-pubsub-schema-3.0.0.sql+\n- MSSQL - +sqlserver-pubsub-schema-3.0.0.sql+\n- DerbyDB - +derby-pubsub-schema-3.0.0.sql+ and +pubsub-db-create-derby.sh+\n\nFor most databases, with the exception of Derby, you only need to execute statements from the proper file.  For example:\n\nMySQL::\n  +mysql -u tigase -p tigase_pubsub < database/mysql-pubsub-schema-3.0.0.sql+\n\nMS SQL::\n  +sqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-pubsub-schema-3.0.0.sql+\n\nPostgreSQL::\n  +psql -h $DB_HOST -q -U ${USR_NAME} -d $DB_NAME -f database/sqlserver-pubsub-schema-3.0.0.sql+\n\nFor DerbyDB you need to execute the +pubsub-db-create-derby.sh+ script and pass proper JDBC URI to database to which you want to load schema (if database does not exist, it will be created).\n-----\ndatabase/pubsub-db-create-derby.sh\n-----\n*NOTE:* It is possible to use same database which was used before - then after upgrade you will have new tables and old tables with _1 suffix.\n\n=== Execute Migration Utility\nIn the +/database+ directory you will find the +pubsub-db-migrate.sh+ file which you need to execute and pass arguments with JDBC URIs needed to connect to source and destination database. If you used dedicated tables for PubSub you will also need to pass a class name used to access database (value of +pubsub/pubsub-repo-class+ variable from +etc/init.properties+ file).\n\nExample for dedicated table used for PubSub:\n[source,sql]\n-----\ndatabase/pubsub-db-migrate.sh -in-repo-class tigase.pubsub.repository.PubSubDAO\n-in 'jdbc:mysql://localhost/tigase_pubsub?user=tigase&password=passwd'\n-out 'jdbc:mysql://localhost/tigase_pubsub?user=tigase&password=passwd'\n-----\n\nExample for use without dedicated PubSub tables:\n[source,sql]\n-----\ndatabase/pubsub-db-migrate.sh\n-in 'jdbc:mysql://localhost/tigase?user=tigase&password=passwd'\n-out 'jdbc:mysql://localhost/tigase?user=tigase&password=passwd'\n-----\n\nExample for use with dedicated tables in a Windows environment:\n[source,sql]\n-----\ndatabase/pubsub-db-migrate.cmd -in-repo-class tigase.pubsub.repository.PubSubDAO\n-in 'jdbc:sqlserver://<hostname>\\\\<instance>:<port>;databaseName=<name>;user=tigase;password=tigase;schema=dbo;lastUpdateCount=false'\n-out 'jdbc:sqlserver://<hostname>\\\\<instance>:<port>;databaseName=<name>;user=tigase;password=tigase;schema=dbo;lastUpdateCount=false'\n-----\n\nDuring execution this utility will report information about migration of PubSub data to the new schema, and the same information will be store in +pubsub_db_migration.log+.\n\n=== Finish\nAfter successful migration you will have all data copied to new tables. Old tables will be renamed by adding suffix _1. After verification that everything works OK, you can delete old tables and it's content as it want be used any more.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_64_-_Components_-_F_-_Server_Monitoring.asciidoc",
    "content": "[[serverMonitoring]]\n= Server Monitoring\n:author: Unknown\n:version: v1.0\n\nAll the documentation and resources related to the Tigase server monitoring.\n\nxref:setupRemoteMonitoring[Setting up Remote Monitoring in the Server]\nxref:retrievingStatisticsFromTheServer[Retrieving Statistics from the Server]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_65_-_Components_-_F_-_Server_Monitoring_-_1_-_Setting_up_Remote_Monitoring_in_the_Server.asciidoc",
    "content": "[[setUpRemoteMonitoring]]\n= Setting Up Remote Monitoring in the Server\n:author: unknown\n:version: v1.0\n:date: 2010-04-06 21:18\n\nTigase server can be remotely monitored over following protocols: *JMX/RMI*, *SNMP* and *HTTP*. Even though JMX offers the biggest control and visibility to the server states, all of the monitoring services give the same basic set of the server statistics:\n\n- Number of network connections for s2s, c2s and Bosh\n- Last second, last minute and last hour load for all main components: SM, MR, c2s, s2s, Bosh, MUC and PubSub\n- System statistics - memory usage (heap and non heap) and the server uptime in milliseconds and human readable text.\n- Users statistics - number of registered users and number of online user session.\n\nJMX/RMI and SNMP servers offer basic security and can restrict access while the HTTP server doesn't offer any access restriction mechanisms. Therefore HTTP monitoring is recommended to operate behind a firewall.\n\nThe monitoring itself causes very low overhead in terms of the resources and CPU consumption on top of the normal Tigase processing requirements so it can be left on without worrying about performance degradation.\n\n*Note.* _This works with the Tigase server from version_ *4.2.0* _or SVN revision_ *1418*.\n\n== What You Need\nUsing v7.1.0 and later, statistics binaries are built-in dist-max and no extra files are needed.  If you have downloaded -dist file, you will need tigase-extras.\n\nTo ensure, two files are necessary to run monitoring:\n\n. link:https://projects.tigase.org/projects/tigase-extras/files[tigase-extras] or the link:https://projects.tigase.org/projects/tigase-server/repositoryr[current snapshot].\n. *jdmkrt.jar* file from link:https://opendmk.java.net/[OpenDMK] project version 5.1 or later. A copy of this jar file in also available in our maven repository: link:http://maven.tigase.org/openDMK/jdmkrt/1.0-b02/[jdmkrt.jar].\n\nBoth files should be in the /jars directory.\n\n\n[[monitoring_activation]]\n== Activation\n\nYou can either run the Tigase installer and use the configuration wizard to activate the monitoring or edit etc/init.properties file and add following line:\n\n[source,bash]\n-----\n--monitoring=jmx:9050,http:9080,snmp:9060\n-----\n\nAs you see there is only a single line where you put list of monitoring servers you want to activate. Each server is responsible for activation of a different protocol and takes a single parameter - port number. There are following protocols supported right now:\n\n- *jmx* - activating monitoring via JMX/RMI\n- *http* - activating monitoring over HTTP protocol\n- *snmp* - activating monitoring over SNMP protocol\n\nYou can have all protocols active at the same time or any combination of them or none.\n\n== Security\n\nBoth JMX and SNMP offer security protection to limit access to monitoring data. The security configuration is a bit different for both.\n\n[[monitoring_jmx]]\n== JMX\nAfter the server installation or in the SVN repository you can find 2 files in the *etc/* directory: *jmx.access* and *jmx.password*.\n\n- *jmx.access* is a user permission file. You can use it to specify whether the user can access the monitoring data for reading only 'readonly' or with read-write 'readwrite' access. There are example entries in the file already and the content may simply look like:\n+\n[source,bash]\n-----\nmonitor readonly\nadmin readwrite\n-----\n\n- *jmx.password* is a user password file. You can set user passwords here and the format again is very simple and the same as for jmx.access. There are example entries already provided for you convenience. Content of the file may look like the example below:\n+\n[source,bash]\n-----\nadmin admin_pass\nmonitor monitor_pass\n-----\n\nUsing above to files you can control who and how can access the JMX monitoring services.\n\n=== SNMP\nAccess to SNMP monitoring is controlled using ACL (access control lists) which can be configured in the file  *snmp.acl* located in *etc/* directory. It contains lots of detailed instructions how to setup ACL and restrict access per user, host and what kind access is allowed. The simplest possible configuration may look like this:\n\n[source,bash]\n-----\nacl = {\n  {\n    communities = public, private\n    access = read-only\n    managers = public.host.com, private.host.com\n  }\n  {\n    communities = admin\n    access = read-write\n    managers = localhost, admin.host.com\n  }\n}\n-----\n\nYou might also need Tigase MIB definition: link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/resources/mib/JVM-MANAGEMENT-MIB.mib[TIGASE-MANAGEMENT-MIB.mib] for the server specific statistics. The MIB contains definition for all the server statistics exposed via SNMP.\n\n=== HTTP\nAccess the server at example.com:9080 and you will be presented with an Agent View.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_66_-_Components_-_F_-_Server_Monitoring_-_2_-_Retrieving_statistics.asciidoc",
    "content": "[[retrievingStatisticsFromTheServer]]\n= Retrieving statistics from the server\n:author: Daniel Wisnewski\n:version: v2.0\n:date: 2015-13-07 11:22\n\n:toc:\n:numbered:\n:website: http://www.tigase.net\n\nBy default we can retrieve server statistics using XMPP, no additional setup is necessary.\n\n== Retrieving statistics using XMPP\n\nAccessing statistics over XMPP protocol requires any XMPP client capable of executing link:http://xmpp.org/extensions/xep-0050.html[XEP-0050: Ad-Hoc Commands]. It's essential to remember, that only administrator (a user whose JID is configured as administrative) can access the statistics.\n\n== Psi XMPP Client\n\nFor the purpose of this guide http://psi-im.org/[Psi] client will be used. After successfully configuring and connecting to account with administrative privileges we need to access _Service Discovery_, either from application menu or from context menu of the particular account account:\n\nimage:images/monitoring_xmpp_1.png[caption=\"Figure 1: \", title=\"Access service discovery\", alt=\"roster-discovery\", width=\"233\"]\n\nIn the _Service Discovery_ window we need to find _Server Statistics_ component:\n\nimage:images/monitoring_xmpp_2.png[caption=\"Figure 2: \", title=\"Access statistics component in service discovery\", alt=\"discovery-stats\", width=\"558\"]\n\nWe can either access statistics for all components or select particular component after expanding the tree. To execute ad-hoc command simply double click on the particular node which will open window with statistics:\n\nimage:images/monitoring_xmpp_3.png[caption=\"Figure 3: \", title=\"Server statistics\", alt=\"server-stats\", width=\"456\"]\n\nIn this window, in addition to see the statistics, we can adjust _Stats level_ by selecting desired level from the list and confim by clicking _Finish_.\n\n\n== Retrieving statistics using JMX\n\nIn order to access statistics over JMX we need to enable support for it in Tigase - xref:monitoring_activation[Monitoring Activation]. Afterwards we can use a number of tools to get to the statistics, for example the following:\n\n== JConsole\n\nAfter opening JConsole we either select local process or provide details of the remote process, including IP, port and credentials from *etc/jmx.** files:\n\nimage:images/monitoring_jmx_jconsole_1.png[caption=\"Figure 4: JConsole\", alt=\"jconsole\", width=\"754\"]\n\nAfterwards we navigate to the MBeans tab from where we can access the `tigase.stats` MBean. It offers similar options to XMPP - either accessing statistics for all components or only for particular component as well as adjusting level for which we want to obtain statistics:\n\nimage:images/monitoring_jmx_jconsole_2.png[caption=\"Figure 5: JConsole\", alt=\"jconsole\", width=\"967\"]\n\n== StatsDumper.groovy\n\nIn order to collect statistics over period of time following groovy script can be used: link:files/StatsDumper.groovy[StatsDumper.groovy]. It's a Simple JMX client that connects to Tigase and periodically saves all statistics to files.\n\nIt takes following parameters:\n[source,bash]\n----\n$ groovy StatsDumper.groovy [hostname] [username] [password] [dir] [port] [delay(ms)] [interval(ms)] [loadhistory(bool)]\n----\n* hostname - address of the instance\n* username - JMX username\n* password - JMX username\n* dir - directory to which save the files with statistics\n* port - port on which to make the connection\n* delay(ms) - initial delay in milliseconds after which statistics should be saved\n* interval(ms) - interval between each retrieval/saving of statistics\n* loadhistory(bool) - indicates whether or not load statistics history from server (if such is enabled in Tigase)\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_67_-_Components_-_F_-_Server_Monitoring_-_3_-_EventBus.asciidoc",
    "content": "[[eventBus]]\n= Eventbus\n:author: Bartosz Malkowski\n:date: 2015-04-09 8:56\n:version: v1.0 September 2015\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nNew for Tigase version 7.1.0, is an *eventbus* component to help with monitoring has been implemented. This allows you to set thresholds for certain predefined tasks and you or other JIDs can be sent a message when those thresholds are passed. You can even configure a mailer extension to have an E-mail sent to system administrators to let them know an event has occured!\nLets begin with setup and requirements.\n\nEventbus is based on a limited http://www.xmpp.org/extensions/xep-0060.html[PubSub] specification. Events are delivered to subscribers as a normal PubSub notification.\n\nEach component or client may subscribe for specific types of events. Only components on cluster nodes are allowed to publish events.\n\n== Setup\nEventbus is enabled by default on v7.1.0 b4001 and later, no setup needed!\n\n== How it Works\nEvents in Eventbus are identified by two elements: name of event and its namespace:\n[source, xml]\n-------\n<EventName xmlns=\"tigase:demo\">\n  <sample_value>1</sample_value>\n</EventName>\n-------\nWhere event name is `EventName` and namespace is `tigase:demo`.\n\nListeners may subscribe for a specific event or for all events with specific a namespace. Because in pubsub, only one node name exists, so we have to add a way to convert the event name and namespace to a node name:\n[source]\n-------\nnodename = eventname + \"|\" + namespace\n-------\nSo for example, to subscribe to `<EventName xmlns=\"tigase:demo\">`, node must be: `EventName|tigase:demo`. If you wish to subscribe to all events with a specific namespace, use an asterisk (`*`) instead of the event name: +*|tigase:demo+.\n\n[NOTE]\n===============================\nIf client is subscribed to /*|tigase:demo node, then events will not be sent from node /*|tigase:demo, but from the *real* node (in this case: `EventName|tigase:demo`).\n===============================\n\n[[availableTasks]]\n== Available Tasks\nEventbus monitoring has several pre-defined tasks that can be monitored and set to trigger. What follows is the list of tasks with the options attributed to each task.\n\n- *disk-task* - Used to check disk usage. +\nAvailable Options\n  . +enabled[B]+ - Enable or disable task, Boolean value.\n  . +period[I]+ - Period of running check, Integer value.\n  . +threshold+ - Percentage of used space on disk, Float value.\n\n- *cpu-temp-task* - Used to check CPU temperature. +\nAvailable Options\n  . +enabled[B]+ - Enable or disable task, Boolean value.\n  . +period[I]+ - Period of running check, Integer value.\n  . +cpuTempThreshold[I]+ - Temperature threshold of CPU in °C.\n\n- *load-checker-task* - Used to check system load. +\nAvailable Options\n. +enabled[B]+ - Enable or disable task, Boolean value.\n. +period[I]+ - Period of running check, Integer value.\n. +averageLoadThreshold[L]+ - Average percent load threshold, Long value.\n\n- *memory-checker-task* - Used to check memory usage. +\nAvailable Options\n. +enabled[B]+ - Enable or disable task, Boolean value.\n. +period[I]+ - Period of running check, Integer value.\n. +maxHeapMemUsagePercentThreshold[I]+ - Alarm when percent of used Heap memory is larger than, Integer value.\n. +maxNonHeapMemUsagePercentThreshold[I]+ - Alarm when percent of used Non Heap memory is larger than, Integer value.\n\n- *logger-task* - Used to transmit log entries depending on level entered. +\n. +enabled[B]+ - Enable or disable task, Boolean value.\n. +levelThreshold+ - Minimal log level that will be the threshold. Possible values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, and ALL.\n\n- *connections-task* - Used to check users disconnections. +\n*NOTE: The event will be generated only if both thresholds (amount and percentage) will be fulfilled.* +\n. +enabled[B]+ - Enable or disable task, Boolean value.\n. +period[I]+ - Period of running check in ms, Integer value.\n. +thresholdMinimal[I]+ - Minimal amount of disconnected users required to generate alarm.\n. +threshold[I]+ - Minimal percent of disconnected users required to generate alarm.\n\n== Configuration\nConfiguration of the eventbus monitor can be done one of two ways; either by lines in init.properties file, or by sending XMPP stanzas to the server.  You may also send XMPP stanzas VIA HTTP REST.\nXMPP stanza configurations will override ones in init.properties, but they will only last until the server restarts.\n\n=== init.properties\nTasks can be configured in the init.properties file. See xref:availableTasks[available tasks] for the tasks that can be setup.\n\nTo enable a specific monitor task, use the following line:\n-----\nmonitor/$TASKNAME/enabled[B]=true\n-----\nWhere monitor is the component name for tigase.monitor.MonitorComponent, and $TASKNAME is one of the xref:availableTasks[available task names].\n\nThis format will be the same for other settings for tasks.  For example:\n-----\nmonitor/$TASKNAME/period[I]=1000\n-----\nwhich sets the check period to 1000 milliseconds.\n\n*NOTE* Once triggers have been activated, they will become dormant.  Think of these as one-shot settings.\n\n==== Subscription Limitations\nTo define list of JIDs allowed to subscribe for events:\n[source, bash]\n-----\neventbus/affiliations/allowedSubscribers=francisco@denmark.lit,bernardo@denmark.lit\n-----\nIf this is left blank, all users can subscribe.\n\n=== Configuration via XMPP\nWe can also configure the eventbus monitor component using XMPP stanzas. This allows us to set and change configurations during server runtime. This is done using a series of +iq+ stanzas send to the monitor component.\n\nWe can query each component for its current settings using the following stanza.\n[source,xml]\n-----\n<iq type=\"set\" to=\"monitor@$DOMAIN/disk-task\" id=\"aad0a\">\n<command xmlns=\"http://jabber.org/protocol/commands\" node=\"x-config\"/>\n</iq>\n-----\n\nThe server will return the component current settings which will make things easier if you wish to edit them. In this case, the server has returned the following to us\n[source,xml]\n-----\n<iq from=\"monitor@$DOMAIN/disk-task\" type=\"result\" id=\"aad0a\" to=\"alice@coffeebean.local/Psi+\">\n<command xmlns=\"http://jabber.org/protocol/commands\" status=\"executing\" node=\"x-config\" sessionid=\"0dad3436-a029-4082-b0e0-04d838c6c0da\">\n<x xmlns=\"jabber:x:data\" type=\"\">\n<title>Task Configuration</title>\n<instructions/>\n<field type=\"boolean\" label=\"Enabled\" var=\"x-task#enabled\">\n<value>0</value>\n</field>\n<field type=\"text-single\" label=\"Period [ms]\" var=\"x-task#period\">\n<value>60000</value>\n</field>\n<field type=\"text-single\" label=\"Disk usage ratio threshold\" var=\"threshold\">\n<value>0.8</value>\n</field>\n</x>\n</command>\n</iq>\n-----\nThis tells us that the disk-task setting is not active, has a period of 60000ms, and will trigger when disk usage is over 80%.\n\nTo send new settings to the monitor component, we can send a similar stanza back to the monitor component.\n\n[source,xml]\n-----\n<iq type=\"set\" to=\"monitor@$DOMAIN/disk-task\" id=\"aad1a\">\n<command xmlns=\"http://jabber.org/protocol/commands\" node=\"x-config\" sessionid=\"0dad3436-a029-4082-b0e0-04d838c6c0da\">\n<x xmlns=\"jabber:x:data\" type=\"submit\">\n<field type=\"boolean\" var=\"x-task#enabled\">\n<value>0</value>\n</field>\n<field type=\"text-single\" var=\"x-task#period\">\n<value>60000</value>\n</field>\n<field type=\"text-single\" var=\"threshold\">\n<value>0.8</value>\n</field>\n</x>\n</command>\n</iq>\n-----\n\nTo which a successful update will give you an XMPP success stanza to let you know everything is set correctly.\n\n(Include what the response will be from this setting!)\n\nAlternatively, you can update specific settings by editing a single field without adding anything else. For example, if we just wanted to turn the +disk-task+ on we could send the following stanza:\n\n[source,xml]\n-----\n<iq type=\"set\" to=\"monitor@$HOSTNAME/disk-task\" id=\"ab53a\">\n<command xmlns=\"http://jabber.org/protocol/commands\" node=\"x-config\">\n<x xmlns=\"jabber:x:data\" type=\"submit\">\n<field type=\"boolean\" var=\"x-task#enabled\">\n<value>1</value>\n</field>\n</x>\n</command>\n</iq>\n-----\n\nTo set any other values, do not forget that certain parts may need to be changed, specifically the\n*<field type=\"boolean\" var=x-task#enabled\">*  fields. +\n- Your field type will be defined by the type of variable specified in the xref:availableTasks [Available Tasks] section. +\n- +var=x task#+ will be followed by the property value taken directly from the xref:availableTasks [Available Tasks] section, minus the data type parameter.\n\n== Getting the Message\nWithout a place to send messages to, eventbus will just trigger and shut down. There are two different methods that eventbus can deliver alarm messages and relevant data; XMPP messages and using the mailer extension.\n\n=== XMPP notification\nIn order to retrieve notifications, a subscription to the +eventbus@tigase.org+ user must be made.\nKeep in mind that subscriptions are not persistent across server restarts, or triggers. +\nThe eventbus schema is very similar to most XMPP subscription requests but with a few tweaks to differentiate it if you wanted to subscribe to a certain task or all of them. Each task is considered a node, and each node has the following pattern: +eventName|eventXMLNS+. Since each monitoring task has the +tigase:monitor:event+ event XMLNS, we just need to pick the event name from the list of tasks.\nSo like the above example, our event node for the disk task will be +disk-task|tigase:monitor:event+.\nApplied to an XMPP stanza, it will look something like this:\n[source,xml]\n-----\n<iq type='set'\n    to='eventbus@tigase.org'\n    id='sub1'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub'>\n    <subscribe node='disk-taskEvent|tigase:monitor:event' jid='$USER_JID'/>\n  </pubsub>\n</iq>\n-----\nDon't forget to replace $USER_JID with the bare JID of the user you want to receive those messages. You can even have them sent to a MUC or any component with a JID.\nAvailable events are as follows:\n- disk-taskEvent for +disk-task+\n- LoggerMonitorEvent for +logger-task+\n- HeapMemoryMonitorEvent for +memory-checker-task+\n- LoadAverageMonitorEvent for +load-checker-task+\n- CPUTempMonitorEvent for +cpu-temp-task+\n- UsersDisconnected for +connections-task+\n\nAlternatively, you can also subscribe to all events within the eventbus by using a wildcard * in place of the event XMLNS like this example:\n[source,xml]\n-----\n<iq type='set'\n    to='eventbus@tigase.org'\n    id='sub1'>\n  <pubsub xmlns='http://jabber.org/protocol/pubsub'>\n    <subscribe node='*|tigase:monitor:event' jid='$USER_JID'/>\n  </pubsub>\n</iq>\n-----\n\n=== Sample notification from Eventbus\n[source, xml]\n-------\n<message from='eventbus.shakespeare.lit' to='francisco@denmark.lit' id='foo'>\n  <event xmlns='http://jabber.org/protocol/pubsub#event'>\n    <items node='EventName|tigase:demo'>\n      <item>\n        <EventName xmlns=\"tigase:demo\" eventSource=\"samplecomponent.shakespeare.lit'\" eventTimestamp=\"1444216850\">\n          <sample_value>1</sample_value>\n        </EventName>\n      </item>\n    </items>\n  </event>\n</message>\n-------\n\n[[monitorMailer]]\n== Mailer Extension\nTigase Server Monitor Mailer Extension (TSMME) can send messages from the monitor component to a specified E-mail address so system administrators who are not logged into the XMPP server.\n\nFor v7.1.0 versions and later, TSMME is already included in your distribution package and no extra installation is needed.\n\nFor versions older than 7.1.0 TSMME requires two files to operate:\n\n- A compiled build of tigase mailer from link:https://projects.tigase.org/projects/tigase-server-ext-mailer/repository[its repository]. Place the compiled .jar file into /jars directory.\n\n- javax.mail.jar file which may be downloaded from link:http://java.net/projects/javamail/downloads/download/javax.mail.jar[this link]. Also place this file in the /jars directory.\n\n[source,properties]\n-----\nmonitor/mailer-smtp-host=mail.tigase.org\nmonitor/mailer-smtp-port=587\nmonitor/mailer-smtp-username=sender\nmonitor/mailer-smtp-password=********\nmonitor/mailer-from-address=sender@tigase.org\nmonitor/mailer-to-addresses=receiver@tigase.org,admin@tigase.org\n-----\n\n- +monitor/mailer-smtp-host+ - SMTP Server hostname.\n- +monitor/mailer-smtp-port+ - SMTP Server port.\n- +monitor/mailer-smtp-usernam+ - name of sender account.\n- +monitor/mailer-smtp-password+ - password of sender account.\n- +monitor/mailer-from-address+ - sender email address. It will be set in field from in email.\n- +monitor/mailer-to-addresses+ - comma separated notification receivers email addresses.\n\nIt is recommended to create a specific e-mail address in your mail server for this purpose only, as the account settings are stored in plaintext without encryption.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_68_-_Components_-_G_-_Server_to_Server_Protocol.asciidoc",
    "content": "[[v5xs2sps]]\n= Server to Server Protocol Settings\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-06-29 21:27\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase server *5.1.0* or later offers new, rewritten from scratch, implementation for s2s communication which allows you to tweak it's configuration to get a better performance in your installation.\n\nS2S (or server to server) protocol is enabled by default with optimal settings chosen. There are however, a set of configuration parameters you can adjust the server behavior to achieve optimal performance on your installation.\n\nThis documents describes following elements of the Tigase server configuration:\n\n. Number of concurrent connections to external servers\n. The connection throughput parameters\n. Maximum waiting time for packets addressed to external servers and the connection inactivity time\n. Custom plugins selecting connection to the remote server\n\n== Number of Concurrent Connections\nNormally only one connection to the remote server is required to send XMPP stanza to that server. In some cases however, under a high load, you can get much better throughput and performance if you open multiple connections to the remote server.\n\nThis is especially true when the remote server works in a cluster mode. Ideally you want to open a connection to each of the cluster nodes on the remote server. This way you can spread the traffic evenly among cluster nodes and improve the performance for s2s connections.\n\nTigase server offers 2 different parameters to tweak the number of concurrent, s2s connections:\n\n- 'max-out-total-conns' - the property specifies the maximum outgoing connections the Tigase server opens to any remote XMPP server. This is 'per domain' limit, which means that this limit applies to each of the remote domains Tigase connects to. If it is set to '4' then Tigase opens a maximum of 4 connections to 'jabber.org' plus maximum 4 connections to 'muc.jabber.org' even if this is the same physical server behind the same IP address.\n+\nTo adjust the limit you have to add following line to the +init.properties+ file:\n+\n[source,bash]\n-----\ns2s/max-out-total-conns[I]=2\n-----\n\n- 'max-out-per-ip-conns' - the property specifies the maximum outgoing connections Tigase server opens to any remote XMPP server to its single IP address. This too, is 'per domain' limit, which means that this limit applies to each of the remote domains Tigase connects to. If it is set to '1', and the above limit is set to '4', and the remote server is visible behind 1 IP address, then Tigase opens a maximum of 1 connection to 'jabber.org' plus a maximum of 1 connection to 'muc.jabber.org' and other subdomains.\n+\nTo adjust the limit you have to add following line to the init.properties file:\n+\n[source,bash]\n-----\ns2s/max-out-per-ip-conns[I]=2\n-----\n\n== Connection Throughput\nOf course everybody wants his server to run with maximum throughput. This comes with a cost on resources, usually increased memory usage. This is especially important if you have large number of s2s connections on your installations. High throughput means lots of memory for network buffers for every single s2s connection. You may soon run out of all available memory.\n\nThere is one configuration property which allows you to adjust the network buffers for s2s connections to lower your memory usage or increase data throughput for s2s communication.\n\nMore details about are available in the init.properties guide under the link to +--net-buff-high-throughput+ property description.\n\n== Maximum Packet Waiting Time and Connection Inactivity Time\nThere are 2 timeouts you can set for the component controlling s2s communication.\n\n- 'max-packet-waiting-time' - this sets the maximum time for the packets waiting for sending to some remote server. Sometimes, due to networking problems or DNS problems it might be impossible to send message to remote server right away. Establishing a new connection may take time or there might be communication problems between servers or perhaps the remote server is restarted. Tigase will try a few times to connect to the remote server before giving up. This parameter specifies how long the packet is waiting for sending before it is returned to the sender with an error. The timeout is specified in seconds:\n+\n[source,bash]\n-----\ns2s/max-packet-waiting-time[L]=420\n-----\n\n- 'max-inactivity-time' - this parameters specifies the maximum s2s connection inactivity time before it is closed. If a connection is not in use for a long time, it doesn't make sense to keep it open and tie resources up. Tigase closes s2s connection after specified period of time and reconnects when it is necessary. The timeout is specified in seconds:\n+\n[source,bash]\n-----\ns2s/max-inactivity-time[L]=900\n-----\n\n== Custom Plugin: Selecting s2s Connection\nSometimes for very large installations you may want to set larger number of s2s connections to remote servers, especially if they work in cluster of several nodes. In such a case you can also have a control over XMPP packets distribution among s2s connections to a single remote server.\n\nThis piece of code is pluggable and you can write your own connection selector. It is enough to implement 'S2SConnectionSelector' interface and set your class name in the configuration using following parameter in +init.properties+ file:\n\n[source,bash]\n-----\ns2s/s2s-conn-selector=YourSelectorImplementation\n-----\n\nThe default selector picks connections randomly.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_69_-_Components_-_H_-_MUC.asciidoc",
    "content": "[[tigaseMUC]]\n= Tigase MUC Component\n:author: not known\n:version: v1.0 October 2015\n:date: 2015-10-01 15:00\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nTigase MUC component is included in all Tigase distributions, to enable MUCs have the following lines in your +init.properties+ file:\n\n-----\n--comp-name-4 = muc\n--comp-class-4 = tigase.muc.MUCComponent\n-----\n\n== Configuration Options\n- *room-log-directory* +\nDirectory to store chat logs\n-----\nmuc/room-log-directory=/var/log/muc/\n-----\n\n- *message-filter-enabled* +\nTo disable filter and allow MUC transfer all subelements in <message/> set:\n-----\nmuc/message-filter-enabled[B]=false\n-----\n\nFor example, this allows users to send XHTML stanzas through MUC chatrooms on your server.\n\n- *presence-filter-enabled* +\nTo disable filter and allow MUC transfer all subelements in <presence/> set:\n-----\nmuc/presence-filter-enabled[B]=false\n-----\n\n- *search-ghosts-every-minute* +\nTo enable pinging occupants every minute\n-----\nmuc/search-ghosts-every-minute[B]=true\n-----\n\n- *ghostbuster-enabled* +\nTo disable active searching of ghosts in MUC Rooms:\n-----\nmuc/ghostbuster-enabled[B]=false\n-----\n\n- *muc-allow-chat-states* +\nTo allow transfer of chat-states in MUC messages:\n-----\nmuc/muc-allow-chat-states[B]=true\n-----\n\n- *muc-lock-new-room* +\nTo turn off default locking newly created rooms:\n-----\nmuc/muc-lock-new-room[B]=false\n-----\nBy default new room will be locked until owner submit room configuration.\n\n- *muc-multi-item-allowed*\nTo disable joining from few resources to sinlge nickname:\n-----\nmuc/muc-multi-item-allowed[B]=false\n-----\n\n=== History Providers Parameters\n- *history-db* +\nDatabase type. By default the same what is used as User Repository in Server.\nProvided types: +derby+, +mysql+, +memory+, +pgsql+, +sqlserver+, +none+.\n-----\nmuc/history-db=none\n-----\n\n- *history-db-uri* +\nURI for database, if should be used different than default from Tigase Server:\n-----\nmuc/history-db-uri=jdbc:derby:/database/tigasedbmuc\n-----\n\n=== Public log\n- *muc-logger-class* +\nTo set custom class for MUC logger:\n-----\nmuc/muc-logger-class=com.example.CustomLogger\n-----\nClass must implment interface +tigase.muc.logger.MucLogger+.\n\n=== Modules\nEach module can be configured to use custom implementation by including it in the init.properties, the defaults are as follows:\n[source,properties]\n-----\nmuc/modules/jabber:iq:version[S]=tigase.component.modules.impl.JabberVersionModule\nmuc/modules/owner[S]=tigase.muc.modules.RoomConfigurationModule\nmuc/modules/presences[S]=tigase.muc.modules.PresenceModuleImpl\nmuc/modules/groupchat[S]=tigase.muc.modules.GroupchatMessageModule\nmuc/modules/invitations[S]=tigase.muc.modules.MediatedInvitationModule\nmuc/modules/urn:xmpp:ping[S]=tigase.component.modules.impl.XmppPingModule\nmuc/modules/unique[S]=tigase.muc.modules.UniqueRoomNameModule\nmuc/modules/disco[S]=tigase.muc.modules.DiscoveryModule\nmuc/modules/iqforwarder[S]=tigase.muc.modules.IqStanzaForwarderModule\nmuc/modules/admin[S]=tigase.muc.modules.ModeratorModule\nmuc/modules/privatemessages[S]=tigase.muc.modules.PrivateMessageModule\nmuc/modules/commands[S]=tigase.component.modules.impl.AdHocCommandModule\n-----\n\n[[mucRoomConfig]]\n=== Room Configuration options\nIn addition to the default Room configuration options defined in the MUC specification Tigase offers following as well:\n\nTigase MUC Options::\n- tigase#presence_delivery_logic - allows configuring logic determining which presence should be used by occupant in the room while using multiple-resource connections under one nickname, following options are available:\n  * PREFERE_PRIORITY\n  * PREFERE_LAST\n- tigase#presence_filtering - (boolean) when enabled broadcasts presence only to selected affiliation groups\n- tigase#presence_filtered_affiliations - when enabled tigase#presence_filtering is enabled one can select affiliation which should receive presences, following are possible to select from:\n  * owner\n  * admin\n  * member\n  * none\n  * outcast\n- muc#roomconfig_maxusers - Allows configuring of maximum users of room.\n\n\nConfiguring default room configuration in init.properties::\n-----\nmuc/default_room_config/<option>=<value>\n-----\nfor example:\n-----\nmuc/default_room_config/tigase#presence_delivery_logic=PREFERE_LAST\n-----\n\nConfiguration per-room::\nPer room configuration is done using IQ stanzas defined in the specification, for example:\n[source,xml]\n-----\n<iq type=\"set\" to=\"roomname@muc.domain\" id=\"config1\">\n    <query xmlns=\"http://jabber.org/protocol/muc#owner\">\n        <x xmlns=\"jabber:x:data\" type=\"submit\">\n            <field type=\"boolean\" var=\"tigase#presence_filtering\">\n                <value>1</value>\n            </field>\n            <field type=\"list-multi\" var=\"tigase#presence_filtered_affiliations\">\n                <value>owner</value>\n            </field>\n        </x>\n    </query>\n</iq>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_70_-_Components_-_I_-_Tigase_Load_Balancing.asciidoc",
    "content": "[[loadBalancing]]\n= Tigase Load Balancing\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-06-10 15:49\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nStarting with version 5.2.0 Tigase introduces a load balancing functionality allowing users to be redirected to the most suitable cluster node. Functionality relies on a see-other-host XMPP stream error message. The basic principle behind the mechanism is that user will get redirect if the host returned by the implementation differ from the host to which user currently tries to connect. It is required that the user JID to be known for the redirection to work correctly.\n\n== Available Implementations\nTigase implementation is, as usual, extensible and allows for different, pluggable redirection strategies that implement the `SeeOtherHostIfc` interface.\n\nCurrently there are three strategies available:\n\n- `SeeOtherHost` - most basic implementation returning either single host configured in init.properties file or name of the current host;\n- `SeeOtherHostHashed` (default) - default implementation for cluster environment of SeeOtherHostIfc returning redirect host based on the hash value of the user's JID; list of the available nodes from which a selection would be made is by default composed and reflects all connected nodes, alternatively hosts list can be configured in the init.properties;\n- `SeeOtherHostDB` - extended implementation of SeeOtherHost using redirect information from database in the form of pairs user_id and node_id to which given user should be redirected.\n\n== Configuration Options\nThe most basic configuration is related to the choice of actual redirection implementation:\n\n[source,bash]\n----\n--cm-see-other-host=\n----\n\n\nPossible values are:\n\n- `tigase.server.xmppclient.SeeOtherHost`\n- `tigase.server.xmppclient.SeeOtherHostHashed`\n- `tigase.server.xmppclient.SeeOtherHostDB`\n- `tigase.server.xmppclient.SeeOtherHostDualIP`\n- `none` - disables redirection\n\nAll the remaining options are configured on a per-connection-manager basis, thus all options need to be prefixed with the corresponding connection manager ID, i.e. c2s, bosh or ws; we will use c2s in the examples:\n\n- `c2s/cm-see-other-host/default-host=host1;host2;host3` - a semicolon separated list of hosts to be used for redirection;\n- `c2s/cm-see-other-host/active=OPEN;LOGIN` - a semicolon separated list of phases in which redirection should be active, currently possible values are:\n  * `OPEN` which enables redirection during opening of the XMPP stream;\n  * `LOGIN` which enables redirection upon authenticating user session;\n\nBy default redirection is currently enabled only in the `OPEN` phase.\n\n=== SeeOtherHostDB\nFor `SeeOtherHostDB` implementation there are additional options:\n\n- `c2s/cm-see-other-host/db-url` - a JDBC connection URI which should be used to query redirect information; if not configured --user-db-uri will be used;\n- `c2s/cm-see-other-host/get-host-query` - a SQL query which should return redirection hostname;\n- `c2s/cm-see-other-host/get-all-data-query` - a SQL helper query which should return all redirection data from database;\n- `c2s/cm-see-other-host/get-all-query-timeout` - allows to set timeout for executed queries.\n\n=== SeeOtherHostDualIP\nThis mechanisms matches internal Tigase cluster nodes with against the lookup table to provide matching and relevant redirection hostname/IP. By default internal Tigase `cluster_nodes` table will be used (and appropriate repository implementation will be used).\n\nTo enable this redirection mechanism following configuration / class should be used:\n\n[source,bash]\n----\n--cm-see-other-host=tigase.server.xmppclient.SeeOtherHostDualIP\n----\n\nIt's possible to configure it on per-connection-manager basis\n[source,bash]\n----\n<connector>/cm-see-other-host[S]=tigase.server.xmppclient.SeeOtherHostDualIP\n----\n\nIt offers following configuration options:\n\n- `data-source` - configuration of the source of redirection information - by default internal Tigase `cluster_nodes` table will be used (and appropriate repository implementation will be used); alternatively it's possible to use `eventbus` source;\n- `db-url` - a JDBC connection URI which should be used to query redirect information; if not configured `--user-db-uri` will be used;\n- `get-all-data-query` - a SQL helper query which should return all redirection data from database;\n- `get-all-query-timeout` - allows to set timeout for executed queries;\n- `fallback-redirection-host` - if there is no redirection information present (i.e. secondary hostname is not configured for the particular node) redirection won't be generated; with this it's possible to configure fallback redirection address.\n\n\nAll options can be configured either globally (without providing type parameter)\n[source,bash]\n----\n--cm-see-other-host/db-url=jdbc:<database>://<uri>\n--cm-see-other-host/data-source=<class implementing tigase.server.xmppclient.SeeOtherHostDualIP.DualIPRepository>\n--cm-see-other-host/get-all-data-query=select * from cluster_nodes\n--cm-see-other-host/get-all-query-timeout=10\n--cm-see-other-host/fallback-redirection-host=<hostname>\n----\n\nor on per-component basis\n[source,bash]\n----\n<connector>/cm-see-other-host/db-url[S]=jdbc:<database>://<uri>\n<connector>/cm-see-other-host/data-source[S]=<class implementing tigase.server.xmppclient.SeeOtherHostDualIP.DualIPRepository>\n<connector>/cm-see-other-host/get-all-data-query[S]=select * from cluster_nodes\n<connector>/cm-see-other-host/get-all-query-timeout[I]=10\n<connector>/cm-see-other-host/fallback-redirection-host[S]=<hostname>\n----\n\n==== EventBus as a source of information\nIt's possible to utilize EventBus and internal Tigase events as a source of redirection data. In order to do that `eventbus` should be used as a value of `data-source` configuration option. In addition, EventBus events needs to be enabled in ClusterConnectionManager. Example configuration:\n\n[source,bash]\n----\ncl-comp/eventbus-repository-notifications[B]=true\n--cm-see-other-host/data-source=eventbus\n----\n\nor on per-component basis:\n\n[source,bash]\n----\ncl-comp/eventbus-repository-notifications[B]=true\n<connector>/cm-see-other-host/data-source[S]=eventbus\n----\n\n== Auxiliary setup options\n=== Enforcing redirection\nIt's possible to enforce redirection of connections on the particular port of connection manager with `force-redirect-to` set to Integer with the following general setting option:\n[source,bash]\n----\n<connection_manager>/connections/<listening_port>/force-redirect-to[I]=<destination_port>\n----\n\nfor example, enable additional port `5322` for `c2s` connection manager and enforce all connections to be redirected to port `5222` (it will utilize hostname retrieved from `SeeOtherHost` implementation and will be only used when such value is returned):\n[source,bash]\n----\nc2s/connections/ports[i]=5222,5322\nc2s/connections/5322/type[S]=accept\nc2s/connections/5322/socket[S]=plain\nc2s/connections/5322/force-redirect-to[I]=5222\n----\n\n=== Configuring hostnames\nTo fully utilize `SeeOtherHostDualIP` setup in automated fashion it's now possible to provide both primary (_internal_) and secondary (_external_) hostname/IP (they need to be correct, `InetAddress.getByName( property );` will be used to verify correctnes). It can be done via JVM properties `tigase-primary-address` and `tigase-secondary-address`. You can also utilize different implementation of DNS resolver by providing class implementing `tigase.util.DNSResolverIfc` interface as value to `resolver-class` property.\nThose properties can be set via `etc/tigase.conf` (uncommenting following lines, or manually exposing in environment):\n[source,bash]\n----\nDNS_RESOLVER=\" -Dresolver-class=tigase.util.DNSResolverDefault \"\n\nINTERNAL_IP=\" -Dtigase-primary-address=hostname.local \"\nEXTERNAL_IP=\" -Dtigase-secondary-address=hostname \"\n----\n\nor in the `etc/init.properties` (they will be converted to JVM properties):\n[source,bash]\n----\n--tigase-resolver-class=tigase.util.DNSResolverDefault\n\n--tigase-primary-address=hostname.local\n--tigase-secondary-address=hostname\n----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_71_-_Components_-_J_-_External_Component_Configuration.asciidoc",
    "content": "[[externalComponentConfiguration]]\n= External Component Configuration\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nIn Tigase server version 4.4.x and later a new implementation for connecting external components has been introduced.\n\nIt is much simpler to setup and follows the same configuration standards as all other components. It is also much more powerful as a single instance can control many TCP/IP ports and many external components on each port and even allows for multiple connections for the same component. It supports both XEP-0114 and XEP-0225 with protocol auto-detection mechanisms. Protocols are pluggable so in future more protocols can be supported or custom extensions to existing protocols can be added.\n\nThe implementation also supports a scripting API and new domains with passwords can be added at run-time using ad-hoc commands. New scripts can be loaded to even further control all connected external components.\n\nEven though it is much simpler to setup and to use it also offers a lot of new functionality and features. Pages in this guide describe in details all the administration aspects of setting up and managing external components.\n\n- xref:tigase4xbasicConfiguration[Basic Configuration Options] (External Component)\n- xref:tigase4xexternalComponent[Tigase as an External Component]\n- xref:loadBalancingExternalComponent[Load Balancing External Components in Cluster Mode]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_72_-_Components_-_J_-_External_Component_Configuration_-_1_-_Basic_Configuration_Options_(external_component).asciidoc",
    "content": "[[tigase4xbasicConfiguration]]\n= Basic Configuration Options (External Component)\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:vesion: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nAs for all Tigase components you can load it and configure it via +init.properties+ file described in details in another guide. This document describes how to load the component and set the initial configuration to accept or initiate connections for an external component.\n\nFirst thing to do is to specify the component class and the component name which must be unique within the Tigase installation. The most commonly name used is +ext+ and the class is +tigase.server.ext.ComponentProtocol+.\n\nFollowing 2 lines in the +init.properties+ will load the component during the server startup time:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n-----\n\nWhile this would load the component, there are no additional configurations provided to the component would be practically useless. It is possible to add necessary parameters (external domains, passwords) during run-time via ad-hoc commands. It is generally a good practice to provide some initial parameters in the configuration file too.\n\nThere are two additional properties used for setting initial configuration for external components connections: --external and --bind-ext-hostnames.\n\nThese two properties are very well described on the online documentation, therefore I will focus on practical and working examples here.\n\n== Simple Case\nThe most common scenario is to connect an external component which works for a specific given domain to the main server. The component authenticates with a defined password and the external component connects to a TCP/IP port the server listens on.\n\nFor example let's say our server works for a virtual domain: +devel.tigase.org+. We want it to listen on port +5270+ for incoming connections from an external component working for a domain: +muc.devel.tigase.org+. The authentication password for the domain is +muc-secret+.\n\nFor such a scenario we need 3 lines in the +init.properties+ file:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.devel.tigase.org:muc-secret:listen:5270\n-----\n\n== More External Components/Domains\nSuppose you want to connect more than one external component. Let's say you want to connect PubSub and MSN components to Tigase server as well.\n\nIn that case you don't have to open another port on the server, all the components can connect to the same port. Of course each of the components connect for a different domain and probably should use a different password.\n\nLet's say then that we want Tigase server accept two more domains with corresponding passwords: (pubsub.devel.tigase.org:pubsub_pass) and (msn.devel.tigase.org:msn_pass). Your configuration properties should look like this:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.devel.tigase.org:muc-secret:listen:5270, \\\n    pubsub.devel.tigase.org:pubsub_pass, \\\n    msn.devel.tigase.org:msn_pass\n-----\n\n_Please note, the --external property with value should be written in a single line. The above example has split the line for readability._\n\n== More TCP/IP Ports\nYou can make Tigase listen on more than one TCP/IP port for incoming external component connections. Please be aware that there is no way, currently to bind an external component to a particular port. If Tigase listens on two or more ports it accepts any external component on any of the ports. Therefore there is no practical reason for opening more than one port.\n\nHowever, if for some reason you need Tigase to listen on more ports then this is an example configuration:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.devel.tigase.org:muc-secret:listen:5270, \\\n   pubsub.devel.tigase.org:pubsub_pass:listen:5271, \\\n   msn.devel.tigase.org:msn_pass:listen:5272\n-----\n\n_Please note, the --external property with value should be written in a single line. The above example has split the line for readability._\n\nThese settings set three TCP/IP ports to listen on: 5270, 5271 and 5272. They also specify 3 different external domains with passwords which are accepted by Tigase. Even though each port is specified with conjunction with a domain they are not bound together in any way. Any of specified domains can connect through any of specified ports.\n\n== Outgoing Connections\nTigase server can not only accept connections from external components, it can also open connections to external components.\n\nTo make Tigase connect to an external component you have to change 'listen' parameter to 'connect' and of course you have to tell where to connect - the address of the external component:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = devel.tigase.org:muc-secret:connect:5270:muc.devel.tigase.org\n-----\n\nAssuming the MUC component listens on the port '5270' at the DNS address: 'muc.devel.tigase.org' Tigase will connect to the component.\n\nYou can of course set as many as you need external components to which you want Tigase to connect to:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = devel.tigase.org:mucsecret:connect:5270:muc.devel.tigase.org, \\\n  devel.tigase.org:pubsub_pass:connect:5271:pubsub.devel.tigase.org, \\\n  devel.tigase.org:msn_pass:connect:5272:msn.devel.tigase.org\n-----\n\nIf external components run on a separate machines you can use the same port number for each of them.\n\n== Specifying Protocol\nOne of the last parameters you can set for the external component/domain is a protocol which should be used for the connection. At the moment the Tigase server supports two protocols defined in link:http://xmpp.org/extensions/xep-0114.html[XEP-0114] and link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] and possibly further protocols.\n\nYou don't have to specify a protocol if you setup a connection in 'listen' mode as the server automatically detects a protocol which is used in incoming connections.\n\nYou can specify the protocol which is used for outgoing connections but you have to add one more parameters to the connection string.\n\nThere are two possibilities:\n\n. 'accept' which is an identifier for protocol defined in link:http://xmpp.org/extensions/xep-0114.html[XEP-0114] (and is default if you do not specify anything)\n. 'client' which is identifier for protocol defined in link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] and is based on the client-to-server protocol.\n\nAn example configuration with protocol specified:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = devel.tigase.org:mucsecret:connect:5270:muc.devel.tigase.org:accept, \\\n  devel.tigase.org:pubsub_pass:connect:5270:pubsub.devel.tigase.org:client\n-----\n\nIt defines two outgoing connections to external protocols, the first uses the link:http://xmpp.org/extensions/xep-0114.html[XEP-0114] protocol and the second uses the link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] protocol.\n\n== Load Balancer Plugin\nThe last option you can set for external component connections is load balancer class.\n\nThe load balancer plugin is used if you have multiple connections for the same component (external domain name) and you want to spread the load over all connections. Perhaps you have an installation with huge number of MUC rooms and you want to spread the load over all MUC instances.\n\nAn example configuration with load balancer plugin specified:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.devel.tigase.org:mucsecret:listen:5270:devel.tigase.org:accept:ReceiverBareJidLB, \\\n  pubsub.devel.tigase.org:pubsub_pass:listen:5270:devel.tigase.org:accept:SenderBareJidLB\n-----\n\nIt defines two listeners for external component with different load balancer plugins. The first load-balance traffic by a packet destination BareJID, which makes sense for MUC component. This way each MUC instance handles a different set of rooms which allows for a good load distribution.\n\nFor the PubSub component we use a different load balancer plugin which distributes load by the sender BareJID instead. This is because for the PubSub destination BareJID is always the same so we cannot use it to distribute the load.\n\nEither the *ReceiverBareJidLB* or *SenderBareJidLB* are class names from package: *tigase.server.ext.lb* however, you can use any class name as a plugin, you just have to provide a full class name and the class name must implement *LoadBalancerIfc* interface.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_73_-_Components_-_J_-_External_Component_Configuration_-_2_-_Tigase_as_External_Component.asciidoc",
    "content": "[[tigase4xexternalComponent]]\n= Tigase as an External Component\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThere are cases when you want to deploy one or more Tigase components separately from the main server, or perhaps you want to run some Tigase components connecting to a different XMPP server, or perhaps you work on a component and you do not want to restart the main server every time you make a change.\n\nThere is a way to run the Tigase server in \"external component mode\". In fact you can run any of Tigase's components as an external component and connect them to the main XMPP server either via link:http://xmpp.org/extensions/xep-0114.html[XEP-0114] or link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] connection.\n\nLet's look at the examples...\n\n== A Simple Case - MUC as an External Component\nA few assumptions:\n\n. We want to run a MUC component for a domain: 'muc.devel.tigase.org' and password 'muc-pass'\n. The main server works at an address: devel.tigase.org and for the same virtual domain\n. We want to connect to the server using link:http://xmpp.org/extensions/xep-0114.html[XEP-0114] protocol and port '5270'.\n\nThere is a special configuration type for this case which simplifies setting needed to run Tigase as an external component:\n\n[source,bash]\n-----\nconfig-type=--gen-config-comp.\n-----\n\nThis generates a configuration for Tigase with only one component loaded by default - the component used for external component connection. If you use this configuration type, your init.properties file may look like this:\n\n[source,bash]\n-----\nconfig-type = --gen-config-comp\n--debug = server\n--user-db = derby\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:derby:/tigasedb\n--virt-hosts = devel.tigase.org\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:accept\n-----\n\nPlease note, you do not need lines:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n-----\n\nas the\n\n[source,bash]\n-----\n--gen-config-comp\n-----\n\nautomatically includes them.\n\n== More Components\nSuppose you want to run more than one component as an external components within one Tigase instance. Let's add another - PubSub component to the configuration above and see how to set it up.\n\nThe most straightforward way is just to add another component and another connection to the main server for the component domain:\n\n[source,bash]\n-----\nconfig-type = --gen-config-comp\n--debug = server\n--user-db = derby\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:derby:/tigasedb\n--virt-hosts = devel.tigase.org\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--comp-name-2 = pubsub\n--comp-class-2 = tigase.pubsub.PubSubComponent\n--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:accept, \\\n  pubsub.devel.tigase.org:pubsub-pass:connect:5270:devel.tigase.org:accept\n-----\n\nPlease note however that we are opening two connections to the same server. This can waste resources and overcomplicate the system. For example, what if we want to run even more components? Opening a separate connection for each component is a tad overkill.\n\nIn fact there is a way to reuse the same connection for all component domains running as an external component. The property '--bind-ext-hostnames' contains a comma separated list of all hostnames (external domains) which should reuse the existing connection.\n\nThere is one catch however. Since you are reusing connections (hostname binding is defined in link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] only), you must use this protocol for the functionality.\n\nHere is an example configuration with a single connection over the link:http://xmpp.org/extensions/xep-0225.html[XEP-0225] protocol used by both external domains:\n\n[source,bash]\n-----\nconfig-type = --gen-config-comp\n--debug = server\n--user-db = derby\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:derby:/tigasedb\n--virt-hosts = devel.tigase.org\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--comp-name-2 = pubsub\n--comp-class-2 = tigase.pubsub.PubSubComponent\n--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:client\n--bind-ext-hostnames=pubsub.devel.tigase.org\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_74_-_Components_-_J_-_External_Component_Configuration_-_3_-_Load_Balancing_External_Components_in_Cluster_Mode.asciidoc",
    "content": "[[loadBalancingExternalComponent]]\n= Load Balancing External Components in Cluster Mode\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2011-07-09 22:45\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThis document describes how to load balance any external components using Tigase XMPP Server and how to make Tigase's components work as external components in a cluster mode.\n\n_Please note, all configuration options described here apply to Tigase XMPP Server version 5.1.0 or later._\n\nThese are actually 2 separate topics:\n\n. One is to distribute load over many instances of a single component to handle larger traffic, or perhaps for high availability.\n. The second is to make Tigase's components work as an external component and make it work in a cluster mode, even if the component itself does not support cluster mode.\n\nHere are step by step instructions and configuration examples teaching how to achieve both goals.\n\n== Load Balancing External Component\nThe first, and most simple scenario is to connect multiple instances of an external component to a single Tigase XMPP Server to distribute load.\n\nThere are at least 2 reasons why this would be an optimal solution: one would be to spread load over more instances/machines and the second is to improve reliability in case one component fails the other one can take over the work.\n\nSo here is a simple picture showing the use case.\n\nimage:images/ExternalCompClustering002.png[]\n\nWe have a single machine running Tigase XMPP Server and 2 instances of the MUC component connecting to Tigase.\n\nThe server configuration\n\n[source,bash]\n-----\nconfig-type = --gen-config-def\n--user-db = mysql\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase\n--virt-hosts = devel.tigase.org\n\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.devel.tigase.org:muc-secret:listen:\\\n       5270:devel.tigase.org:accept:ReceiverBareJidLB\n-----\n\nAnd configuration for both instances of the MUC component (identical for both of them):\n\n[source,bash]\n-----\nconfig-type = --gen-config-comp\n--user-db = mysql\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase\n--virt-hosts = devel.tigase.org\n\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--external = muc.devel.tigase.org:muc-secret:connect:\\\n       5270:devel.tigase.org:accept\n-----\n\nFor those familiar with Tigase's configuration, this should be pretty basic. The difference is one small element in the server configuration. At the end of the component connection we have *ReceiverBareJidLB*.\n\nThis is the load balancing plugin class. Load balancing plugin decides how the traffic is distributed among different component connections that is different component instances. For the MUC component it makes sense to distribute the traffic based on the receiver bare JID because this is the MUC room address. This way we just distribute MUC rooms and traffic over different MUC component instances.\n\nThis distribution strategy does not always work for all possible components however. For transports for example this would not work at all. A better way to spread load for transports would be based on the source bare JID. And it is possible if you use plugin with class name: *SenderBareJidLB*.\n\nThis are two basic load distribution strategies available now. For some use cases none of them is good enough. If you have PubSub, then you probably want to distribute load based on the PubSub node. There is no plugin for that yet but it is easy enough to write one and put the class name in configuration.\n\n== External Component and Cluster\nIf you want to use Tigase's component in a cluster mode which does not have clustering implemented yet there is a way to make it kind of cluster-able. In the previous section we connected many MUC components to a single Tigase server. Now we want to connect a single MUC component to many Tigase servers (or many Tigase cluster nodes).\n\nLet's say we have Tigase XMPP Server working for domain: *xmpp-test.org* and the server is installed on three cluster nodes: *red.xmpp-test.org,* *green.xmpp-test.org* and *blue.xmpp-test.org.*\n\nimage:images/ExternalCompClustering003_0.png[]\n\nWe want to make it possible to connect the MUC component to all nodes, so here is configuration for the server (for each node is the same):\n\n[source,bash]\n-----\nconfig-type=--gen-config-def\n--admins=admin@xmpp-test.org\n--virt-hosts = xmpp-test.org\n\n--cluster-mode = true\n--cluster-nodes=red.xmpp-test.org,green.xmpp-test.org,blue.xmpp-test.org\n\n--auth-db=tigase-auth\n--user-db=mysql\n--user-db-uri=jdbc:mysql://localhost/db?user=tigase&password=tigase\n\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n--external = muc.xmpp-test.org:muc-secret:listen:5270:\\\n       xmpp-test.org:accept:ReceiverBareJidLB\n-----\n\nAs you can see there is nothing special here. The most interesting part comes on the MUC side.\n\n[source,bash]\n-----\nconfig-type = --gen-config-comp\n--user-db = mysql\n--admins = admin@xmpp-test.orgg\n--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase\n\n--virt-hosts = xmpp-test.org\n\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--external = muc.xmpp-test.org:muc-secret:connect:5270:xmpp-test.org;blue.xmpp-test.org;green.xmpp-test.org,red.xmpp-test.org:accept\n-----\n\nAs you can see remote host name is not a simple domain but a character string with a few comma separated parts. The first part is our remote domain and the rest are addresses of the host to connect to. This can be a list of domain names or IP addresses.\n\nOf course it is possible to connect multiple external component to all cluster nodes, this way the whole installation would be really working in the cluster and also load balanced.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_75_-_Virtual_Hosts_in_the_Tigase_Server.asciidoc",
    "content": "[[tigase41virtualHosts]]\n= Virtual Hosts in Tigase Server\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase server supports multiple virtual hosts in a single server installation. This is supported via link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/vhosts/VHostManagerIfc.java[VHostManager] - the new Tigase server component added recently to the implementation. Virtual hosts can be added or removed, enabled or disabled during runtime without restarting the service or disrupting normal operation.\n\nThis document describes how virtual hosts work in Tigase server and how to get the most out of this feature in your installation.\n\nThe simplest and default way to set virtual hosts is in the server configuration. You can either edit manually the +init.properties+ file or use the graphical installer/configuration program to set the property. If you want to edit it manually search for '--virt-hosts' property for more detailed description.\n\nAlternatively you can use the GUI installer as shown below to set a list of virtual hosts.\n\nimage:images/tigase-basic-config-vhosts.png[]\n\nThis method however has many disadvantages. It requires a server restart after each change, and the configuration file is not the best place to store long list of virtual domains. Furthermore you can not set any additional parameters for the domain other than whether it exists or not.\n\nThere is another way to store and control virtual domains in Tigase. That information can be put in the database and managed using ad-hoc commands. List of domains can be modified outside Tigase server through any third-party system or web application and the server reloads the list of when received *VHOSTS_RELOAD* ad-hoc command.\n\nThere are 2 more ad-hoc commands which allow you to add/update and remove virtual hosts via XMPP protocol:\n\n- *VHOSTS_UPDATE* - for adding new virtual host or changing parameters of the existing domain\n- *VHOSTS_REMOVE* - for removing existing virtual domain from the list of the server domains.\n\nBy default, both commands cause the vhosts list to update in the permanent repository. This is however link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/vhosts/VHostRepository.java[VHostRepository] implementation dependent feature and can be changed in your repository implementation.\n\nCommands for virtual domain management can be executed using any XMPP client with proper support for service discovery and ad-hoc commands, for example link:http://psi-im.org/[Psi]. Commands are accepted only when they are sent by the service administrator.\n\nPlease refer to documents listed below for more detailed information on the following topics:\n\n// - ////<<managingVirtualDomainsMissing,////Managing Virtual Domains Using Psi Client.\n- xref:ad-hocCommands[Specification for ad-hoc Commands Used to Manage Virtual Domains].\n- xref:virtualComponents[Virtual Components for the Tigase Cluster]\n\nYou may also want to reference these for additonal information\n- xref:addManageDomain[API Description for Virtual Domains Management in Tigase Server].\n- link:http://docs.tigase.org/tigase-server/snapshot/Properties_Guide/html_chunk/virtHosts.html[virtHosts Property guide]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_76_-_Virtual_Hosts_in_the_Tigase_Server_-_A_-_Specification_for_ad-hoc_Commands_Used_to_Manage_Virtual_Domains.asciidoc",
    "content": "[[ad-hocCommands]]\n= Specification for ad-hoc Commands Used to Manage Virtual Domains\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThere are 3 ad-hoc commands for virtual domains management in the Tigase server:\n\n. *VHOSTS_RELOAD* used to reload virtual domains list from the repository (database).\n. *VHOSTS_UPDATE* used to add a new virtual domain or update information for existing one.\n. *VHOSTS_REMOVE* used to remove an existing virtual host from the running server.\n\nSyntax of the commands follows the specification described in link:http://xmpp.org/extensions/xep-0050.html[XEP-0050]. Extra information required to complete the command is carried as data forms described in link:http://xmpp.org/extensions/xep-0004.html[XEP-0004].\n\nAll commands are accepted by the server only when send by the installation administrator. If the command is sent from any other account +&lt;not-authorized /&gt;+ error is returned. To grant administrator rights to an account you have to set *--admins* property in the +init.Properties+ configuration file.\n\nCommands are sent to the 'vhost-man' server component and the 'to' attribute of the stanza must contain a full JID of the VHostManager on the server. The full *JID* consists of the component name: 'vhost-man' and the local domain, that is domain which is already on the list of virtual domains and is active. Assuming 'existing.domain.com' one of domains already activated for the server installation the *JID* is: 'vhost-man@existing.domain.com'.\n\n== Reloading the Domains List from the Database\nIn order to reload virtual domains from the permanent repository other than configuration file, you have to send *VHOSTS_RELOAD* ad-hoc command to the VHostManager on the server.\n\nThe reload command request is of the form:\n\n[source,xml]\n-----\n<iq type=\"set\"\n    to=\"vhost-man@existing.domain.com\"\n    id=\"aac8a\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           node=\"VHOSTS_RELOAD\" />\n</iq>\n-----\n\nThe server sends a response upon successful completion of the command with current number of virtual domains server by the installation:\n\n[source,xml]\n-----\n<iq from=\"vhost-man@existing.domain.com\"\n    type=\"result\"\n    to=\"cmd-sender-admin@existing.domain.com\"\n    id=\"aac8a\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           status=\"completed\"\n           node=\"VHOSTS_RELOAD\">\n    <x xmlns=\"jabber:x:data\" type=\"result\">\n      <field type=\"fixed\" var=\"Note\">\n        <value>Current number of VHosts: 123</value>\n      </field>\n    </x>\n  </command>\n</iq>\n-----\n\nIf the command is sent from an account other than admin, the server returns an error:\n\n[source,xml]\n-----\n<iq from=\"vhost-man@existing.domain.com\"\n    type=\"error\"\n    to=\"cmd-sender-admin@existing.domain.com\"\n    id=\"aac8a\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           node=\"VHOSTS_RELOAD\" />\n  <error type=\"auth\" code=\"401\">\n    <not-authorized xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />\n    <text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"\n          xml:lang=\"en\">\n      You are not authorized for this action.\n    </text>\n  </error>\n</iq>\n-----\n\nThe response doesn't have any special meaning other then end-user information. The client may ignore the response as it is sent after the command has been executed.\n\n== Adding a New Domain or Updating Existing One\nIn order to add a new domain or update existing one you have to send an ad-hoc command *VHOSTS_UPDATE* with at least one domain name in the command data form. You can also specify whether the domain is enabled or disabled but this is optional. Future releases may allow for setting additional parameters for the domain: maximum number of user accounts for this domain, anonymous login enabled/disabled for the domain, registration via XMPP enabled/disabled for this domain and some more parameters not specified yet.\n\nThe domain add/update command request is of the form:\n\n[source,xml]\n-----\n<iq type=\"set\"\n    to=\"vhost-man@existing.domain.com\"\n    id=\"aacba\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           node=\"VHOSTS_UPDATE\">\n    <x xmlns=\"jabber:x:data\" type=\"submit\">\n      <field type=\"text-single\"\n             var=\"VHost\">\n        <value>new-virt.domain.com</value>\n      </field>\n      <field type=\"list-single\"\n             var=\"Enabled\">\n        <value>true</value>\n      </field>\n    </x>\n  </command>\n</iq>\n-----\n\nPlease note: Character case in the command field variable names does matter.\n\nUpon successful completion of the command the server sends a response back to the client with information of the existing number of virtual hosts on the server:\n\n[source,xml]\n-----\n<iq from=\"vhost-man@existing.domain.com\"\n    type=\"result\"\n    to=\"cmd-sender-admin@existing.domain.com\"\n    id=\"aacba\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           status=\"completed\"\n           node=\"VHOSTS_UPDATE\">\n    <x xmlns=\"jabber:x:data\" type=\"result\">\n      <field type=\"fixed\" var=\"Note\">\n        <value>Current number of VHosts: 124</value>\n      </field>\n    </x>\n  </command>\n</iq>\n-----\n\n== Removing a Virtual Domain From the Server\nIn order to remove a virtual domain you have to send *VHOSTS_REMOVE* command to the server with the domain name.\n\nThe domain remove command is sent by the client:\n\n[source,xml]\n-----\n<iq type=\"set\"\n    to=\"vhost-man@existing.domain.com\"\n    id=\"aacba\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           node=\"VHOSTS_REMOVE\">\n    <x xmlns=\"jabber:x:data\" type=\"submit\">\n      <field type=\"text-single\"\n             var=\"VHost\">\n        <value>virt-nn.domain.com</value>\n      </field>\n    </x>\n  </command>\n</iq>\n-----\n\nUpon successful completion of the command the server sends a response back to the client with information of the existing number of virtual hosts on the server:\n\n[source,bash]\n-----\n<iq from=\"vhost-man@existing.domain.com\"\n    type=\"result\"\n    to=\"cmd-sender-admin@existing.domain.com\"\n    id=\"aacba\">\n  <command xmlns=\"http://jabber.org/protocol/commands\"\n           status=\"completed\"\n           node=\"VHOSTS_REMOVE\">\n    <x xmlns=\"jabber:x:data\" type=\"result\">\n      <field type=\"fixed\" var=\"Note\">\n        <value>Current number of VHosts: 124</value>\n      </field>\n    </x>\n  </command>\n</iq>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_77_-_Virtual_Hosts_in_the_Tigase_Server_-_B_-_Virtual_Components_for_Cluster_Mode.asciidoc",
    "content": "[[virtualComponents]]\n= Virtual Components for the Cluster Mode\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nLet's assume you have a cluster installation and you want to include a component in your installation which doesn't support the cluster mode yet. If you put it on all nodes as a separate instances they will work out of sync and overall functionality might be useless. If you put on one node only it will work correctly but it will be visible to users connected to this one node only.\n\nIdeally you would like to have a mechanism to install it on one node and put some redirections on other nodes to forward all packets for this component to a node where this component is working. Redirection on it's own is not enough because the component must be visible in service discovery list and must be visible somehow to users connected to all nodes.\n\nThis is where the virtual components are handy. They are visible to users as a local normal component, they seem to be a real local component but in fact they just forward all requests/packets to a cluster node where the real component is working.\n\nVirtual component is a very lightweight ServerComponent implementation in Tigase server. It can pretend to be any kind of component and can redirect all packets to a given address. They can mimic native Tigase components as well as third-party components connected over external component protocol (XEP-0114).\n\nConfiguration is very simple and straightforward, in fact it is very similar to configuration of any Tigase component. You set a real component name as a name of the component and a virtual component class name to load. Let's say we want to deploy MUC component this way. The MUC component is visible as +muc.domain.our+ in the installation. Thus the name of the component is: +muc+\n\n[source,bash]\n-----\n--comp-name-1=muc\n--comp-class-1=tigase.cluster.VirtualComponent\n-----\nThis is pretty much all you need to load a virtual component. A few other options are needed to point to correct destination addresses for packets forwarding and to set correct service discovery parameters:\n\n[source,bash]\n-----\nmuc/redirect-to=muc@cluster-node-with-real-muc.domain.our\nmuc/disco-name=Multi User Chat\nmuc/disco-node=\nmuc/disco-type=text\nmuc/disco-category=conference\nmuc/disco-features=http://jabber.org/protocol/muc\n-----\n\nThat's it.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_78_-_Using_Tigase.asciidoc",
    "content": "= Using Tigase - Applies to All Tigase Server Versions\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:numbered:\n:website: http://tigase.net\n\nThis section keeps set of documents which apply to all the Tigase server version and contain more generic or introductory information on general use and features.\n\n\n- xref:logs[Tigase Log Guide]\n- xref:debuggingTigase[Debugging Tigase]\n- xref:systemchecks[Basic System Checks]\n- xref:addManageDomain[Add and Manage Domains]\n- xref:presenceForwarding[Presence Forwarding]\n- xref:registerXMPP[Register Your Own XMPP Domain]\n- xref:Pymsn-t[Tigase and PyMSN Transport]\n- xref:multiplesessionmanagers[Multiple Session Managers]\n- xref:watchdog[Watchdog]\n- xref:tipsandTricks[Tips And Tricks]\n. xref:tigaseTip_RuntimeEnvironment[Runtime Environment Tip]\n. xref:tigaseTip_CheckingClusterConnections[Checking Cluster Connections]\n. xref:bestWebPrax[Best Practices for Connecting to Tigase XMPP server From Web Browser]\n- xref:commandLineTools2[Command Line Tools]\n. xref:configurationManagement2[Configuration Management Tool]\n- xref:scripsupport[Scripting Support in Tigase]\n. xref:scriptingintro[Scripting Introduction - Hello World!]\n. xref:newElements[Tigase Scripting Version 4.4.x Update for Administrators]\n. xref:tigaseandPython[Tigase and Python Scripting]\n- xref:tigase3xconfiguration[Configuration Wizards]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_79_-_Using_Tigase_-_A_-_Log_Guide.asciidoc",
    "content": "[[logs]]\n= Tigase Log Guide\n:author: Daniel Wisnewski\n:version: v1.0 August 2015\n:date: 2015-10-08 12:13\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nTigase has multiple levels of logging available to help provide targeted and detailed information on processes, components, or traffic. In these documents we will look at where tigase generates logs, what they contain, and how we can customize them to our needs.\n\nThe list of available documents here is presented from the Tigase root directory.\n[source,list]\n-----\n*/*\nderby.log\ninstall.log\n\n*/etc*\nconfig-dump.properties\n\n*/logs*\ntigase.log.#\ntigase.pid\ntigase-console.log\n-----\n\n\n== install.log\nThis log file is a basic list of files that are made on install of Tigase server.  Although you may not need to use it, it can provide a handy list to see if any files were not written to your hard drive upon installation.\n\n== derby.log\nIf you are using the derby database installed with Tigase installer, this is the startup log for the database itself.  Issues that might be related to the database, can be found in this file.  Typically, if everything works okay, it's a very small file with only 10 lines.  It is overwritten on startup of the datbase.\n\n== config-dump.properties\nThe config-dump.properties is dump file of all your properties listed for every option within Tigase and components.  The structure of the log lines is as follows.\n-------\nmodulename/settingformodulename[Data type]=value(s)\n-------\nLets take the value for admins, listing who is administrator for the server.\n-----\nbasic-conf/admins[s]=admin@jabber.freehost.org, administrator@jabber.freehost.org, fJones@jabber.freehost.org\n-----\nThe admin parameter which is an array of strings noted by the s, has 3 users listed.\n*NOTE* you can lookup the available Data types in the xref:initPropertiesGuide[init.properties guide].\n\nThis file is re-written every time tigase starts.\n\n== tigase.log.#\nThe tigase.log files are where the majority of logging will take place. The rules for writing to these longs can be manipulated by editing files in the int.properties file.  To see how, see the xref:debuggingTigase[Debugging Tigase] section of this manual for more details about how to turn on debug logging, and how to manipulate log settings.\nEntries to these logs are made in the following format:\n-----\n2015-08-10 13:09:41.504 [main]      Sctipr.init()         INFO: Initilized script command, id: comp-manager, lang:Groovy, ext: groovy\n-----\nThe format of these logs is below:\n<timestamp> <thread_name> <class>.<method>    <log_level>: <message> <thread_name>. This can vary - for components it would be <direction>_<int>_<component name>, for plugins it will just be the plugin name.\n\nLet's look at another example from the log file.\n-----\n2015-08-10 12:31:40.893 [in_14_muc] InMemoryMucRepository.createNewRoom()   FINE: Creating new room 'chatroom@muc.localhost.com'\n-----\nThe process ID may sometimes come in a different format such as `[in_14-muc]` which specifies the component (muc) along with the process thread identifier (14).  As you can see, the format otherwise is nearly identical.\n\ntigase.log can get very large in size rather quickly reaching it's maximum size.  To prevent the loss of information, we have implemented a rotating file system.  The server begins writing to tigase.log.0 when it is first run, and continues to dump information until the log size limit is hit. At this point, Tigase renames tigase.log.0 as tigase.log.1. A new tigase.log.0 will be created, and Tigase will begin logging to this file.  When this file is full, tigase.log.1 will be renamed tigase.log.2 and tigase.log.0 will be renamed tigase.log.1.  Using this scheme, tigase.log.0 will *always* be your most recent log.\n\nBy default, Tigase has a limit of 10000000 bytes or 10mb with a file rotation of 10 files. You can edit these values by editing the init.properties guide and adding the following lines.\n\n[source,bash]\n-----\nbasic-conf/logging/java.util.logging.FileHandler.limit=20000000\nbasic-conf/logging/java.util.logging.FileHandler.count=15\n-----\nThis code, if entered into the init.properties file increases the size of the files to 15, and enlarges the maximum size to 20mb.  Note the larger the collective log space is, the larger number of sectors on hard disk are active.  Large log blocks may impact system performance.\n\n_You may see a tigase.log.0.ick file in the directory while the server is running.  This is a temporary file only and is deleted once Tigase is cleanly shut down._\n\n== statistics.log.#\nStatistics log will duplicate any information that is related to sending of statistics to Tigase if you are using an unlicenced copy of Tigase XMPP server.  Mainly it will consist output of +LicenceChecker+.  The numbering logic will be the same as tigase.log.# files.\n\n== tigase.pid\ntigase.pid is a file that just contains the Process ID or PID for the current run of Tigase. It is only valid for the current or most recent run cycle and is overwritten every time Tigase starts.\n\n\n== tigase-console.log\nThis file contains information related to Tigase's running environment, and is a dump from the server itself on what is being loaded, when, and if any issues are encountered.\nIt will start by loading Java classes (consequently making sure the Java environment is present and functioning).  Then it will begin loading the configuration file, and adding default values to settings that have not been customized.  You can then see all the components being loaded, and settings added where default values are needed.  Lastly you will see a log of any plugins that are loaded, and any parameters therein.\nYou may see tags such as INFO or WARNING in the logs. Although they may contain important information, the program will continue to operate as normal are not of too great concern.\n\nERROR flags are issues you will want to pay attention as they may list problems that prevent Tigase or components from properly functioning.\n\n*NOTE* Windows does not create this file, rather the output is shown in the commandline and is not dumped to a file.\n\nIf Tigase is gracefully shut down, tigase-console.log will add statistics from the server's operation life in the following format.\n-----\ncomponent/statistic = value\n-----\n_Any component that may have a statistic, whether used or not, will place a value here_\n\nThis file can be handy if you are tracking issues in the server.\n\ntigase-console.log is appended during each run session of the server.\n\n== Log File Location\nYou can also change the location of log files if you have a specific directory you wish to use.  The configuration may be made by the following line in your init.properties file:\n[source,properties]\n-----\nbasic-conf/logging/java.util.logging.FileHandler.pattern=/var/log/tigase/tigase.log\n-----\n\nThis setting changes the log file location to /var/log/tigase/ where all log files will be made.  Files in the original location will be left.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_80_-_Using_Tigase_-_B_-_Debugging_Tigase.asciidoc",
    "content": "[[debuggingTigase]]\n= Debuging Tigase\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nIf something goes wrong and you can't find out why it is not working as expected, you might want more detailed debugging options switched on.\n\nTigase is a Java application and it uses Java logging library, this gives you the flexibility to switch logging on for selected Java packages or even for a single Java class.\n\nLogs files are stored in +logs/+ directory. +tigase-console.log+ stores basic log data, but is the main log file. +tigase.log.N+ files keep all the detailed logging entries. So this is the place where you should look in case of problems.\n\n== The easy way - init.properties file\nThe easiest way to change logging for Tigase is modifying in +init.properies+ following line:\n\n[source,bash]\n-----\n--debug=server\n-----\n\nThe line above says: \"_Switch on ALL debug messages for packet: tigase.server_\". The +tigase.server+ packet keeps all it's component's classes, so it allows you to monitor what is going on in each component, what packets it receives and what it is sending out.\n\nUsually people want to see what is going on the network level. That is what has been sent and what has been received by the server - the actual character data. The class which would print all received and sent character data is: +tigase.xmpp.XMPPIOService+. To enable all debugging info for this class you have to modify the debug line:\n\n[source,bash]\n-----\n--debug=xmpp.XMPPIOService\n-----\n\n_Note, you can skip the tigase. part._\n\nYou can also have debugging switched on for many packages/classes at the same time:\n\n[source,bash]\n-----\n--debug=server,xmpp.XMPPIOService\n-----\n\nOther packages you might be interested in are:\n\n- +tiagse.io+ and +tigase.net+ which can print out what is going on a very low level network level including TLS/SSL stuff.\n- +tigase.xml+ would print the XML parser debugging data.\n- +tigase.cluster+ would print all the clustering related stuff. So if you have clustered installation you might be interested in debug settings:\n+\n[source,bash]\n-----\n--debug=server,cluster\n-----\n- +tigase.xmpp.impl+ would print logs from all plugins loaded to Tigase server.\n\nThis method, however has 2 main disadvantages:\n\n. You have to remove your XML config file and regenerate it which might be inconvenient. (only applicable to versions before 5.0.0)\n. You can't set logging this way for classes and packages other than Tigase. This might be a problem if you include your own code in and load it into the server.\n\nTo enable logging for your own packages from packages different than Tigase, you have to use another option which has been made available for this:\n\n[source,bash]\n-----\n--debug-packages = your.com.package\n-----\n\nYou can also specify more parameters for the Tigase logging mechanisms like the file size, number of files rotated, and location where all Tigase logs are stored. The following lines are some examples of those filters using lines in the +init.properties+ file:\n\n[source,bash]\n-----\nbasic-conf/logging/java.util.logging.FileHandler.limit=100000000\nbasic-conf/logging/java.util.logging.FileHandler.count=20\nbasic-conf/logging/java.util.logging.FileHandler.pattern=/var/log/tigase/tigase.log\n-----\n\n== The more difficult but more powerful - tigase.xml file (only applicable to versions before 5.0.0)\nIf you want to modify debugging settings without regenerating the whole XML config file, you can modify it yourself by manually adding debug entries. This must be done very carefully or you could break the XML file and configuration won't work.\n\nOpen the XML config file with a good text editor (or XML editor) and find the line:\n\n[source,bash]\n-----\n<node name=\"logging\">\n-----\n\nBelow is a list of all logging settings.\n\n[source,bash]\n-----\n<entry value=\"INFO\" type=\"String\" key=\".level\"/>\n-----\n\nWhich says: +INFO+ debug level for all the code which gives you very little debugging information. For example your +init.properties+ line +--debug=server+ adds one extra line in there:\n\n[source,bash]\n-----\n<entry value=\"ALL\" type=\"String\" key=\"tigase.server.level\"/>\n-----\n\nYou can add a similar line changing only \"key\" attribute. If you need to switch logging on for a specific class - +tigase.xmpp.XMPPIOService+ for example, add:\n\n[source,bash]\n-----\n<entry value=\"ALL\" type=\"String\" key=\"tigase.xmpp.XMPPIOService.level\"/>\n-----\n\nYou can also put there your own package or class name. After you changed the config file you will have to restart the server.\n\n_Note, don't overdose the debugging or your logs will be loaded with useless information._\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_81_-_Using_Tigase_-_C_-_Basic_System_Checks.asciidoc",
    "content": "[[systemchecks]]\n= Basic System Checks\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-03-06 20:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nPreviously, a configuration article is available about xref:linuxhighload[Linux settings for high load systems]. This has a description of basic settings which are essential to successfully run XMPP service for hundreds or thousands of online users.\n\nOf course, high load and high traffic systems require much more tuning and adjustments. If you use selinux you have to be careful as it can interfere with the service while it is under a high load. Also some firewall settings may cause problems as the system may decide it is under a DDOS attack and can start blocking incoming connections or throttle the traffic.\n\nIn any case, there are some basic checks to do every time you deploy XMPP service to make sure it will function properly. I am trying to keep the article mentioned above up to date and add all the settings and parameters I discover while working with different installations. _If you have some suggestions for different values or different parameters to add, please let me know._\n\n// The article, while helpful, seems to be not enough though.\n\nIf you want to run a service on a few cluster nodes (5 or even 10), then manually checking every machine and adjusting these settings is time consuming and it is very easy to forget about.\n\nTo overcome this problem I started to work on a shell script which would run all the basic checks and report problems found. Ideally it should be also able to adjust some parameters for you.\n\nInside the Tigase server link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/scripts[/scripts/] repository find a script called +machine-check.sh+. It performs all the basic checks from the article and also tries to adjust them when necessary. Have a link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/scripts/machine-check.sh[look at the code] or link:https://projects.tigase.org/projects/tigase-server/repository/changes/scripts/machine-check.sh?rev=master[check it out] and run for yourself.\n\nAny comments or suggestions, as usual, are very much appreciated.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_82_-_Using_Tigase_-_D_-_Add_and_Manage_Virtual_Domains.asciidoc",
    "content": "[[addManageDomain]]\n= Add and Manage Domains\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-08-23 21:13\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nFor everybody interested in using our service to host their own XMPP domain we have good news! You do not have to ask an administrator to add your domain or add users for your domain anymore. You can do it on your own.\n\nPlease note, this is very new stuff. Something may go wrong or may not be polished. Please report any problems, notices or suggestions.\n\nThis is the guide to walk you through the new functions and describes how to add a new domain and new users within your domain.\n\nYou can do everything from your XMPP client or you can use our web application that allows you to connect to the service and execute admin commands. I recommend link:http://psi-im.org/[Psi] because of its excellent support for parts of the XMPP protocol which are used for domains and user management. You may use other clients as well, but we can only offer support and help if you use Psi client.\n\nSecondly, you need an account on the server. This is because all the commands and features described here are available to local users only. Therefore, if you do not have a registered domain with us yet, please go ahead and register an account on the website either the link:http://jabber.me/[Jabber.Me] or link:http://www.tigase.im/[Tigase.IM].\n\n== Adding a New Domain\nOnce you register an account on one of the websites, connect to the XMPP server using the account on the Psi client. We will be using the following account: green@tigase.im which is this guide.\n\nWhen you are ready right click on the account name in Psi roster window to bring up context menu. Select *Service Discovery* element.\n\nimage:images/service_disco_menu.png[]\n\nA new windows pops up as in the example on the right. The service discovery window is where all the stuff installed on XMPP service should show up. Most of elements on the list are well known transports, MUC and PubSub components. The new stuff on the list, which we are interested in, are 2 elements: *VHost Manager* and *Session Manager*.\n\nimage:images/service_disco_window_vhost.png[]\n\n*VHost Manager* component in Tigase is responsible for managing and controlling virtual hosts on the installation. It provides virtual hosts information to all other parts of the system and also allows you to add new hosts and remove/update existing virtual hosts.\n\n*Session Manager* component in Tigase is responsible for managing users. In most cases online users but it can also perform some actions on user repository where all user data is stored.\n\nSelect *VHost Manager* and double click on it. A new windows shows up (might be hidden behind the service discovery window). The window contains another menu with a few items: *Add..., Remove...* and *Update...* . These are for adding, removing and updating VHost information. For now, just select the first element *Add....*\n\nimage:images/command_menu_add_vhost.png[]\n\nClick *Execute* and you get a new window where you can enter all of your VHost configuration details. All fields should be self explanatory. Leave a blank field for *Other parameters* for now. *Owner* is you, that is Jabber ID which controls the domain and can change the domain configuration settings or can remove the domain from the service. *Administrators* field can be left blank or can contain comma separated list of Jabber IDs for people who can manage users within the domain. You do not need to add your user name to the list as Owners can always manage users for the domain.\n\nimage:images/add_vhost_window.png[]\n\nWhen you are ready click the *Finish* button. All done, hopefully. You can get either a window confirming everything went well or a window printing an error message if something went wrong. What can be wrong? There are some restrictions I decided to put on the service to prevent abuse. One of the restrictions is the maximum number of domains a user can register for himself which is *25* right now. Another restriction is that the domain which you add must have a valid DNS entry pointing to our service. The XMPP guide describes all the details about DNS settings. Please refer to these instructions if you need more details.\n\n== Adding a New User\nAdding a new user process is quite similar, almost identical to adding a new domain. This time, however we have to select *Session Manager* in the service discovery window.\n\nimage:images/service_disco_window_sm.png[]\n\nDouble click on the *Session Manager* and a window with SM's commands list shows up. Right now, there is only one command available to domain administrators - *Add user*. I am going to make available more commands in the future and I am waiting for your suggestions.\n\nimage:images/command_menu_add_user.png[]\n\nIf you click *Execute* a window presented on the left shows up. Fill all fields accordingly and press *Finish*.\n\nimage:images/add_user_window.png[]\n\nIf everything went well you have just added a new user and you should get a window confirming successful operation. If something went wrong, a window with an error message should show up. Possible errors may be you tried to add a user which is already present, or you may have tried to add a user for a domain to which you do not have permission or to non-existen domain.\n\n== SSL Certificate Management\nSSL Certificate Management has been implemented, and certificates can be manipulated when in a .pem form. For more details, see xref:certspem[Creating and Loading the Server Certificate in pem Files] section of documentation for more information.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_83_-_Using_Tigase_-_E_-_Presence_Forwarding.asciidoc",
    "content": "[[presenceForwarding]]\n= Presence Forwarding\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-08-23 21:52\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nHave you ever thought of displaying your users presence status on the website? Or, maybe, you wanted to integrate XMPP service with your own system and share not only users' accounts but also presence status?\n\nNot only is it possible but also very simple. You have a new option in the domain control form.\n\nActually there are 2 new options:\n\n. Presence forward address\n. Message forward address - not fully implemented yet\n\nPresence forward address can be any XMPP address. Usually you want it to be a bot address which can collect your users' presence information. Once this option is set to a valid XMPP address Tigase forwards user's presence, every time the user changes his status. The presence is processed normally, of course, and distributed to all people from the contact list (roster), plus to this special address. It can be a component or a bot. If this is a bot connecting to a regular XMPP account, *Make sure the presence forward address contains resource part and the bot is connecting with this resource.* Otherwise the presence won't be delivered to the bot.\n\nimage:images/vhost-presence-forward.png[]\n\nAs the screenshot shows, there are new input lines with option for presence forwarding address and message forwarding address. As you can see this option can be specified separately for each domain, so you can have a different forward address for each domain.\n\nIf you have your own Tigase installation, the forwarding address can be also set globally and can be the same for all domains. However, for this website, we offer this feature to all our users who have own domains and this can be set on per-domain basis.\n\nNow, the big question. How this can be used? I am attaching below an example code. With just a few lines of code you can connect a command line bot to the server as a client which would collect all presences from users. Code below is a simple Groovy script which receives presence packet and displays them on the console. However, it should be easy enough to store users' presence information in a database and then load it from a web application.\n\nThe bot/client uses our link:https://projects.tigase.org/projects/jaxmpp2[JaXMPP2] library which is available form our project management system.\n\nYou should be able to find a few more code examples on the wiki page.\n\n\n[source,java]\n-----\npackage jaxmppexample\nimport tigase.jaxmpp.core.client.BareJID\nimport tigase.jaxmpp.core.client.SessionObject\nimport tigase.jaxmpp.core.client.exceptions.JaxmppException\nimport tigase.jaxmpp.core.client.observer.Listener\nimport tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule\nimport tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule.PresenceEvent\nimport tigase.jaxmpp.j2se.Jaxmpp\n\nfinal Jaxmpp jaxmpp = new Jaxmpp()\njaxmpp.getProperties().setUserProperty( SessionObject.USER_BARE_JID,\n  BareJID.bareJIDInstance( \"test4@test.tigase.org\" ) )\njaxmpp.getProperties().setUserProperty(SessionObject.RESOURCE, \"presence-collector\")\njaxmpp.getProperties().setUserProperty( SessionObject.PASSWORD, \"pass\" )\njaxmpp.getModulesManager().getModule( PresenceModule.class ).addListener(\n  PresenceModule.ContactChangedPresence,  new Listener() {\n    public void handleEvent( PresenceEvent be ) {\n      def msg = (be.getStatus() != null) ? be.getStatus() : \"none\"\n      println( \"Presence received:\\t\" + be.getJid() + \" is now \" + be.getShow() +\n        \" (\" + msg + \")\" )\n    }\n  }\n)\nprintln( \"Loging in...\" )\njaxmpp.login()\nprintln( \"Waiting for the presence for 10 minutes\" )\nThread.sleep( 10 * 60 * 1000 )\ndisconnect()\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_84_-_Using_Tigase_-_F_-_Register_Own_XMPP_Domain.asciidoc",
    "content": "[[registerXMPP]]\n= Register Your Own XMPP Domain\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-08-23 21:05\n:version: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nYou can have XMPP service running in your own domain. The only condition right now is that this must be a DNS registered domain and DNS must point to the following DNS address: *tigase.me*. Please note, do not confuse it with tigase.im domain name.\n\nWe recommend to use SRV records as this is required by the XMPP specifications but as some DNS services do not allow for SRV records yet we do not require SRV records either. If you want to register: *your-domain.tld* on our XMPP service make sure that either the command:\n\n[source,sh]\n-----\n$ host your-domain.tld\nyour-domain.tld has address 94.23.164.209\n-----\n\ndisplays *94.23.164.209* address or commands:\n\n[source,sh]\n-----\n$ host -t SRV _xmpp-server._tcp.your-domain.tld\n_xmpp-server._tcp.your-domain.tld has SRV record 10 0 5269 tigase.me.\n$ host -t SRV _xmpp-client._tcp.your-domain.tld\n_xmpp-client._tcp.your-domain.tld has SRV record 10 0 5222 tigase.me.\n-----\n\ndisplay *tigase.me* DNS name. We strongly recommend not to use the IP address directly however, as if the service grows too much, it will be much easier for us to migrate and expand it using the DNS name rather then IP address.\n\nIf you want to have MUC and PubSub available under your domain, you have to setup DNS for your *muc.your-domain.tld* and *pubsub.your-domain.tld* domains too.\n\nFor MUC:\n\n[source,sh]\n-----\n$ host -t SRV _xmpp-server._tcp.muc.your-domain.tld\n_xmpp-server._tcp.muc.your-domain.tld has SRV record 10 0 5269 tigase.me.\n$ host -t SRV _xmpp-client._tcp.muc.your-domain.tld\n_xmpp-client._tcp.muc.your-domain.tld has SRV record 10 0 5222 tigase.me.\n-----\n\nFor PubSub :\n\n[source,sh]\n-----\n$ host -t SRV _xmpp-server._tcp.pubsub.your-domain.tld\n_xmpp-server._tcp.pubsub.your-domain.tld has SRV record 10 0 5269 tigase.me.\n$ host -t SRV _xmpp-client._tcp.pubsub.your-domain.tld\n_xmpp-client._tcp.pubsub.your-domain.tld has SRV record 10 0 5222 tigase.me.\n-----\n\nNow, how do you register your domain with our service?\n\nThere are a few ways. We recommend checking with the xref:xref:addManageDomain[Add and Manage Domains] section of the documentation on setting that up. If you cannot or don't want to do it on your own, the way described in the guide please send us a message, either via XMPP to admin@tigase.im or the contact form requesting new domain. User registration is available via in-band registration protocol. You can also specify whether you want to allow anonymous authentication to be available for your domain and you can specify maximum number of users for your domain.\n\nAny comments or suggestions are very welcomed.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_85_-_Using_Tigase_-_G_-_Tigase_and_PyMSN-t_Transport.asciidoc",
    "content": "[[Pymsn-t]]\n= Tigase and PyMSN-t Transport\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nAny XMPP server and any transport can connect with each other through an external component protocol (link:http://www.xmpp.org/extensions/xep-0114.html[XEP-0114]). So all you need to do is to correctly prepare configuration for this protocol on both sides.\n\n_Continue reading to learn how to setup Tigase and PyMSN for working together..._\n\nThere are a few basic parameters to set for this protocol:\n\n- *PORT number* - this is a standard thing for any TCP/IP connection. Usually the port number should be above 1024 and for PyMSN-t transport it is usually *5347*.\n- *IP address* - again, a standard thing for any TCP/IP connection. If both applications - XMPP server and transport run on the same machine the IP address should be *127.0.0.1*.\n- *SECRET* - this is kind of connection password. Transport connects to the XMPP server and authenticates itself using this password. So no other unauthorized transport can connect to the XMPP server. For now lets use the password *secret*.\n- *Transport ID* - is an ID in XMPP network. Let's say we want to setup transport for *MSN* for the server *tigase.org*. Transport ID can be: msn.tigase.org. It could be also: *anything.tigase.org* but this name while still valid would be confusing for users and my suggestion is to avoid confusing names. *Note!* Transport ID should resolve to correct IP address. For your tests you can add the ID to +/etc/hosts+ file.\n\nHere is side by side configuration for both applications: PyMSN-t and Tigase to make them work together. Both services are setup with the hostname *test-d*. To make sure both *test-d* and *msn.test-d* resolve to correct IP address an entry to the +/etc/hosts+ file is added:\n\n[source,bash]\n-----\n## In your case the IP address should be probably different.\n192.168.0.13    test-d            msn.test-d\n-----\n\nTigase server connects to MySQL database (or built-in XMLBD for simpler configuration variant).\n\nI am not going to setup *PyMSN-t* to run in background as a system service. This is specific to the system you use and is covered in transport documentation and your operating system. Most systems have their own scripts to start services so I would recommend to use them. Here howeevr, it is run in the foreground with full logging switched on to the console to make it easier track what happens.\n\n== PyMSN-t - /etc/jabber/pymsn-t.xml file\n\n[source,bash]\n-----\n\n<pymsnt>\n  <!-- The JabberID of the transport -->\n  <jid>msn.test-d</jid>\n  <!-- The public IP or DNS name of the machine\n    the transport is running on -->\n  <host>test-d</host>\n  <!-- The location of the PID file, relative\n    to the PyMSNt directory -->\n  <pid>/var/run/jabber/pymsn-t.pid</pid>\n  <!-- If set, the transport will background\n    itself when run, we don't want to do this right\n    now. -->\n  <!-- <background/> -->\n  <!-- The IP address of the main XMPP server\n    to connect to -->\n  <mainServer>127.0.0.1</mainServer>\n  <!-- The TCP port to connect to the XMPP\n    server on (this is the default for Jabberd2) -->\n  <port>5347</port>\n  <!-- The authentication token to use when\n    connecting to the XMPP server -->\n  <secret>secret</secret>\n  <lang>en</lang>\n  <website>http://test-d/</website>\n  <allowRegister/>\n  <getAllAvatars/>\n  <!-- Please give the port to listen for XMPP\n    socks5 transfers on. Note the standard port number\n    set here is <strong>8010</strong>. This port\n    however is in use on my machine so this is why\n    I had to set it to different value.-->\n  <ftJabberPort>8014</ftJabberPort>\n  <admins>\n    <jid>tus@test-d</jid>\n  </admins>\n  <!-- The logging level\n    0 -> No logging\n    1 -> Log tracebacks\n    2 -> Log tracebacks, warnings and errors\n    3 -> Log everything -->\n  <debugLevel>3</debugLevel>\n  <!-- The file to log to. Leave this disabled\n    for stdout -->\n  <!-- <debugFile>debug.log</debugFile> -->\n</pymsnt>\n-----\n\n== PyMSN-t - run command\n\n[source,sh]\n-----\npython /usr/lib/python2.4/site-packages/pymsn-t/pymsn-t.py \\\n  -c /etc/jabber/pymsn-t.xml\n-----\n\n*Note!* the full path to PyMSN-t config file is important.\n\n== PyMSN-t - expected output\n\n[source,bash]\n-----\nA few last lines should look like:\n[2007-05-07 13:00:39] Starting factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n[2007-05-07 13:00:39] <twisted.internet.tcp.Connector\n  instance at 0xb7ceb24c> will retry in 2 seconds\n[2007-05-07 13:00:39] Stopping factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n[2007-05-07 13:00:41] Starting factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n[2007-05-07 13:00:41] <twisted.internet.tcp.Connector\n  instance at 0xb7ceb24c> will retry in 5 seconds\n[2007-05-07 13:00:41] Stopping factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n[2007-05-07 13:00:46] Starting factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n[2007-05-07 13:00:46] <twisted.internet.tcp.Connector\n  instance at 0xb7ceb24c> will retry in 15 seconds\n[2007-05-07 13:00:46] Stopping factory\n  <twisted.xish.xmlstream.XmlStreamFactory\n  instance at 0xb7ce80ac>\n-----\n\nAnd PyMSN should continue to print lines until it successfully connects to the Tigase server. When that happens, the following lines should be printed:\n\n[source,bash]\n-----\n[2007-05-07 13:29:04] Starting factory\n  <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7cf00ac>\n[2007-05-07 13:29:04] INFO ::  ::  :: componentConnected\n  :: PyTransport :: {'xmlstream': <twisted.xish.xmlstream.XmlStream\n  instance at 0xb7d0feac>, 'self': 'instance'}\n-----\n\n== Tigase - etc/tigase.conf file\n\nYou may consider removing the last 2 lines from TIGASE_OPTIONS variable to avoid using MySQL for now. Tigase will then use internal XMLDB which doesn't need any special setup. (Just remember to leave closing double quotes...)\n\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver\"\nCLASSPATH=\"${CLASSPATH}:libs/jdbc-mysql.jar\"\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\nTIGASE_CONFIG=\"etc/tigase-mysql.xml\"\n## All TIGASE_OPTIONS settings must be in single line\n## They are split to make them more readable\nTIGASE_OPTIONS=\"--gen-config-all --admins \\\"tus@test-d\\\"\n --virt-hosts test-d,localhost --debug server\n --ext-comp \\\"test-d,msn.test-d,5347,secret,plain,accept\\\"\n --user-db mysql --user-db-uri\n \\\"jdbc:mysql://localhost/tigase?user=tigase&password=mypass\\\" \"\n-----\n\n== Tigase - run command\n\n[source,sh]\n-----\n./bin/tigase.sh start etc/tigase.conf\n-----\n\n== Tigase - expected output\n\nTo see the log output from Tigase server execute following command:\n\n[source,sh]\n-----\ntail -f logs/tigase-console.log\n-----\n\nAfter transport connects to Tigase server you should see lines like:\n\n[source,bash]\n-----\n2007-05-07 12:29:05\n  ComponentConnectionManager.processHandshake() FINE:\n  Connected to: msn.test-d\n2007-05-07 12:29:05\n  ComponentConnectionManager.updateServiceDiscovery()\n  FINEST: Modifing service-discovery info:\n  <item name=\"XEP-0114 connected\"\n  jid=\"msn.test-d\"/>\n-----\n\n*Note!* There was a bug in the *jabber:iq:register* plugin which caused problems when registering account in transport. Please use build +432+ or later.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_86_-_Using_Tigase_-_H_-_Two_or_more_SessionManagers.asciidoc",
    "content": "[[multiplesessionmanagers]]\n= Two or More SessionManagers\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nIn the most cases just one SessionManager object is used for Tigase server installation. A single SM can handle multiple virtual domains with separate SSL certificates for each domain.\n\nSometimes, however you need a different configuration for each domain. For example, if you wish to use a separate database for a selected domain or you need a different set of plugins for each domain. For one domain you might want to allow user registration via XMPP and for another you might want to disable this feature.  In this case you need to load more than one session manager.\n\nFor Tigase, this is not a problem. You just need to add another component in the configuration and adjust default settings.\n\nThe question is now how does Tigase server know which session manager it has to forward packets received from the network? Keep in mind, there is only one component responsible for handling client connections. So it needs to know which session manager is the receiver for certain packets.  Of course you can set domain names in session manager too, but that may not be enough. Tigase server supports cluster mode configuration where session manager can be run on a separate machine. So packet routings rules cannot be controlled by just the domain name. Therefore client connection manager (*c2s*) must know which session manager is responsible for handling the packet received from the network.\n\nTo solve the problem a *routing* concept has been introduced. You can define packet routings based on the domain name set during XMPP stream initialization.  Each time the *c2s* component receives packet from the network it tries to resolve destination component for the packet based on the current routings table. If you look in you server XML configuration file and search for *c2s* configuration section you can find routing node. Default configuration for the routing table is quite simple, just a single regular expression:\n\n[source,bash]\n-----\n   <node name=\"routings\">\n    <map>\n     <entry key=\".+\" type=\"String\" value=\"sess-man%40tigase.org\"/>\n     <entry key=\"multi-mode\" type=\"Boolean\" value=\"true\"/>\n    </map>\n   </node>\n-----\n\nAs you can see this routing table forwards all packets to a single destination - the session manager located on the *tigase.org* server.\n\nNow let's say we have two session managers, each of them is responsible for a separate +domain.sm1@tigase.org+ handling requests for *tigase.org* and +sm2@tigase.net+ handling requests for domain *tigase.net*. The modifications to the configuration to properly spread the traffic between the two session managers would look like this:\n\n[source,bash]\n-----\n   <node name=\"routings\">\n    <map>\n     <entry key=\"tigase.org\" type=\"String\" value=\"sm1%40tigase.org\"/>\n     <entry key=\"tigase.net\" type=\"String\" value=\"sm2%40tigase.net\"/>\n     <entry key=\"multi-mode\" type=\"Boolean\" value=\"true\"/>\n    </map>\n   </node>\n-----\n\nPlease remember that a key is a regular expression in Java style: link:http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html[Pattern.html]. You can match more than a single domain with the key, for example: _tigase.+_ to match all domains starting with *tigase*. The expression, however won't match domain: *xmpp.tigase.org*. To match this domain the expression would need to be: _.+tigase.+_.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_87_-_Using_Tigase_-_I_-_Watchdog.asciidoc",
    "content": "[[watchdog]]\n= Watchdog\n:author: Wojciech Kapcia\n:date: 2015-10-15 10:50\n:version: v1.0 October, 2015\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nTigase's Watchdog was implemented to help Tigase close connections that have become stale or inactive. Sometimes the connection is delayed, maybe dropped packets, or a service interruption.  After a time, if that connection is re-established, both server and client (or server and server) will continue on as if nothing happened. However, these gaps in connection can last longer, and some installations will rely on the operating system to detect and close stale connections. Some operating systems or environments can take up to 2 hours or more to determine whether a connection is bad and wait for a response from a foreign entity and may not be configured.\nThis can not only slow down performance, but can lead to security issues as well.  To solve this problem, we have introduced Watchdog to monitor connections independent of operating system and environments to keep those broken connections from becoming a problem.\n\n== Setup\nNo extra setup is necessary, Watchdog is already included with your build of Tigase (as long as it's 7.1.0 or newer).  Follow the steps in the configuration section.\n\n== Watchdog Configuration\nTo configure watchdog, the following lines need to be present or edited in init.properties file:\n[source,bash]\n-----\n--watchdog_timeout=70000\n--watchdog_delay=60000\n--watchdog_ping_type=xmpp\n-----\nThe three settings are as follows:\n- +--watchdog_timeout=70000+ This setting sets the amount of time that watchdog will consider before it determines a connection may be stale. This setting sets the timeout at 70000ms or 70 seconds.\n- +--watchdog_delay=60000+ This setting sets how often the watchdog should conduct the check, current setting sets the delay at 60000ms or 60 seconds.\n- +--watchdog_ping_type=whitespace+ This setting determines the type of ping sent to components when watchdog is testing for activity.\n\nYou may, if you choose, to specify individual watchdog settings for specific components by adding them to the component settings, for example if we wanted to change the Client2Server settings to include watchdog, use the following lines in init.properties:\n[source,bash]\n-----\nc2s/watchdog_timeout=3000\nc2s/watchdog_delay=1500\n-----\nIf any settings are not set, the global or settings will be used.\n+watchdog_delay+ default is set to 10 min\n+watchdog_ping_type+ default is set to xmpp\n\n== Logic\nWatchdog compares it's own pings, and records the time it takes for a round trip to different components, clustered connections, and if one variable is larger than the other, watchdog will commence closing that stale connection.\nHere is a breakdown:\n\n. A check is performed of a connection(s) on every +watchdog_delay+ interval.\n. During this check two things occur\n  * If the last transfer time exceeds +max-inactivity-time+ a stop service command is given to terminate and broadcast unavailable presence.\n  * If the last transfer time is lower than +max-inactivity-time+ but exceeds +watchdog_timeout+ watchdog will try to send a ping (of +watchdog_ping_type+).\n  This ping may be one of two varieties (set in init.properties)\n    - +whitespace+ ping which will yield the time of the last data transfer in any direction.\n    - +xmpp+ ping which will yield the time of the last received xmpp stanza.\n. If the 2nd option is true, the connection will remain open, and another check will begin after the +watchdog_delay+ time has expired.\n\nFor example, lets draw this out and get a visual representation\n\nThis line represents how often the check is performed. Each - is 10 seconds, so the check is done every 60 seconds (watchdog_delay=60000)\n-----\n-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------\n\n     |     |     |     |     |     |     |     |     |     |     |\n-----\n\nThis line is client activity, here the client has sent a message at 20 seconds and has gone idle. +\n\n-----\n-+------------------------------------------------------------------\n-----\n\nThe following line represents the logic, with settings set at: +watchdog_timeout=120000 | +c2s/max-inactivity-time[L]=180000+ (timeout at 120 seconds and max inactivity timeout at 180 seconds)\n\n-----\n 1   2     3     4     5     6\n-*---*-----*-----*-----*-----*\n-----\n\n1 - 20 seconds - at this point \"last transfer\" or \"last received\" time is updated. +\n2 - 60 seconds - watchdog runs - it check the connection and says \"ok, last client transfer was 20s ago - but it's lower than both inactivity (so don't disconnect) and timeout (so don't send ping). +\n3 - 120 seconds - 2nd check - last transfer was 100s ago - still lower than both values - do nothing. +\n4 - 180 seconds - 3rd check - last transfer was 160s ago - lower than inactivity but greater than delay - ping it sent. +\n5 - 240 seconds - 4th check - last transfer was 220s ago - client still has not responded,  watchdog compares idle time to +max-inactivity-timeout+ and finds that it is greater, connection is terminated. +\n\nIt is possible that the connection is broken, and could be detected during the sending of a ping and the connection would be severed at step 4 instead of waiting for step 5.  *NOTE* This MAY cause JVM to throw an exception.\n\n\n*NOTE: Global settings may not be ideal for every setup. Since each component has its own settings for +max-inactivity-time+ you may find it necessary to design custom watchdog settings, or edit the inactivity times to better suit your needs.  Below is a short list of components with thier default settings:*\n\n-----\nbosh/max-inactivity-time[L]=600\nc2s/max-inactivity-time[L]=86400\ncl-comp/max-inactivity-time[L]=180\ns2s/max-inactivity-time[L]=900\nws2s/max-inactivity-time[L]=86400\n-----\n\nAgain remember, for Watchdog to properly work, the +max-inactivity-time+ MUST be longer than the +watchdog_timeout+ setting\n\n\n== Testing\nThe tigase.log.0 file can reveal some information about watchdog and how it is working (or how it might be fighting your settings). To do so, enter the following line into your init.properties file:\n-----\n--debug=server,xmpp.init\n-----\n\nThis will set debug mode for your log, and enable some more information about what Tigase is doing.  These logs are truncated for simplicity. Lets look at the above scenario in terms of the logs:\n\nStage Two +\n2015-10-16 08:00:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: user@xmpp.domain.org/mobile, sinceLastTransfer: 20,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP\n\nStage Three +\n2015-10-16 08:01:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: user@xmpp.domain.org/mobile, sinceLastTransfer: 100,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP\n\nStage Four +\n2015-10-16 08:02:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: user@xmpp.domain.org/mobile, sinceLastTransfer: 160,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP +\n2015-10-16 08:02:00.697 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: user@xmpp.domain.org/mobile, sending XMPP ping from=null, to=null, DATA=<iq from=\"xmpp.domain.com\" id=\"tigase-ping\" to=\"user@xmpp.domain.com/mobile\" type=\"get\"><ping xmlns=\"urn:xmpp:ping\"/></iq>, SIZE=134, XMLNS=null, PRIORITY=NORMAL, PERMISSION=NONE, TYPE=get\n\nStage Five +\n2015-10-16 08:03:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: user@xmpp.domain.org/mobile, sinceLastTransfer: 100,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP +\n2015-10-16 08:03:00.248 [pool-20-thread-6]  ConnectionManager.serviceStopped()  FINER:  [[c2s]] Connection stopped: c2s@xmpp./domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@lenovo-z585/192.168.0.150_5222_192.168.0.201_50368 Socket[unconnected], jid: user@xmpp.domain.com +\n2015-10-16 08:03:00.248 [pool-20-thread-6]  ClientConnectionManager.xmppStreamClosed()  FINER: Stream closed: c2s@xmpp.domain.com/192.168.0.150_5222_192.168.0.201_50368\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_88_-_Using_Tigase_-_J_-_Tips_and_Tricks.asciidoc",
    "content": "[[tipsAndTricks]]\n= Tips and Tricks\n:author: Daniel Wisnewski\n:version: v1.0\n:date: 2015-13-07 11:32\n\n:toc:\n\nThe section contains some short tricks and tips helping in different kinds of issues related to the server administration and maintenance.\n\n- xref:tigaseTip_RuntimeEnvironment[Runtime Environment Tip]\n- xref:bestWebPrax [Best Practices for Connecting to Tigase XMPP server From Web Browser]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_89_-_Using_Tigase_-_J_-_Tips_and_Tricks_-_1_-_Tigase_Tip_Checking_the_Runtime_Environment.asciidoc",
    "content": "[[tigaseTip_RuntimeEnvironment]]\n= Tigase Tip: Checking the Runtime Environment\n:author:  not known\n:version: v1.0 inital ver\n:date: not known\n\n\n:toc:\n\nIt has happened recently that we have tried very hard to fix a few annoying problems on one of the Tigase installations. Whatever we did, the problem still existed after uploading a new version and restarting the server. It worked fine in our development environment and it just didn't on the target system.\n\nIt turned out that due to specific environment settings on the target system, an old version of Tigase server was always started regardless of what updates uploaded. We finally located the problem by noticing that the logs were not being generated in the proper locations.  This led us to finding the issue: improper environment settings.\n\nThe best way to check all the environment settings used to start the Tigase server is to use..... *check* command line parameter:\n\n[source,sh]\n-----\n./scripts/tigase.sh check etc/tigase.conf\nChecking arguments to Tigase\nTIGASE_HOME = .\nTIGASE_JAR = jars/tigase-server.jar\nTIGASE_PARAMS = etc/tigase.conf\nTIGASE_CONFIG = etc/tigase.xml\nTIGASE_RUN = tigase.server.XMPPServer -c etc/tigase.xml --property-file etc/init.properties\nTIGASE_PID = ./logs/tigase.pid\nTIGASE_OPTIONS = --property-file etc/init.properties\nJAVA_OPTIONS = -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 \\\n    -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver \\\n    -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m\nJAVA = /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java\nJAVA_CMD =\nCLASSPATH = ./jars/tigase-server.jar:./libs/jdbc-mysql.jar:./libs/jdbc-postgresql.jar:\\\n    ./libs/tigase-extras.jar:./libs/tigase-muc.jar:./libs/tigase-pubsub.jar:\\\n    ./libs/tigase-utils.jar:./libs/tigase-xmltools.jar\nTIGASE_CMD = /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java \\\n    -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 \\\n    -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver \\\n    -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m \\\n    -cp ./jars/tigase-server.jar:./libs/jdbc-mysql.jar:./libs/jdbc-postgresql.jar:\\\n    ./libs/tigase-extras.jar:./libs/tigase-muc.jar:./libs/tigase-pubsub.jar:\\\n    ./libs/tigase-utils.jar:./libs/tigase-xmltools.jar tigase.server.XMPPServer \\\n    -c etc/tigase.xml --property-file etc/init.properties\nTIGASE_CONSOLE_LOG = ./logs/tigase-console.log\n-----\n\nIn our case *TIGASE_HOME* was set to a fixed location pointing to an old version of the server files. The quick *check* command may be a real time saver.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_91_-_Using_Tigase_-_J_-_Tips_and_Tricks_-_3_-_Best_Practices_for_Connecting_From_Web_Browser_to_Tigase_XMPP_Server.asciidoc",
    "content": "[[bestWebPrax]]\n== Best Practices for Connecting to Tigase XMPP server From Web Browser\n:author: Andrzej Wojcik <andrzejw@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-12-15 19:27\n:version: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nCurrently we have 2 ways to connect to Tigase XMPP Server from web browsers:\n\n. BOSH (Bidirectional-streams Over Synchronous HTTP)\n. WebSocket (XMPP over WebSocket)\n\nYou will find more informations about these ways for connecting to Tigase XMPP Server with some useful tips below.\n\n== BOSH\nBOSH protocol specified in link:http://xmpp.org/extensions/xep-0124.html[XEP-0124] is one of first protocols defined to allow to establish XMPP connection to XMPP servers from web browsers due to this protocol being widely supported and used. It is also easy to use in single server mode. It's enabled by default in Tigase XMPP Server and available at port 5280.\n\nIn clustered mode we can deploy it with load balancer deployed with guarantees that each BOSH connection from web browser will be forwarded to same Tigase XMPP Server instance. So in clustered mode if we have two XMPP server +t1+ and +t2+ which are hosting domain +example.com+ we would need to have load balancer which will respond for HTTP request to domain +example.com+ and forward all requests from same IP address to same node of a cluster (i.e. all request from +192.168.122.32+ should be forwarded always to node +t1+.\n\n[[tip_1_bosh_in_cluster_mode_without_load_balancer]]\n=== Tip #1 - BOSH in Cluster Mode Without Load Balancer\n\nThere is also a way to use BOSH without load balancer enabled. In this case the XMPP client needs to have more logic and knowledge about all available cluster nodes (with names of nodes which will identify particular cluster nodes from internet). Using this knowledge XMPP client should select one random node from list of available nodes and always establish BOSH connections to this particular node. In case if BOSH connection fails due to network connection issues, the XMPP client should randomly pick other node from list of rest of available nodes.\n\n_Solution:_\n\nTigase XMPP Server by default provides server side solution for this issue by sending additional +host+ attribute in +body+ element of BOSH response. As value of this attribute Tigase XMPP Server sends domain name of server cluster node to which client connected and to which next connections of this session should be opened.\nIt is possible to disable this custom feature by addition of of following line to +etc/init.properties+ config file:\n\n+bosh/send-node-hostname[B]=false+\n\n_Example:_\n\nWe have servers +t1.example.com+ and +t2.example.com+ which are nodes of a cluster hosting domain +example.com+. Web client retrieves list of cluster nodes from web server and then when it needs to connect to the XMPP server it picks random host from list of retrieved cluster nodes (i.e. +t2.example.com+) and tries to connect using BOSH protocol to host +t2.example.com+ but it should send +example.com+ as name of the server it tries to connect to (+example.com+ should be value of +to+ attribute of XMPP stream).\n\n== WebSocket\nWebSocket protocol is newly standardized protocol which is supported by many of current versions of browsers. Currently there is a draft of protocol link:https://datatracker.ietf.org/doc/draft-ietf-xmpp-websocket/[draft-ietf-xmpp-websocket-00] which describes usage of WebSocket to connect to XMPP servers. Tigase XMPP Server implementation of WebSocket protocol to connect to XMPP server is very close to this draft of this specification. By default Tigase XMPP Server has XMPP-over-WebSocket protocol enabled without encryption on port 5290. To use this protocol you need to use library which supports XMPP-ober-WebSocket protocol.\n\n=== Tip #1 - Encrypted WebSocket Connection\n\nIt is possible to enable encrypted WebSocket connection in Tigase XMPP Server. To do this you need to add following lines to +etc/init.properties+ config file:\n[source,xml]\n-----\nws2s/connections/ports[i]=5290,5291\nws2s/connections/5291/socket=plain\nws2s/connections/5291/type=accept\nws2s/connections/5290/socket=ssl\nws2s/connections/5290/type=accept\n-----\nIn this example we enabled WebSocket endpoint on port 5290 allowing unencrypted connections, and encrypted WebSocket endpoint on port 5291.\nAs this is TLS/SSL connection (no STARTTLS) it uses default certificate installed in Tigase XMPP Server instance. This certificate is located in +certs/default.pem+.\n\n*NOTE* There is no default configuration for non-default ports.  All ports outside 443 MUST be configured.\n\n=== Tip #2 - Encrypted WebSocket Connection - Dealing With Multiple VHosts\nAs mentioned in Tip #1 WebSocket endpoint is plain TLS/SSL port, so it always serves default certificate for Tigase XMPP Server instance. That is ok if we are hosting single domain and if default certificate matches matches our domain. But If we host multiple domain we cannot use +wss://example1.com:5291/+ connection URL, if our default certificate is for domain +example2.com+. In this situation it is recommended to use the default certificate for the domain under which the server is accessible from the internet. This domain should identify this server, so this domain would not point to two nodes of a cluster. After we deploy separate certificate for each of cluster nodes, we should follow same tip as Tip #1 for BOSH. Our web-based XMPP client should have knowledge about each node of a cluster and when it needs to connect it should randomly select one node from list of available cluster nodes and try to connect using connection URL that would contain name of server under which it can be identified from internet.\n\n_Example:_\n\nWe have servers +t1.example1.com+ and +t2.example1.com+ which are nodes of a cluster in hosting domain +example2.com+. Each of our nodes contains default SSL certificate with domain names matching the cluster node. Web client retrieves list of cluster nodes from web server and then when it needs to connect to XMPP server it picks random host from list of retrieved cluster nodes (i.e. +t2.example1.com+) and tries to connect using WebSocket encrypted protocol to host +t2.example1.com+ using the following URL: +wss://t2.example1.com:5291/+. Upon connection the client should still send example2.com as name of server to which it tries to connect (+example2.com+ should be value of to attribute of XMPP stream). This will allow browser to validate certificate as it will be for the same domain to which browser connects, and it will allow XMPP client to connect to domain +example2.com+, which is one of hosted vhosts.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_92_-_Using_Tigase_-_K_-_Command_Line_Tools.asciidoc",
    "content": "[[commandLineTools2]]\n= Command Line Admin Tools\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:vesion: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTwo command line tools have been created to make it easier to manage server configurations and user repositories.\n\nConfiguration tool allows to look at configuration settings and modify parameters. It takes care of proper parameters types and encoding.\n\nRepository management tool allows to print repository content for all or for selected users. Modify repository data, add, delete users and copy data from one repository to another.\n\nThis guide describe how to efficiently use command line tools which are available for user repository and configuration management.\n\nThese 2 command line tools for managing configuration and repository are:\n\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/scripts/config.sh[config.sh] for configuration management.\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/scripts/repo.sh[repo.sh] for repository management.\n\nBoth scripts call class from Tigase package. If you run any of those script with *-h* parameter you will get help screen describing all available parameters.\n\nI will not concentrate on that help information which is easily accessible anyway. This guide will focus on particular use cases. So it will answer the question: \"How to do use the tool?\".\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_93_-_Using_Tigase_-_K_-_Command_Line_Tools_-_1_-_Configuration_Managament_Tool.asciidoc",
    "content": "[[configurationManagement2]]\n= Configuration Management Tool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nThe configuration tool allows a user to look at configuration settings and modify parameters.\n\nFirst, an answer to the question: \"Why use this configuration tool instead of directly, manually editing the config file?\"\n\nThere are a couple of reasons why you should NOT manually edit configuration file and use the tool instead to modify settings:\n\n. Configuration is kept in XML file which can be easily broken if not edited carefully. The tool takes care of creating valid XML configuration file for you. So you can focus on your task - setting proper parameters for your server.\n. Configuration values are kept *UUEncoded* in the config file. If you edit file manually you have to take care of proper encoding of special characters. The tool presents parameters to you in decoded form which is easy to read and can accept all settings also in decoded form which is easier for you to write. Then when writing your parameters to configuration file settings are automatically encoded to correct form.\n. Data in configuration file have *TYPES*. That is some parameters are expected to be *Strings* other are expected to be *Integers*, *Booleans* or arrays keeping data in any of that type. If data type is set incorrectly then Tigase may have problems with reading configuration data. The configuration tool takes care of proper data types in configuration file.\n\nConfiguration management tool is a Java class - link:http://server.tigase.org/browser/trunk/src/tigase/conf/Configurator.java[tigase.conf.Configurator]. To make it easier to use this class there is also shell script available - link:http://server.tigase.org/browser/trunk/scripts/config.sh[config.sh].\n\nFirst thing you can do is running the script with +-h+ parameter:\n\n[source,sh]\n-----\n./scripts/config.sh -h\n-----\n\nIn response you get description of all available parameters:\n\n[source,sh]\n-----\nParameters:\n -h             this help message\n -c file        configuration file\n -key key       node/key for the value to set\n -value value   value to set in configuration file\n -set           set given value for given key\n -add           add given value to the values list for given key\n -print         print content of all configuration settings or of given node/key\n -f             force creation of the new property - dangerous option...\nSamples:\n Setting admin account - overwriting any previous value(s)\n $ ./scripts/config.sh -c tigase-config.xml -print -set -key session_1/admins -value admin1@localhost\n Adding next admin account leaving old value(s)\n $ ./scripts/config.sh -c tigase-config.xml -print -add -key session_1/admins -value admin2@localhost\n\nNote: adding -print option is useful always, even with -set or -add\n      option as it prints set value afterwards.\n-----\n\nLet's assume configuration for your server is located in *tigase-config.xml* file. So the first thing you need to set when calling the tool is location of the configuration file.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_94_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase.asciidoc",
    "content": "[[scriptsupport]]\n= Scripting support in Tigase\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nTigase server supports scripting languages in versions 4.3.1 and higher. These pages describe this feature in details how to create new scripts, upload them to the server, and execute them. The guide also contains API description with code examples.\n\n*PLEASE NOTE* Tigase server is known for it very low memory consumption and successfully runs with less then 10MB of RAM memory. However adding scripting support for any non-standard (default) language to Tigase server significantly increases memory requirements for the installation. You cannot expect Tigase server to run on 10MB RAM system if you enabled Python, Scala or any other non-standard language.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_95_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_1_-_Scripting_Introduction_-_Hello_World.asciidoc",
    "content": "[[scriptingintro]]\n= Scripting Introduction - Hello World!\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nimage:images/tiger3-small.png[]\n\nThis document is the first in a series describing scripting support in the Tigase server showing how to load, install, update and call a script. It contains also an introduction to the scripting API with the first \"Hello world!\" example.\n\nSince Tigase version 4.3.1 the server supports scripting for administrator commands as well as standard commands.\n\nIn theory many different languages can be used to write scripts and the only requirement is that support link:http://www.jcp.org/en/jsr/detail?id=223[JSR-223] for the language is installed. More details can be found on the link:https://scripting.dev.java.net/[Java scripting project site].\n\nIn practice some languages are better supported than others, at the moment we recommend link:http://groovy.codehaus.org/[Groovy]. However the following languages are also confirmed to be working: link:http://www.scala-lang.org/[Scala], link:http://www.python.org/[Python] and link:http://www.ruby-lang.org/en/[Ruby]. The link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/src/main[Tigase SVN] contains a few examples for these languages.\n\nPlease note, the default Tigase installation contains only libraries for Groovy. Adding support for a different language is as simple as copying a few JAR files to the Tigase *libs/* directory.\n\nAll the examples presented in this guide are also available as ready to use scripts in the Tigase SVN repository in directory: link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/src/main/groovy/tigase/admin[src/main/groovy/tigase/admin].\n\nThe scripting utilizes only standard XMPP extensions and is by no means specific to any particular solution. We use and prefer Psi client. The whole guide and all the screen-shots are created using Psi client. You can, however, use any other client which supports these extensions as well. As the whole thing is based on the service discovery and ad-hoc commands you need a XMPP client with a good support for both features.\n\nTo follow the guide and run all the examples you need will need to have installed Tigase server version 4.3.1 or newer and you have to connect to the server as administrator.\n\n== Loading Script at Run Time\nAll the scripting stuff is usually based on the service discovery and ad-hoc commands in the Tigase server.\n\nimage:images/service-disco.png[]\n\nThe first thing to do, therefore, is to browse service discovery on the running server. The result you receive will depend on your installation and installed components.\n\nThe most interesting things right now are all items with \"*http://jabber.org/protocol/admin*\" in their node part. You may have a few scripts loaded already but there are two commands used for scripting management. Their names are descriptive enough: \"*New command script*\" and \"*Remove command script*\".\n\nThe first is for adding a new script or updating existing and the second is for removing script from the server.\n\nTo add a new script you have just to execute \"*New command script*\". In Psi this is done by double clicking on the element in service discovery list.\n\nimage:images/hello1-new-script.png[]\n\nThe screenshot above shows a couple of options to set for the loaded script:\n\n- *Description* - is what shows as the script name in the service discovery window. There are no special restrictions on what to put there.\n- *Command id* - is a unique ID of the script (admin command). This is what shows after the \"http://jabber.org/protocol/admin\" in node part. This needs to be unique or existing script is overwritten.\n- *Language* - a drop down list of all supported scripting languages for your installation. Tigase automatically detects all libraries for scripting languages and lists them here. So all you need is to select the correct language for your script.\n- *Script text* - is just your script content.\n\nWhen your script is ready and all fields are correctly set, simply press \"*Finish*\" button and you should receive a message confirming that the script has been loaded successfully.\n\nimage:images/loaded-ok-small.png[]\n\nIn this guide we are creating a simple \"Hello world\" script written in Groovy. What it does is displays a window (ad-hoc command result) with a message: \"_Hello admin, how are you?_\".\n\nIt uses a basic scripting API which is described line by line below:\n\n. It imports basic Tigase classes.\n. Set's a local variable \\'+p+' which points to a \\'+packet+' variable with data received from the client.\n. Creates a \\'+res+' variable which is response sent back to the client (administrator). The response to the client is of type \\'+result+'. Other possible types will be introduced later.\n. We operate on ad-hoc commands here so the script uses Tigase utility class to set/retrieve command parameters. It sets the window title and a simple message displayed to the user (administrator).\n. The last line returns new packet as a script execution result.\n\nThe first, very simple version looks like this:\n\n[source,java]\n-----\nimport tigase.server.*\ndef p = (Packet)packet\ndef res = p.commandResult(Command.DataType.result)\nCommand.addTitle(res, \"Hello World Script\")\nCommand.addInstructions(res, \"Hello admin, how are you?\")\nreturn res\n-----\n\n== Executing Script\nOnce the script is successfully loaded you will have to reload/refresh the service discovery window which now should display one more element on the list.\n\nimage:images/service-disco-with-new-hello.png[]\n\nAs you can see script name is set to what you have entered as \"Description\" in script loading window - \"_Hello world script_\". The command node is set to: \"http://jabber.org/protocol/admin#hello\" if \"*hello*\" is what is set as the script ID.\n\nTo execute the script you just have to double click on the script name (or click execute command if you use any other client).\n\nAs a result you should see a simple window similar to the screenshot below displaying our message.\n\nimage:images/hello1-result-small.png[]\n\n== Interaction in Scripts\nDisplaying just a message is very nice but is not very useful in most cases. Normally you need to ask the user for some more data or parameters before you can perform any real processing.\n\nTherefore in most cases the administrator script has to display a new window with input fields asking the user for some more data. In this document we present very simple examples, just an introduction so let's ask about the administrator name before displaying a greeting.\n\nimage:images/hello2-asking-for-name-small.png[]\n\nTo ask the user for some more information we have to extend example above with some more code:\n\n[source,java]\n-----\nimport tigase.server.*\n\ndef p = (Packet)packet\n\ndef name = Command.getFieldValue(packet, \"name\")\n\nif (name == null) {\n  def res = p.commandResult(Command.DataType.form);\n  Command.addTitle(res, \"Hello World Script\")\n  Command.addInstructions(res, \"Please provide some details\")\n  Command.addFieldValue(res, \"name\", name ?: \"\", \"text-single\",\n    \"Your name\")\n  return res\n}\n\ndef res = p.commandResult(Command.DataType.result)\nCommand.addTitle(res, \"Hello World Script\")\nCommand.addInstructions(res, \"Hello ${name}, how are you?\")\n\nreturn res\n-----\n\nIf you compare both scripts you see that they are quite similar. Before displaying greeting, however, the script tries to retrieve data from the \\'+name+' input field. If the name had been provided the greeting is displayed, otherwise the script asks for the user name.\n\nimage:images/hello2-result-small.png[]\n\nPlease note, in this case the packet sent back to the user is of type form instead of +result+. The practical difference is that the type +result+ displays only *OK* button which when pressed doesn't send any data to the server. The form packet displays more buttons - *Finish* and *Cancel*. Whichever you press some data is sent back to the server.\n\nThis script demonstrates use of two new methods from the utility class \"Command\": getFieldValue and addFieldValue.\n\n- The first argument to all Command methods is the packet with ad-hoc command.\n- The second argument is usually the input field name\n\nThese two method parameters are actually enough to read the ad-hoc command data. Methods creating input fields in the ad-hoc command need a few arguments more:\n\n- Next arguments sets a default value displayed to the user. The way to it is set in the example above is specific to Groovy language and is quite useful what will be apparent in later examples.\n- After that we have to specify the field type. All field types are defined in the link:http://xmpp.org/extensions/xep-0004.html#protocol-fieldtypes[XEP-0004] article.\n- The last argument specifies the field label which is displayed to the user.\n\nimage:images/hello2-new-script.png[]\n\nThere are a few other different utility methods in the Command class to set different types of input fields and they will be described in details later on.\n\nTo reload the script simply call \"New command script\" again, enter the script text and make sure you entered exactly the same command ID to replace the old script with the new one.\n\nOr of course, you can enter a new command id to create a new command and make it available on your server.\n\nWhen the script is loaded on the server, try to execute it. You should get a new dialog window asking for your name as in the screenshot at the beginning of this section. When you have entered your name and clicked the \"Finish\" button you will see another window with a greeting message along with your name.\n\n== Automatic Scripts Loading at Startup Time\nThe last thing described in this guide is how to automatically load your scripts when the Tigase server starts. The ability to load scripts at run time, update and remove remove them is very useful, especially in emergency cases if something wrong is going on and you want to act without affecting the service.\n\nIf you, however have a few dozens scripts you don't want to manually load them every time the server restarts.\n\nTigase server automatically loads all scripts at the startup time which are located in the admin scripts directory. Unless you set it differently in the configuration it is: *YourTigaseInstallationDir/scripts/admin/*. All you have to do is to copy all your scripts to this directory and they will be loaded next time the server starts.\n\nBut hold on. What about the script parameters: language, description, command id? How are you supposed to set them?\n\nLanguage is simple. It is detected automatically by the script file extension. So just make sure file extensions are correct and the language is sorted.\n\nThe script description and command id needs a little bit more work. You have to include in your script following lines:\n\n[source,java]\n-----\nAS:Description: The command description\nAS:CommandId: command-id\nAS:Component: comp_name\n-----\n\nPlease note, there must be at least a single space after the \"+AS:Description:+\" or \"+AS:CommandId:+\" string. Everything rest after that, until the end of the line, is treated as either the script description or command id. Put these in your script file and the loader will detect them and set correctly for your script.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_96_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_2_-_Tigase_Scripting_Version_4.4.x_Update_for_Administrators.asciidoc",
    "content": "[[newElements]]\n= Tigase Scripting Version 4.4.x Update for Administrators\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:18\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nimage:images/tiger-looking-left-small.png[]\n\nScripting functionality is quite useful in Tigase server for all sorts of administrator tasks. The possibility to load new scripts or replace old ones at the server runtime opens quite new area for the service maintenance.\n\nIn earlier versions of the Tigase server scripting capabilities was available only in the session manager component while it might be very useful in many other places - connection managers, MUC, PubSub, VHostManager and what even more important in completely new, custom components created for specific needs. It would be quite wasteful to reinvent the wheel every time and implementing scripting capabilities for each component separately.\n\nTherefore the scripting capabilities has been implemented in the core of the Tigase server. It is now part of the API and is automatically available to all components without any additional coding. A detailed developer guide will be published separately.\n\nThis document describes changes from the user/administrator perspective because there are some usability changes related to the new implementation.\n\nPlease note. The description and screenshots are taken from the Psi client and most likely interface for ad-hoc commands and service discovery on other client looks different. I recommend to do some initial testing and experiments using Psi client and then switch to your preferred application for your day-to-day use.\n\nAs it always was in the Tigase you can access all the functions via XMPP service discovery on the server. However, as soon as you connect to the server you can see some changes there.\n\nimage:images/new-service-disco-admin.png[]\n\nThere are no command on the list. They are hidden from the main service discovery list. You can see on the list only the server main components.\n\nThis had to be done for many reasons. One of them is, obviously, the cleaner access to the main server stuff. Another, probably more important, is to avoid a long list of commands for different components mixed together. Commands for different components can have the same name/description and they can even do similar things but they are executed on a different server component. To avoid any confusion and minimise opportunities for mistake the commands are now closely tight to their components. To access a list of commands for a particular component you have to double click on the component name on the list or click 'Execute command\" icon on top of the window when your component is selected.\n\nA new window should show up with drop-down list of available commands. All the commands are related to the selected component and are executed kind of \"inside the component environment\". You can of course add new command or delete existing one and of course execute any of the commands showing on the list.\n\nimage:images/new-command-list.png[]\n\nAs a reminder, in the window title you can see the component ID and you should check it before running any command to make sure you accidentally don't break your system.\n\nimage:images/new-add-command.png[]\n\nThere has been also a small change made to the script adding window. As you can see on the screenshot there is one additional option added - \"Save to disk\". This means that once you submitted the script to the server it is written to the hard drive and will be automatically loaded at next startup time.\n\nThis option is enabled by default as this seems to be a logical choice that the administrator wants to save his new script for later reuse. This, however requires proper configuration of the server and give writing permission to the directory where all scripts are stored. Otherwise the server won't be able to write script files on the hard drive.\n\nAs in previous version only users with administrator permissions can execute commands and access all the critical elements on the server. There has been, however, another change made, long time requested by users. In the new version all the administrator specific elements are hidden for the rest of users.\n\nServer components don't show up on the service discovery, the user can't see administrator commands nor he can execute them. This hasn't been implemented to improve the server security but to reduce confusion for general users who would otherwise see a lot of stuff which can't be used by them anyway.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_97_-_Using_Tigase_-_L_-_Scripting_Support_in_Tigase_-_3_-_Tigase_and_Python.asciidoc",
    "content": "[[tigaseandPython]]\n= Tigase and Python\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n//below line moved since page is not available\n//Looking in the link:http://www.tigase.org/content/what-scripting-language-you-would-use-admin-commands-tigase[last poll] it is clear that the most people are mainly interested in Python support in the Tigase server.\n//link below needs updating\nAs I mentioned in link:http://www.tigase.org/content/scripting-introduction-hello-world[one of previous articles], Tigase supports virtually any scripting language as long as there is link:http://www.jcp.org/en/jsr/detail?id=223[JSR-223] support for that language.\n\nThis article describes how to get Python working as a scripting language for ad-hoc commands in Tigase server. The first part is installation, and the second shows a few code examples with explanation of the differences between Python usage and some other languages.\n\n_Please note, we are not a Python developer, and by no means this is Python development guide. All the code examples are used only to present the API available and there are certainly better ways to do it in the proper Python style. If you have any suggestions or have a better code examples I am happy to include them in the guide._\n\n== Installation\nIn short, installation is extremely simple: just copy the file attached to this article to your Tigase installation, to the +libs/+ directory. Restart the server and you are ready to start scripting and executing Python.\n\nIn theory the Tigase offers scripting support defined in link:http://www.jcp.org/en/jsr/detail?id=223[JSR-223]. You can use any language for which there is such support for JVM. This includes also stand-alone python implementations and the JSR-223 plugins acts just as a bridge. This, however, does not make much sense as you are not able to interact with JVM code (Tigase API). Therefore you need a language which is executed within JVM and can easily exchange data between the main application (Tigase server) and the script.\n\nimage:images/lang-list-no-python-small.png[]\n\nThe best way to go is to use Jython implementation. It works very well within JVM and more importantly, perfectly integrates with Tigase server. Tigase server is tested with *Jython-2.2.1* and is confirmed to work fine. Version *Jython-2.5.1* is recommended however, and all the examples are executed with this version installed. Please note, _Jython-2.5.0_ does not work at all. Both supported versions can be downloaded from the link:http://wiki.python.org/jython/DownloadInstructions[Jython website].\n\n*Version 2.5.1* is a bit simpler to install. When you download and run the Jython installer, find +jython.jar+ file in the directory where you installed Jython. Copy the file to the Tigase's *libs/* directory and all is ready to go. Please note, this is the same file as the one attached to this article for your convenience.\n\n*Version 2.2.1* needs a little bit more work. The first part is the same. It is not, however enough to copy the +jython.jar+ file. One more file is necessary for the Jython to work with the Tigase server. You have to install JSR-223 engine separately which can be downloaded from the link:https://scripting.dev.java.net/[Java scripting project website]. The binary file has to be unpacked and +jython-engine.jar+ file needs to be copied to the Tigase +libs/+ directory.\n\nThe best way to check if the Jython is installed correctly and support for Python is enabled, is by trying to submit a new script to the Tigase server. Browser the server service discovery, select \"_Session manager_\" component and run \"_Execute command_\" function. A new window should show with a list of all available ad-hoc commands. Select \"_New command script_\" item and click \"_Execute_\". Ad-hoc command dialog windows should show up. One of the field is \"_Language_\" with pull down list of available scripting languages. If \"_python_\" is on the list it means everything is ok and support for Python is enabled.\n\nimage:images/lang-list-with-python-small.png[]\n\n== Writing Python Scripts\nPython scripts work in a similar way to Groovy or other languages scripts, except one significant difference. You cannot call \"_return_\" from the script itself. Hence you cannot simply pass script results by calling \"_return_\" statement directly from the script.\n\nTo overcome the problem, Tigase offers another way to pass script execution results. It checks the value of a special variables on the script completion: \"+result+\" and \"+packet+\". By assigning value to one of these variables the Python (or any other language) can pass execution results back to the Tigase server.\n\n- \"+result+\" allows to return simple text (or characters String) from the script.\n- \"+packet+\" allows to return Packet instance which is send back to the user.\n\nThe simplest possible Python script may look like this one:\n\n+result = \"Hello world!\"+\n\nFor instructions how to load and execute the script, please refer to the xref:scriptingintro[introductory article] for scripting in Tigase server. There were some minor changes in Tigase 4.4.0 and later versions, so please have a look at the xref:newElements[article] describing new elements as well.\n\nAn example of a more advanced script asks the user for providing required parameters for the actual script execution:\n\n[source,java]\n-----\nfrom java.lang import *\nfrom tigase.server import *\n\nnum1 = Command.getFieldValue(packet, \"num1\")\nnum2 = Command.getFieldValue(packet, \"num2\")\n\nif num1 is None or num2 is None:\n  res = Iq.commandResultForm(packet)\n  Command.addTextField(res, \"Note\", \"This is a Python script!\")\n  Command.addFieldValue(res, \"num1\", \"\")\n  Command.addFieldValue(res, \"num2\", \"\")\n  packet = res\nelse:\n  result = num1 + num2\n-----\n\nExcept this minor difference, the rest part of scripting in Python for the Tigase administrator commands is the same as all other languages. As all languages can return execution results via these special variables, it could be argued there is no difference at all.\n\nlink:http://docs.tigase.org/tigase-server/snapshot/Development_Guide/html_chunk/cil6.html[In another article], I am going to present the Tigase server API available for scripting framework. My main language is Groovy as it offers the best integration with JVM and Tigase API, however I will try to include Python example code as well.\n\nI hope this article encourages you to try the scripting support in the Tigase server. If you have any suggestions or questions please do not hesitate to send me your comments. I have also created a new link:http://www.tigase.org/forums/tigase-scripts[tigase scripts] forum on the website. If you have an interesting script to share or want to discuss some aspects of this functionality do not hesitate to add your post.\n\n- link:files/jython-2.5.1.jar[jython-2.5.1.jar] 6.44 MB\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_98_-_Using_Tigase_-_M_-_Configuration_Wizards.asciidoc",
    "content": "[[tigase3xconfiguration]]\n= Configuration Wizards\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nFrom build #247 you can use configuration generators to easily and quickly create configuration files for every complex case.\n\nConfiguring *Tigase* is not too easy to understand and maintain. Even with current command line tools you still have to know what the all options are for.\n\nTo make it easier for average administrators or people who run the server for the first time or even for those who want to quickly test *Tigase* server in different scenarios configuration generators have been created. For each generator you can have also a few extra options which allows you to create configuration which you don't need to change for some time.\n\nA few definitions first to make it easier to read the rest:\n\n. *sm* - session manager component.\n. *c2s* - client connection manager component\n. *s2s* - server connection manager component\n. *ext2s* - external component connection manager\n. *ssender* - xref:stanzaSender[StanzaSender component]\n\nThe are 4 generators currently available:\n\n. +--gen-config-all+ - creating configuration file with all available components. That is: +sm, c2s, s2s, ext2s, ssender+.\n. +--gen-config-default+ - creating default configuration file. That is configuration which is most likely needed for basic installation. Components included in configuration are: +sm, c2s, s2s+.\n. +--gen-config-sm+ - creating configuration for instance with session manager and external component only. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: +sm+ and +ext2s+.\n. +--gen-config-cs+ - creating configuration for instance with components managing network connections. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: +c2s, s2s, ext2s+.\n\nFor each of above generators you can use additional parameters specifying other configuration details like database type you want to connect to, virtual hosts you want to support, administrator accounts and details for external component connection:\n\n- +--user-db+ db-type - where 'db-type' can be one of possible values: *mysql, pgsql, xml*\n\n- +--user-db-uri+ +connection-uri+ - where 'connection-uri' is a full resource uri for user repository data source. If you skip this parameter default value is used depending on database type you selected:\n+\n -- jdbc:mysql://localhost/tigase?user=root&password=mypass\n -- jdbc:postgresql://localhost/tigase?user=tigase\n -- user-repository.xml\n+\n- +--auth-db+ +db-type+ - where 'db-type' can be one of possible values: *mysql, pgsql, xml, drupal, libresource* (If omitted 'user-db' settings are used.)\n\n- +--auth-db-uri+ +connection-uri+ - where 'connection-uri' is a full resource uri for user repository data source. (If omitted 'user-db-uri' settings are used.)\n\n- +--ext-comp+ +connection-string+ - possible values: connection string 'localdomain,remotedomain,port,passwd,plain/ssl,accept/connect,routing'\n+\n*Note:* It is also possible to generate configuration for many external components. To do so place +--ext-comp_1+ 'parameters' +--ext-comp_2+ 'parameters' and so on...\n\n- +--virt-hosts+ +virtual-hosts-list+ - possible values: list of virtual domains to support 'domain1,domain2'. This option causes to use virtual hosts given here instead of default/automatically detected host names.\n\n- +--admins+ +admin-accounts-list+ - possible values: list of admin accounts: 'user1@domain,user2@domain2'\n\n- +--test+ - this parameter informs that config is generated for test instance, which means that all loggings are turned off\n\n- +--debug+ +tigase-package+ - you can turn on debugs log for thwe selected tigase package. For example if you want to turn debug logs on for package: *tigase.server* then you have to put parameter: +--debug server+. If you have any problems with your server the best way to get help from me is to generate configuration with --debug server and run the server. Then from the +logs/tigase-console.log+ log file I can get all information I need to give you a help.\n\n*Note!* _If configuration file already exists none of existing settings are overwritten. Configuration generator is activated only if config file does not exist at program startup or for config entries which are missing at startup time. So you can as well leave these settings in the file._\n\n*Note!* +tigase.conf+ _property file is NOT read by the tigase server. These properties are read by the bash shell to create a proper Tigase server startup command. It will not work on MS Windows unless you run it in bash (using CygWin for example). On windows however you can use configuration wizards too by preparing proper server startup command manually. For example command for the first below presented conf file would look like (all in single line):_\n\n[source,sh]\n-----\njava -Djdbc.drivers=org.postgresql.Driver\n -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\n -server -Xms100M -Xmx100M\n -cp \"libs/pg73jdbc3.jar;jars/tigase-server.jar;libs/tigase-xmltools.jar;libs/tigase-utils.jar\"\n tigase.server.XMPPServer\n -c \"etc/tigase.xml\"\n --gen-config-def --user-db pgsql\n --user-db-uri \"jdbc:postgresql://localhost/tigase?user=tigase\"\n-----\n\nSo for example to take advantage of these options you can create tigase.conf and start Tigase server with usual command to generate ''tigase-config.xml'' configuration file:\n\n[source,sh]\n-----\n./bin/tigase.sh run tigase.conf\n-----\n\nA few sample files are included below for your convenience:\n\n- +tigase-def-pgsql.conf+ - default installation with PostgreSQL database support:\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=org.postgresql.Driver\"\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\n\nTIGASE_CONFIG=\"tigase-pgsql.xml\"\nTIGASE_OPTIONS=\"--gen-config-def --user-db pgsql --user-db-uri jdbc:postgresql://localhost/tigase?user=tigase \"\n-----\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=org.postgresql.Driver\"\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\n\nTIGASE_CONFIG=\"tigase-pgsql.xml\"\nTIGASE_OPTIONS=\"--gen-config-def --user-db pgsql \"\n-----\n\n- +tigase-cs.conf+ - installation of network connections management components (no DB is used by this instance):\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nJAVA_OPTIONS=\"${ENC} -server -Xms100M -Xmx100M \"\n\nTIGASE_CONFIG=\"etc/tigase-cs.xml\"\nTIGASE_OPTIONS=\"--gen-config-cs --virt-hosts cs.tigase.org,tigase.org,sm.tigase.org \\\n  --ext-comp cs.tigase.org,sm.tigase.org,5678,very-secret,plain,connect\"\n-----\n\n- +tigase-sm-mysql.conf+ - installation of session manager instance and resource connection string is the same as default so we can skip '--user-db-uri' parameter:\n+\n[source,bash]\n-----\nENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver\"\n\nJAVA_OPTIONS=\"${ENC} ${DRV} -server -Xms100M -Xmx100M \"\nTIGASE_CONFIG=\"etc/tigase-sm-mysql.xml\"\nTIGASE_OPTIONS=\"--gen-config-sm --user-db mysql --auth-db mysql --virt-hosts tigase.org,sm.tigase.org \\\n  --ext-comp sm.tigase.org,cs.tigase.org,5678,very-secret,plain,accept\"\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Admin_Guide_99_-_Using_Tigase_-_N_-_Offline_Messages.asciidoc",
    "content": "[[offlineMessages]]\n= Offline Messages\n:author: Daniel Wisnewski\n:version: v1.0, March 2016\n:date: 2016-03-07 07:54\n\n:toc:\n:numbered:\n:website: http://www.tigase.net\n\nTigase like any XMPP server supports storing of messages for users who are offline so that they may receive messages sent to them while they were not logged in.\n\nBy default, Tigase +MessageAmp+ processor is responsible for storing offline messages, and will automatically store offline messages.  This guide has multiple sections for setting limits globally, per user, and others.\n\nMany of the features listed here require the use of the Advanced Message Processor Plugin which is turned on by default. To ensure AMP is turned on your system, view your init.properties file and be sure the following is there in your plugins line:\n[source,bash]\n-----\n--sm-plugins=+amp\n-----\nMessages will be delivered to intended recipients when they first login after roster exchange.\n\n\n[[offlineMessageLimits]]\n== Offline Message Limits\nSupport for limiting number of stored offline messages on a per-user basis has now been added to Tigase as of v7.1.0.  By default, Tigase comes with a limit of stored offline messages which is set for every user. This limit by default is 100 offline messages for barejid-barejid pair. This value can be changed by the +store-limit+ property. To change to 200 messages on barejid-barejid paid, add the following entries to the init.properties file:\n[source,properties]\n-----\nsess-man/plugins-conf/amp/store-limit[L]=200\namp/store-limit[L]=200\n-----\n\nThis setting applies to every user.\n\n=== User Limit\nEach user is able to configure the number of offline messages which should be stored for him. To enable this feature, the following lines need to be entered into the init.properties file:\n[source,properties]\n-----\nsess-man/plugins-conf/amp/user-store-limit-enable[B]=true\namp/user-store-limit-enable[B]=true\n-----\n\nValues of user-specific limits will be stored in UserRepository under subnode of +offline-msgs+ and key +store-limit+. Data storage will be stored in +tig_pairs+ key with the value and a proper record from +tig_nodes+ points to this record.\n\n=== Handling of Offline Messages Exceeding Limits\nThere are two possible ways to handle offline messages that exceed the limitations:\n. +error+ sending message with error type back to sender.\n. +drop+ drop of message without notifications to sender.\n\nBy default, Tigase sends a message back to the original sender with an error type of +service-unavailable+ with a proper description of error according to link:http://www.xmpp.org/extensions/xep-0160.html[XEP-0160].\nHowever, it is possible to change this behavior to better suit your needs. This is done by adding the following line to your init.properties file.\n[source,properties]\n-----\nsess-man/plugins-conf/amp/quota-exceeded=drop\n-----\nThis will force Tigase to drop packets that exceed the offline message limit.\n\n=== Setting of Limits by User\nUsers wishing to set a custom limit of stored offline messages for barejid-barejid pairs needs to send the following XMPP stanza to the server:\n[source,xml]\n-----\n<iq type=\"set\" id=\"${random-id}\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"${limit}\"/>\n</iq>\n-----\nWhere:\n. ${random-id} is a random ID of the stanza (can be any string).\n. ${limit} is the integer value of the offline message limit. This can be set to +false+ to disable offline message limits.\n\nIn response, the server will send back an +iq+ stanza with a result type:\n[source,xml]\n-----\n<iq type=\"result\" id=\"${random-id}\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"${limit}\"/>\n</iq>\n-----\n\n==== Example of Setting Limit of Stored Offline Messages to 10\nXMPP client sends the following to the server:\n[source,xml]\n-----\n<iq type=\"set\" id=\"aabba\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"10\"/>\n</iq>\n-----\n\nServer response:\n[source,xml]\n-----\n<iq type=\"result\" id=\"aabba\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"10\"/>\n</iq>\n-----\n\n==== Example of Disabling Offline Message Limit\nXMPP client sends the following to the server:\n[source,xml]\n-----\n<iq type=\"set\" id=\"aabbb\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"false\"/>\n</iq>\n-----\n\nServer response:\n[source,xml]\n-----\n<iq type=\"result\" id=\"aabbb\">\n  <msgoffline xmlns=\"msgoffline\" limit=\"false\"/>\n</iq>\n-----\n\n[[nonBodyElements]]\n== Storing offline messages without body content\nTigase can now store offline messages without <body/> content.\nSee link:http://xmpp.org/extensions/xep-0334.html[XEP-0334] for protocol details.\n\nSupport also added to set a list of paths and xmlns to trigger and place storage of offline messages using the following settings in init.properties:\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=/message/received[urn:xmpp:receipts],/message/store-offline\n-----\n\n\n[[addOfflinePaths]]\n== Adding Custom Storage Paths\nSupport has been added to set a list of paths and xmlns to trigger and place storage of offline messages using the following settings in init.properties:\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=/message/received[urn:xmpp:receipts],/message/store-offline\n-----\n\n[[offlineMessageReceipts]]\n== Message Receipts\nTigase AMP component has support for message receipts and storage.  By default, offline message delivery receipts will be sent to offline message storage.  Note this WILL count against the total number of stored offline messages as explored earlier.\n\n=== Offline Storage\nIt is possible to set storage of message receipts, and add other types to save:\n[source,properties]\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=/message/received[urn:xmpp:receipts],/message/store-offline,-/message/do-not-store\n-----\nThe above setting in the init.properties file will do three things:\n- Messages with a <received> subelement of xmlns set to urn:xmpp:receipts will now be stored.\n- Messages with <store-offline> subelement will be stored without checking for associated xmlns.\n- Messages with <do-not-store> element *will not* be saved.\n\nAny of these can be adjusted for your installation, remember that a '-' will stop storage of messages with the indicated property.\nMessages will be checked by these matchers and if any of them result in a positive they will override default settings.\nMatcher logic uses left to right ordering, in that matches on the first statement will ignore/override later listed matchers.\n\nFor example, if you wanted to store messages with <received> element, but not ones with <plain> element:\n*THIS STATEMENT WILL NOT WORK*\n[source,properties]\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=/message/received,-/message/plain\n-----\n\nAs it will just store all messages with <receieved> subelement.  The below statement will properly filter your results.\n[source,properties]\n-----\nsess-man/plugins-conf/amp/msg-store-offline-paths[s]=-/message/plain,/message/received\n-----\n\n[[disableOfflineMessages]]\n== Disabling Offline Messages\nIf you wish to disable the storing of offline messages, use the following line in your init.properties file.  This will not disable other features of the AMP plugin.\n[source,properties]\n-----\nsess-man/plugins-conf/amp/msg-offline=false\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/asciidoc/text/Tigase_v7.1.0.asciidoc",
    "content": "[[tigase710]]\n= Tigase v7.1.0 announcement\n:author: Daniel Wisnewski\n:date: 2015-25-08 22:09\n\n\nIntroducing Tigase v7.1.0!  We have been working hard to improve and implement new features to the Tigase Sever program to give you a more secure, leaner, and better working XMPP server.\n\nWe have a few new features, components, and lots of fixes to share.\nPlease note that not all issues are accessible as notes and fixes may contain private customer information.\n\n:toc:\n\n\n== Major Changes\n\nTigase has undergone a few major changes to our code and structure. To continue to use Tigase, a few changes may be needed to be made to your systems.  Please see them below:\n\n=== HTTP Component renamed\nThe HTTP component has been renamed, if you still have the old tigase.rest.RestMessageReciever in your init.properties file, please update the component name to:\n[source,bash]\n-----\ntigase.http.HttpMessageReceiver\n-----\n\n=== New JDK v8 required\nAs Oracle has dropped support for version 7 of it's Java runtime environment and developer kit, we have moved to version 8 of the JDK.  Furthermore, some new features and fixes for Tigase Server now require the use of JDK v8 or later. Please upgrade your Java packages from link:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[this link].\n\n=== Changes to Database Schemas\nTigase has undergone a number or database schema changes, the current versions being main database schema v7.1 and pubsub schema v3.2.0.  If you are upgrading to v7.1.0 from a previous version of tigase, it is recomended you visit xref:v710notice[this section] in the documentation to prepare your new installation.\n\n=== Presence Plugin Split\nThe plugin handling all presence processing has been split from one plugin (Presence.java) into separate plugins:\n- PresenceAbstract.java handles most common presence-related methods, and is also used by the following two plugins.\n- PresenceSubscription.java to handle subscription presence processing like for roster updates.\n- PresenceState.java to handle initial presences from new logins.\n\n\n== New Features & Components\n\n=== New HTTP API\n\nTigase now features an HTTP API that not only allows web client chat, but administrators can change settings, manage users, and even write and run scripts all from the comfort of a browser window.   Furthermore, commands can be passed through this interface using REST to create and run custom scripts and commands.\nWe plan on expanding on the look and feel of this interface as time goes on, but in the meantime enjoy the real-time XMPP experience now with a user-friendly GUI.\n\n=== New Admin HTTP interface\n\nTigase now comes with its own build-in web XMPP client!  It can be accessed from http://yourhost.com:8080/ui/. For more details, see the Admin UI guide.\n\n=== Added support for XEP-0334\n\nXEP-0334 is now supported.  See xref:nonBodyElements[this section] for details.\n\n=== Kernel Bean Configurator has been Improved\n\nAdded aliases for bean properties to allow for a 'high level' of configuration.\nInstead of using\n-----\ncomponent/bean-name/property=value\n-----\nThe following easier to use method will work\n-----\ncomponent/property=value\n-----\n\n=== Support for XEP-0352\nClient State Indication is now enabled by default on Tigase XMPP Servers.  Details xref:sessManMobileOpts[here].\n\n== One Certificate for multiple Vhosts\n\nTigase now allows for wildcards in setting server certificate per Vhosts.  See more xref:onecertmultipledomain[in this section].\n\n=== Maximum users setting for MUC\n\nAdministrators can now set that maximum number of users allowed on specific MUCs.\nSee xref:mucRoomConfig[MUC Room Configuration].\n\n=== HTTP Rest API Support\n\nTigase now supports REST commands via HTTP, they can be sent from ad-hoc commands, a web interface, or other REST tools. See xref:tigase_http_api[documentation] for more.\n\n=== Empty Nicknames\n\nTigase can now support users with empty nicknames.  See xref:emptyNicks[this] for details.\n\n=== Offline Message Limits\n\nTigase now has support to enable and change Offline Message Limits as handled by AMP. xref:offlineMessageLimits[Documentation here].\n\n=== Offline Message Sink\n\nA new way to store offline messages has been implemented, it may not replace standard offline messages, but can be used in other ways.\nxref:offlineMessageSink[Documentation here].\n\n=== Adding Components to trusted list\n\nComponents can now be added to trusted list and will be shared with all clustered servers.\nlink:https://projects.tigase.org/issues/3244[#3244]\n\n=== Tigase Mailer Extension now Included\n\nTigase Mailer extension is now included in distributions of Tigase server. This extension enables the monitor component to deliver E-mails to and from specified e-mail addresses when monitor are triggered.  For more information see xref:monitorMailer[monitor mailer section].\n\n=== EventBus implemented\n\nTigase now has a simple PubSub component called EventBus to report tasks and triggers.  More details are available xref:eventBus[Here].\n\n=== XEP-0191 Blocking Command Support added\n\nBlocking Command support has been added to Tigase, all functions of link:http://xmpp.org/extensnions/xep-0191/html[XEP-0191] should be implemented.  See xref:blockingCommand[Admin Guide] for details.\n\n=== Stream management now has new settings available for stream timeout\n\nMaximum stream timeout and default stream timtout times can now be set in init.properties. Details of these two settings can be found xref:streamResumptiontimeout[here].\n\n=== JVM Default configuration updated\n\nDefault tigase.conf file has been updated with the following change in JVM options:\n-----\nPRODUCTION_HEAP_SETTINGS=\" -Xms5G -Xmx5G \" # heap memory settings must be adjusted on per deployment-base!\nJAVA_OPTIONS=\"${GC} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} -XX:MaxDirectMemorySize=128m \"\n-----\nAs the comment says, we recommend adjusting the heap memory settings for your specific installations.\nlink:https://projects.tigase.org/issues/3567[#3567]\n\n==== Java Garbage Collection Settings have been improved\nAfter significant testing and investigation, we have improved the Java GC settings to keep memory usage from becoming too high on systems.\nlink:https://projects.tigase.org/issues/3248[#3248]\n\nFor more information about JVM defaults and changes to settings, see link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/#jvm_settings[our Documentation].\n\n=== New Rest API added to obtain a JID login time\n\n+GetUserInfo+ command has been expanded to obtain user login and logout times in addition to standard information. See xref:getUserInfoREST[this section] for full details.\n\n=== New init.properties properties\n\n+--ws-allow-unmasked-frames=false+\nAllows for unmasked frames to be sent to Tigase server VIA Websocket and not force-close the connection when set to true.  RFC 6455 specifies that all clients must mask frames that it sends to the server over Websocket connections.  If unmasked frames are sent, regardless of any encryption, the server must close the connection.  Some clients however, may not support masking frames, or you may wish to bypass this security measure for development purposes.\n\n+--vhost-disable-dns-check=true+\nDisables DNS checking for vhosts when changed or edited.\nWhen new vhosts are created, Tigase will automatically check for SRV records and proper DNS settings for the new vhosts to ensure connectivity for outside users, however if these validations fail, you will be unable to save those changes. This setting allows you to bypass that checking.\n\n=== Connection Watchdog\n\nA watchdog property is now available to monitor stale connections and sever them before they become a problem.  More details xref:watchdog[here].\n\n=== Web Installer Setup Page now has restricted access\n\nThe Web Installer Setup Page, available through http://yourserver.com/8080/setup/ now requires an admin level JID or a user/password combo specified in init.properties.  See the xref:webinstall[Web Installer] section for default settings.  See xref:httpCompProp[Component Properties] section for details on the new property.\n\n=== Offline Message Receipts Storage now Configurable\n\nAdmins may now configure Offline Message Receipts Storage to specify filters and controls as to what they want stored in offline messages. See xref:offlineMessageReceipts[more details here].\n\n=== Account Registration Limits\n\nIn order to protect Tigase servers from DOS attacks, a limit on number of account registrations per second has been implemented.  See xref:accountRegLimit[this link] for configuration settings.\n\n=== Enable Silent Ignore on Packets Delivered to Unavailable Resources\n\nYou can now have Tigase ignore packets delivered to unavailable resources to avoid having a packet bounce around and create unnecessary traffic. Learn how xref:silentIgnore[here].\n\n=== Cluster Connections Improved\n\nCluster commands now operate at CLUSTER priority, giving the packets higher status than HIGH which otherwise has caused issues during massive disconnects.\nNew Configuration options come with this change.  The first being able to change the number of connections for CLUSTER packets using the following init.property setting:\n-----\ncl-comp/cluster-sys-connections-per-node[I]=2\n-----\nAlso a new class which implements the a new connection selection interface, but uses the old mechanism where any connection can send any command.\n-----\ncl-comp/connection-selector=tigase.cluster.ClusterConnectionSelectorOld\n-----\n\n=== Cluster Connections Testing Implemented\n\nWatchdog has now been added to test cluster connections by default.  Watchdog sends an XMPP ping to all cluster connections every 30 seconds and checks to see if a ping response has been received in the last 3 minutes. If not, the cluster connection will be dropped automatically. Global watchdog settings will not impact cluster testing feature.\n\n=== Cluster Map implemented\n\nTigase can now generate cluster maps through a new API.  See the link:http://docs.tigase.org/tigase-server/snapshot/Development_Guide/html/#clusterMapInterface[development guide] for a description of the API.\n\n=== New Licensing Procedures\n\nWith the release of Tigase XMPP server v7.1.0, our licensing procedures have changed.  For more information about how to obtain, retain, and install your license, please see xref:licenseserver[this section].\n\n=== Message Archive expanded to include non-body elements\n\nMessage Archive can now be configured to store messages that may not have body element, this option is explained in xref:nonBodyStore[this section].\n\n=== New Ability to Purge Data from Unified Archive\n\nData from Unified Archive or Message Archive can be automatically or manually purged depending on age or expired status.  Information on configuring this is available xref:maPurging[here].\n\n=== Force Redirection\n\nIt's possible now to redirect connections on one port to be forced to connect to another port using the +force-redirect-to+ setting.  link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/#_enforcing_redirection[Details here].\n\n=== SASL-SCRAM now enabled\nSASL-SCRAM is now enabled by default for available authentication methods.\n\n=== Dual IP installtions\n\nTigase now has a Dual IP setup which can now use a separate internal and external IP and use a DNS resolver for the connection redirection.  Setup instructions are link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/#_configuring_hostnames[Located here].\n\n=== Error counting\n\nIt is now possible to conduct error counting and collect it from statistics.  This feature is explained in more detail xref:errorCounting[here].\n\n=== New Database Disconnections Counter\n\n3 new statistics were added to +basic-conf+ to help monitor database connection stability, and how often the XMPP Server needs to reconnect to the database. The list of new statistics are listed xref:repo-factoryStatistics[here].\n\n=== New Known Cluster Statistic\n\nA new statistic has been added to cl-comp displaying the number of connected Cluster Nodes if there are more than one. Displayed as an INFO level statistic.\n\n=== New Documentation Structure\n\nThere has been a lot of changes and fixes to our documentation over the last few months. If you have links to any of our documentation, please update them as the filenames may have changed.\n\n=== Full XML of last available presence may be saved to repository\n\nA more detailed last available presence can now be made from some configuration changes, along with a timestamp before the entire presence stanza is saved to the repository.  More information is available xref:storeFullXMLLastPresence[here].\n\n=== Setting available to enable automatic subscriptions\nTigase supports enabling automatic presence subscriptions and roster authorizations.  For more information on these settings, check the xref:autoSub[Automatic Subscriptions] section.\n\n=== New Program Defaults\n\nTigase has improved default settings to improve performance.  These include:\n- Increase the number of database connections in relation to the number of available CPUs (factor by 4 by default).\n- Plugins code has been revised.\n- Default thread pools have been increased for better performance.\n- New option added to globally increase thread pool counts +sess-man/sm-threads-factor[I]=1+. Setting increases thread factor by specified factor.\n- Improved JVM default settings.\n- Improved JVM Garbage Collection.\n\n== New Minor Features & Behavior Changes\n\n- Old monitor component depreciated and turned off.\n- JTDS MS SQL Server driver updated to v1.3.1.\n- +tigase-utils+ and +tigase-xmltools+ are now included in tigase-server builds.\n- Tigase Kernal has been updated and improved.\n- tigase.stats.CounterDataFileLogger file now includes timestamps.\n- Javadoc is no longer generated by installer as files are already included in distributions.\n- Node connection events to administrator have been improved and are more informative.\n- link:https://projects.tigase.org/issues/163[#163] link:http://xmpp.org/extensions/xep-0012.html[XEP-0012] User +LastActivity+ implemented\n- link:https://projects.tigase.org/issues/593[#593] link:http://xmpp.org/extensions/xep-0202.html[XEP-0202 Entity Time] has been implemented.\n- link:https://projects.tigase.org/issues/788[#788] End User Session from link:http://xmpp.org/extensions/xep-0133.html[XEP-0133 Service Administration] implemented.\n- #811 Plugin API extended allowing more XML parameters to be considered for processing.\n- link:https://projects.tigase.org/issues/813[#813] Default number of connections between cluster nodes set at 5, default number of connections for CLUSTER level traffic set to 2.\n- link:https://projects.tigase.org/issues/1436[#1436] +ClusterConnectionManager+ now sends ping packets every 30 seconds to check status of live cluster connections.\n- link:https://projects.tigase.org/issues/1449[#1449] Monitoring can now be run in OSGI mode.\n- link:https://projects.tigase.org/issues/1601[#1601] XMPPPresenceUpdateProcessorIFC interface has been removed and replaced with eventbus with dedicated threadpool.\n- link:https://projects.tigase.org/issues/2426[#2426] Support for link:http://xmpp.org/extensions/xep-0334.html[XEP-0334] has been added.\n- link:https://projects.tigase.org/issues/2530[#2530] RosterFlat implementation now allows for a full element to be injected into presence stanzas instead of just a custom status.\n- link:https://projects.tigase.org/issues/2561[#2561] & link:https://projects.tigase.org/issues/85[#85] Offline messages now consider sessions without presence & resources negative priority in delivery logic.\n- link:https://projects.tigase.org/issues/2596[#2596] Delivery errors are no longer run through preprocessors.\n- link:https://projects.tigase.org/issues/2823[#2823] +staticStr+ element method now implemented.\n- link:https://projects.tigase.org/issues/2835[#2835] Allowing of +setPermissions+ on incoming packets before they are processed by plugins.\n- link:https://projects.tigase.org/issues/2903[#2903] +see-other-host+ has new option to make it configurable on a per vhost basis.\n- link:https://projects.tigase.org/issues/3034[#3034] Improved handling of data types and primitives within Tigase.\n- #3173 Stanzas with unescaped XML special characters are now ignored instead of sending a force-close of connection to sender.\n- link:https://projects.tigase.org/issues/3180[#3180] Protected access to JDBC repository now enabled.\n- link:https://projects.tigase.org/issues/3230[#3230] Verification added to check against CUSTOM domain rules when submitted.\n- #3258 Retrieval of PubSub/PEP based avatars using REST API now supported. xref:avatarRetrievalRequests[Command URLs here].\n- #3282 VCard4 support added along with VCardTemp compatibility and integration.\n- link:https://projects.tigase.org/issues/3285[#3285] Stream Management changed to fully support XEP-0203.\n- link:https://projects.tigase.org/issues/3330[#3330] Error for adding users already in db now returns Error 409 with +User exists+.\n- #3364 Clustering support has been re-factored to remove duplicate +nodeConnected+ and +nodeDisconnected+ methods.\n- #3463 +offline-roster-last-seen+ feature as a part of presence probe is now disabled by default.\n- link:https://projects.tigase.org/issues/3496[#3496] TigUserLogout has been improved to use +sha1_user_id = sha1(lower(_user_id))+ instead of \"_user_id\".\n- link:https://projects.tigase.org/issues/3511[#3511] Stream closing mechanism in SessionManager, new STREAM_CLOSED command has been added to organize shutdown of XMPP streams.\n- #3569 Fixed error occuring when attempting to remove offline users from roster.\n- #3609 Added new configuration option for BOSH to disable hostname attribute. xref:tip_1_bosh_in_cluster_mode_without_load_balancer[Details here].\n- link:https://projects.tigase.org/issues/3670[#3670] Hardened mode now uses long DH keys (2048) by default.\n- link:https://projects.tigase.org/issues/3849[#3849] New Roster size limit configurable setting. See info xref:rosterLimit[Here].\n- link:https://projects.tigase.org/issues/3872[#3872] PostgreSQL driver updated to v9.4.\n- #3892 PEP plugin now supports processing of http://jabber.org/protocol/pubsub#owner.\n- link:https://projects.tigase.org/issues/3908[#3908] Logs now print whether components or plugins are depreciated, and recommend configuration settings changes.\n- link:https://projects.tigase.org/issues/3937[#3937] Windows setup given one-click solution to file initialization.\n- link:https://projects.tigase.org/issues/3945[#3945] SSLContextContainer has been replaced with JDKv8 extension version now known as SNISSLContextContainer adding support for SNI of SSL/TLS.\n- link:https://projects.tigase.org/issues/3948[#3948] Tigase PubSub now responds to +disco#info+ requests in line with link:http://xmpp.org/extensions/xep-0060.html#entity-metadata[XEP-0060 - Discover Node Metadata].\n- link:https://projects.tigase.org/issues/3950[#3950] MongoDB driver updated to v2.14.1.\n- #3985 Improved disco#info to return extended results for MUC component as per link:http://xmpp.org/extensions/xep-0128.html[XEP-0128 Service Discovery Extensions].\n- #3986 Added new index for tig_nodes collection in MongoDB Databases.\n- #4020 SeeOtherHostSualIP implementation has been fixed to support MongoDB.\n- link:https://projects.tigase.org/issues/4120[#4120] Duplication of messages in offline storage when +Message+ and +OfflineMessage+ processors are used has been resolved.\n- #4162 xml:lang attribute is now supported in Tigase MUC component.\n- #4248 Changed +ErrorCounter+ from +XMPPProcessorIFC+ to +XMPPPacketFilterIfc+ for more accurate functionality.\n- link:https://projects.tigase.org/issues/4256[#4256] Reduced Statistics memory usage by interning statistics labels and changing data types.\n- link:https://projects.tigase.org/issues/4356[#4356] Message Archive component has been converted to kernel and beans.\n- link:https://projects.tigase.org/issues/4352[#4352] Websocket implementation has been changed to properly parse HTTP headers with omitted spaces for HTTP 1.1 protocol.\n- link:https://projects.tigase.org/issues/4358[#4358] Several methods have been renamed or removed to prepare for v7.2.0 Kernel setup.\n- #4385 Minor tweak to web-installer to skip unnecessary showing of blank init.properties file & enabled post-setup editing and saving.\n\n\n== Fixes\n\n- link:https://projects.tigase.org/issues/8[#8] XML parser no longer passes malformed XML statements to server.\n\n- link:https://projects.tigase.org/issues/1396[#1396] & link:https://projects.tigase.org/issues/663[#663] User roster behaves correctly. Tigase now waits for user authorization before users are added to a Roster.\n\n- link:https://projects.tigase.org/issues/1488[#1488] NPE in ad-hoc for managing external components fixed.\n\n- link:https://projects.tigase.org/issues/1602[#1602] Minor optimization in MessageCarbons with new functions added to XMPPResourceConnection.\n\n- link:https://projects.tigase.org/issues/2003[#2003] Fixed bug with C2S streams where server would not always overwrite from attribute with full JID in subcription-related presence stanzas.\n\n- link:https://projects.tigase.org/issues/2118[#2118] Username modification bugfix. Tigase now returns \"\" for blank usernames instead of string after a username has been made blank.\n\n- link:https://projects.tigase.org/issues/2859[#2859] & link:https://projects.tigase.org/issues/2997[#2997] STARTTLS stream error on SSL sockets fixed.\n\n- link:https://projects.tigase.org/issues/2860[#2860] Fixed issue with SSL socket client certificate not working.\n\n- link:https://projects.tigase.org/issues/2877[#2877] Fixed issue in Message Carbons if message contains AMP payload.\n\n- link:https://projects.tigase.org/issues/3034[#3034] Streamlined primitive and Object array handling.\n\n- link:https://projects.tigase.org/issues/3067[#3067] Fixed Bug where if duplicate commands were sent to MS SQLServer a race condition would occur.\n\n- link:https://projects.tigase.org/issues/3075[#3075] Fixed error when compiling Tigase in Red Hat Enterprise Linux v6.\n\n- link:https://projects.tigase.org/issues/3080[#3080] --net-buff-high-throughput now parses integers properly. Setting no longer reverts to default when new values are set.\n\n- link:https://projects.tigase.org/issues/3126[#3126] Calculation of percentage of heap memory used in Statistics now selects proper heap.\n\n- link:https://projects.tigase.org/issues/3131[#3131] Fixed messages with AMP payload bound for plugins getting redirected to AMP for processing.\n\n- link:https://projects.tigase.org/issues/3150[#3150] Default Log level changed for certain records. All log entries with skipping admin script now have log level +FINEST+ instead of +CONFIG+\n\n- link:https://projects.tigase.org/issues/3158[#3158] Fixed issue with OSGi not reporting proper version, and PubSub errors in OSGi mode.\n\n- link:https://projects.tigase.org/issues/3159[#3159] User Privacy lists now activate properly and does not wait for presence stanza to filter packets.\n\n- link:https://projects.tigase.org/issues/3164[#3164] Fixed NPE in +StreamManagementIOProcessor+ when <a/> is processed after connection is closed.\n\n- link:https://projects.tigase.org/issues/3166[#3166] NPE in SessionManager checking SSL null connections fixed.\n\n- link:https://projects.tigase.org/issues/3181[#3181] S2S connection multiplexing now has consistent behavior.\n\n- link:https://projects.tigase.org/issues/3194[#3194] Fixed issue with single long lasting HTTP connection blocking other HTTP requests. Default timeout set to 4 threads after 60 seconds.\n\n- link:https://projects.tigase.org/issues/3200[#3200] Implemented a faster way to close stale connections using MS SQL server, reducing calm down time after large user disconnects.\n\n- #3203 Correct presence status shows for contacts if authorization was accepted while user was offline.\n\n- link:https://projects.tigase.org/issues/3223[#3223] +GetUserInfo+ ad-hoc command no longer omits information about local sessions when a remote session is active.\n\n- #3226 Fixed NPE & argument type mismatch in Pubsub.\n\n- link:https://projects.tigase.org/issues/3245[#3245] Fixed ClassCastException when Websocket is configured to use SSL.\n\n- link:https://projects.tigase.org/issues/3249[#3249] JabberIQVersion plugin now returns proper client information when requested from self.\n\n- link:https://projects.tigase.org/issues/3259[#3259] Websocket no longer loops when receiving stanzas between 32767 and 65535 bytes in size.\n\n- link:https://projects.tigase.org/issues/3261[#3261] Fixed issue with duplicate disco#info responses.\n\n- link:https://projects.tigase.org/issues/3274[#3274] NPE when removing roster nickname fixed.\n\n- link:https://projects.tigase.org/issues/3307[#3307] Rosters are no longer re-saved when a user logs in and roster is read resulting in a performance boost.\n\n- link:https://projects.tigase.org/issues/3328[#3328] Presence processing by PEP plugin optimized.\n\n- link:https://projects.tigase.org/issues/3336[#3336] Fixed issues with reloading vhosts in trusted after configuration change.\n\n- link:https://projects.tigase.org/issues/3337[#3337] tls-jdk-nss-bug-workaround-active is now disabled by default. This fix is disabled by default which may impact older OpenSSL versions that may no longer be supported.  You may enable this using an init.properties setting.\n\n- #3341 IQ Packet processing changed for packets sent to bare JID in Cluster mode.\n\n- link:https://projects.tigase.org/issues/3372[#3372] Fixed NPE when presence was re-broadcasted to users who did not exit server gracefully.\n\n- link:https://projects.tigase.org/issues/3374[#3374] PubSub Schema changed to be more compatible with MS SQL.\n\n- link:https://projects.tigase.org/issues/3375[#3375] Users removed VIA REST commands are now disconnected immediately.\n\n- link:https://projects.tigase.org/issues/3386[#3386] Fixed AMP logic to avoid querying for (default) Privacy list if user does not exist.\n\n- #3389 Fixed issue of sending packets to connections that were closed, but connection write lock had not been acquired.\n\n- link:https://projects.tigase.org/issues/3401[#3401] Multiple issues fixed with Tigase.IM web client.\n\n- link:https://projects.tigase.org/issues/3422[#3422] UTC Timestamps now enforced inside cluster_nodes table.\n\n- #3440 Fixed WebSocket error 12030 showing unexpectedly.\n\n- link:https://projects.tigase.org/issues/3446[#3446] Fixed Installer configuring MUC incorrectly.\n\n- #3449 Wrapper.conf updated with current library folder for windows Service wrapper.\n\n- link:https://projects.tigase.org/issues/3453[#3453] Fixed NPE when using comparator when sorting messages.\n\n- #3485 Fixed JDBCMsgRepository inserting duplicate user JID into table while using AMP.\n\n- link:https://projects.tigase.org/issues/3489[#3489] Various fixes to Tigase test suite.  Fixed race condition from XMPPSession conflicts when new sessions and closing session events happen at the same time.\n\n- link:https://projects.tigase.org/issues/3495[#3495] Fixed messages being duplicated by message carbons.\n\n- #3499 Various fixes to AMP component.\n\n- #3530 Fixed +null cert chain+ error when connecting to other servers using S2S connection with StartTLS.\n\n- #3550 Fixed NPE in sess-man when trying to delete all user information using Pidgin or Psi.\n\n- link:https://projects.tigase.org/issues/3556[#3556] JavaDoc updated to include documentation for +xmltools+, +tigase-extras+, and +tigase-util+ packages.\n\n- link:https://projects.tigase.org/issues/3559[#3559] Fixed Web admin UI not updating Cluster node when it id disconnected.\n\n- link:http://projects.tigase.org/issues/3579[#3579] Fixed NPE in SimpleParser.\n\n- link:http://projects.tigase.org/issues/3580[#3580] Replaced misleading +feature not implemented+ error when SM attempts to put a packet to processor and queue is full.\n\n- #3598 Fixed error in removing users from blocked list.\n\n- #3599 Fixed +FlexibleOfflineMessages+ not being delivered to connection due to lack of explicit connection addressing.\n\n- #3612 Fixed issue when processing packets sent to full JID in cluster mode when user is connected to more than one cluster node at once.\n\n- #3619 Fixed issue with non-presistent contacts being unable to be added to roster.\n\n- #3649 Changed privacy list processing to always allow communication between XMPP connections with the same BareJID.\n\n- link:https://projects.tigase.org/issues/3655[#3655] Increased max loop in infinity loop detection logic to 100000 in order to aid larger transfers.\n\n- #3656 Add option to BOSH output command without a timer task to avoid generation of packets to closed connections.\n\n- #3686 XHTML-IM parser has been fixed, restoring link:http://xmpp.org/extensions/xep-0071.html[XEP-0071] functionality.\n\n- link:https://projects.tigase.org/issues/3688[#3688] Issues with Eventbus in cluster mode fixed.\n\n- link:https://projects.tigase.org/issues/3689[#3689] Avoid using sender address when packets are returned from Cluster Manager using stream management.\n\n- #3717 Support added to store messages without <body/> element if storage method other than <body/> is used. Support also added for JAXMPP to retrieve whole element from Message Archiving instead of only <body>.\n\n- #3718 Removed +DISCONNECTING!+ debug stanza from AbstractWebSocketConnector.java that was causing NPE when user fails authentication in WebSocket.\n\n- link:https://projects.tigase.org/issues/3753[#3753] Fixed NPE when using Blocking command.\n\n- link:https://projects.tigase.org/issues/3775[#3775] Fixed +ThreadExceptionHandler+ error in Tigase mailer.\n\n- link:https://projects.tigase.org/issues/3781[#3781] Fixed issue with sending C2S message \"The user connection is no longer active\".\n\n- link:https://projects.tigase.org/issues/3800[#3800] Changed Jenkins to always pull latest binaries from repositories.  Windows wrapper changed to use wildcards to load /jars folder.\n\n- #3848 Changes made to JDBCMessageArchiveRepository to fix potential MySQL deadlocks when adding entries to repository.\n\n- #3902 Fixed issue where wss:// connections were closed after 3 minutes of inactivity.\n\n- #3910 Fixed NPE in SessionManager when session was closed during execution of everyMinute method.\n\n- #3911 Fixed load distribution error between threads that could cause high CPU usage.\n\n- #3931 Fixed error caused by AMP running in clustered installations.\n\n- #3966 Changed type of msg & body columns in muc_history table for SQLServer to prevent loss of special characters.\n\n- #3973 Adjusted throttling settings for S2S and cluster connections.\n\n- #3977 Fixed MUC History to reflect messages from JID of room and not JID of original sender.\n\n- #3984 Fixed distinct usage on large data which causes errors on lookup of PubSub nodes in MongoDB.\n\n- link:https://projects.tigase.org/issues/3970[#3970] Fixed duplication of messages with AMP payload in cluster mode.\n\n- link:https://projects.tigase.org/issues/4044[#4044] Fixed various web installer issues.\n\n- #4051 Fixed NPE in java when processing message with no body.\n\n- link:https://projects.tigase.org/issues/4052[#4052] Fixed issue with ClusterRepoItem not properly resulting in +tigase.db.comp.RepositoryChangeListenerIfc.itemUpdated(Item)+ being executed.\n\n- link:https://projects.tigase.org/issues/4056[#4056] Items removed from cluster repository are not removed from memory correctly.\n\n- link:https://projects.tigase.org/issues/4071[#4071] Updated groovy script to properly add owner to node creation VIA ad-hoc command.\n\n- link:https://projects.tigase.org/issues/4142[#4142] Updated wrapper.conf file to match tigase.conf default settings.\n\n- link:https://projects.tigase.org/issues/4183[#4183] Fixed issue where objects monitored by Ghostbuster.java in MUC could not be removed by it.\n\n- link:https://projects.tigase.org/issues/4185[#4185] Fixed issue with +PacketCounter+ that caused duplicate messages to be sent on stream resumption.\n\n- link:https://projects.tigase.org/issues/4188[#4188] Standardized timestamp between +AbstractMessageArchiveRepository+ and +TimestampHelper+.\n\n- link:https://projects.tigase.org/issues/4262[#4262] Fixed messages getting lost when StreamResumption is used when a disconnected user reconnects to the server.  This issue is also fixed on servers using ACS component.\n\n- link:https://projects.tigase.org/issues/4365[#4365] Fixed direct presence not working with non-roster elements using barejid.\n\n- Patch added to fix ConcurrentModificationException in BlockingCommand plugin.\n\n- Fixed negation in SASL mechanism selector.\n\n- Fixed checking for user session without localpart in to address.\n\n- Distributed EventBus improved to allow POJO based events to be fired locally.\n\n- Added missing classes to IzPack installer.\n\n- Tigase.xml removed from documentation and default tigase.conf file.\n\n- Logs function added to eventbus publisher operations.\n\n- Fixed responding to same hostname as sender as \"to\" in stream-error stanza.\n\n- Fixed issue where attempts to delete empty MUC room would create and then destroy room.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/adminguide/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../../..</dist_path>\n\t\t<guide_name>Administration</guide_name>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-docs-admin</artifactId>\n\t<name>Tigase XMPP Server Documentation - ${guide_name} Guide</name>\n\n\t<packaging>pom</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-docs</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t</parent>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-docbook</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.agilejava.docbkx</groupId>\n\t\t\t\t<artifactId>docbkx-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-pdf</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-webhelp</id>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-epub3</id>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>Remove *.fo file</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/css/docbook-xsl.css",
    "content": "/*\n  CSS stylesheet for XHTML produced by DocBook XSL stylesheets.\n*/\n\nbody {\n  font-family: Georgia,serif;\n}\n\ncode, pre {\n  font-family: \"Courier New\", Courier, monospace;\n}\n\nspan.strong {\n  font-weight: bold;\n}\n\nbody blockquote {\n  margin-top: .75em;\n  line-height: 1.5;\n  margin-bottom: .75em;\n}\n\nhtml body {\n  margin: 1em 5% 1em 5%;\n  line-height: 1.2;\n}\n\nbody div {\n  margin: 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\n\ndiv.toc p:first-child,\ndiv.list-of-figures p:first-child,\ndiv.list-of-tables p:first-child,\ndiv.list-of-examples p:first-child,\ndiv.example p.title,\ndiv.sidebar p.title\n{\n  font-weight: bold;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n  margin-bottom: 0.2em;\n}\n\nbody h1 {\n  margin: .0em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h2 {\n  margin: 0.5em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h3 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h4 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h5 {\n  margin: .8em 0 0 -2%;\n  line-height: 1.3;\n}\n\nbody h6 {\n  margin: .8em 0 0 -1%;\n  line-height: 1.3;\n}\n\nbody hr {\n  border: none; /* Broken on IE6 */\n}\ndiv.footnotes hr {\n  border: 1px solid silver;\n}\n\ndiv.navheader th, div.navheader td, div.navfooter td {\n  font-family: Arial,Helvetica,sans-serif;\n  font-size: 0.9em;\n  font-weight: bold;\n  color: #527bbd;\n}\ndiv.navheader img, div.navfooter img {\n  border-style: none;\n}\ndiv.navheader a, div.navfooter a {\n  font-weight: normal;\n}\ndiv.navfooter hr {\n  border: 1px solid silver;\n}\n\nbody td {\n  line-height: 1.2\n}\n\nbody th {\n  line-height: 1.2;\n}\n\nol {\n  line-height: 1.2;\n}\n\nul, body dir, body menu {\n  line-height: 1.2;\n}\n\nhtml {\n  margin: 0; \n  padding: 0;\n}\n\nbody h1, body h2, body h3, body h4, body h5, body h6 {\n  margin-left: 0\n} \n\nbody pre {\n  margin: 0.5em 10% 0.5em 1em;\n  line-height: 1.0;\n  color: navy;\n}\n\ntt.literal, code.literal {\n  color: navy;\n}\n\n.programlisting, .screen {\n  border: 1px solid silver;\n  background: #f4f4f4;\n  margin: 0.5em 10% 0.5em 0;\n  padding: 0.5em 1em;\n}\n\ndiv.sidebar {\n  background: #ffffee;\n  margin: 1.0em 10% 0.5em 0;\n  padding: 0.5em 1em;\n  border: 1px solid silver;\n}\ndiv.sidebar * { padding: 0; }\ndiv.sidebar div { margin: 0; }\ndiv.sidebar p.title {\n  margin-top: 0.5em;\n  margin-bottom: 0.2em;\n}\n\ndiv.bibliomixed {\n  margin: 0.5em 5% 0.5em 1em;\n}\n\ndiv.glossary dt {\n  font-weight: bold;\n}\ndiv.glossary dd p {\n  margin-top: 0.2em;\n}\n\ndl {\n  margin: .8em 0;\n  line-height: 1.2;\n}\n\ndt {\n  margin-top: 0.5em;\n}\n\ndt span.term {\n  font-style: normal;\n  color: navy;\n}\n\ndiv.variablelist dd p {\n  margin-top: 0;\n}\n\ndiv.itemizedlist li, div.orderedlist li {\n  margin-left: -0.8em;\n  margin-top: 0.5em;\n}\n\nul, ol {\n    list-style-position: outside;\n}\n\ndiv.sidebar ul, div.sidebar ol {\n    margin-left: 2.8em;\n}\n\ndiv.itemizedlist p.title,\ndiv.orderedlist p.title,\ndiv.variablelist p.title\n{\n  margin-bottom: -0.8em;\n}\n\ndiv.revhistory table {\n  border-collapse: collapse;\n  border: none;\n}\ndiv.revhistory th {\n  border: none;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\ndiv.revhistory td {\n  border: 1px solid silver;\n}\n\n/* Keep TOC and index lines close together. */\ndiv.toc dl, div.toc dt,\ndiv.list-of-figures dl, div.list-of-figures dt,\ndiv.list-of-tables dl, div.list-of-tables dt,\ndiv.indexdiv dl, div.indexdiv dt\n{\n  line-height: normal;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n/*\n  Table styling does not work because of overriding attributes in\n  generated HTML.\n*/\ndiv.table table,\ndiv.informaltable table\n{\n    margin-left: 0;\n    margin-right: 5%;\n    margin-bottom: 0.8em;\n}\ndiv.informaltable table\n{\n    margin-top: 0.4em\n}\ndiv.table thead,\ndiv.table tfoot,\ndiv.table tbody,\ndiv.informaltable thead,\ndiv.informaltable tfoot,\ndiv.informaltable tbody\n{\n    /* No effect in IE6. */\n    border-top: 3px solid #527bbd;\n    border-bottom: 3px solid #527bbd;\n}\ndiv.table thead, div.table tfoot,\ndiv.informaltable thead, div.informaltable tfoot\n{\n    font-weight: bold;\n}\n\ndiv.mediaobject img {\n    margin-bottom: 0.8em;\n}\ndiv.figure p.title,\ndiv.table p.title\n{\n  margin-top: 1em;\n  margin-bottom: 0.4em;\n}\n\ndiv.calloutlist p\n{\n  margin-top: 0em;\n  margin-bottom: 0.4em;\n}\n\na img {\n  border-style: none;\n}\n\n@media print {\n  div.navheader, div.navfooter { display: none; }\n}\n\nspan.aqua { color: aqua; }\nspan.black { color: black; }\nspan.blue { color: blue; }\nspan.fuchsia { color: fuchsia; }\nspan.gray { color: gray; }\nspan.green { color: green; }\nspan.lime { color: lime; }\nspan.maroon { color: maroon; }\nspan.navy { color: navy; }\nspan.olive { color: olive; }\nspan.purple { color: purple; }\nspan.red { color: red; }\nspan.silver { color: silver; }\nspan.teal { color: teal; }\nspan.white { color: white; }\nspan.yellow { color: yellow; }\n\nspan.aqua-background { background: aqua; }\nspan.black-background { background: black; }\nspan.blue-background { background: blue; }\nspan.fuchsia-background { background: fuchsia; }\nspan.gray-background { background: gray; }\nspan.green-background { background: green; }\nspan.lime-background { background: lime; }\nspan.maroon-background { background: maroon; }\nspan.navy-background { background: navy; }\nspan.olive-background { background: olive; }\nspan.purple-background { background: purple; }\nspan.red-background { background: red; }\nspan.silver-background { background: silver; }\nspan.teal-background { background: teal; }\nspan.white-background { background: white; }\nspan.yellow-background { background: yellow; }\n\nspan.big { font-size: 2em; }\nspan.small { font-size: 0.6em; }\n\nspan.underline { text-decoration: underline; }\nspan.overline { text-decoration: overline; }\nspan.line-through { text-decoration: line-through; }\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/files/tigase-server.psf",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<psf version=\"2.0\">\n\t<provider id=\"org.tigris.subversion.subclipse.core.svnnature\">\n\t\t<project reference=\"0.9.3,https://svn.tigase.org/reps/tigase-server/trunk,tigase-server\"/>\n\t\t<project reference=\"0.9.3,https://svn.tigase.org/reps/tigase-utils/trunk,tigase-utils\"/>\n\t\t<project reference=\"0.9.3,https://svn.tigase.org/reps/tigase-xmltools/trunk,tigase-xmltools\"/>\n\t</provider>\n</psf>\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/index.asciidoc",
    "content": "Tigase Development Guide\n========================\nTigase Team <team@tigase.com>\n:toc:\n:numbered:\n:website: http://tigase.net\n\n:leveloffset: 1\n:no title:\n:no author:\n\n//intro\ninclude::text/Development_Guide_01_-_Basic_Information.asciidoc[]\n\n//writing for Tigase\ninclude::text/Development_Guide_02_-_Hack_Tigase_Jabber-XMPP_Server_in_Eclipse.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_03_-_API_Changes_in_Tigase_Server_5.x.asciidoc[]\n\n:leveloffset: 1\n\n//compiling\ninclude::text/Development_Guide_04_-_Server_Compilation.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_05_-_Tigase_XMPP_Server_5.2.0_and_Later_-_Compilation_and_Generating_Distribution_Packages.asciidoc[]\n\ninclude::text/Development_Guide_06_-_Tigase_Packages_Dependency_Change_-_Server_Compilation_Version_4.x_or_Later.asciidoc[]\n\n//removed is outdate?\n//include::text/Development_Guide_07_-_Server_Compilation_-_Version_2.x_and_3.x.asciidoc[]\n\n:leveloffset: 1\n\n//components\ninclude::text/Development_Guide_08_-_Component_Development.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_09_-_Component_Implementation_-_Lesson_1_-_Basics.asciidoc[]\n\ninclude::text/Development_Guide_10_-_Component_Implementation_-_Lesson_2_-_Configuration.asciidoc[]\n\ninclude::text/Development_Guide_11_-_Component_Implementation_-_Lesson_3_-_Multi-threading.asciidoc[]\n\ninclude::text/Development_Guide_12_-_Component_Implementation_-_Lesson_4_-_Service_Discovery.asciidoc[]\n\ninclude::text/Development_Guide_13_-_Component_Implementation_-_Lesson_5_-_Statistics.asciidoc[]\n\ninclude::text/Development_Guide_14_-_Component_Implementation_-_Lesson_6_-_Scripting_Support.asciidoc[]\n\ninclude::text/Development_Guide_15_-_Component_Implementation_-_Lesson_7_-_Data_Repository.asciidoc[]\n\ninclude::text/Development_Guide_16_-_Component_Implementation_-_Lesson_8_-_Startup_Time.asciidoc[]\n\ninclude::text/Development_Guide_17_-_Configuration_API.asciidoc[]\n\ninclude::text/Development_Guide_18_-_Packet_Filtering_in_Component.asciidoc[]\n\ninclude::text/Development_Guide_43_-_EventBus_API.asciidoc[]\n\ninclude::text/Development_Guide_42_-_Cluster_Map_Interface.asciidoc[]\n\n:leveloffset: 1\n\n//plugins\ninclude::text/Development_Guide_19_-_Plugin_Development.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_20_-_Writing_Plugin_Code.asciidoc[]\n\ninclude::text/Development_Guide_21_-_Plugin_Configuration.asciidoc[]\n\ninclude::text/Development_Guide_22_-_How_Packets_are_Processed_by_the_SM_and_Plugins.asciidoc[]\n\ninclude::text/Development_Guide_23_-_SASL_Custom_Mechanisms_and_Configuration.asciidoc[]\n\n:leveloffset: 1\n\n//maven\n\ninclude::text/Development_Guide_24_-_Using_Maven.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_25_-_Setting_Up_Maven_In_Windows.asciidoc[]\n\ninclude::text/Development_Guide_26_-_A_Very_Short_Maven_Guide.asciidoc[]\n\ninclude::text/Development_Guide_27_-_Maven_2.x_Support.asciidoc[]\n\n:leveloffset: 1\n\n//Tests\n\ninclude::text/Development_Guide_28_-_Tests.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_29_-_Tigase_Test_Suite.asciidoc[]\n\ninclude::text/Development_Guide_30_-_Test_Suite_Scripting_Language.asciidoc[]\n\ninclude::text/Development_Guide_31_-_Writing_Tests_for_Plugins.asciidoc[]\n\ninclude::text/Development_Guide_32_-_Test_Case_Parameters_Description.asciidoc[]\n\n:leveloffset: 1\n\n//experimental\ninclude::text/Development_Guide_33_-_Experimental.asciidoc[]\n\n:leveloffset: 2\n\ninclude::text/Development_Guide_34_-_Dynamic_Rosters.asciidoc[]\n\ninclude::text/Development_Guide_35_-_Mobile_Optimizations.asciidoc[]\n\ninclude::text/Development_Guide_36_-_Bosh_Session_Cache.asciidoc[]\n//Old\n\n:leveloffset: 1\n\ninclude::text/Development_Guide_37_-_Old_Stuff.asciidoc[]\n\ninclude::text/Development_Guide_38_-_Tigase_DB_Schema_Explained.asciidoc[]\n\ninclude::text/Development_Guide_39_-_Why_the_Most_Recent_JDK.asciidoc[]\n\ninclude::text/Development_Guide_40_-_Generating_Tigase_Installer.asciidoc[]\n\ninclude::text/Development_Guide_41_-_API_Description_for_Virtual_Domains_Management_in_the_Tigase_Server.asciidoc[]\n\ninclude::text/Development_Guide_44_-_Stanza_Limitations.asciidoc[]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_01_-_Basic_Information.asciidoc",
    "content": "[[basicInfo]]\n= Basic Information\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n== Tigase Server Elements\nTo make it easier to get into the code below are defined basic terms in the Tigase server world and there is a brief explanation how the server is designed and implemented. This document also points you to basic interfaces and implementations which can be used as example code reference.\n\nLogically all server code can be divided into 3 kinds of modules: *components*, *plug-ins* and *connectors*.\n\n. *Components* are the main element of Tigase server. Components are a bigger piece of code which can have separate address, receive and send stanzas, and be configured to respond to numerous events. Sample components implemented for Tigase server are: _c2s connection manager_, _s2s connection manager_, _session manager_, _XEP-0114 - external component connection manager_, _MUC - multi user char rooms_.\n. *Plug-ins* are usually small pieces of code responsible for processing specific XMPP stanzas. They don't have thier own address. As a result of stanza processing they can produce new XMPP stanzas. Plug-ins are loaded by _session manager_ component or the _c2s connection manager_ component. Sample plug-ins are: _vCard_ stanza processing, _jabber:iq:register_ to register new user accounts, _presence_ stanza processing, and _jabber:iq:auth_ for non-sasl authentication.\n. *Connectors* are modules responsible for access to data repositories like databases or LDAP to store and retrieve user data. There are 2 kinds of connectors: authentication connectors and user data connectors. Both of them are independent and can connect to different data sources. Sample connectors are: _JDBC database_ connector, _XMLDB - embedded database_ connector, _Drupal database_ connector, and the _LibreSource database_ connector.\n\nThere is an API defined for each kind of above modules and all you have to do is enable the implementation of that specific interface. Then the module can be loaded to the server based on it's configuration settings. There is also abstract classes available, implementing these interfaces to make development easier.\n\nHere is a brief list of all interfaces to look at and for more details you have to refer to the guide for specific kind of module.\n\n=== Components\nThis is list of interfaces to look at when you work on a new component:\n\n. *tigase.server.ServerComponent* - This is the very basic interface for component. All components must implement it.\n. *tigase.server.MessageReceiver* - This interface extends +ServerComponent+ and is required to implement by components which want to receive data packets like _session manager_ and _c2s connection manager_.\n. *tigase.conf.Configurable* - Implementing this interface is required to make it configurable. For each object of this type, configuration is pushed to it at any time at runtime. This is necessary to make it possible to change configuration at runtime. Be careful to implement this properly as it can cause issues for modules that cannot be configured.\n. *tigase.disco.XMPPService* - Objects using this interface can respond to \"ServiceDiscovery\" requests.\n. *tigase.stats.StatisticsContainer* - Objects using this interface can return runtime statistics. Any object can collect job statistics and implementing this interface guarantees that statistics will be presented in consisted way to user who wants to see them.\n\nInstead of implementing above interfaces directly I would recommend to extend one of existing abstract classes which take care of the most of \"dirty and boring\" stuff. Here is a list the most useful abstract classes:\n\n\n- *tigase.server.AbstractMessageReceiver* - Implements 4 basic interfaces:\n\n+ServerComponent+, +MessageReceiver+, +Configurable+ and +StatisticsContainer+. AbstractMessageReceiver also manages internal data queues using it's own threads which prevents dead-locks from resource starvation. It offers even-driven data processing which means whenever packet arrives the +abstract void processPacket(Packet packet);+ method is called to process it. You have to implement this abstract method in your component, if your component wants to send a packet (in response to data it received for example).\n\n[source,java]\n-----\nboolean addOutPacket(Packet packet)\n-----\n\n\n- *tigase.server.ConnectionManager* - This is an extension of +AbstractMessageReceiver+ abstract class. As the name says this class takes care of all network connection management stuff. If your component needs to send and receive data directly from the network (like c2s connection, s2s connection or external component) you should use this implementation as a basic class. It takes care of all things related to networking, I/O, reconnecting, listening on socket, connecting and so on. If you extend this class you have to expect data coming from to sources: from the +MessageRouter+ and this is when the\n\n[source,java]\n-----\nabstract void processPacket(Packet packet);\n-----\nmethod is called and from network connection and then the\n[source,java]\n-----\nabstract Queue processSocketData(XMPPIOService serv);\n-----\nmethod is called.\n\n=== Plug-ins\nAll Tigase plugins currently implemented are located in package: tigase.xmpp.impl. You can use this code as a sample code base. There are 3 types of plug-ins and they are defined in interfaces located in +tigase.xmpp+ package:\n\n. *XMPPProcessorIfc* - The most important and basic plug-in. This is the most common plug-in type which just processes stanzas in normal mode. It receives packets, processes them on behalf of the user and returns resulting stanzas.\n. *XMPPPreprocessorIfc* - This plugin performs pre-processing of the packet, intended for the pre-processors to setup for packet blocking.\n. *XMPPPostprocessorIfc* - This plugin performs processing of packets for which there was no specific processor.\n\n== Connector\n\n=== Data, Stanzas, Packets - Data Flow and Processing\nData received from the network are read from the network sockets as bytes by code in the +tigase.io+ package. Bytes then are changed into characters in classes of +tigase.net+ package and as characters they are sent to the XML parser (+tigase.xml+) which turns them to XML DOM structures.\n\nAll data inside the server is exchanged in XML DOM form as this is the format used by XMPP protocol. For basic XML data processing (parsing characters stream, building DOM, manipulate XML elements and attributes) we use link:https://projects.tigase.org/projects/tigase-xmltools[Tigase XML parser and DOM builder].\n\nEach stanza is stored in the +tigase.xml.Element+ object. Every Element can contain any number of +child Elements+ and any number of attributes. You can access all these data through the class API.\n\nTo simplify some, most common operations Element is wrapped in +tigase.server.Packet+ class which offers another level of API for the most common operations like preparation of response stanza based on the element it contains (swap to/from values, put type=result attribute and others).\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_02_-_Hack_Tigase_Jabber-XMPP_Server_in_Eclipse.asciidoc",
    "content": "[[hackingTigase]]\n= Hack Tigase XMPP Server in Eclipse\n:author: Daniel Wisnewski\n:version: v1.0 August 2015\n:date: 2015-18-08 10:07\n\n:toc:\n:numbered:\n:website: http://www.tigase.org\n\nIf you want to write code for *Tigase* server we recommend using link://https://eclipse.org/downloads/[Eclipse IDE].  Either the IDE for Java or Java EE developers will work.\n\n== Requirements\nEclipse IDE currently requires the use of link:http://www.oracle.com/technetwork/java/javase/downloads/jre7-downloads-1880261.html[Java Runtime Environment 7].  Although this is an outdated version of Java (and Tigase requires JDK version 8) Eclipse has not yet moved to the latest Java Build so you will need both versions installed.\n\nYou will also need the M2E plugin for Maven integration, however this can be done inside Elcipse now, so refer to the xref:m2EPlugin[Plugin Installation] section for that.\n\n== Installation\nEclipse does not come as an installer, but rather an archive.  Extract the directory to a working location wherever you would like.\nNow install the JRE 7 software, location is not important as Eclipse will find it autmoatically.\n\nBefore we begin, we will need to clone the repository from git.\n\n=== Linux\nFor linux operating systems, navigate to a directory where you want the repository to be cloned to and type the following into terminal.\n\n-----\ngit clone https://repository.tigase.org/git/tigase-server.git\n-----\n\n=== Windows\nPlease see the Windows coding guide for instructions on how to obtain source code from git.\nIf you don't want to install git software specifically, you can use Eclipse's git plugin to obtain the repository without any new software.\nFirst click on File, then Import...\nNext select from Git folder and the Projects from Git\n\nimage:images/win-git1.jpg[]\n\nClick next, and now select clone URI\n\nimage:images/win-git2.jpg[]\n\nNow click next, and in this window enter the following into the URI field\n\n-----\ngit://repository.tigase.org/git/tigase-server.git\n-----\nThe rest of the fields will populate automatically\n\nimage:images/win-git3.jpg[]\n\nSelect the master branch, and any branches you wish to edit.  *The master branch should be the only one you need, branches are used for specific code changes*\n\nimage:images/win-git4.jpg[]\n\nNow select the directory where you wanted to clone the repository to.  This was function as the project root directory you will use later on in the setup.\n\nimage:images/win-git5.jpg[]\n\nOnce you click next Eclipse will download the repository and any branches you selected to that directory.  Note you will be unable to import this git directory since there are no git a project specific files downloaded.  However, once downloading is complete you may click cancel, and the git repository will remain in the directory you have chosen.\n\n[[m2EPlugin]]\n== Setup\nOnce you have the main window open and have established a workspace (where most of your working files will be stored), click on Help and then Install New Software...\n\nimage:images/Eclipse-help.jpg[]\n\nUnder the Work With field enter the following and press enter:\nhttp://download.eclipse.org/technology/m2e/releases/\n\n*Note: You may wish to click the Add... button and add the above location as a permanent software location to keep the location in memory*\n\n\nimage:images/Eclipse-m2Einstall.jpg[]\n\nYou should see the M2 Eclipse software packages show in the main window.  Click the check-box and click Next.  Once the installer is finished it will need to restart Eclipse.\n\nOnce that is done, lets connect Eclipse to the cloned repository.\n\nClick File and Import... to bring up the import dialog window.\nSelect Maven and then Existing Maven Project.\n\nimage:images/Eclipse-importMaven.jpg[]\n\nNow click Next and point the root directory to where you cloned the git repository, Eclipse should automatically see the pom.xml file and show up in the next window.\n\nimage:images/Eclipse-importMaven2.jpg[]\n\nOnce the import is finished, you are able to now begin working with Tigase's code inside Eclipse!  Happy coding!\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_03_-_API_Changes_in_Tigase_Server_5.x.asciidoc",
    "content": "[[apiChanges]]\n= API changes in the Tigase Server 5.x\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe API changes can effect you only if you develop own code to run inside Tigase server. The changes are not extensive but in some circumstances may require many simple changes in a few files.\n\nAll the changes are related to introducing tigase.xmpp.JID and tigase.xmpp.BareJID classes. It is recommended to use them for all operations performed on the user JID instead of the String class which was used before changes.\n\nThere are a few advantages to using the new classes. First of all they do all the user JID checking and parsing, they also perform stringprep processing. Therefore if you use data kept by instance of the JID or BareJID you can be sure they are valid and correct.\n\nThese are not all advantages however. JID parsing code appears to use a lot of CPU power to conduct it's operations. JIDs and parts of the JIDs are used in many places of the stanza processing and the parsing is performed over and over again in all these places, wasting CPU cycles, memory and time.  Therefore, great performance benefits can be gained from these new class are in if, once parsed, JIDs are reused in all further stanza processing.\n\nThis is where the tigase.server.Packet class comes in handy. Instances of the Packet class encloses XML stanza and pre-parses some, the most commonly used elements of the stanza, stanza source and destination addresses among them. As an effect there are all new methods available in the class:\n\n[source,java]\n-----\nJID getStanzaFrom();\nJID getStanzaTo();\nJID getFrom();\nJID getTo();\nJID getPacketFrom();\nJID getPacketTo();\n-----\n\nWhereas following methods are still available but have been deprecated:\n\n[source,java]\n-----\nString getElemFrom();\nString getElemTo();\n-----\n\nPlease refer to the JavaDoc documentation for the link:http://docs.tigase.org/tigase-server/snapshot/javadoc/tigase/server/Packet.html[+Packet+] class and methods to learn all the details of these methods and difference between them.\n\nAnother difference is that you can no longer create the +Packet+ instance using a constructor. Instead there are a few factory methods available:\n\n[source,java]\n-----\nstatic Packet packetInstance(Element elem);\nstatic Packet packetInstance(Element elem,\n    JID stanzaFrom, JID stanzaTo);\n-----\n\nAgain, please refer to the JavaDoc documentation for all the details. The main point of using these methods is that they actually return an instance of one of the following classes instead of the +Packet+ class: +Iq+, +Presence+ or +Message+.\n\nThere is also a number of utility methods helping with creating a copy of the Packet instance preserving as much pre-parsed data as possible:\n\n[source,java]\n-----\nPacket copyElementOnly();\nPacket errorResult(...);\nPacket okResult(...);\nPacket swapFromTo();\nPacket swapStanzaFromTo();\n-----\n\nWe try to keep the link:http://docs.tigase.org/tigase-server/snapshot/javadoc/[JavaDoc] documentation as complete as possible. Please contact us if you find missing or incorrect information.\n\nThe main point is to reuse +JID+ or +BareJID+ instances in your code as much as possible. You never know, your code may run in highly loaded systems with throughput of 100k XMPP packets per second.\n\nAnother change. This one a bit risky as it is very difficult to find all places where this could be used. There are several utility classes and methods which accept source and destination address of a stanza and produce something.  There was a great confusion with them, as in some of them the first was the source address and in others the destination address. All the code has been re-factored to keep the parameter order the same in all places. Right now the policy is: *source address first*.  Therefore in all places where there was a method:\n\n[source,java]\n-----\nPacket method(String to, String from);\n-----\n\nit has been changed to:\n\n[source,java]\n-----\nPacket method(JID from, JID to);\n-----\n\nAs far as I know most of these method were used only by myself so I do not expect much trouble for other developers.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_04_-_Server_Compilation.asciidoc",
    "content": "[[serverCompilation]]\n= Server Compilation\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:11\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nList of documents describing how to work with sources and how to compile them.\n\n- xref:compile[Tigase XMPP Server 5.2.0 and Later - Compilation and Generating Distribution Packages]\n- xref:scv4ol[Tigase Packages Dependency Change - Server Compilation Version 4.x or Later]\n- xref:scv23[Server Compilation - Version 2.x and 3.x]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_05_-_Tigase_XMPP_Server_5.2.0_and_Later_-_Compilation_and_Generating_Distribution_Packages.asciidoc",
    "content": "[[compile]]\n= Tigase XMPP Server 5.2.0 and later - Compilation and Generating Distribution Packages\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-08-08 12:42\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nStarting with version 5.2.0 Tigase Server package distribution generation has switched from Ant to Maven. This will allow better dependency management as well as build repeatability.\n\nFor details on Maven and it's use, please see the xref:usingMaven[Maven Guide.]\n\n== Distribution Packages\nStarting from version 5.2.0 there will be two separate distribution archives:\n\n- *-dist* is a minimal version containing only tigase-server, tigase-xmltools and tigase-utils\n- *-dist-max* is a version containing all additional tigase components (MUC, PubSub, HTTP API, OSGi support, etc.) as well as dependencies required by those components.\n\nThey will be available as both zip and tarball.\n\n== Building Server and Generating Packages\nAfter cloning tigase-server repository:\n\n[source,bash]\n-----\ngit clone https://repository.tigase.org/git/tigase-server.git\ncd tigase-server\n-----\n\nYou compile server with maven using project distribution profile (dist):\n\n[source,bash]\n-----\nmvn -Pdist -f modules/master/pom.xml clean install\n-----\n\nThis will:\n\n- compile server binaries\n- generate javadoc documentation\n- grab all latest versions of all declared dependencies and put them in jars/ directory\n- create both types of distribution packages (-dist and -dist-max) and place them in pack/ directory\n\nIn order to create installer packages you have to execute two shell scripts:\n\n[source,bash]\n-----\n./scripts/installer-prepare.sh\n./scripts/installer-generate.sh\n-----\n\nHowever, in order for them to succeed you have to build the server first using maven as described earlier. You should also have git, python2, docutils and LaTeX distributions installed (please see src/main/izpack/README.txt for details).\n\n== Running Server\nAfterwards you can run the server with the regular shell script:\n\n[source,bash]\n-----\n./scripts/tigase.sh start etc/tigase.conf\n-----\n\nPlease bear in mind, that you need to provide correct setup in etc/init.properties configuration files for the server to work correctly.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_06_-_Tigase_Packages_Dependency_Change_-_Server_Compilation_Version_4.x_or_Later.asciidoc",
    "content": "[[scv4ol]]\n= Tigase Packages Dependency Change - Server Compilation Version 4.x or Later\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe dependency for link:https://projects.tigase.org/projects/tigase-utils[Tigase Utils Package] has changed. This is important for everybody who builds the Tigase server manually from sources using link:http://ant.apache.org/[Ant] tool. The link:http://maven.apache.org/[Maven] handles all the dependencies automatically and scripts have been updated.\n\nPlease keep reading for more details how to compile the server from sources in current repositories.\n\nIf you have an old *Tigase MUC* or *Tigase Extras* package lying in the _server/libs/_ directory please remove it now. You have to update it too and copy it over to the _server/jars/_ directory after you completed steps below.\n\nFor all those who build the server from sources manually using link:http://ant.apache.org/[Ant] here is a short guide:\n\n. Checkout all the sources first:\n+\n- link:https://projects.tigase.org/projects/tigase-xmltools/repository[https://projects.tigase.org/projects/tigase-xmltools/repository]\n- link:https://projects.tigase.org/projects/tigase-utils/repository[https://projects.tigase.org/projects/tigase-utils/repository]\n- link:https://projects.tigase.org/projects/tigase-server/repository[https://projects.tigase.org/projects/tigase-server/repository]\n. Build the Tigase XMLTools and copy the jar file over to the *utils* and*server* libs/ directory\n+\n- +cd xmltools+\n- +ant clean jar-dist+\n- +cp jars/tigase-xmltools.jar ../utils/libs+\n- +cp jars/tigase-xmltools.jar ../server/libs+\n. Build the Tigase Utils and copy the jar file to the *server* _libs/_ directory\n+\n- +cd ../utils+\n- +ant clean jar-dist+\n- +cp jars/tigase-utils.jar ../server/libs+\n. Build the Tigase Server binary\n+\n- +cd ../server+\n- +ant clean jar-dist+\n\nThis is a very short guide but I hope it helps. If you have any problems, please let me know.\n\nAddendum: starting with version 5.2.0 all libraries and jar files for the server are in jars/ directory; however with that version we strongly encourage to switch to maven build system as we are phasing out Ant - please follow guide Tigase XMPP Server 5.2.0 and Later - Compilation and Generating Distribution Packages\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_07_-_Server_Compilation_-_Version_2.x_and_3.x.asciidoc",
    "content": "[[scv23]]\n= Server Compilation - version 2.x and 3.x\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n_Tigase XMPP Server version *4.x* or later need slightly different procedure to compile._\n\nAlthough the server doesn't need any third-party libraries apart from Java 6.0 (1.6beta2) compliant JVM to run, link:http://ant.apache.org/[Apache Ant] tool and link:http://ant-contrib.sourceforge.net/[Ant-Contrib] are used to build binaries of *Tigase* applications and libraries. Another tools which is needed is a link:http://subversion.tigris.org/[Subversion] which is required to download the most recent sources from *Tigase* repository.\n\nTo make it a list, again:\n\n. link:http://java.sun.com/javase/6/webnotes/install/index.html[JDK-1.6] - Java SDK to compile and run *Tigase* applications.\n. link:http://ant.apache.org/[Apache Ant] - the build tool\n. link:http://ant-contrib.sourceforge.net/[Ant-Contrib] - *Apache Ant* extensions used by build script (ant-contrib on gentoo, and ant-optional on Ubuntu)\n. link:http://subversion.tigris.org/[Subversion] - version control system used by *Tigase*.\n\nInstall all above in standard way, appropriate for your operating system. It is enough if they are available in system PATH variable so you can execute them from command line.\n\n*Tigase Server* has been divided into a few smaller sub-projects some time ago. In order to have it all working together we need to do compile them one by one. Here is step by step instruction how to do it. Assuming you already run command line shell and changed to directory where you want to keep all *Tigase* files do as follows:\n\n. Get *tigase-utils* sources and compile them:\n+\n[source,bash]\n-----\nsvn co https://svn.tigase.org/reps/tigase-utils/trunk/ utils\ncd utils\nant clean jar\ncd ..\n-----\n. Get *tigase-xmltools* sources and compile them:\n+\n[source,bash]\n-----\nsvn co https://svn.tigase.org/reps/tigase-xmltools/trunk/ xmltools\ncd xmltools\nant clean jar\ncd ..\n-----\n. Get *tigase-server* sources and compile them:\n+\n[source,bash]\n-----\nsvn co https://svn.tigase.org/reps/tigase-server/trunk/ server\ncp xmltools/jars/tigase-xmltools.jar server/libs/\ncp utils/jars/tigase-utils.jar server/libs/\ncd server\nant clean jar\n-----\n\nNow you have *Tigase Server* compiled and ready to run. To check and make sure it is indeed compiled and can be executed you can try to start the server. Assuming you are in the directory where you executed the last compilation command for server sources run following command:\n\n[source,bash]\n-----\njava -cp libs/tigase-utils.jar:libs/tigase-xmltools.jar:jars/tigase-server.jar tigase.server.XMPPServer\n-----\n\nIf it all worked correctly you should see output similar to presented below:\n\n[source,bash]\n-----\n2006-10-04 17:00:38  ConfigRepository.init()        WARNING:  Can not open existing configuration file\n2006-10-04 17:00:38  XMLDB.setupNewDB()                  INFO:     Create empty DB.\n2006-10-04 17:00:38  MessageRouter.addRegistrator()      INFO:     Adding registrator: Configurator\n2006-10-04 17:00:38  MessageRouter.addComponent()        INFO:     Adding component: Configurator\n2006-10-04 17:00:38  Configurator.setupLogManager()      WARNING:  DONE\n2006-10-04 17:00:38  Configurator.setupLogManager()      WARNING:  DONE\n2006-10-04 17:00:39  XMLRepository.()              WARNING:  Can not open existing user repository file\n-----\n\nNow you can proceed to configuration document to learn how to tweak server settings or you can just start hacking server code and do experiments.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_08_-_Component_Development.asciidoc",
    "content": "[[componentdevelpoment]]\n= Component Development\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nA component in the Tigase is an entity with its own JID address. It can receive packets, process them, and can also generate packets.\n\nAn example of the best known components is MUC or PubSub. In Tigase however, almost everything is actually a component: Session Manager, s2s connections manager, Message Router, etc... Components are loaded based on the server configuration, new components can be loaded and activated at run-time. You can easily replace a component implementation and the only change to make is a class name in the configuration entry.\n\nCreating components for Tigase server is an essential part of the server development hence there is a lot of useful API and ready to use code available. This guide should help you to get familiar with the API and how to quickly and efficiently create your own component implementations.\n\n. xref:cil1[Component implementation - Lesson 1 - Basics]\n. xref:cil2[Component implementation - Lesson 2 - Configuration]\n. xref:cil3[Component implementation - Lesson 3 - Multi-Threading]\n. xref:cil4[Component implementation - Lesson 4 - Service Discovery]\n. xref:cil5[Component implementation - Lesson 5 - Statistics]\n. xref:cil6[Component implementation - Lesson 6 - Scripting Support]\n. xref:cil7[Component implementation - Lesson 7 - Data Repository]\n. xref:cil8[Component implementation - Lesson 8 - Startup Time]\n. xref:configurationAPI[Configuration API]\n. xref:packetfiltering[Packet Filtering in Component]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_09_-_Component_Implementation_-_Lesson_1_-_Basics.asciidoc",
    "content": "[[cil1]]\n= Component Implementation - Lesson 1 - Basics\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nCreating a Tigase component is actually very simple and with broad API available you can create a powerful component with just a few lines of code. You can find detailed API description elsewhere. This series presents hands on lessons with code examples, teaching how to get desired results in the simplest possible code using existing Tigase API.\n\nEven though all Tigase components are just implementations of the *ServerComponent* interface I will keep such a low level information to necessary minimum. Creating a new component based on just interfaces, while very possible, is not very effective. This guide intends to teach you how to make use of what is already there, ready to use with a minimal coding effort.\n\nThis is just the first lesson of the series where I cover basics of the component implementation.\n\nLet's get started and create the Tigase component:\n\n[source,java]\n-----\nimport java.util.logging.Logger;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log = Logger.getLogger(TestComponent.class.getName());\n\n  @Override\n  public void processPacket(Packet packet) {\n    log.finest(\"My packet: \" + packet.toString());\n  }\n\n}\n-----\n\nThe only element mandatory when you extend *AbstractMessageReceiver* is the implementation of *void processPacket(Packet packet)* method. This is actually logical as the main task for your component is processing packets. Class name for our new component is *TestComponent* and we have also initialized a separated logger for this class. Doing This is very useful as it allows us to easily find log entries created by our class.\n\nWith these a few lines of code you have a fully functional Tigase component which can be loaded to the Tigase server; it can receive and process packets, shows as an element on service discovery list (for administrators only), responds to administrator ad-hoc commands, supports scripting, generates statistics, can be deployed as an external component, and a few other things.\n\nBefore we go any further with the implementation let's configure the component in Tigase server so it is loaded next time the server starts.\nAssuming our *init.properties* file looks like this one:\n\n[source,java]\n-----\nconfig-type = --gen-config-def\n--debug = server\n--user-db = derby\n--admins = admin@devel.tigase.org\n--user-db-uri = jdbc:derby:/Tigase/tigasedb\n--virt-hosts = devel.tigase.org\n--comp-name-1 = muc\n--comp-class-1 = tigase.muc.MUCComponent\n--comp-name-2 = pubsub\n--comp-class-2 = tigase.pubsub.PubSubComponent\n-----\n\nWe can see that it already is configured to load two other components: *MUC* and *PubSub*. Let's add a third - our new component to the configuration file by appending two following lines in the properties file:\n\n[source,java]\n-----\n--comp-name-3 = test\n--comp-class-3 = TestComponent\n-----\n\nNow we have to remove the *etc/tigase.xml* file and restart the server.\n\nThere are a few ways to check whether our component has been loaded to the server. Probably the easiest is to connect to the server from an administrator account and look at the service discovery list.\n\nimage:images/service-disco-test-comp-admin-300.png[]\n\nIf everything goes well you should see an entry on the list similar to the highlighted one on the screenshot. The component description is \"_Undefined description_\" which is a default description and we can change it later on, the component default JID is: *test@devel.tigase.org*, where *devel.tigase.org* is the server domain and test is the component name.\n\nAnother way to find out if the component has been loaded is by looking at the log files. Getting yourself familiar with Tigase log files will be very useful thing if you plan on developing Tigase components. So let's look at the log file *logs/tigase.log.0*, if the component has been loaded you should find following lines in the log:\n\n[source,bash]\n-----\nMessageRouter.setProperties() FINER: Loading and registering message receiver: test\nMessageRouter.addRouter() INFO: Adding receiver: TestComponent\nMessageRouter.addComponent() INFO: Adding component: TestComponent\nMessageRouter.addComponent() FINER: Adding: test component to basic-conf registrator.\nConfigurator.componentAdded() CONFIG:  component: test\n-----\n\nIf your component did not load you should first check configuration files. Maybe you forgot to remove the *tigase.xml* file before restarting the server or alternatively the Tigase could not find your class at startup time. Make sure your class is in *CLASSPATH* or copy a JAR file with your class to Tigase *libs/* directory.\n\nAssuming everything went well and your component is loaded by the sever and it shows on the service discovery list as on the screenshot above you can double click on it to get a window with a list of ad-hoc commands - administrator scripts. A window on the screenshot shows only two basic commands for adding and removing script which is a good start.\n\nimage:images/commands-list-test-200.png[]\n\nMoreover, you can browse the server statistics in the service discovery window to find your new test component on the list. If you click on the component it shows you a window with component statistics, very basic packets counters.\n\nimage:images/service-disco-stats-200.png[]\n\nAs we can see with just a few lines of code our new component is quite mighty and can do a lot of things without much effort from the developer side.\n\nNow, the time has come to the most important question. Can our new component do something useful, that is can it receive and process XMPP packets?\n\nLet's try it out. Using you favorite client send a message to JID: *test@devel.tigase.org* (assuming your server is configured for *devel.tigase.org* domain). You can either use kind of XML console in your client or just send a plain message to the component JID. According to our code in *processPacket(...)* method it should log our message. For this test I have sent a message with subject: \"_test message_\" and body: \"_this is a test_\". The log file should contain following entry:\n\n[source,bash]\n-----\nTestComponent.processPacket() FINEST: My packet: to=null, from=null,\ndata=<message from=\"admin@devel.tigase.org/devel\"\n  to=\"test@devel.tigase.org\" id=\"abcaa\" xmlns=\"jabber:client\">\n  <subject>test message</subject>\n  <body>this is a test</body>\n</message>, XMLNS=jabber:client, priority=NORMAL\n-----\n\nIf this is a case we can be sure that everything works as expected and all we now have to do is to fill the *processPacket(...)* method with some useful code.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_10_-_Component_Implementation_-_Lesson_2_-_Configuration.asciidoc",
    "content": "[[cil2]]\n= Component Implementation - Lesson 2 - Configuration\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nIt might be hard to tell what the first important thing you should do with your new component implementation. Different developers may have a different view on this. It seems to me however that it is always a good idea to give to your component a way to configure it and provide some runtime settings.\n\nThis guide describes how to add configuration handling to your component.  There is detailed Configuration API description available so again I am not getting deep into all details just the necessary code.\n\nTo demonstrate how to implement component configuration let's say we want to configure which types of packets will be logged by the component. There are three possible packet types: *message*, *presence* and *iq* and we want to be able to configure logging of any combination of the three. Furthermore we also want to be able to configure the text which is prepended to the logged message and to optionally switch secure login. (Secure logging replaces all packet CData with text: _CData size: NN_ to protect user privacy.)\n\nLet's create the following private variables in our component:\n\n[source,java]\n-----\nprivate String[] packetTypes = {\"message\", \"presence\", \"iq\"};\nprivate String prependText = \"My packet: \";\nprivate boolean secureLogging = false;\n-----\n\nAs the component configuration is maintained in a form of a _(key, value)_ map, we have to invent keys for each of our configuration entry:\n\n[source,java]\n-----\nprivate static final String PACKET_TYPES_KEY = \"packet-types\";\nprivate static final String PREPEND_TEXT_KEY = \"log-prepend\";\nprivate static final String SECURE_LOGGING_KEY = \"secure-logging\";\n-----\n\nThere are two methods used to maintain the component configuration: +getDefaults(...)+ where the component provides some configuration defaults and +setProperties(...)+ which sets a working configuration for the component:\n\n[source,java]\n-----\n@Override\npublic Map<String, Object> getDefaults(Map<String, Object> params) {\n  Map<String, Object> defs = super.getDefaults(params);\n  defs.put(PACKET_TYPES_KEY, packetTypes);\n  defs.put(PREPEND_TEXT_KEY, prependText);\n  defs.put(SECURE_LOGGING_KEY, secureLogging);\n  return defs;\n}\n\n@Override\npublic void setProperties(Map<String, Object> props) {\n  super.setProperties(props);\n  if (props.get( PACKET_TYPES_KEY ) != null ) {\n    packetTypes = (String[]) props.get( PACKET_TYPES_KEY );\n  }\n  if (props.get( PREPEND_TEXT_KEY ) != null ) {\n    prependText = (String) props.get( PREPEND_TEXT_KEY );\n  }\n  if (props.get( SECURE_LOGGING_KEY ) != null ) {\n    secureLogging = (Boolean) props.get( SECURE_LOGGING_KEY );\n  }\n}\n-----\n\nYou do not have to implement the +getDefaults(...)+ method and provide default settings for your configuration, but doing so gives you a few benefits.\n\nThe first from a developer point of view, you don't have to check in the +setProperties(...)+ whether the value is of a correct type or convert it from String to the correct type as it always be either the default or user provided. It will be of a correct type as the configuration framework takes care of the types comparing between the user provided settings and default values. So this just makes your +setProperties(...)+ code much simpler and clearer.\n\nPlease note that currently Tigase allows changing properties automatically. Hence you should check each time if a given property was updated at the given call of +setProperties()+.\n\nimage:images/test-comp-config-list-smaller.png[]\n\nSecondly this also makes the administrator's life easier. As you can see on the screenshot, configuration parameters provided with default values can be changed via configuration ad-hoc commands. So the administrator can maintain your component durinmg run-time from his XMPP client.\n\nRegardless, if you implemented the +getDefaults(...)+ method or not you can always manually add parameters to the +init.properties+ file.\n\nThe syntax in +init.properties+ file is very simple and is described in details in the _Admin Guide_. As it shows on the screenshot the configuration parameter name consists of: _component name, property key_. To set the configuration for your component in +init.properties+ file you have to append following lines to the file:\n\n[source,bash]\n-----\ntest/log-prepend=\"My packet: \"\ntest/packet-types[s]=message,presence,iq\ntest/secure-logging[B]=true\n-----\n\nThe square brackets denote the property type, have a look at the _Admin Guide_ documentation for more details.\n\nAnd this is the complete code of the new component with a modified +processPacket(...)+ method taking advantage of configuration settings:\n\n[source,java]\n-----\nimport java.util.Map;\nimport java.util.logging.Logger;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log =\n    Logger.getLogger(TestComponent.class.getName());\n\n  private static final String PACKET_TYPES_KEY = \"packet-types\";\n  private static final String PREPEND_TEXT_KEY = \"log-prepend\";\n  private static final String SECURE_LOGGING_KEY = \"secure-logging\";\n\n  private String[] packetTypes = {\"message\", \"presence\", \"iq\"};\n  private String prependText = \"My packet: \";\n  private boolean secureLogging = false;\n\n  @Override\n  public void processPacket(Packet packet) {\n    for (String pType : packetTypes) {\n      if (pType == packet.getElemName()) {\n        log.finest(prependText + packet.toString(secureLogging));\n      }\n    }\n  }\n\n  @Override\n  public Map<String, Object> getDefaults(Map<String, Object> params) {\n    Map<String, Object> defs = super.getDefaults(params);\n    defs.put(PACKET_TYPES_KEY, packetTypes);\n    defs.put(PREPEND_TEXT_KEY, prependText);\n    defs.put(SECURE_LOGGING_KEY, secureLogging);\n    return defs;\n  }\n\n  @Override\n  public void setProperties(Map<String, Object> props) {\n    super.setProperties(props);\n    if (props.get( PACKET_TYPES_KEY ) != null ) {\n      packetTypes = (String[]) props.get( PACKET_TYPES_KEY );\n    }\n    // Make sure we can compare element names by reference\n    // instead of String content\n    for (int i = 0; i < packetTypes.length; i++) {\n      packetTypes[i] = packetTypes[i].intern();\n    }\n    if (props.get( PREPEND_TEXT_KEY ) != null ) {\n      prependText = (String) props.get( PREPEND_TEXT_KEY );\n    }\n    if (props.get( SECURE_LOGGING_KEY ) != null ) {\n      secureLogging = (Boolean) props.get( SECURE_LOGGING_KEY );\n    }\n  }\n\n}\n-----\n\nOf course we can do much more useful packet processing in the +processPacket(...)+ method. This is just an example code. Please note: comparing packet element name with our packet type by reference is intentional and allowed in this context. All *Element* names are processed with +String.intern()+ function to preserve memory and improve performance of string comparison.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_11_-_Component_Implementation_-_Lesson_3_-_Multi-threading.asciidoc",
    "content": "[[cil3]]\n= Component Implementation - Lesson 3 - Multi-Threading\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nMulti core and multi CPU machines very common nowadays, especially for an application like the XMPP server you most likely deployed your service on. Your new custom component however, processes all packets in a single thread.\n\nThis is especially important if the packet processing is CPU expensive like, for example, SPAM checking. In such a case you could experience single Core/CPU usage at 100% while other Cores/CPUs are idling. Ideally, you want your component to use all available CPUs.\n\nTigase API offers a very simple way to execute component's +processPacket(Packet packet)+ method in multiple threads. Methods +int processingOutThreads()+ and +int processingInThreads()+ returns number of threads assigned to the component. By default it returns just '1' as not all component implementations are prepared to process packets concurrently. By overwriting the method you can return any value you think is appropriate for the implementation. Please note, there are two methods, one is for a number of threads for incoming packets to the component and another for outgoing packets from the component. It used to be a single method but different components have different needs and the best performance can be achieved when the outgoing queues have a separate threads pool from incoming queues. Also some components only receive packets while other only send, therefore assigning an equal number of threads for both that could be a waste of resources.\n\nIf the packet processing is CPU bound only, you normally want to have as many threads as there are CPUs available:\n\n[source,java]\n-----\n@Override\npublic int processingInThreads() {\n  return Runtime.getRuntime().availableProcessors();\n}\n@Override\npublic int processingOutThreads() {\n  return Runtime.getRuntime().availableProcessors();\n}\n-----\n\nIf the processing is I/O bound (network or database) you probably want to have more threads to process requests. It is hard to guess the ideal number of threads right on the first try. Instead you should run a few tests to see how many threads is best for implementation of the component.\n\nNow you have many threads for processing your packets, but there is one slight problem with this. In many cases packet order is essential. If our +processPacket(...)+ method is executed concurrently by a few threads it is quite possible that a message sent to user can takeover the message sent earlier. Especially if the first message was large and the second was small. We can prevent this by adjusting the method responsible for packet distribution among threads.\n\nThe algorithm for packets distribution among threads is very simple:\n\n[source,java]\nint thread_idx = hashCodeForPacket(packet) % threads_total;\n\nSo the key here is using the +hashCodeForPacket(...)+ method. By overwriting it we can make sure that all packets addressed to the same user will always be processed by the same thread:\n\n[source,java]\n-----\n@Override\npublic int hashCodeForPacket(Packet packet) {\n  if (packet.getElemTo() != null) {\n    return packet.getElemTo().hashCode();\n  }\n  // This should not happen, every packet must have a destination\n  // address, but maybe our SPAM checker is used for checking\n  // strange kind of packets too....\n  if (packet.getElemFrom() != null) {\n    return packet.getElemFrom().hashCode();\n  }\n  // If this really happens on your system you should look\n  // carefully at packets arriving to your component and\n  // find a better way to calculate hashCode\n  return 1;\n}\n-----\n\nThe above two methods give control over the number of threads assigned to the packets processing in your component and to the packet distribution among threads. This is not all Tigase API has to offer in terms of multi-threading.\n\nSometimes you want to perform some periodic actions. You can of course create Timer instance and load it with TimerTasks. As there might be a need for this, every level of the Class hierarchy could end-up with multiple Timer (threads in fact) objects doing similar job and using resources. There are a few methods which allow you to reuse common Timer object to perform all sorts of actions.\n\nFirst, you have three methods allowing your to perform some periodic actions:\n\n[source,java]\n-----\npublic synchronized void everySecond();\npublic synchronized void everyMinute();\npublic synchronized void everyHour();\n-----\n\nAn example implementation for periodic notifications sent to some address could look like this one:\n\n[source,java]\n-----\n@Override\npublic synchronized void everyMinute() {\n  super.everyMinute();\n  if ((++delayCounter) >= notificationFrequency) {\n    addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),\n      StanzaType.chat, \"Detected spam messages: \" + spamCounter,\n      \"Spam counter\", null, newPacketId(\"spam-\")));\n    delayCounter = 0;\n    spamCounter = 0;\n  }\n}\n-----\n\nThis method sends every *notificationFrequency* minute a message to *abuseAddress* reporting how many spam messages have been detected during last period. Please note, you have to call +super.everyMinute()+ to make sure other actions are executed as well and you have to also remember to keep processing in this method to minimum, especially if you overwrite +everySecond()+ method.\n\nThere are also two methods which allow you to schedule tasks executed at certain time, they are very similar to the +java.util.Timer+ API with the only difference is that Timer is reused among all levels of Class hierarchy. There is a separate +Timer+ for each Class instance though, to avoid interferences between separate components:\n\n[source,java]\n-----\naddTimerTask(TimerTask task, long delay, TimeUnit unit);\naddTimerTask(TimerTask task, long delay);\n-----\n\nThere is one more method which can be used which is not directly related to multi-threading, but might be very helpful for executing some actions at a very specific point of time. This is the point of time when the server has just been initialized, that is all components have been created and received their configuration for the first time. When this happens Tigase calls +void initializationCompleted()+ method for each server component. You can overwrite this method to execute some actions at the time when you are sure the Tigase has started and is fully functional.\n\nHere is a code of an example component which uses all the API discussed in this article:\n\n[source,java]\n-----\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.logging.Logger;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.util.JIDUtils;\nimport tigase.xmpp.StanzaType;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log =\n    Logger.getLogger(TestComponent.class.getName());\n\n  private static final String BAD_WORDS_KEY = \"bad-words\";\n  private static final String WHITELIST_KEY = \"white-list\";\n  private static final String PREPEND_TEXT_KEY = \"log-prepend\";\n  private static final String SECURE_LOGGING_KEY = \"secure-logging\";\n  private static final String ABUSE_ADDRESS_KEY = \"abuse-address\";\n  private static final String NOTIFICATION_FREQ_KEY = \"notification-freq\";\n\n  private String[] badWords = {\"word1\", \"word2\", \"word3\"};\n  private String[] whiteList = {\"admin@localhost\"};\n  private String prependText = \"Spam detected: \";\n  private String abuseAddress = \"abuse@locahost\";\n  private int notificationFrequency = 10;\n  private int delayCounter = 0;\n  private boolean secureLogging = false;\n  private long spamCounter = 0;\n\n  @Override\n  public void processPacket(Packet packet) {\n    // Is this packet a message?\n    if (\"message\" == packet.getElemName()) {\n      String from = JIDUtils.getNodeID(packet.getElemFrom());\n      // Is sender on the whitelist?\n      if (Arrays.binarySearch(whiteList, from) < 0) {\n        // The sender is not on whitelist so let's check the content\n        String body = packet.getElemCData(\"/message/body\");\n        if (body != null && !body.isEmpty()) {\n          body = body.toLowerCase();\n          for (String word : badWords) {\n            if (body.contains(word)) {\n              log.finest(prependText + packet.toString(secureLogging));\n              ++spamCounter;\n              return;\n            }\n          }\n        }\n      }\n    }\n    // Not a SPAM, return it for further processing\n    Packet result = packet.swapFromTo();\n    addOutPacket(result);\n  }\n\n  @Override\n  public int processingInThreads() {\n    return Runtime.getRuntime().availableProcessors();\n  }\n\n  @Override\n  public int processingOutThreads() {\n    return Runtime.getRuntime().availableProcessors();\n  }\n\n  @Override\n  public int hashCodeForPacket(Packet packet) {\n    if (packet.getElemTo() != null) {\n      return packet.getElemTo().hashCode();\n    }\n    // This should not happen, every packet must have a destination\n    // address, but maybe our SPAM checker is used for checking\n    // strange kind of packets too....\n    if (packet.getElemFrom() != null) {\n      return packet.getElemFrom().hashCode();\n    }\n    // If this really happens on your system you should look carefully\n    // at packets arriving to your component and decide a better way\n    // to calculate hashCode\n    return 1;\n  }\n\n  @Override\n  public Map<String, Object> getDefaults(Map<String, Object> params) {\n    Map<String, Object> defs = super.getDefaults(params);\n    defs.put(BAD_WORDS_KEY, badWords);\n    defs.put(WHITELIST_KEY, whiteList);\n    defs.put(PREPEND_TEXT_KEY, prependText);\n    defs.put(SECURE_LOGGING_KEY, secureLogging);\n    defs.put(ABUSE_ADDRESS_KEY, abuseAddress);\n    defs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);\n    return defs;\n  }\n\n  @Override\n  public void setProperties(Map<String, Object> props) {\n    super.setProperties(props);\n    badWords = (String[])props.get(BAD_WORDS_KEY);\n    whiteList = (String[])props.get(WHITELIST_KEY);\n    Arrays.sort(whiteList);\n    prependText = (String)props.get(PREPEND_TEXT_KEY);\n    secureLogging = (Boolean)props.get(SECURE_LOGGING_KEY);\n    abuseAddress = (String)props.get(ABUSE_ADDRESS_KEY);\n    notificationFrequency = (Integer)props.get(NOTIFICATION_FREQ_KEY);\n  }\n\n  @Override\n  public synchronized void everyMinute() {\n    super.everyMinute();\n    if ((++delayCounter) >= notificationFrequency) {\n      addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),\n        StanzaType.chat, \"Detected spam messages: \" + spamCounter,\n        \"Spam counter\", null, newPacketId(\"spam-\")));\n      delayCounter = 0;\n      spamCounter = 0;\n    }\n  }\n\n}\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_12_-_Component_Implementation_-_Lesson_4_-_Service_Discovery.asciidoc",
    "content": "[[cil4]]\n= Component Implementation - Lesson 4 - Service Discovery\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nYou component still shows in the service discovery list as an element with \"_Undefined description_\". It also doesn't provide any interesting features or sub-nodes.\n\nIn this article I will show how to, in a simple way, change the basic component information presented on the service discovery list and how to add some service disco features. As a bit more advanced feature the guide will teach you about adding/removing service discovery nodes at run-time and about updating existing elements.\n\nComponent description and category type can be changed by overriding two following methods:\n\n[source,java]\n-----\n@Override\npublic String getDiscoDescription() {\n  return \"Spam filtering\";\n}\n\n@Override\npublic String getDiscoCategoryType() {\n  return \"spam\";\n}\n-----\n\nPlease note, there is no such *\\'spam'* category type defined in the link:http://xmpp.org/registrar/disco-categories.html[Service Discovery Identities registry]. It has been used here as a demonstration only. Please refer to the Service Discovery Identities registry document for a list of categories and types and pick the one most suitable for you.\n\nAfter you have added the two above methods and restarted the server with updated code, have a look at the service discovery window. You should see something like on the screenshot.\n\nimage:images/spam-filtering-disco-small.png[]\n\nAlthough this was easy, this particular change doesn't affect anything apart from just a visual appearance. Let's get then to more advanced and more useful changes.\n\nOne of the limitations of methods above is that you can not update or change component information at run-time with these methods. They are called only once during +setProperties(...)+ method call and the component service discovery information is created and prepared for later use. Sometimes, however it is useful to be able to change the service discovery during run-time.\n\nIn our simple spam filtering component let's show how many messages have been checked out as part of the service discovery description string. Every time we receive a message we can to call:\n\n[source,java]\n-----\nupdateServiceDiscoveryItem(getName(), null,\n  getDiscoDescription() + \": [\" +\n  (++messagesCounter) + \"]\", true);\n-----\n\n_A small performance note, in some cases calling +updateServiceDiscoveryItem(...)+ might be an expensive operation so probably a better idea would be to call the method not every time we receive a message but maybe every 100 times or so._\n\nThe first parameter is the component JID presented on the service discovery list. However, Tigase server may work for many virtual hosts so the hostname part is added by the lower level functions and we only provide the component name here. The second parameter is the service discovery node which is usually '*null*' for top level disco elements. Third is the item description (which is actually called 'name' in the disco specification). The last parameter specifies if the element is visible to administrators only.\n\nimage:images/spam-filter-counter-small.png[]\n\nThe complete method code is presented below and the screenshot above shows how the element of the service discovery for our component can change if we apply our code and send a few messages to the component.\n\nUsing the method we can also add submodes to our component element. The XMPP service discovery really is not for showing application counters, but this case it is good enough to demonstrate the API available in Tigase so we continue with presenting our counters via service discovery. This time, instead of using 'null' as a node we put some meaningful texts as in example below:\n\n[source,java]\n-----\n// This is called whenever a message arrives\n// to the component\nupdateServiceDiscoveryItem(getName(), \"messages\",\n  \"Messages processed: [\" + (++messagesCounter) + \"]\", true);\n// This is called every time the component detects\n// spam message\nupdateServiceDiscoveryItem(getName(), \"spam\", \"Spam caught: [\" +\n  (++totalSpamCounter) + \"]\", true);\n-----\n\nAgain, have a look at the full method body below for a complete code example. Now if we send a few messages to the component and some of them are spam (contain words recognized as spam) we can browse the service discovery of the server. Your service discovery should show a list similar to the one presented on the screenshot on the left.\n\nOf course depending on the implementation, initially there might be no sub-nodes under our component element if we call the +updateServiceDiscoveryItem(...)+ method only when a message is processed. To make sure that sub-nodes of our component show from the very beginning you can call them in +setProperties(...)+ for the first time to populate the service discovery with initial sub-nodes.\n\nPlease note, the +updateServiceDiscoveryItem(...)+ method is used for adding a new item and updating existing one. There is a separate method though to remove the item:\n\n[source,java]\n-----\nvoid removeServiceDiscoveryItem(String jid,\n  String node, String description)\n-----\n\nActually only two first parameters are important: the *jid* and the *node* which must correspond to the existing, previously created service discovery item.\n\nThere are two additional variants of the _update_ method which give you more control over the service discovery item created. Items can be of different categories and types and can also present a set of features.\n\nThe simpler is a variant which sets a set of features for the updated service discovery item. There is a link:http://xmpp.org/registrar/disco-features.html[document] describing existing, registered features. We are creating an example which is going to be a spam filter and there is no predefined feature for spam filtering but for purpose of this guide we can invent two feature identification strings and set it for our component. Let's call +update+ method with following parameters:\n\n[source,java]\n-----\nupdateServiceDiscoveryItem(getName(), null, getDiscoDescription(),\n  true, \"tigase:x:spam-filter\", \"tigase:x:spam-reporting\");\n-----\n\nThe best place to call this method is the +setProperties(...)+ method so our component gets a proper service discovery settings at startup time. We have set two features for the component disco: _tigase:x:spam-filter_ and _tigase:x:spam-reporting_. This method accepts a variable set of arguments so we can pass to it as many features as we need or following Java spec we can just pass an array of *Strings*.\n\nUpdate your code with call presented above, and restart the server. Have a look at the service discovery for the component now.\n\nThe last functionality might be not very useful for our case of the spam filtering component, but it is for many other cases like MUC or PubSub for which it is setting proper category and type for the service discovery item. There is a document listing all currently registered service discovery identities (categories and types). Again there is entry for spam filtering. Let's use the _automation_ category and _spam-filter_ type and set it for our component:\n\n[source,java]\n-----\nupdateServiceDiscoveryItem(getName(), null, getDiscoDescription(),\n  \"automation\", \"spam-filtering\", true,\n  \"tigase:x:spam-filter\", \"tigase:x:spam-reporting\");\n-----\n\nOf course all these setting can be applied to any service discovery create or update, including sub-nodes. And here is a complete code of the component:\n\n[source,java]\n-----\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.logging.Logger;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.util.JIDUtils;\nimport tigase.xmpp.StanzaType;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log =\n    Logger.getLogger(TestComponent.class.getName());\n\n  private static final String BAD_WORDS_KEY = \"bad-words\";\n  private static final String WHITELIST_KEY = \"white-list\";\n  private static final String PREPEND_TEXT_KEY = \"log-prepend\";\n  private static final String SECURE_LOGGING_KEY = \"secure-logging\";\n  private static final String ABUSE_ADDRESS_KEY = \"abuse-address\";\n  private static final String NOTIFICATION_FREQ_KEY = \"notification-freq\";\n\n  private String[] badWords = {\"word1\", \"word2\", \"word3\"};\n  private String[] whiteList = {\"admin@localhost\"};\n  private String prependText = \"Spam detected: \";\n  private String abuseAddress = \"abuse@locahost\";\n  private int notificationFrequency = 10;\n  private int delayCounter = 0;\n  private boolean secureLogging = false;\n  private long spamCounter = 0;\n  private long totalSpamCounter = 0;\n  private long messagesCounter = 0;\n\n  @Override\n  public void processPacket(Packet packet) {\n    // Is this packet a message?\n    if (\"message\" == packet.getElemName()) {\n      updateServiceDiscoveryItem(getName(), \"messages\",\n        \"Messages processed: [\" + (++messagesCounter) + \"]\", true);\n      String from = JIDUtils.getNodeID(packet.getElemFrom());\n      // Is sender on the whitelist?\n      if (Arrays.binarySearch(whiteList, from) < 0) {\n        // The sender is not on whitelist so let's check the content\n        String body = packet.getElemCData(\"/message/body\");\n        if (body != null && !body.isEmpty()) {\n          body = body.toLowerCase();\n          for (String word : badWords) {\n            if (body.contains(word)) {\n              log.finest(prependText + packet.toString(secureLogging));\n              ++spamCounter;\n              updateServiceDiscoveryItem(getName(), \"spam\", \"Spam caught: [\" +\n                (++totalSpamCounter) + \"]\", true);\n              return;\n            }\n          }\n        }\n      }\n    }\n    // Not a SPAM, return it for further processing\n    Packet result = packet.swapElemFromTo();\n    addOutPacket(result);\n  }\n\n  @Override\n  public int processingThreads() {\n    return Runtime.getRuntime().availableProcessors();\n  }\n\n  @Override\n  public int hashCodeForPacket(Packet packet) {\n    if (packet.getElemTo() != null) {\n      return packet.getElemTo().hashCode();\n    }\n    // This should not happen, every packet must have a destination\n    // address, but maybe our SPAM checker is used for checking\n    // strange kind of packets too....\n    if (packet.getElemFrom() != null) {\n      return packet.getElemFrom().hashCode();\n    }\n    // If this really happens on your system you should look carefully\n    // at packets arriving to your component and decide a better way\n    // to calculate hashCode\n    return 1;\n  }\n\n  @Override\n  public Map<String, Object> getDefaults(Map<String, Object> params) {\n    Map<String, Object> defs = super.getDefaults(params);\n    defs.put(BAD_WORDS_KEY, badWords);\n    defs.put(WHITELIST_KEY, whiteList);\n    defs.put(PREPEND_TEXT_KEY, prependText);\n    defs.put(SECURE_LOGGING_KEY, secureLogging);\n    defs.put(ABUSE_ADDRESS_KEY, abuseAddress);\n    defs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);\n    return defs;\n  }\n\n  @Override\n  public void setProperties(Map<String, Object> props) {\n    super.setProperties(props);\n    badWords = (String[])props.get(BAD_WORDS_KEY);\n    whiteList = (String[])props.get(WHITELIST_KEY);\n    Arrays.sort(whiteList);\n    prependText = (String)props.get(PREPEND_TEXT_KEY);\n    secureLogging = (Boolean)props.get(SECURE_LOGGING_KEY);\n    abuseAddress = (String)props.get(ABUSE_ADDRESS_KEY);\n    notificationFrequency = (Integer)props.get(NOTIFICATION_FREQ_KEY);\n    updateServiceDiscoveryItem(getName(), null, getDiscoDescription(),\n      \"automation\", \"spam-filtering\", true,\n      \"tigase:x:spam-filter\", \"tigase:x:spam-reporting\");\n  }\n\n  @Override\n  public synchronized void everyMinute() {\n    super.everyMinute();\n    if ((++delayCounter) >= notificationFrequency) {\n      addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),\n        StanzaType.chat, \"Detected spam messages: \" + spamCounter,\n        \"Spam counter\", null, newPacketId(\"spam-\")));\n      delayCounter = 0;\n      spamCounter = 0;\n    }\n  }\n\n  @Override\n  public String getDiscoDescription() {\n    return \"Spam filtering\";\n  }\n\n  @Override\n  public String getDiscoCategoryType() {\n    return \"spam\";\n  }\n\n}\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_13_-_Component_Implementation_-_Lesson_5_-_Statistics.asciidoc",
    "content": "[[cil5]]\n= Component Implementation - Lesson 5 - Statistics\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nIn most cases you'll want to gather some run-time statistics from your component to see how it works, detect possible performance issues or congestion problems. All server statistics are exposed and are accessible via XMPP with ad-hoc commands, HTTP, JMX and some selected statistics are also available via SNMP. As a component developer you don't have to do anything to expose your statistic via any of those protocols, you just have to provide your statistics and the admin will be able to access them any way he wants.\n\nThis lesson will teach you how to add your own statistics and how to make sure that the statistics generation doesn't affect application performance.\n\nimage:images/spam-statitics-small.png[]\n\nYour component from the very beginning generates some statistics by classes it inherits. Let's add a few statistics to our spam filtering component:\n\n[source,java]\n-----\n@Override\npublic void getStatistics(StatisticsList list) {\n  super.getStatistics(list);\n  list.add(getName(), \"Spam messages found\", totalSpamCounter, Level.INFO);\n  list.add(getName(), \"All messages processed\", messagesCounter, Level.FINER);\n  if (list.checkLevel(Level.FINEST)) {\n    // Some very expensive statistics generation code...\n  }\n}\n-----\n\nI think the code should be pretty much self-explanatory.\n\nYou have to call +super.getStatistics(...)+ to update stats of the parent class. +StatisticsList+ is a collection which keeps all the statistics in a way which is easy to update, search, and retrieve them. You actually don't need to know all the implementation details but if you are interested please refer to the source code and JavaDoc documentation.\n\nThe first parameter of the +add(...)+ method is the component name. All the statistics are grouped by the component names to make it easier to look at particular component data. Next is a description of the element. The third parameter is the element value which can be any number or string.\n\nThe last parameter is probably the most interesting. The idea has been borrowed from the logging framework. Each statistic item has importance level.  Levels are exactly the same as for logging methods with *SEVERE* the most critical and *FINEST* the least important. This parameter has been added to improve performance and statistics retrieval. When the *StatisticsList* object is created it gets assigned a level requested by the user. If the +add(...)+ method is called with lower priority level then the element is not even added to the list. This saves network bandwidth, improves statistics retrieving speed and is also more clear to present to the end-user.\n\nOne thing which may be a bit confusing at first is that, if there is a numerical element added to statistics with *0* value then the Level is always forced to *FINEST*. The assumption is that the administrator is normally not interested *zero-value* statistics, therefore unless he intentionally request the lowest level statistics he won't see elements with *zeros*.\n\nThe *if* statement requires some explanation too. Normally adding a new statistics element is not a very expensive operation so passing it with +add(...)+ method at an appropriate level is enough. Sometimes, however preparing statistics data may be quite expensive, like reading/counting some records from database. Statistics can be collected quite frequently therefore it doesn't make sense to collect the statistics at all if there not going to be used as the current level is higher then the item we pass anyway. In such a case it is recommended to test whether the element level will be accepted by the collection and if not skip the whole processing altogether.\n\nAs you can see, the API for generating and presenting component statistics is very simple and straightforward. Just one method to overwrite and a simple way to pass your own counters. Below is the whole code of the example component:\n\n[source,java]\n-----\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.util.JIDUtils;\nimport tigase.xmpp.StanzaType;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log =\n  Logger.getLogger(TestComponent.class.getName());\n\n  private static final String BAD_WORDS_KEY = \"bad-words\";\n  private static final String WHITELIST_KEY = \"white-list\";\n  private static final String PREPEND_TEXT_KEY = \"log-prepend\";\n  private static final String SECURE_LOGGING_KEY = \"secure-logging\";\n  private static final String ABUSE_ADDRESS_KEY = \"abuse-address\";\n  private static final String NOTIFICATION_FREQ_KEY = \"notification-freq\";\n\n  private String[] badWords = {\"word1\", \"word2\", \"word3\"};\n  private String[] whiteList = {\"admin@localhost\"};\n  private String prependText = \"Spam detected: \";\n  private String abuseAddress = \"abuse@locahost\";\n  private int notificationFrequency = 10;\n  private int delayCounter = 0;\n  private boolean secureLogging = false;\n  private long spamCounter = 0;\n  private long totalSpamCounter = 0;\n  private long messagesCounter = 0;\n\n  @Override\n  public void processPacket(Packet packet) {\n    // Is this packet a message?\n    if (\"message\" == packet.getElemName()) {\n      updateServiceDiscoveryItem(getName(), \"messages\",\n        \"Messages processed: [\" + (++messagesCounter) + \"]\", true);\n      String from = JIDUtils.getNodeID(packet.getElemFrom());\n      // Is sender on the whitelist?\n      if (Arrays.binarySearch(whiteList, from) < 0) {\n        // The sender is not on whitelist so let's check the content\n        Stringbody = packet.getElemCData(\"/message/body\");\n        if (body != null && !body.isEmpty()) {\n          body = body.toLowerCase();\n          for (String word : badWords) {\n            if (body.contains(word)) {\n              log.finest(prependText + packet.toString(secureLogging));\n              ++spamCounter;\n              updateServiceDiscoveryItem(getName(), \"spam\", \"Spam caught: [\" +\n                (++totalSpamCounter) + \"]\", true);\n              return;\n            }\n          }\n        }\n      }\n    }\n    // Not a SPAM, return it for further processing\n    Packet result = packet.swapElemFromTo();\n    addOutPacket(result);\n  }\n\n  @Override\n  public int processingThreads() {\n    return Runtime.getRuntime().availableProcessors();\n  }\n\n  @Override\n  public int hashCodeForPacket(Packet packet) {\n    if (packet.getElemTo() != null) {\n      return packet.getElemTo().hashCode();\n    }\n    // This should not happen, every packet must have a destination\n    // address, but maybe our SPAM checker is used for checking\n    // strange kind of packets too....\n    if (packet.getElemFrom() != null) {\n      return packet.getElemFrom().hashCode();\n    }\n    // If this really happens on your system you should look carefully\n    // at packets arriving to your component and decide a better way\n    // to calculate hashCode\n    return 1;\n  }\n\n  @Override\n  public Map<String, Object> getDefaults(Map<String, Object> params) {\n    Map<String, Object> defs = super.getDefaults(params);\n    defs.put(BAD_WORDS_KEY, badWords);\n    defs.put(WHITELIST_KEY, whiteList);\n    defs.put(PREPEND_TEXT_KEY, prependText);\n    defs.put(SECURE_LOGGING_KEY, secureLogging);\n    defs.put(ABUSE_ADDRESS_KEY, abuseAddress);\n    defs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);\n    return defs;\n  }\n\n  @Override\n  public void setProperties(Map<String, Object> props) {\n    super.setProperties(props);\n    badWords = (String[])props.get(BAD_WORDS_KEY);\n    whiteList = (String[])props.get(WHITELIST_KEY);\n    Arrays.sort(whiteList);\n    prependText = (String)props.get(PREPEND_TEXT_KEY);\n    secureLogging = (Boolean)props.get(SECURE_LOGGING_KEY);\n    abuseAddress = (String)props.get(ABUSE_ADDRESS_KEY);\n    notificationFrequency = (Integer)props.get(NOTIFICATION_FREQ_KEY);\n    updateServiceDiscoveryItem(getName(), null, getDiscoDescription(),\n      \"automation\", \"spam-filtering\", true,\n      \"tigase:x:spam-filter\", \"tigase:x:spam-reporting\");\n  }\n\n  @Override\n  public synchronized void everyMinute() {\n    super.everyMinute();\n    if ((++delayCounter) >= notificationFrequency) {\n      addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),\n        StanzaType.chat, \"Detected spam messages: \" + spamCounter,\n        \"Spam counter\", null, newPacketId(\"spam-\")));\n      delayCounter = 0;\n      spamCounter = 0;\n    }\n  }\n\n  @Override\n  public String getDiscoDescription() {\n    return \"Spam filtering\";\n  }\n\n  @Override\n  public String getDiscoCategoryType() {\n    return \"spam\";\n  }\n\n  @Override\n  public void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n    list.add(getName(), \"Spam messages found\", totalSpamCounter, Level.INFO);\n    list.add(getName(), \"All messages processed\", messagesCounter, Level.FINE);\n    if (list.checkLevel(Level.FINEST)) {\n      // Some very expensive statistics generation code...\n    }\n  }\n\n}\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_14_-_Component_Implementation_-_Lesson_6_-_Scripting_Support.asciidoc",
    "content": "[[cil6]]\n= Component Implementation - Lesson 6 - Scripting Support\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-01-06 20:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nScripting support is a basic API built-in to Tigase server and automatically available to any component at no extra resource cost. This framework, however, can only access existing component variables which are inherited by your code from parent classes. It can not access any data or any structures you added in your component. A little effort is needed to expose some of your data to the scripting API.\n\nThis guide shows how to extend existing scripting API with your component specific data structures.\n\nIntegrating your component implementation with the scripting API is as simple as the code below:\n\n[source,java]\n-----\nprivate static final String BAD_WORDS_VAR = \"badWords\";\nprivate static final String WHITE_LIST_VAR = \"whiteList\";\n\n@Override\npublic void initBindings(Bindings binds) {\n  super.initBindings(binds);\n  binds.put(BAD_WORDS_VAR, badWords);\n  binds.put(WHITE_LIST_VAR, whiteList);\n}\n-----\n\nThis way you expose two the component variables: +badWords+ and +whiteList+ to scripts under names the same names - two defined constants. You could use different names of course but it is always a good idea to keep things straightforward, hence we use the same variable names in the component and in the script.\n\nAlmost done, almost... In our old implementation these two variables are Java arrays of *String*s. Therefore we can only change their elements but we can not add or remove elements from these structures inside the script. This is not very practical and it puts some serious limits on the script's code. To overcome this problem I have changed the test component code to keep bad words and whitelist in *java.util.Set* collection. This gives us enough flexibility to manipulate data.\n\nAs our component is now ready to cooperate with the scripting API, I will demonstrate now how to add remove or change elements of these collections using a script and ad-hoc commands.\n\nimage:images/test-comp-newscript.png[]\n\nFirst, browse the server service discovery and double click on the test component. If you use link:http://psi-im.org/[Psi] client this should bring to you a new window with ad-hoc commands list. Other clients may present available ad-hoc commands differently.\n\nThe screenshot below shows how this may look. You have to provide some description for the script and an ID string. We use Groovy in this guide but you can as well use any different scripting language.\n\nimage:images/badwords-list-script.png[]\n\nPlease refer to the Tigase scripting documentation for all the details how to add support for more languages. From the Tigase API point of view it all looks the same. You have to select a proper language from the pull-down list on windows shown on the right. If your preferred language is not on the list, it means it is not installed properly and Tigase is unable to detect it.\n\nThe script to pull a list of current bad words can be as simple as the following Groovy code:\n\n[source,java]\n-----\ndef badw = (java.util.Set)badWords\ndef result = \"\"\nfor (s in badw) { result += s + \"\\n\" }\nreturn result\n-----\n\nAs you see from the code, you have to reference your component variables to a variables in your script to make sure a correct type is used. The rest is very simple and is a pure scripting language stuff.\n\nLoad the script on to the server and execute it. You should receive a new window with a list of all bad words currently used by the spam filter.\n\nBelow is another simple script which allows updating (adding/removing) bad words from the list.\n\n[source,java]\n-----\nimport tigase.server.Command\nimport tigase.server.Packet\n\ndef WORDS_LIST_KEY = \"words-list\"\ndef OPERATION_KEY = \"operation\"\ndef REMOVE = \"Remove\"\ndef ADD = \"Add\"\ndef OPERATIONS = [ADD, REMOVE]\n\ndef badw = (java.util.Set)badWords\ndef Packet p = (Packet)packet\ndef words = Command.getFieldValue(p, WORDS_LIST_KEY)\ndef operation = Command.getFieldValue(p, OPERATION_KEY)\n\nif (words == null) {\n  // No data to process, let's ask user to provide\n  // a list of words\n  def res = (Packet)p.commandResult(Command.DataType.form)\n  Command.addFieldValue(res, WORDS_LIST_KEY, \"\", \"Bad words list\")\n  Command.addFieldValue(res, OPERATION_KEY, ADD, \"Operation\",\n    (String[])OPERATIONS, (String[])OPERATIONS)\n  return res\n}\n\ndef words_list = words.tokenize(\",\")\n\nif (operation == ADD) {\n  words_list.each { badw.add(it.trim()) }\n  return \"Words have been added.\"\n}\n\nif (operation == REMOVE) {\n  words_list.each { badw.remove(it.trim()) }\n  return \"Words have been removed.\"\n}\n\nreturn \"Unknown operation: \" + operation\n-----\n\nThese two scripts are just the beginning. The possibilities are endless and with the simple a few lines of code in your test component you can then extend your application at runtime with scripts doing various things; you can reload scripts, add and remove them, extending and modifying functionality as you need. No need to restart the server, no need to recompile the code and you can use whatever scripting language you like.\n\nOf course, scripts for whitelist modifications would look exactly the same and it doesn't make sense to attach them here.\n\nHere is a complete code of the test component with the new method described at the beginning and data structures changed from array of *String*s to Java *Set*:\n\n[source,java]\n-----\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.script.Bindings;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.util.JIDUtils;\nimport tigase.xmpp.StanzaType;\n\npublic class TestComponent extends AbstractMessageReceiver {\n\n  private static final Logger log =\n    Logger.getLogger(TestComponent.class.getName());\n\n  private static final String BAD_WORDS_KEY = \"bad-words\";\n  private static final String WHITELIST_KEY = \"white-list\";\n  private static final String PREPEND_TEXT_KEY = \"log-prepend\";\n  private static final String SECURE_LOGGING_KEY = \"secure-logging\";\n  private static final String ABUSE_ADDRESS_KEY = \"abuse-address\";\n  private static final String NOTIFICATION_FREQ_KEY = \"notification-freq\";\n\n  private static final String BAD_WORDS_VAR = \"badWords\";\n  private static final String WHITE_LIST_VAR = \"whiteList\";\n  private static final String[] INITIAL_BAD_WORDS = {\"word1\", \"word2\", \"word3\"};\n  private static final String[] INITIAL_WHITE_LIST = {\"admin@localhost\"};\n\n  /**\n   * This might be changed in one threads while it is iterated in\n   * processPacket(...) in another thread. We expect that changes are very rare\n   * and small, most of operations are just iterations.\n   */\n  private Set<String> badWords = new CopyOnWriteArraySet<String>();\n  /**\n   * This might be changed in one threads while it is iterated in\n   * processPacket(...) in another thread. We expect that changes are very rare\n   * and small, most of operations are just contains(...).\n   */\n  private Set<String> whiteList = new ConcurrentSkipListSet<String>();\n  private String prependText = \"Spam detected: \";\n  private String abuseAddress = \"abuse@locahost\";\n  private int notificationFrequency = 10;\n  private int delayCounter = 0;\n  private boolean secureLogging = false;\n  private long spamCounter = 0;\n  private long totalSpamCounter = 0;\n  private long messagesCounter = 0;\n\n  @Override\n  public void processPacket(Packet packet) {\n    // Is this packet a message?\n    if (\"message\" == packet.getElemName()) {\n      updateServiceDiscoveryItem(getName(), \"messages\",\n        \"Messages processed: [\" + (++messagesCounter) + \"]\", true);\n      String from = JIDUtils.getNodeID(packet.getElemFrom());\n      // Is sender on the whitelist?\n      if (!whiteList.contains(from)) {\n        // The sender is not on whitelist so let's check the content\n        String body = packet.getElemCData(\"/message/body\");\n        if (body != null && !body.isEmpty()) {\n          body = body.toLowerCase();\n          for (String word : badWords) {\n            if (body.contains(word)) {\n              log.finest(prependText + packet.toString(secureLogging));\n              ++spamCounter;\n              updateServiceDiscoveryItem(getName(), \"spam\", \"Spam caught: [\" +\n                (++totalSpamCounter) + \"]\", true);\n              return;\n            }\n          }\n        }\n      }\n    }\n    // Not a SPAM, return it for further processing\n    Packet result = packet.swapElemFromTo();\n    addOutPacket(result);\n  }\n\n  @Override\n  public int processingThreads() {\n    return Runtime.getRuntime().availableProcessors();\n  }\n\n  @Override\n  public int hashCodeForPacket(Packet packet) {\n    if (packet.getElemTo() != null) {\n      return packet.getElemTo().hashCode();\n    }\n    // This should not happen, every packet must have a destination\n    // address, but maybe our SPAM checker is used for checking\n    // strange kind of packets too....\n    if (packet.getElemFrom() != null) {\n      return packet.getElemFrom().hashCode();\n    }\n    // If this really happens on your system you should look carefully\n    // at packets arriving to your component and decide a better way\n    // to calculate hashCode\n    return 1;\n  }\n\n  @Override\n  public Map<String, Object> getDefaults(Map<String, Object> params) {\n    Map<String, Object> defs = super.getDefaults(params);\n    Collections.addAll(badWords, INITIAL_BAD_WORDS);\n    Collections.addAll(whiteList, INITIAL_WHITE_LIST);\n    defs.put(BAD_WORDS_KEY, INITIAL_BAD_WORDS);\n    defs.put(WHITELIST_KEY, INITIAL_WHITE_LIST);\n    defs.put(PREPEND_TEXT_KEY, prependText);\n    defs.put(SECURE_LOGGING_KEY, secureLogging);\n    defs.put(ABUSE_ADDRESS_KEY, abuseAddress);\n    defs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);\n    return defs;\n  }\n\n  @Override\n  public void setProperties(Map<String, Object> props) {\n    super.setProperties(props);\n    Collections.addAll(badWords, (String[])props.get(BAD_WORDS_KEY));\n    Collections.addAll(whiteList, (String[])props.get(WHITELIST_KEY));\n    prependText = (String)props.get(PREPEND_TEXT_KEY);\n    secureLogging = (Boolean)props.get(SECURE_LOGGING_KEY);\n    abuseAddress = (String)props.get(ABUSE_ADDRESS_KEY);\n    notificationFrequency = (Integer)props.get(NOTIFICATION_FREQ_KEY);\n    updateServiceDiscoveryItem(getName(), null, getDiscoDescription(),\n      \"automation\", \"spam-filtering\", true,\n      \"tigase:x:spam-filter\", \"tigase:x:spam-reporting\");\n  }\n\n  @Override\n  public synchronized void everyMinute() {\n    super.everyMinute();\n    if ((++delayCounter) >= notificationFrequency) {\n      addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),\n        StanzaType.chat, \"Detected spam messages: \" + spamCounter,\n        \"Spam counter\", null, newPacketId(\"spam-\")));\n      delayCounter = 0;\n      spamCounter = 0;\n    }\n  }\n\n  @Override\n  public String getDiscoDescription() {\n    return \"Spam filtering\";\n  }\n\n  @Override\n  public String getDiscoCategoryType() {\n    return \"spam\";\n  }\n\n  @Override\n  public void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n    list.add(getName(), \"Spam messages found\", totalSpamCounter,\n      Level.INFO);\n    list.add(getName(), \"All messages processed\", messagesCounter,\n       Level.FINE);\n    if (list.checkLevel(Level.FINEST)) {\n      // Some very expensive statistics generation code...\n    }\n  }\n\n  @Override\n  public void initBindings(Bindings binds) {\n    super.initBindings(binds);\n    binds.put(BAD_WORDS_VAR, badWords);\n    binds.put(WHITE_LIST_VAR, whiteList);\n  }\n\n}\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_15_-_Component_Implementation_-_Lesson_7_-_Data_Repository.asciidoc",
    "content": "[[cil7]]\n= Component Implementation - Lesson 7 - Data Repository\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-27 16:19\n\n== ConfigRepository\nThere are cases when you want to store some data permanently by your component. You can of course use the component configuration to provide some database connection settings, implement your own database connector and store records you need. There is, however, a very simple and useful framework which allows you to read and store some data transparently in either a database or a disk file. The framework also supports ad-hoc command interface straight away so you can manipulate your component data using an XMPP client.\n\nIn order to use it one needs to extend +tigase.db.comp.ConfigRepository+ abstract class.\n\n== RepositoryFactory\nIn order to have more freedom while accessing repositories it's possible to use +tigase.db.RepositoryFactory+ and any of the methods that pertain to desired type of repository one wants to access (auth, user, data):\n\n* +RepositoryFactory.getAuthRepository()+\n* +RepositoryFactory.getUserRepository()+\n* +RepositoryFactory.getDataRepository()+\n\nEach method takes same set of arguments:\n\n* __class_name__ - qualified name of the class that implements aforementioned repositories type\n* _URI_ - repository URI\n* _params_ - map containing additional configuration for the connection.\n\nIf there is already available repository for the `<class_name><URI>` identifier then it's returned, otherwise new instance is created.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_16_-_Component_Implementation_-_Lesson_8_-_Startup_Time.asciidoc",
    "content": "[[cil8]]\n= Component Implementation - Lesson 8 - Startup Time\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2011-05-27 22:52\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nA startup hook in the Tigase is different from the shutdown hook.\n\nThis is because you cannot really tell when exactly the startup time is. Is it when the application started, is it when configuration is loaded, is it when all objects are initialized. And this might be even different for each component. Therefore, in fact, there is no startup hook in Tigase in the same sense as the shutdown hook.\n\nThere are a few methods which are called at startup time in the following order:\n\n. *Constructor* - there is of course constructor which has no parameters.  However it does not guarantee that this instance of the component will be used at all. The object could be created just to call +getDefaults(...)+ and may be destroyed afterwards.\n. *void setName(String name)* - the second call for the component is to set it's unique name within a Tigase instance. It still does not mean too much from the component run-time point of view but some components initialize service discovery data at this point.\n. *void start()* - this is a second void which means the component can start it's internal jobs or worker threads or whatever it needs for future activity. Component's queues and threads are initialized at this point.\n. *Map<String, Object> getDefaults(Map params)* - this is the next call made by configuration manager to collect all the default settings for the component. To help generate default settings, configuration manager passes general properties (starting with '--') in the Map as parameter to the component. As a result it expects specific settings applicable to the component only (not starting with '--').\n. *setProperties(Map<String, Object> props)* - after collecting component's defaults, the connection manager combines them with configuration options (not starting with '--', but starting with the component name) loaded from configuration repository (init.properties file, database, possibly other files). Then the final configuration is passed to the component with +setProperties(...)+ method call. Database connections are usually initialized at this point.\n. *void initializationCompleted()* - this method is called for all components after all components are loaded and configuration was set (via +setProperties(...)+ method call) for all components.\n\n\nTherefore, the +initializationCompleted()+ hook is the best point if you want to be sure that Tigase server is fully loaded, initialized and functional.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_17_-_Configuration_API.asciidoc",
    "content": "[[configurationAPI]]\n= Configuration API\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-27 10:25\n\n== Introduction\nThe component configuration API is quite simple, it consists of two methods:\n\n[source,java]\n-----\nMap<String, Object> getDefaults(Map<String, Object> params);\nvoid setProperties(Map<String, Object> properties);\n-----\n\nThe first method retrieves configuration defaults from the component while the second sets the new configuration for the component. Although it looks simple, and it is, we should go over some details in order to use them more effectively.\n\n== Component Startup Sequence\nBefore we go into all the details it might be helpful to know the full component initialization sequence, how the component is brought to life and when the configuration is set. The component loading and starting sequence looks like this:\n\n. Component class is loaded and a new class instance is created using public constructor with no parameters.\n. Component setName(+compName+); method is called to set a name for the component. This method is (should) be called only once in the components operation.\n. Component +start();+ method is called which starts all the component internal threads. This method, together with +stop();+ can be called many times to put the component processing on hold or restart processing. Developers should normally not be concerned about these, unless he decided to overwrite these methods.\n. Component +getDefaults();+ method is called to retrieve initial settings for the component. This method is normally called only once during operation.\n. User provided configuration is mixed with the component defaults. Settings which the user has provided overwrite existing defaults, leaving the rest unchanged.\n. Component +setProperties();+ is called to set new configuration for the component. This method can be called many times at any point during the component life time.\n. Component +initializationCompleted();+ method is called to notify the component that the global server initialization has been finished. This method is called only once during the server startup time, after all components have been initialized and configured. This method is mainly used by network connection managers which wait with activating socket listeners until the server is fully functional.\n\nThe important thing about all the configuration stuff is that the component does not read/ask/request configuration. *The configuration is pushed to the component by the configuration manager.* The +setProperties()+ method can be called at any time and any number of times while the server is running. This design allows for the server reconfiguration during runtime. Developers should be aware of this and properly code the method to allow for the component reconfiguration at runtime.\n\n== Configuration API\nBoth API methods operate on Map<String, Object>, hence, essentially the component configuration is just a list of +(key, value)+ pairs. The Object can any of following:\n\n- String\n- Integer\n- Long\n- Double\n- Boolean\n- Array of any of above\n\nIt is guaranteed that if the component returns a default configuration entry in any of above types, the +setProperties()+ method sets the configuration entry in the same exact type. This is quite convenient as you can limit type conversions (numbers parsing for example) in your code.\n\n== getDefaults()\n\n[source,java]\n-----\nMap<String, Object> getDefaults(Map<String, Object> params);\n-----\n\n_This method is normally called only once, just after the component instance has been created. It is used to get some initial settings from the component and create a default/initial configuration which can be modified by the user. It is recommended that the component returns all possible settings with it's default values so they can be presented to the end-user for configuration or diagnostic purposes.  No component initialisation can take place here and the developer can not assume that this method is called only once. Every time this method is called it should return only defaults not the settings set with +setProperties()+.  The +Map<String, Object>+ params provided as a parameter to this method can contain some 'hints' or 'pre-initial' parameters which can affect generating default configuration. This is because configuration for some components may be complex and can have many different presets or optimisations depending on the use case. These presets can be used to generate proper default configuration.  If the component implementation extends AbstractMessageReceiver then the implementation of the method should always look like this:_\n\n[source,java]\n-----\n@Override\npublic Map<String, Object> getDefaults(Map<String, Object> params) {\n  Map defs = super.getDefaults(params);\n  defs.put(CONF_ENTRY_KEY, conf_entry_val);\n  return defs;\n}\n-----\n\n== setProperties()\n\n[source,java]\nvoid setProperties(Map<String, Object> properties);\n\n_This method is called to set configuration for the component. It can be called at any time and many times during the server run-time. The configuration will always contain all entries returned by +getDefaults+ method but some of them might be overwritten by user provided settings.  If the component implementation extends +AbstractMessageReceiver+ then the implementation of the method should always look like this:_\n\n[source,java]\n-----\n@Override\npublic void setProperties(Map properties) {\n  super.setProperties(properties);\n  int conf_entry_val = (Integer) properties.get(CONF_ENTRY_KEY);\n}\n-----\n\n== Useful Presets\nNormally configuration presets depend on the component implementation and are different for each component. There are a few presets however which are often used commonly by different components:\n\n- +test+ If set it means that the server runs in a test mode, which may mean different things for different components. The component may use this parameter to turn testing mode on.\n- +admins+ If set it provides a list of administrator IDs. These user may have special access permissions for the component. They usually can execute administrator ad-hoc commands.\n- +user-db-uri+ If set it contains the main database connection string. The component may keep its own data.\n\n== Global Configuration Settings\nThere are some global settings which are provided to all components and can be used by all of them. Usually they point so some shared resources which can be used by all components.\n\n- *SHARED_USER_REPO_PROP_KEY* is a configuration key for the user repository instance. This instance can be shared among components and used to store component data in database as well as access to user data.\nTo access the use repository instance you can use the following code:\n[source,java]\n-----\nUserRepository user_repo;\nuser_repo = (UserRepository) properties.get(RepositoryFactory.SHARED_USER_REPO_PROP_KEY);\n-----\n\n- *SHARED_USER_REPO_POOL_PROP_KEY* is a configuration key for the user repository pool which in most cases is just an SQL database. To improve the access to the database a connection pool is created which is realized by creating many UserRepository instances connecting to the same database.\nTo access the use repository instance you can use the following code:\n\n[source,java]\n-----\nUserRepository user_repo;\nuser_repo = (UserRepository) properties.get(RepositoryFactory.SHARED_USER_REPO_POOL_PROP_KEY);\n-----\n\n- *SHARED_AUTH_REPO_PROP_KEY* is a configuration key for the authentication repository. Components normally do not need access to this repository unless they deal with user authentication and authentication data is kept separately from the rest of the user data.\nTo access the use repository instance you can use the following code:\n\n[source,java]\n-----\nAuthRepository auth_repo;\nauth_repo = (AuthRepository) properties.get(RepositoryFactory.SHARED_AUTH_REPO_PROP_KEY);\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_18_-_Packet_Filtering_in_Component.asciidoc",
    "content": "[[packetfiltering]]\n= Packet Filtering in Components\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n== The Packet Filter API\nTigase server offers an API to filter packet traffic inside every component. You can separately filter incoming and outgoing packets.\n\nBy filtering we mean intercepting a packet and possibly making some changes to the packet or just blocking the packet completely. By blocking we mean stopping from any further processing and just dropping the packet.\n\nThe packet filtering is based on the link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/server/PacketFilterIfc.java[PacketFilterIfc] interface. Please have a look in the JavaDoc documentation to this interface for all the details. The main filtering method is +Packet filter(Packet packet); + which takes packets as an input, processes it, possibly alerting the packet content (may add or remove some payloads) and returns a *Packet* for further processing. If it returns *null* it means the packet is blocked and no further processing is permitted otherwise it returns a *Packet* object which is either the same object it received as a parameter or a modified copy of the original object.\n\nPlease note, although *Packet* object is not unmodifiable instance it is recommended to not make any changes on the existing object. The same *Packet* might be processed at the same time by other components or threads, therefore modification of the *Packet* may lead to unpredictable results.\n\nPlease refer to an example code in link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/server/PacketFilterIfc.java[PacketCounter] which is a very simple filter counting different types of packets. This filter is by default loaded to all components which might be very helpful for assessing traffic shapes on newly deployed installation. You can get counters for all types of packets, where they are generated, where they flow, what component they put the most load on.\n\nThis is because packet filter can also generate and present its own statistics which are accessible via normal statistics monitoring mechanisms. To take advantage of the statistics functionality the packet filter has to implement +void getStatistics(StatisticsList list);+ method. Normally the method can be empty but you can generate and add to the list own statistics from the filter. Please refer to link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/server/filters/PacketCounter.java[PacketCounter] for an example implementation code.\n\n== Configuration\nPacket filters are configurable, that is a list of packet filters can be provided in Tigase server's configuration for each component separately and for each traffic direction. This gives you a great flexibility and control over the data flow inside the Tigase server.\n\nYou can for example, load specific packet filters to all connections managers to block specific traffic or specific packet source from sending messages to users on your server. You could also reduce the server overall load by removing certain payload from all packets. The possibilities are endless.\n\nThe default configuration is generated in such a way that each component loads a single packet filter - PacketCounter for each traffic direction:\n\n[source,bash]\n-----\nmessage-router/incoming-filters=tigase.server.filters.PacketCounter\nmessage-router/outgoing-filters=tigase.server.filters.PacketCounter\nsess-man/incoming-filters=tigase.server.filters.PacketCounter\nsess-man/outgoing-filters=tigase.server.filters.PacketCounter\nc2s/incoming-filters=tigase.server.filters.PacketCounter\nc2s/outgoing-filters=tigase.server.filters.PacketCounter\ns2s/incoming-filters=tigase.server.filters.PacketCounter\ns2s/outgoing-filters=tigase.server.filters.PacketCounter\nbosh/incoming-filters=tigase.server.filters.PacketCounter\nbosh/outgoing-filters=tigase.server.filters.PacketCounter\nmuc/incoming-filters=tigase.server.filters.PacketCounter\nmuc/outgoing-filters=tigase.server.filters.PacketCounter\n-----\n\nNow, let's say you have a packet filter implemented in class: *com.company.SpamBlocker*. You want to disable PacketCounter on most of the components leaving it only in the message router component and you want to install SpamBlocker in all connection managers.\n\n_Please note, in case of the connection managers 'incoming' and 'outgoing' traffic is probably somehow opposite from what you would normally expect._\n\n- *incoming* is traffic which is submitted to a component by message router and has to be further processed. For connection managers this further processing means sending it out to the network.\n- *outgoing* is traffic which is 'generated' by the component and goes out of the component. Such a packet is submitted to message router which then decides where to send it for further processing. For connection managers *outgoing* traffic is all the packets just received from the network.\n\nAccording to that we have to apply the SpamBlocker filter to all 'outgoing' traffic in all connection managers. You may also decide that it might be actually useful to compare traffic shape between Bosh connections and standard XMPP c2s connections. So let's leave packet counters for this components too.\n\nHere is our new configuration applying SpamBlocker to connection managers and PacketCounter to a few other components:\n\n[source,bash]\n-----\nmessage-router/incoming-filters=tigase.server.filters.PacketCounter\nmessage-router/outgoing-filters=tigase.server.filters.PacketCounter\nsess-man/incoming-filters=\nsess-man/outgoing-filters=\nc2s/incoming-filters=tigase.server.filters.PacketCounter\nc2s/outgoing-filters=tigase.server.filters.PacketCounter,com.company.SpamBlocker\ns2s/incoming-filters=\ns2s/outgoing-filters=com.company.SpamBlocker\nbosh/incoming-filters=tigase.server.filters.PacketCounter\nbosh/outgoing-filters=tigase.server.filters.PacketCounter,com.company.SpamBlocker\nmuc/incoming-filters=\nmuc/outgoing-filters=\n-----\n\nThe simplest way to apply the new configuration is via the init.properties file which is in details described in the _Admin Guide_.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_19_-_Plugin_Development.asciidoc",
    "content": "[[pluginDev]]\n= Plugin Development\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThis is a set of documents explaining details what is a plugin, how they are designed and how they work inside the Tigase server. The last part of the documentation explains step by step creating the code for a new plugin.\n\n- xref:writePluginCode[Writing Plugin Code]\n- xref:pluginConf[Plugin Configuration]\n- xref:packetprocess[How Packets are Processed by the SM and Plugins]\n- xref:saslcmac[SASL Custom Mechanisms and Configuration]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_20_-_Writing_Plugin_Code.asciidoc",
    "content": "[[writePluginCode]]\n= Writing Plugin Code\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nStanza processing takes place in 4 steps. A different kind of plugin is responsible for each step of processing:\n\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/XMPPPreprocessorIfc.java[XMPPPreprocessorIfc] - is the interface for packets pre-processing plugins.\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/XMPPProcessor.java[XMPPProcessorIfc] - is the interface for packets processing plugins.\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/XMPPPostprocessorIfc.java[XMPPPostprocessorIfc] - is the interface for packets post-processing plugins.\n. link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/XMPPPacketFilterIfc.java[XMPPPacketFilterIfc] - is the interface for processing results filtering.\n\nIf you look inside any of these interfaces you will only find a single method. This is where all the packet processing takes place. All of them take a similar set of parameters and below is a description for all of them:\n\n- *Packet packet* - packet is which being processed. This parameter may never be null. Even though this is not an immutable object it mustn't be altered. None of it's fields or attributes can be changed during processing.\n- *XMPPResourceConnection session* - user session which keeps all the user session data and also gives access to the user's data repository. It allows for the storing of information in permanent storage or in memory only during the life of the session. This parameter can be null if there is no online user session at the time of the packet processing.\n- *NonAuthUserRepository repo* - this is a user data storage which is normally used when the user session (parameter above) is null. This repository allows for a very restricted access only. It allows for storing some user private data (but doesn't allow overwriting existing data) like messages for offline users and it also allows for reading user public data like VCards.\n- *Queue<Packet> results* - this a collection with packets which have been generated as input packet processing results. Regardless a response to a user request is sent or the packet is forwarded to it's destination it is always required that a copy of the input packet is created and stored in the *results* queue.\n- *Map<String, Object> settings* - this map keeps plugin specific settings loaded from the Tigase server configuration. In most cases it is unused, however if the plugin needs to access an external database that this is a way to pass the database connection string to the plugin.\n\nAfter a closer look in some of the interfaces you can see that they extend another interface: link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/XMPPImplIfc.java[XMPPImplIfc] which provides a basic meta information about the plugin implementation. Please refer to link:http://docs.tigase.org/tigase-server/snapshot/javadoc/tigase/xmpp/impl/package-summary.html[JavaDoc] documentation for all details.\n\nFor purpose of this guide we are implementing a simple plugin for handling all *<message/>* packets that is forwarding packets to the destination address. Incoming packets are forwarded to the user connection and outgoing packets are forwarded to the external destination address. This link:https://projects.tigase.org/projects/tigase-server/repository/changes/src/main/java/tigase/xmpp/impl/Message.java[message plugin] is actually implemented already and it is available in our Git repository. The code has some comments inside already but this guide goes deeper into the implementation details.\n\nFirst of all you have to choose what kind of plugin you want to implement. If this is going to be a packet processor you have to implement the *XMPPProcessorIfc* interface, if this is going to be a pre-processor then you have to implement the *XMPPPreprocessorIfc* interface. Of course your implementation can implement more than one interface, even all of them. There are also two abstract helper classes, one of which you should use as a base for all you plugins *XMPPProcessor* or use *AnnotatedXMPPProcessor* for annotation support.\n\n\n== Using annotation support\nThe class declaration should look like this (assuming you are implementing just the packet processor):\n\n[source,java]\n-----\npublic class Message extends AnnotatedXMPPProcessor\n   implements XMPPProcessorIfc\n-----\n\nThe first thing to create is the plugin *ID*. This is a unique string which you put in the configuration file to tell the server to load and use the plugin. In most cases you can use XMLNS if the plugin wants packets with elements with a very specific name space. Of course there is no guarantee there is no other packet for this specific XML element too. As we want to process all messages and don't want to spend whole day on thinking about a cool ID, let's say our ID is: _message_.\n\nA plugin informs about it's presence using a static *ID* field and *@Id* annotation placed on class:\n\n[source,java]\n-----\n@Id(ID)\npublic class Message extends AnnotatedXMPPProcessor\n   implements XMPPProcessorIfc {\n  protected static final String ID = \"message\";\n}\n-----\n\nAs mentioned before, this plugin receives only this kind of packets for processing which it is interested in. In this example, the plugin is interested only in packets with *<message/>* elements and only if they are in the \"*jabber:client*\" namespace. To indicate all supported elements and namespaces we have to add 2 more annotations:\n\n[source,java]\n-----\n@Id(ID)\n@Handles({\n  @Handle(path={ \"message\" },xmlns=\"jabber:client\")\n})\npublic class Message extends AnnotatedXMPPProcessor\n   implements XMPPProcessorIfc {\n  private static final String ID = \"message\";\n}\n-----\n\n== Using older non-annotation based implementation\nThe class declaration should look like this (assuming you are implementing just the packet processor):\n\n[source,java]\n-----\npublic class Message extends XMPPProcessor\n   implements XMPPProcessorIfc\n-----\n\nThe first thing to create is the plugin *ID* like above.\n\nA plugin informs about it's ID using following code:\n\n[source,java]\n-----\nprivate static final String ID = \"message\";\npublic String id() { return ID; }\n-----\n\nAs mentioned before this plugin receives only this kind of packets for processing which it is interested in. In this example, the plugin is interested only in packets with *<message/>* elements and only if they are in \"*jabber:client*\" namespace. To indicate all supported elements and namespaces we have to add 2 more methods:\n\n[source,java]\n-----\npublic String[] supElements() {\n  return new String[] {\"message\"};\n}\n\npublic String[] supNamespaces()\t{\n  return new String[] {\"jabber:client\"};\n}\n-----\n\n== Implementation of processing method\nNow we have our plugin prepared for loading in Tigase. The next step is the actual packet processing method. For the complete code, please refer to the plugin in the Git. I will only comment here on elements which might be confusing or add a few more lines of code which might be helpful in your case.\n\n[source,java]\n-----\n@Override\npublic void process(Packet packet, XMPPResourceConnection session,\n\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\tthrows XMPPException {\n\n\t// For performance reasons it is better to do the check\n\t// before calling logging method.\n\tif (log.isLoggable(Level.FINEST)) {\n\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\t}\n\n\t// You may want to skip processing completely if the user is offline.\n\tif (session == null) {\n\t\treturn;\n\t}    // end of if (session == null)\n\n\ttry {\n\n\t\t// Remember to cut the resource part off before comparing JIDs\n\t\tBareJID id = (packet.getStanzaTo() != null) ? packet.getStanzaTo().getBareJID() : null;\n\n\t\t// Checking if this is a packet TO the owner of the session\n\t\tif (session.isUserId(id)) {\n\n\t\t\t// Yes this is message to 'this' client\n\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t// This is where and how we set the address of the component\n\t\t\t// which should receive the result packet for the final delivery\n\t\t\t// to the end-user. In most cases this is a c2s or Bosh component\n\t\t\t// which keep the user connection.\n\t\t\tresult.setPacketTo(session.getConnectionId(packet.getStanzaTo()));\n\n\t\t\t// In most cases this might be skipped, however if there is a\n\t\t\t// problem during packet delivery an error might be sent back\n\t\t\tresult.setPacketFrom(packet.getTo());\n\n\t\t\t// Don't forget to add the packet to the results queue or it\n\t\t\t// will be lost.\n\t\t\tresults.offer(result);\n\n\t\t\treturn;\n\t\t}    // end of else\n\n\t\t// Remember to cut the resource part off before comparing JIDs\n\t\tid = (packet.getStanzaFrom() != null) ? packet.getStanzaFrom().getBareJID() : null;\n\n\t\t// Checking if this is maybe packet FROM the client\n\t\tif (session.isUserId(id)) {\n\n\t\t\t// This is a packet FROM this client, the simplest action is\n\t\t\t// to forward it to its destination:\n\t\t\t// Simple clone the XML element and....\n\t\t\t// ... putting it to results queue is enough\n\t\t\tresults.offer(packet.copyElementOnly());\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Can we really reach this place here?\n\t\t// Yes, some packets don't even have from or to address.\n\t\t// The best example is IQ packet which is usually a request to\n\t\t// the server for some data. Such packets may not have any addresses\n\t\t// And they usually require more complex processing\n\t\t// This is how you check whether this is a packet FROM the user\n\t\t// who is owner of the session:\n\t\tJID jid = packet.getFrom();\n\n\t\t// This test is in most cases equal to checking getElemFrom()\n\t\tif (session.getConnectionId().equals(jid)) {\n\n\t\t\t// Do some packet specific processing here, but we are dealing\n\t\t\t// with messages here which normally need just forwarding\n\t\t\tElement el_result = packet.getElement().clone();\n\n\t\t\t// If we are here it means FROM address was missing from the\n\t\t\t// packet, it is a place to set it here:\n\t\t\tel_result.setAttribute(\"from\", session.getJID().toString());\n\n\t\t\tPacket result = Packet.packetInstance(el_result, session.getJID(),\n\t\t\t\tpacket.getStanzaTo());\n\n\t\t\t// ... putting it to results queue is enough\n\t\t\tresults.offer(result);\n\t\t}\n\t} catch (NotAuthorizedException e) {\n\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\"You must authorize session first.\", true));\n\t}    // end of try-catch\n}\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_21_-_Plugin_Configuration.asciidoc",
    "content": "[[pluginconf]]\n= Plugin Configuration\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nPlugin configuration is not very straightforward at the moment but we are going to change it soon.\n\nFor now,  the best and the simplest way to tell the Tigase server to load or not to load the plugin is via +init.properties+ file. The +--sm-plugins+ property takes a comma separated list of plugin *IDs* to active at the runtime. Please refer to the documentation for a more complete description.\n\nObviously you have to know the list of standard plugin IDs to add your to the set. There are 2 ways to find out the list. One is the log file: logs/tigase-console.log. If you look inside you can find following output:\n\n[source,bash]\n-----\nLoading plugin: jabber:iq:register ...\nLoading plugin: jabber:iq:auth ...\nLoading plugin: urn:ietf:params:xml:ns:xmpp-sasl ...\nLoading plugin: urn:ietf:params:xml:ns:xmpp-bind ...\nLoading plugin: urn:ietf:params:xml:ns:xmpp-session ...\nLoading plugin: roster-presence ...\nLoading plugin: jabber:iq:privacy ...\nLoading plugin: jabber:iq:version ...\nLoading plugin: http://jabber.org/protocol/stats ...\nLoading plugin: starttls ...\nLoading plugin: vcard-temp ...\nLoading plugin: http://jabber.org/protocol/commands ...\nLoading plugin: jabber:iq:private ...\nLoading plugin: urn:xmpp:ping ...\n-----\n\nand this is a list of plugins which are loaded in your installation.\n\nAnother way is to look inside the session manager source code which has the default list hardcoded:\n\n[source,java]\n-----\nprivate static final String[] PLUGINS_FULL_PROP_VAL =\n  {\"jabber:iq:register\", \"jabber:iq:auth\", \"urn:ietf:params:xml:ns:xmpp-sasl\",\n   \"urn:ietf:params:xml:ns:xmpp-bind\", \"urn:ietf:params:xml:ns:xmpp-session\",\n   \"roster-presence\", \"jabber:iq:privacy\", \"jabber:iq:version\",\n   \"http://jabber.org/protocol/stats\", \"starttls\", \"msgoffline\",\n   \"vcard-temp\", \"http://jabber.org/protocol/commands\", \"jabber:iq:private\",\n   \"urn:xmpp:ping\", \"basic-filter\", \"domain-filter\"};\n-----\n\n\nIn you wish to load a plugin outside these defaults, you have to edit the list and add your plugin IDs as a value to the plugin list property. Let's say our plugin ID is *message* as in our all examples:\n\n[source,bash]\n-----\n --sm-plugins=jabber:iq:register,jabber:iq:auth,......,message\n-----\n\nAssuming your plugin class is in the classpath it will be loaded and used at the runtime.\n\nThere is another part of the plugin configuration though. If you looked at the xref:writePluginCode[Writing Plugin Code] guide you can remember the *Map settings* processing parameter. This is a map of properties you can set in the configuration file and these setting will be passed to the plugin at the processing time.\n\nAgain *init.properties* is the place to put the stuff. These kind of properties start with a string: *sess-man/plugins-conf/*, then you add your *plugin ID* and at the end and follow it with key and value pair for your setting:\n\n[source,bash]\n-----\nsess-man/plugins-conf/pluginID/key1=val1\nsess-man/plugins-conf/pluginID/key2=val2\nsess-man/plugins-conf/pluginID/key3=val3\n-----\n\nIt is possible to provide settings for a few plugins within one configuration string by specifying *multiple pluginIDs* separated with a comma like below:\n\n[source,bash]\n-----\nsess-man/plugins-conf/plugin1,plugin2,plugin3/key1=val1\n-----\nThis will make key/pair setting available only to listed plugins, in above case plugin1, plugin2 and plugin3.\n\nLast but not least - in case you have *omitted plugin ID*:\n\n[source,bash]\n-----\nsess-man/plugins-conf/key1=val1\n-----\nthen the configured key-value pair will be a global/common plugin setting available to all loaded plugins.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_22_-_How_Packets_are_Processed_by_the_SM_and_Plugins.asciidoc",
    "content": "[[packetProcess]]\n= How Packets are Processed by the SM and Plugins\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:website: http://tigase.net/\n\nFor Tigase server plugin development it is important to understand how it all works. There are different kind of plugins responsible for processing packets at different stages of the data flow. Please read the introduction below before proceeding to the actual coding part.\n\n== Introduction\nIn Tigase server *plugins* are pieces of code responsible for processing particular XMPP stanzas. A separate plugin might be responsible for processing messages, a different one for processing presences, a separate plugins responsible for iq roster, and a different one for iq version and so on.\n\nA plugin provides information about what exact XML element(s) name(s) with xmlns it is interested in. So you can create a plugin which is interested in all packets containing caps child.\n\nThere might be no plugin for a particular stanza element, in this case the default action is used which is simple forwarding stanza to a destination address. There might be also more than one plugin for a specific XML element and then they all process the same stanza simultaneously in separate threads so there is no guarantee on the order in which the stanza is processed by a different plugins.\n\nEach stanza goes through the Session Manager component which processes packets in a few steps. Have a look at the picture below:\n\nimage:images/sm-consumer.png[Consumer]\n\nThe picture shows that each stanza is processed by the session manager in 4 steps:\n\n. Pre-processing - All loaded pre-processors receive the packet for processing. They work within session manager thread and they have no internal queue for processing. As they work within Session Manager thread it is important that they limit processing time to absolute minimum as they may affect the Session Manager performance.  The intention for the pre-processors is to use them for packet blocking. If the pre-processing result is 'true' then the packet is blocked and no further processing is performed.\n. Processing - This is the next step the packet gets through if it wasn't blocked by any of the pre-processors. It gets inserted to all processors queues with requested interest in this particular XML element. Each processor works in a separate thread and has own internal fixed size processing queue.\n. Post-processing - If there is no processor for the stanza then the packet goes through all post-processors. The last post-processor that is built into session manager post-processor tries to apply a default action to a packet which hasn't been processed in step 2. Normally the default action is just forwarding the packet to a destination. Most commonly it is applied to <message/> packets.\n. Finally, if any of above 3 steps produced output/result packets all of them go through all filters which may or may not block them.\n\nAn important thing to note is that we have two kinds or two places where packets may be blocked or filtered out. One place is before packet is processed by the plugin and another place is after processing where filtering is applied to all results generated by the processor plugins.\n\nIt is also important to note that session manager and processor plugins act as packet consumers. The packet is taken for processing and once processing is finished the packet is destroyed. Therefore to forward a packet to a destination one of the processor must create a copy of the packet, set all properties and attributes and return it as a processing result. Of course processor can generate any number of packets as a result. Result packets can be generated in any of above 4 steps of the processing. Have a look at the picture below:\n\nimage:images/user-sends-to-comp.png[User Send to Comp]\n\nIf the packet P1 is sent from outside of the server, for example to a user on another server or to some component (MUC, PubSub, transport), then one of the processor must create a copy (P2) of the packet and set all attributes and destination addresses correctly. Packet P1 has been consumed by the session manager during processing and a new packet has been generated by one of the plugins.\n\nThe same of course happens on the way back from the component to the user:\n\nimage:images/comp-sends-to-user.png[Comp Sends to User]\n\nThe packet from the component is processed and one of the plugins must generate a copy of the packet to deliver it to the user. Of course packet forwarding is a default action which is applied when there is no plugin for the particular packet.\n\nIt is implemented this way because the input packet P1 can be processed by many plugins at the same time therefore the packet should be in fact immutable and must not change once it got to the session manager for processing.\n\nThe most obvious processing work flow is when a user sends request to the server and expects a response from the server:\n\nimage:images/user-request-response.png[User Request Response]\n\nThis design has one surprising consequence though. If you look at the picture below showing communication between 2 users you can see that the packet is copied twice before it is delivered to a final destination:\n\nimage:images/user-sends-to-user.png[User Sends to User]\n\nThe packet has to be processed twice by the session manager. The first time it is processed on behalf of the User A as an outgoing packet and the second time it is processed on behalf of the User B as an incoming packet.\n\nThis is to make sure the User A has permission to send a packet out and all processing is applied to the packet and also to make sure that User B has permission to receive the packet and all processing is applied. If, for example, the User B is offline there is an offline message processor which should send the packet to a database instead of User B.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_23_-_SASL_Custom_Mechanisms_and_Configuration.asciidoc",
    "content": "[[saslcmac]]\n= SASL Custom Mechanisms and Configuration\n:author: Bartosz Malkowski <bmalkowski@tigase.pl>\n:version: 2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-01-23 03:54\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*This API is available from Tigase XMPP Server version 5.2.0 or later on our current master branch.*\n\n_Note that API is under active development. This description may be updated at any time._\n\n== Basic SASL Configuration\nSASL implementation in Tigase XMPP Server is compatible with Java API, the same exact interfaces are used.\n\nThe SASL implementation consists of following parts:\n\n. mechanism\n. CallbackHandler\n\nProperties list for SASL plugin _(sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl):_\n\n[width=\"90%\"]\n|=====================================================================\n| *Property* | *Description*\n| factory | A factory class for SASL mechanisms. Detailed description at xref:mechconf[Mechanisms configuration]\n| callbackhandler |A default callback handler class. Detailed description at xref:cbconf[CallbackHandler configuration]\n| callbackhandler-${MECHANISM} | A callback handler class for a particular mechanism. Detailed description at xref:cbconf[CallbackHandler configuration]\n| mechanism-selector | A class for filtering SASL mechanisms available in a stream. Detailed description at xref:selmech[Selecting mechanisms]\n|=====================================================================\n\n[[mechconf]]\n=== Mechanisms Configuration\nTo add a new mechanism, a new factory for the mechanism has to be registered. It can be done with a new line in the +init.properties+ file like this one:\n\n+sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/factory=com.example.OwnFactory+\n\nThe class must implement the +SaslServerFactory+ interface. All mechanisms returned by +getMechanismNames()+ method will be registered automatically.\n\nThe default factory that is available and registered by default is +tigase.auth.TigaseSaslServerFactory+ which provides +PLAIN+ and +ANONYMOUS+ mechanisms.\n\n[[cbconf]]\n=== CallbackHandler Configuration\nThe +CallbackHandler+ is a helper class used for loading/retrieving authentication data from data repository and providing them to a mechanism.\n\nTo register a new callback handler a new line in the +init.properties+ file like this one has to be added:\n\n+sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/callbackhandler=com.example.DefaultCallbackHandler+\n\nIt is also possible to register different callback handlers for different mechanisms:\n\n+sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/callbackhandler-PLAIN=com.example.PlainCallbackHandler+\n\n+sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/callbackhandler-OAUTH=com.example.OAuthCallbackHandler+\n\nDuring the authentication process, Tigase server always checks for a handler specific to selected mechanisms, and if there is no specific handler the default one is used.\n\n[[selmech]]\n=== Selecting Mechanisms Available in the Stream\nThe +tigase.auth.MechanismSelector+ interface is used for selecting mechanisms available in a stream. Method +filterMechanisms()+ should return a collection with mechanisms available based on:\n\n. all registered SASL factories\n. XMPP session data (from +XMPPResourceConnection+ class)\n\nThe default selector returns mechanisms from Tigase's default factory +(TigaseSaslServerFactory)+ only.\n\nIt is possible to use a custom selector by specifying it's class int the +init.properties+ file:\n\n+sess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/mechanism-selector=com.example.OwnSelector+\n\n== Logging/Authentication\nAfter the XMPP stream is opened by a client, the server checks which SASL mechanisms are available for the XMPP session. Depending on whether the stream is encrypted or not, depending on the domain, the server can present different available authentication mechanisms. MechanismSelector is responsible for choosing mechanisms. List of allowed mechanisms is stored in the XMPP session object.\n\nWhen the client/user begins the authentication procedure it uses one particular mechanism. It must use one of the mechanisms provided by the server as available for this session. The server checks whether mechanisms used by the client is on the list of allowed mechanisms. It the check is successful, the server creates +SaslServer+ class instance and proceeds with exchanging authentication information. Authentication data is different depending on the mechanism used.\n\nWhen the SASL authentication is completed without any error, Tigase server should have authorized user name or authorized BareJID. In the first case, the server automatically builds user's JID based on the domain used in the stream opening element in +to+ attribute.\n\nIf, after a successful authentication, method call: +getNegotiatedProperty(\"IS_ANONYMOUS\")+ returns +Boolean.TRUE+ then the user session is marked as anonymous. For valid and registered users this can be used for cases when we do not want to load any user data such as roster, vcard, privacy lists and so on. This is a performance and resource usage implication and can be useful for use cases such as support chat. The authorization is performed based on the client database but we do not need to load any XMPP specific data for the user's session.\n\nMore details about implementation can be found in the xref:cmd[custom mechanisms development] section.\n\n== Built-in Mechanisms\n\n*PLAIN*\n\n_TODO!_\n\n*ANONYMOUS*\n\n_TODO!_\n\n[[cmd]]\n== Custom Mechanisms Development\n=== *Mechanism*\n\n+getAuthorizationID()+ method from +SaslServer+ class *should* return bare JID authorized user. In case that the method returns only user name such as *romeo* for example, the server automatically appends domain name to generate a valid BareJID: _romeo@example.com_. In case the method returns a full, valid BareJID, the server does not change anything.\n\n+handleLogin()+ method from +SessionManagerHandler+ will be called with user's Bare JID provided by +getAuthorizationID()+ (or created later using stream domain name).\n\n=== *CallbackHandler*\n\nFor each session authorization, the server creates a new and separate empty handler. Factory which creates handler instance allows to inject different objects to the handler, depending on interfaces implemented by the handler class:\n\n- +AuthRepositoryAware+ - injects +AuthRepository;+\n- +DomainAware+ - injects domain name within which the user attempts to authenticate\n- +NonAuthUserRepositoryAware+ - injects +NonAuthUserRepository+, although I have no idea what for...\n\n=== General Remarks\n\n+JabberIqAuth+ used for non-SASL authentication mechanisms uses the same callback as the SASL mechanisms.\n\nMethods +auth+ in +Repository+ interfaces will be deprecated. These interfaces will be treated as user details providers only. There will be new methods available which will allow for additional login operations on the database such as last successful login recording.\n\n=== Known Problems\n\nBecause +JabberIqAuth+ is initialized separately, we strongly recommend to use more general prefix in *+init.properties+*:\n\n[source,bash]\nsess-man/plugins-conf/${KEY}=${VALUE}\n\ninstead of\n\n[source,bash]\nsess-man/plugins-conf/urn\\:ietf\\:params\\:xml\\:ns\\:xmpp-sasl/${KEY}=${VALUE}\n\nIf +JabberIqAuth+ is disabled, then this is not necessary.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_24_-_Using_Maven.asciidoc",
    "content": "[[usingmaven]]\n= Using Maven\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nDocuments Describing Maven Use with the Tigase Projects\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_25_-_Setting_Up_Maven_In_Windows.asciidoc",
    "content": "= Setting up Maven in Windows\n:author: Daniel Wisnewski\n:version: v1.0 August 2015\n:date: 2015-03-08 10:57\n\n:toc:\n:numbered:\n\nHere at Tigase, we employ Apache Maven to download latest builds, compile codes for export, and check for errors in the code during build.  This guide will go over installing and running Maven from a Windows operating environment.  We will consider windows versions 7, 8, and 8.1 for this guide.\nBecause Maven does not come with an installer, there is a manual install process which might be a bit daunting for the new user, but setup and use is fairly simple.\n\n== Requirements\n. Maven requires Java Development Kit (JDK) 6 or later.  As Tigase requires the latest JDK to run, that will do for our purposes.  If you haven't installed it yet, download the installer from link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[this website]. Once you install JDK and restart your machine, be sure that you have the *JAVA_HOME* variable entered into Environment Variables so calls to Java will work from the command line.\n\n. Download the Maven package from link:https://maven.apache.org/download.cgi[here] and unpack it into a directory of your choice.  For this guide we will use `C:\\Maven\\` .\n\n== Setting up Environment Variables\nThe Environment Variables panel is brought up from the Control Panel by clicking *System and Security* > *System* > *Advanced System Settings*.\nNow click the image:images/Env-button.jpg[Environment Variables] button at the bottom of the panel and the Environment Variables panel will show.\n\n*IMPORTANT NOTICE: CHANGING THESE SETTINGS CAN BREAK OTHER FUNCTIONS IN THE OPERATING SYSTEM.  DO NOT FOLLOW THIS GUIDE IF YOU DO NOT KNOW WHAT YOU ARE DOING!*\n\nimage::images/Env-Panel.jpg[]\n\nWe need to first add two variable paths to the System variables to account for Maven's install location.  As there are some programs that look for M2_HOME, and others that look for MAVEN_HOME, it's easier to just add both and have all the bases covered.\n\nClick on New...\n\nimage::images/Env-New.jpg[]\n\nFor the Name, use M2_HOME, and for the variable enter the path to maven, which in this case is\n----\nC:\\Maven\n----\n\nCreate another new variable with the MAVEN_HOME name and add the same directory.\n*These variable values just point to where you have unpacked maven, so they do not have to be in the C directory.*\n\nGo down to the system variables dialog and select Path, then click on Edit.\nThe Path variables are separated by semicolons, find the end of the Variable value string, and add the following after the last entry:\n-----\n;%M2_HOME%\\bin;%MAVEN_HOME%\\bin;\n-----\nWe have added two variables using the %% wildcards surrounding our Variable names from earlier.\n\n\n== Testing Maven\nNow we must test the command line to be sure everything installed correctly.\nBring up the command line either by typing `cmd` in search, or navigating the start menu.\n\nFrom the prompt, you do not need to change directory as setting Path allows you to reference it.\nType the following command:\n`mvn -v`\n\nsomething like this should show up\n-----\nApache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T04:57:3\n7-07:00)\nMaven home: C:\\Maven\nJava version: 1.8.0_45, vendor: Oracle Corporation\nJava home: C:\\Program Files\\Java\\jdk1.8.0_45\\jre\nDefault locale: en_US, platform encoding: Cp1252\nOS name: \"windows 7\", version: \"6.1\", arch: \"amd64\", family: \"dos\"\n-----\n\nIf you see this message, success!  You have finished installation and are ready to use Maven!  If not, go back on your settings and insure that JDK is installed, and the JAVA_HOME, M2_HOME, and MAVEN_HOME variables are set properly.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_26_-_A_Very_Short_Maven_Guide.asciidoc",
    "content": "[[mavenguide]]\n= A Very Short Maven Guide\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nIf you don't use link:http://maven.apache.org/[Maven] at all or use it once a year you may find the document a useful maven commands reminder:\n\n== Snapshot Compilation and Snapshot Package Generation\n- +mvn compile+ - compilation of the snapshot package\n- +mvn package+ - create snapshot jar file\n- +mvn install+ - install in local repository shanpshot jar file\n- +mvn deploy+ - deploy to the remote repository snapshot jar file\n\n== Release Compilation, Generation\n\n- +mvn release:prepare+ prepare the project for a new version release\n- +mvn release:perform+ execute new version release generation\n\n== Generating tar.gz, tar.bz2 File With Sources Only\n\n- +mvn -DdescriptorId=src assembly:assembly+\n\nAny of these commands will work when your commandline is in a directory with a pom.xml file.  This file will instruct what Maven will do.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_27_-_Maven_2.x_Support.asciidoc",
    "content": "[[maven2support]]\n= Maven 2.x Support\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nAddendum: for a more recent guide please follow Tigase XMPP Server 5.2.0 and Later - Compilation and Generating Distribution Packages.\n\nThanks to link:http://www.tigase.org/user/2[bmalkow] you can now build Tigase server from sources using link:http://maven.apache.org/[Maven 2.x] tool.  This should greatly simplify first steps with Tigase code and it was requested by many of those trying to get the server running from sources.  Maven repository with Tigase packages is located at address: link:http://maven.tigase.org/[maven.tigase.org].  Now all you need to compile sources and generate packages needed to run the server is just a few simple steps below:\n\n. Download and install Maven 2.x\n. Checkout Tigase server sources from link:http://www.tigase.org/content/=[Subversion] repository:\n\n[source,bash]\n-----\nsvn co https://svn.tigase.org/reps/tigase-server/trunk/ tigase-server\n-----\n. Now go to directory with server code:\n\n[source,bash]\n-----\ncd tigase-server\n-----\n. And run maven command to generate server package:\n\n[source,bash]\n-----\nmvn assembly:assembly\n-----\n. After maven finished his work there should be new subdirectory created: target. Go to this directory now:\n\n[source,bash]\n-----\ncd target/\n-----\n. and list content of this directory.  On Linux, Unix system:\n\n[source,bash]\n-----\nls -l\n-----\n+\nOn MS Windows system:\n+\n[source,bash]\n-----\ndir\n-----\n. You should see at least 2 files like these:\n+\n[source,bash]\n-----\ntigase-server-2.4.0-SNAPSHOT-prodenv.tar.gz\ntigase-server-2.4.0-SNAPSHOT-prodenv.zip\n-----\n. Unpack one of these files whichever you like:\n+\n[source,bash]\n-----\ntar -xzvf tigase-server-2.4.0-SNAPSHOT-prodenv.tar.gz\n-----\n+\nor\n+\n[source,bash]\n-----\nunzip tigase-server-2.4.0-SNAPSHOT-prodenv.zip\n-----\n. New directory will be created in our case it will be: +tigase-server-2.4.0-SNAPSHOT/+. Now go to this directory:\n+\n[source,bash]\n-----\ncd tigase-server-2.4.0-SNAPSHOT/\n-----\n. Now almost everything is ready to run the server. Almost because sometimes on Unix like (including Linux) operating systems you have to change script execution bit before you can run it:\n+\n[source,bash]\n-----\nchmod u+x bin/*\n-----\n. Now you can run Tigase server:\n+\n[source,bash]\n-----\n./bin/tigase.sh run etc/tigase.conf\n-----\n+\nYou can get a few warnings about missing configuration file (which will be automatically created) and user repository file (which will be automatically created when you register first user).\n\nFor your convenience there are a few other startup files in +etc/+ directory. You can look and modify them according to your needs.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_28_-_Tests.asciidoc",
    "content": "[[tests]]\n= Tests\n:author: Mateusz Fiolka\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n== Tests\nTests are very important part of Tigase server development process.\n\nEach release goes through fully automated testing process. All server functions are considered implemented only when they pass the testing cycle. Tigase test suite is used for all our automatic tests which allows to define different test scenarios.\n\nThere is no tweaking on databases for tests. All databases are installed in a standard way and run with default settings. Databases are cleared each time before the test cycle starts.\n\nThere are no modifications needed to be made to Tigase's configuration file as well. All tests are performed on a default configuration generated by the configuration wizards.\n\nThe server is tested in all supported environments:\n\n. *XMLDB* - tests with built-in simple XML database. This is a simple and efficient solution for small installations. It is recommended for services with up to 100 user accounts although it has been successfully tested with 10,000 user accounts.\n. *MySQL* - tests with a link:http://www.mysql.com/[MySQL] database. Much slower than XMLDB but may handle many more user accounts.\n. *PostgreSQL* - tests with a link:http://www.postgresql.org/[PostgreSQL] database. Again it is much slower than XMLDB but may handle much more user accounts. This is basically exactly the same code as for MySQL database (SQL Connector) but tests are executed to make sure the code is compatible with all supported SQL databases and to compare performance.\n. *Distributed* - is a test for distributed installation where c2s and s2s components run on separated machine which connects using external an component protocol (link:http://www.xmpp.org/extensions/xep-0114.html[XEP-0114]) to another machine with SessionManager running.\n\n\n=== Functional Tests\n\nBasic checking to see if all the functions work at correctly. These tests are performed every time the code is sent to source repository.\n[width=\"90%\"]\n|=====================================================================\n| Version| XMLDB| MySQL| PGSQL| Distributed\n| 3.3.2-b889| link:tests/3.3.2-b889/func/xmldb/functional-tests.html[00:00:12]| link:tests/3.3.2-b889/func/mysql/functional-tests.html[00:00:17]| link:tests/3.3.2-b889/func/pgsql/functional-tests.html[00:00:17]| none\n| 3.3.2-b880| link:tests/3.3.2-b880/func/xmldb/functional-tests.html[00:00:13]| link:tests/3.3.2-b880/func/mysql/functional-tests.html[00:00:15]| link:tests/3.3.2-b880/func/pgsql/functional-tests.html[00:00:15]| None\n| 3.0.2-b700| link:tests/3.0.2-b700/func/xmldb/functional-tests.html[00:00:22]| link:tests/3.0.2-b700/func/mysql/functional-tests.html[00:00:24]| link:tests/3.0.2-b700/func/pgsql/functional-tests.html[00:00:25]| link:tests/3.0.2-b700/func/sm-mysql/functional-tests.html[00:00:25]\n| 2.9.5-b606| link:tests/2.9.5-b606/func/xmldb/functional-tests.html[00:00:22]| link:tests/2.9.5-b606/func/mysql/functional-tests.html[00:00:24]| link:tests/2.9.5-b606/func/pgsql/functional-tests.html[00:00:24]| link:tests/2.9.5-b606/func/sm-mysql/functional-tests.html[00:00:24]\n| 2.9.3-b548| link:tests/2.9.3-b548/func/xmldb/functional-tests.html[00:00:22]| link:tests/2.9.3-b548/func/mysql/functional-tests.html[00:00:23]| link:tests/2.9.3-b548/func/pgsql/functional-tests.html[00:00:25]| link:tests/2.9.3-b548/func/sm-mysql/functional-tests.html[00:00:25]\n| 2.9.1-b528| link:tests/2.9.1-b528/func/xmldb/functional-tests.html[00:00:21]| link:tests/2.9.1-b528/func/mysql/functional-tests.html[00:00:23]| link:tests/2.9.1-b528/func/pgsql/functional-tests.html[00:00:24]| link:tests/2.9.1-b528/func/sm-mysql/functional-tests.html[00:00:25]\n| 2.8.6-b434| link:tests/2.8.6-b434/func/xmldb/functional-tests.html[00:00:21]| link:tests/2.8.6-b434/func/mysql/functional-tests.html[00:00:24]| link:tests/2.8.6-b434/func/pgsql/functional-tests.html[00:00:24]| link:tests/2.8.6-b434/func/sm-mysql/functional-tests.html[00:00:25]\n| 2.8.5-b422| link:tests/2.8.5-b422/func/xmldb/functional-tests.html[00:00:21]| link:tests/2.8.5-b422/func/mysql/functional-tests.html[00:00:24]| link:tests/2.8.5-b422/func/pgsql/functional-tests.html[00:00:24]| link:tests/2.8.5-b422/func/sm-mysql/functional-tests.html[00:00:26]\n| 2.8.3-b409| link:tests/2.8.3-b409/func/xmldb/functional-tests.html[00:00:27]| link:tests/2.8.3-b409/func/mysql/functional-tests.html[00:00:29]| link:tests/2.8.3-b409/func/pgsql/functional-tests.html[00:00:29]| link:tests/2.8.3-b409/func/sm-mysql/functional-tests.html[00:00:32]\n| 2.7.2-b378| link:tests/2.7.2-b378/func/xmldb/functional-tests.html[00:00:30]| link:tests/2.7.2-b378/func/mysql/functional-tests.html[00:00:34]| link:tests/2.7.2-b378/func/pgsql/functional-tests.html[00:00:33]| link:tests/2.7.2-b378/func/sm-mysql/functional-tests.html[00:00:35]\n| 2.6.4-b300| link:tests/2.6.4-b300/func/xmldb/functional-tests.html[00:00:30]| link:tests/2.6.4-b300/func/mysql/functional-tests.html[00:00:32]| link:tests/2.6.4-b300/func/pgsql/functional-tests.html[00:00:35]| link:tests/2.6.4-b300/func/sm-mysql/functional-tests.html[00:00:39]\n| 2.6.4-b295| link:tests/2.6.4-b295/func/xmldb/functional-tests.html[00:00:29]| link:tests/2.6.4-b295/func/mysql/functional-tests.html[00:00:32]| link:tests/2.6.4-b295/func/pgsql/functional-tests.html[00:00:45]| link:tests/2.6.4-b295/func/sm-mysql/functional-tests.html[00:00:36]\n| 2.6.0-b287| link:tests/2.6.0-b287/func/xmldb/functional-tests.html[00:00:31]| link:tests/2.6.0-b287/func/mysql/functional-tests.html[00:00:34]| link:tests/2.6.0-b287/func/pgsql/functional-tests.html[00:00:47]| link:tests/2.6.0-b287/func/sm-mysql/functional-tests.html[00:00:43]\n| 2.5.0-b279| link:tests/2.5.0-b279/func/xmldb/functional-tests.html[00:00:30]| link:tests/2.5.0-b279/func/mysql/functional-tests.html[00:00:34]| link:tests/2.5.0-b279/func/pgsql/functional-tests.html[00:00:45]| link:tests/2.5.0-b279/func/sm-mysql/functional-tests.html[00:00:43]\n| 2.4.0-b263| link:tests/2.4.0-b263/func/xmldb/functional-tests.html[00:00:29]| link:tests/2.4.0-b263/func/mysql/functional-tests.html[00:00:33]| link:tests/2.4.0-b263/func/pgsql/functional-tests.html[00:00:45]| link:tests/2.4.0-b263/func/sm-mysql/functional-tests.html[00:00:44]\n| 2.3.4-b226 | None | link:tests/functional-tests.html[00:00:48]| None| None\n|=====================================================================\n\n=== Performance Tests\nChecking to see whether the function performs well enough.\n[width=\"90%\"]\n|=====================================================================\n|Version| XMLDB| MySQL| PGSQL| Distributed\n|3.3.2-b889| link:tests/3.3.2-b889/perf/xmldb/performance-tests.html[00:12:17]| link:tests/3.3.2-b889/perf/mysql/performance-tests.html[00:13:42]| link:tests/3.3.2-b889/perf/pgsql/performance-tests.html[00:17:10]| none\n|3.3.2-b880| link:tests/3.3.2-b880/perf/xmldb/performance-tests.html[00:13:39]| link:tests/3.3.2-b880/perf/mysql/performance-tests.html[00:14:09]| link:tests/3.3.2-b880/perf/pgsql/performance-tests.html[00:17:39]| None\n|3.0.2-b700| link:tests/3.0.2-b700/perf/xmldb/performance-tests.html[00:10:26]| link:tests/3.0.2-b700/perf/mysql/performance-tests.html[00:11:00]| link:tests/3.0.2-b700/perf/pgsql/performance-tests.html[00:12:08]| link:tests/3.0.2-b700/perf/sm-mysql/performance-tests.html[00:24:05]\n|2.9.5-b606| link:tests/2.9.5-b606/perf/xmldb/performance-tests.html[00:09:54]| link:tests/2.9.5-b606/perf/mysql/performance-tests.html[00:11:18]| link:tests/2.9.5-b606/perf/pgsql/performance-tests.html[00:37:08]| link:tests/2.9.5-b606/perf/sm-mysql/performance-tests.html[00:16:20]\n|2.9.3-b548| link:tests/2.9.3-b548/perf/xmldb/performance-tests.html[00:10:00]| link:tests/2.9.3-b548/perf/mysql/performance-tests.html[00:11:29]| link:tests/2.9.3-b548/perf/pgsql/performance-tests.html[00:36:43]| link:tests/2.9.3-b548/perf/sm-mysql/performance-tests.html[00:16:47]\n|2.9.1-b528| link:tests/2.9.1-b528/perf/xmldb/performance-tests.html[00:09:46]| link:tests/2.9.1-b528/perf/mysql/performance-tests.html[00:11:15]| link:tests/2.9.1-b528/perf/pgsql/performance-tests.html[00:36:12]| link:tests/2.9.1-b528/perf/sm-mysql/performance-tests.html[00:16:36]\n|2.8.6-b434| link:tests/2.8.6-b434/perf/xmldb/performance-tests.html[00:10:02]| link:tests/2.8.6-b434/perf/mysql/performance-tests.html[00:11:45]| link:tests/2.8.6-b434/perf/pgsql/performance-tests.html[00:36:36]| link:tests/2.8.6-b434/perf/sm-mysql/performance-tests.html[00:17:36]\n|2.8.5-b422| link:tests/2.8.5-b422/perf/xmldb/performance-tests.html[00:12:37]| link:tests/2.8.5-b422/perf/mysql/performance-tests.html[00:14:40]| link:tests/2.8.5-b422/perf/pgsql/performance-tests.html[00:38:59]| link:tests/2.8.5-b422/perf/sm-mysql/performance-tests.html[00:21:40]\n|2.8.3-b409| link:tests/2.8.3-b409/perf/xmldb/performance-tests.html[00:12:32]| link:tests/2.8.3-b409/perf/mysql/performance-tests.html[00:14:26]| link:tests/2.8.3-b409/perf/pgsql/performance-tests.html[00:37:57]| link:tests/2.8.3-b409/perf/sm-mysql/performance-tests.html[00:21:26]\n|2.7.2-b378| link:tests/2.7.2-b378/perf/xmldb/performance-tests.html[00:12:28]| link:tests/2.7.2-b378/perf/mysql/performance-tests.html[00:14:57]| link:tests/2.7.2-b378/perf/pgsql/performance-tests.html[00:37:09]| link:tests/2.7.2-b378/perf/sm-mysql/performance-tests.html[00:22:20]\n|2.6.4-b300| link:tests/2.6.4-b300/perf/xmldb/performance-tests.html[00:12:46]| link:tests/2.6.4-b300/perf/mysql/performance-tests.html[00:14:59]| link:tests/2.6.4-b300/perf/pgsql/performance-tests.html[00:36:56]| link:tests/2.6.4-b300/perf/sm-mysql/performance-tests.html[00:35:00]\n|2.6.4-b295| link:tests/2.6.4-b295/perf/xmldb/performance-tests.html[00:12:23]| link:tests/2.6.4-b295/perf/mysql/performance-tests.html[00:14:59]| link:tests/2.6.4-b295/perf/pgsql/performance-tests.html[00:42:24]| link:tests/2.6.4-b295/perf/sm-mysql/performance-tests.html[00:30:18]\n|2.6.0-b287| link:tests/2.6.0-b287/perf/xmldb/performance-tests.html[00:13:50]| link:tests/2.6.0-b287/perf/mysql/performance-tests.html[00:16:53]| link:tests/2.6.0-b287/perf/pgsql/performance-tests.html[00:48:17]| link:tests/2.6.0-b287/perf/sm-mysql/performance-tests.html[00:49:06]\n|2.5.0-b279| link:tests/2.5.0-b279/perf/xmldb/performance-tests.html[00:13:29]| link:tests/2.5.0-b279/perf/mysql/performance-tests.html[00:16:58]| link:tests/2.5.0-b279/perf/pgsql/performance-tests.html[00:47:15]| link:tests/2.5.0-b279/perf/sm-mysql/performance-tests.html[00:41:52]\n|2.4.0-b263| link:tests/2.4.0-b263/perf/xmldb/performance-tests.html[00:13:20]| link:tests/2.4.0-b263/perf/mysql/performance-tests.html[00:16:21]| link:tests/2.4.0-b263/perf/pgsql/performance-tests.html[00:43:56]| link:tests/2.4.0-b263/perf/sm-mysql/performance-tests.html[00:42:08]\n|2.3.4-b226 | None | link:tests/performance-tests.html[01:23:30]| None| None\n|=====================================================================\n\n=== Stability Tests\nChecking to see whether the function behaves well in long term run. It must handle hundreds of requests a second in a several hour server run.\n[width=\"90%\"]\n|=====================================================================\n|Version| XMLDB| MySQL| PGSQL| Distributed\n|2.3.4-b226 | None | link:tests/stability-tests.html[16:06:31]| None | None\n|=====================================================================\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_29_-_Tigase_Test_Suite.asciidoc",
    "content": "[[testSuite]]\n= Tigase Test Suite\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nTigase Test Suite is an engine which allows you to run tests. Essentially it just executes *TestCase* implementations. The tests may depend on other tests which means they are executed in specific order. For example authentication test is executed after the stream open test which in turn is executed after network socket connection test.\n\nEach *TestCase* implementation may have it's own set of specific parameters. There is a set of common parameters which may be applied to any *TestCase*. As an example of the common parameter you can take *-loop = 10* which specified that the *TestCase* must be executed 10 times. The test specific parameter might be *-user-name = tester* which may set the user name for authentication test.\n\nThe engine is very generic and allows you to write any kind of tests but for the Tigase projects the current TestCase implementations mimic an XMPP client and are designed to test XMPP servers.\n\nThe suite contains a kind of scripting language which allows you to combine test cases into a test scenarios. The test scenario may contain full set of functional tests for example, another test scenario may contain performance tests and so on.\n\n== Running Tigase Test Suite (TTS)\nTo obtain TTS, you will first need to clone the repository\n-----\ngit clone https://repository.tigase.org/git/tigase-testsuite.git\n-----\n\nOnce cloning is finished, navigate to the TTS root directory and compile with maven:\n-----\nmvn clean install\n-----\n\nMaven will compile TTS and place jars in the necessary locations.  From the same directory, you can begin running TTS using the following command:\n-----\n./scripts/all-tests-runner.sh\n-----\n\nYou should see the following, which outlines the possible options to customize your test run\n[source,bash]\n------------\nRun selected or all tests for Tigase server\n----\nAuthor: Artur Hefczyc <artur_hefczyc@vnu.co.uk>\nVersion: 2.0.0\n----\n  --help|-h\tThis help message\n  --func [mysql|pgsql|derby|mssql|mongodb]\n              Run all functional tests for a single database configuration\n  --lmem [mysql|pgsql|derby|mssql|mongodb]\n              Run low memory tests for a single database configuration\n  --perf [mysql|pgsql|derby|mssql|mongodb]\n              Run all performance tests for a single database configuration\n  --stab [mysql|pgsql|derby|mssql|mongodb]\n              Run all stability tests for a single database\n              configuration\n  --func-all  Run all functional tests for all database\n              configurations\n  --lmem-all  Run low memory tests for all database\n              configurations\n  --perf-all  Run all performance tests for all database\n              configurations\n  --stab-all  Run all stability tests for all database\n              configurations\n  --all-tests Run all functionality and performance tests for\n              database configurations\n  --single test_file.cot\n  --other script_file.xmpt\n----\n  Special parameters only at the beginning of the parameters list\n  --debug|-d                 Turns on debug mode\n  --skip-db-relad|-no-db     Turns off reloading database\n  --skip-server|-no-serv     Turns off Tigase server start\n  --small-mem|-sm            Run in small memory mode\n-----------\n  Other possible parameters are in following order:\n  [server-dir] [server-ip]\n------------\n\n=== Customizing Tigase Test Suite\nYou may run the tests from a command line like above, however you may create and edit the /scripts/tests-runner-settings.sh file to fit your Tigase installation and avoid having to have long complex commands as this template shows:\n[source,script]\n-----\n#!/bin/bash\n\nfunc_rep=\"func-rep.html\"\nperf_rep=\"perf-rep.html\"\ndb_name=\"tigasetest\"\ndb_user=\"tigase\"\ndb_pass=\"tigase\"\nroot_user=\"root\"\nroot_pass=\"root\"\n\nTESTS=(\"derby\" \"mysql\" \"pgsql\" \"mssql\")\nIPS=(\"127.0.0.1\" \"127.0.0.1\" \"127.0.0.1\" \"127.0.0.1\")\n\nserver_timeout=10\n\nserver_dir=\"/home/tigase/tigase-server\"\ndatabase=\"derby\"\n#database=\"mysql\"\nserver_ip=\"127.0.0.1\"\n\nMS_MEM=100\nMX_MEM=1000\n\nSMALL_MS_MEM=10\nSMALL_MX_MEM=50\n-----\n\nThis will allow you to maintain identical settings through multiple runs of TTS.  See the next section for learning how the scripting language works and how you can create and run your own custom tests.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_30_-_Test_Suite_Scripting_Language.asciidoc",
    "content": "[[testSuideScripts]]\n= Test Suite Scripting Language\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe test suite contains scripting language which allows you to combine test cases into a test scenarios. On the lowest level, however the language is designed to allow you to describe the test by setting test parameters, test comments, identification and so on.\n\nLet's look at the example test description.\n\n[source,java]\n-----\nShort name@test-id-1;test-id-2: Short description for the test case\n{\n -loop = 10\n -user-name = Frank\n # This is a comment which is ignored\n}\n>> Long, detailed description of the test case <<\n-----\n\nMeaning of all elements:\n\n. *Short name* is any descriptive name you want. It doesn't need to be unique, just something which tells you what this test is about. @ is a separator between the short name and the test ids.\n. *test-id-1;test-id-2* is a semicolon separated of the test cases IDs. The tests cases are executed in the listed order. And listing them there means that the test-id-2 depends on test-id-1. Normally you don't have to list all the dependencies because all mandatory dependencies are included automatically. Which means if you have an authentication test case the suite adds the network socket connection and stream opening tests automatically. Sometimes however, there are dependencies which are optional or multiple mandatory dependencies and you need to select which one has to be executed. As a good example is the authentications test case. There are many authentication tests: PLAIN-AUTH, SASL-DIGESTMD5, SASL-PLAIN, DIGEST-AUTH and they are all mandatory for most of other tests like roster, presence and so on. One of the authentication tests is a default dependency but if you put on the list different authentication it will be used instead of default one.\n. *:* is a separator between test cases ids list and the short test description.\n. *Short test description* is placed between : - colon and opening *{* - curly bracket. This is usually quite brief, single line test description.\n. *{  }* curly brackets contain all the test parameters, like how many times the test has to be executed or run the test in a separate thread, user name, host IP address for the network connection and many others.\n. *>>  <<* inside the double greater than and double less than you put a very long, multiple line test description.\n\nAs for the testing script between open curly brackets { and close one } you can put all the test case parameters you wish. The format for it is:\n\n*-parameter-name = value*\n\nParameter names always start with *-*. Note, some parameters don't require any value. They can exist on their own without any value assigned:\n\n*-debug-on-error*\n\nThis imitates if you were to put *yes* or *true* as the value.\n\nThe scripting language includes also support for variables which can be assigned any value and used multiple times later on. You assign a value to the variable the same way as you assign it to the parameter:\n\n*$(variable-name) = value*\n\nThe variable name must be always enclosed with brackets *()* and start with *$*.\n\nThe value may be enclosed within double quotes *\"\"* or double quotes may be omitted. If this is a simple string like a number or character string consisting only of digits, letters, underscore *_* and hyphen *-* then you can omit double quotes otherwise you must enclose the value.\n\nThe test case descriptions can be nested inside other test case descriptions. Nested test case descriptions inherit parameters and variables from outer test case description.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_31_-_Writing_Tests_for_Plugins.asciidoc",
    "content": "[[writingTests]]\n= Writing Tests for Plugins\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nYou can write tests in a simple text file which is loaded during test suite runtime.\n\nYou simply specify what should be send to the server and what response should be expected from the server. No need to write Java code and recompile the whole test suite for new tests. It means new test cases can be now written easily and quickly which hopefully means more detailed tests for the server.\n\nHow it works:\n\nLet's take link:http://www.xmpp.org/extensions/xep-0049.html[XEP-0049] Private XML Storage. Looking into the spec we can see the first example:\n\nExample 1. Client Stores Private Data\n\n*CLIENT:*\n\n[source,xml]\n-----\n<iq type=\"set\" id=\"1001\">\n  <query xmlns=\"jabber:iq:private\">\n    <exodus xmlns=\"exodus:prefs\">\n      <defaultnick>Hamlet</defaultnick>\n    </exodus>\n  </query>\n</iq>\n-----\n\n*SERVER:*\n\n[source,xml]\n<iq type=\"result\" id=\"1001\"/>\n\nThis is enough for the first simple test. I have to create text file +JabberIqPrivate.test+ looking like this:\n\n[source,java]\n-----\nsend: {\n\n<iq type=\"set\" id=\"1001\">\n  <query xmlns=\"jabber:iq:private\">\n    <exodus xmlns=\"exodus:prefs\">\n      <defaultnick>Hamlet</defaultnick>\n    </exodus>\n  </query>\n</iq>\n}\n\nexpect: {\n<iq type=\"result\" id=\"1001\"/>\n}\n-----\n\nAnd now I can execute the test:\n\n[source,bash]\n-----\ntestsuite $ ./scripts/all-tests-runner.sh --single JabberIqPrivate.test\n\nTigase server home directory: ../server\nVersion: 2.8.5-b422\nDatabase:         xmldb\nServer IP:        127.0.0.1\nExtra parameters: JabberIqPrivate.test\nStarting Tigase:\nTigase running pid=6751\n\nRunning: 2.8.5-b422-xmldb test, IP 127.0.0.1...\nScript name: scripts/single-xmpp-test.xmpt\nCommon test:  Common test  ...        failure!\nFAILURE,  (Received result doesnt match expected result.,\nExpected one of: [<iq id=\"1001\" type=\"result\"/>],\nreceived:\n[<iq id=\"1001\" type=\"error\">\n  <query xmlns=\"jabber:iq:private\">\n    <exodus xmlns=\"exodus:prefs\">\n      <defaultnick>Hamlet</defaultnick>\n    </exodus>\n  </query>\n  <error type=\"cancel\">\n    <feature-not-implemented xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>\n    <text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">\n      Feature not supported yet.</text>\n  </error>\n</iq>]),\n\nTotal: 100ms\nTest time: 00:00:02\nShutting down Tigase: 6751\n-----\n\nIf I just started working on this XEP and there is no code on the server side, the result is perfectly expected although maybe this is not what we want. After a while of working on the server code I can execute the test once again:\n\n[source,bash]\n-----\ntestsuite $ ./scripts/all-tests-runner.sh --single JabberIqPrivate.test\n\nTigase server home directory: ../server\n\nVersion: 2.8.5-b422\n\nDatabase:         xmldb\n\nServer IP:        127.0.0.1\n\nExtra parameters: JabberIqPrivate.test\n\nStarting Tigase:\n\nTigase running pid=6984\n\nRunning: 2.8.5-b422-xmldb test, IP 127.0.0.1...\n\nScript name: scripts/single-xmpp-test.xmpt\n\nCommon test:  Common test  ... success,  Total: 40ms\n\nTest time: 00:00:01\n\nShutting down Tigase: 6984\n-----\n\nThis is it. The result we want in a simple and efficient way. We can repeat it as many times we want which is especially important in longer term trials. Every time we change the server code we can re-run tests to make sure we get correct responses from the server.\n\nYou can have a look in the current build, with more complete test cases, file for link:https://projects.tigase.org/projects/tigase-testsuite/repository/revisions/master/entry/tests/data/JabberIqPrivate.cot[JabberIqPrivate].\n\nNow my server tests are no longer outdated. Of course not all cases are so simple. Some XEPs require calculations to be done before stanza is sent or to compare received results. A good example for this case is user authentication like SASL and even NON-SASL. But still, there are many cases which can be covered by simple tests: roster management, privacy lists management, vCard, private data storage and so on.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_32_-_Test_Case_Parameters_Description.asciidoc",
    "content": "= Test Case Parameters Description\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThere is long list of parameters which can be applied to any test case. Here is the description of all possible parameters which can be used to build test scenarios.\n\n== Test Report Configuration\nThere are test report parameters which must be set in the main script file in order to generate HTML report from the test. These parameters have no effect is they are set inside the test case description.\n\n. *-version = 2.0.0* sets the test script version. This is used to easily detect incompatibility issues when the test suite loads a script created for more recent version of the suite and may not work properly for this version.\n. *-output-format = (html | html-content)* sets the output format for the test report. There is actually only one format possible right now - HTML. The only difference between these 2 options is that the *html* format creates full HTML page with HTML header and body. The *html-content* format on the other hand creates only what is inside +<body/>+ element. And is used to embed test result inside other HTML content.\n. *-output-file = \"report-file.html\"* sets the file name for the test report.\n. *-output-history = (yes | no)* sets logging of the all protocol data sent between test suite and the XMPP server. Normally for functional tests it is recommended to set it to *yes* but for all other tests like performance or load tests it should be set to *no*.\n. *-history-format = separate-file* sets protocol data logging to a separate file. Currently this is the only possible option.\n. *-output-cols = (5 | 7)* Only valid values are:\n+\n[source,bash]\n-----\n5: \"Test name\", \"Result\", \"Test time\", \"Description\" [, \"History\" ]\n7: \"Test name\", \"Result\", \"Total time\", \"OK\", \"Average\", \"Description\" [, \"History\" ]\n-----\n\n. *-title* = \"The title of the report page\" This parameter sets the test report title which is placed in the HTML page in the +<title/>+ element as well as in the first page header.\n\n== Basic Test Parameters\nThese parameters can be set on per-test case basis but usually they are set in the main script file to apply them to all test cases.\n\n. *-base-ns = \"jabber:client\"* sets the XML name space used for the XML stream in the XMPP connection. Some test cases can be used to test client to server protocol as well as server to server protocol and possibly different protocols added in the future.\n. *-debug* switches debugging mode on. All the communication between the test suite and the server is printed out to the text console and all other debugging information including java exceptions are displayed as well. It is especially useful when some test fails and you want to find out why.\n. *-debug-on-error* switches on debugging mode on error detection. Normally debug output generates lots of message which makes the output very hard to read. Especially in the performance tests not only you can read fast scrolling lines of the protocol data but also it slows the test down. This option however turns debugging off if everything is working well and then generates debug output if any test error us detected.\n. *-def-auth = (auth-plain | auth-digest | auth-sasl)* sets the default authentication method for the user connection.\n. *-def-stream = (stream-client | stream-server | stream-component | stream-bosh)* sets the connection stream to be tested and the name space for the connection.\n. *-host = \"host.name\"* the vhost name the tested server runs for. It may be the real DNS name or just configured for testing purposes hostname. It must match however the server configuration.\n. *-keys-file = \"certs/keystore\"* sets the location of the keys store file. No need to touch it.\n. *-keys-file-password = keystore* sets the password for the keystore file. Normally you don't have to touch it.\n. *-serverip = \"127.0.0.1\"* defines the XMPP server IP address. You may omit this parameter and then the IP address will be determined automatically based on the server DNS address. However if the DNS address can not be correctly resolved or if you run tests on the localhost you can use this parameter to enforce the IP address.\n. *-socket-wait = 10000* sets the network socket timeout in milliseconds that is maximum time the test suite will wait for the response from the server. You may want to increase the timeout for some specific tests which require lots of computation or database activity on the server. Normally 10 seconds is enough for most cases.\n. *-stop-on-fail = true* causes the script to terminate all actions on the first failed test case. It helps diagnosing the server state at the failure point.\n. *-trust-file = \"certs/client_truststore\"* sets the file name for the client trust store file. No need to change it.\n. *-trust-file-password = truststore* sets the password for the trust store file. Normally you don't have to touch it.\n. *-user-name = tester* sets the user name used for the XMPP connections between the test suite and the XMPP server. It is usually set globally the same for all tests and for some tests like receiving the server configuration you may want to use a different account (with admin permissions). Then you can set a different user for this specific test case.\n. *-user-pass = tester-password* sets the password for the user used for the XMPP connection between the test suite and the XMPP server.\n. *-user-resr = resource* sets the user JID resource part for the XMPP connection between the test suite and the XMPP server.\n\n== Test Case Parameters\nTest parameters which are normally set on per-test case basis and apply only to the test they are set for and all inherited tests. Some of the parameters though are applied only to inherited test cases. Please look in the description below to find more details.\n\n. *-active-connection* is a similar parameter to *-on-one-socket* option. If set the suite doesn't close the network socket and if the test is run in loop each loop run re-uses the network connection. Unlike in the -on-one-socket mode the whole test is executed on each run including XMPP stream initialization and user authentication. This option is currently not recommended in a normal use. It is useful only to debug the server behavior in very special use cases.\n. *-background* executes the test in a separate thread in background and immediately returns control to the test suite program without waiting for the test to complete. Default behavior is to execute all tests sequentially and run next test when previous one has been completed. This parameter however allows to run tests concurrently. This a bit similar option to the *-daemon* parameter. The daemon test/task however is ignored completely and results from the daemon are not collected where the background test is a normal test which is run concurrently with another one or possibly many other tests.\n. *-daemon* creates a task running in background in a separate thread. Such a test runs infinitely as a daemon, it is not recorded in the test report and it's result is not calculated. The purpose of such test/task is to work as a helper for other test cases. A good example of such daemon test is message responder - the test which runs under a different user name and waits for messages and responding to the sender.\n. *-delay = 1000* sets the waiting time in milliseconds after the test case is completed. You may use it if you want to introduce short delay between each test cases run in the loop or if you start the helper daemon thread and you have to add the delay to make sure it is ready to work before next real test starts sending requests to the daemon.\n. *-expect-type = error* sets the type for a packet expected as a response. Some test cases like message sender expects sometimes response with the same type it has sent the packet ( *chat* ) but in some other cases when it sends a message to a user who has privacy lists set to block messages the response should be with an error. This way we can use the same test cases for testing different responses scenarios.\n. *-loop = 10* sets the number of times the test (and all inherited tests) are repeated. You can use a *$(loop)* pseudo-variable to obtain and use the current loop run number. This is useful if you want to run every loop run for a different user name like registering 10 different user accounts. To do this you stick the $(loop) variable to the user name string: *-user-name = \"nick_name_$(loop)\"*.\n. *-loop-delay = 10* sets a delay in milliseconds between each individual loop run for the tests which is run multiple times. This is similar parameter to the *-delay* one but the *-delay* option introduces a delay after the whole test (or all loop runs) has been completed. The loop delay options adds waiting time between each run of the looped test.\n. *-loop-start = 5* sets the loop starting value. It doesn't affect number of loop runs in a any way. It only affects the value of the *$(loop)* variable. Let's say you want to run a load test for the server with 100k concurrent users and you want to run the test from 3 different machines. To make sure each machine uses distinct user accounts you have to set a different *-loop-start* parameter on each to prevent from overlapping.\n. *-messages = 10* sets the number of messages to send to the server. This is another way of looping the test. Instead of repeating the whole test with opening network connection, XMPP stream, authentication and so on it causes only to send the message this many times. This parameters is accepted by some test cases only which send messages. For the messages listeners - test cases which is supposed to respond to the messages the number set here specifies how many times the the response must be sent before the test successfully terminates it's work.\n. *-multi-thread* option causes to run the test case and all inherited in all levels test cases in separate threads. Normally the test case where you put the parameter doesn't have a test ID (what you put between '@' and ':' characters so it doesn't run a test on it's own. Instead it contains a series of test cases inside which are then run in a separate thread each. This is a key parameter to run tests for many concurrent users. (Not a load tests though.) For example you can see whether the server behaves correctly when 5 simultaneous modifies their roster. The execution time all inherited tests run in a separate threads is added together and also results from each individual test is calculated and added to the total main test results.\n. *-no-record* is used for kind of configuration tests (tasks) which are used to prepare the XMPP server or database for later tests. As an example can be creation of the test user account which is later on used for the roster tests. Usually you don't want to include such tests in the test report and using this parameter you essentially exclude the test from the report. The test and the result however shows in the command line output so you can still track what is really going on.\n. *-on-one-socket* is a modifier for a looped test case. Normally when we switch looping on using *-loop* parameter the suite resets the state, closes the network socket and runs the test from the very beginning including opening network socket, XMPP stream, authentication and so on. This parameter however changes this behavior. The network socket is not closed when the test run is completed (successfully) and next run executes only the last part of the test omitting the XMPP stream initialization, authentication and all others but last. This is useful when you want to send many messages to the server (although this effect may be accomplished using *-messages* parameter as well) or registering many user accounts on the server, unregistering user accounts and any other which might make sense repeating many times.\n. *-port = 5223* this parameter is similar to the IP address setting and can be also set globally for all tests. Normally however you set it for a selected tests only to check SSL connection. For all other tests default port number is used. Therefore this parameters has been included in this section instead of \"Basic test parameters\".\n. *-presence* this parameter enables sending initial presence with positive priority after connection and binding the session.\n. *-repeat-script = 100* and *-repeat-wait = 10* are 2 parameters are specific to the common test cases. (The test cases which reads the test input/output data from the pseudo-xml text file. The first parameter is another variation of test looping. It sets how many times the test has to be repeated. It works very much like the *-on-one-socket* parameter. The only difference is that the common test can preserve some internal states between runs and therefore it has more control over the data. The second parameter sets the timeout in milliseconds to wait/delay between each individual test run and it is a very similar parameter to the *-delay* one but it sets a timeout inside the common test instead.\n. *-source-file = \"dir/path/to/file.cot\"* is a parameter to set the \"common test\" script file. The common test is a test cases which depends on the authentication test case and can read data to send and responses to expect from the text file. The \"cot\" file is a pseudo-xml file with stanzas to send and stanzas to expect. The the test cases compares the received packets with those in the text file and reports the test result. This is usually a more convenient way to write a new test cases than coding them in Java.\n. *-time-out-ok* is set for a test case when we expect socket timeout as a correct result from the test case. Normally the timeout means that the test failed and there was no response from the server at all or the response was incorrect. For some tests however (like sending a message to the user who is blocking messages through privacy lists) the timeout is the desired correct test result.\n. *-to-jid = \"user_name@host.name\"* sets the destination address for packets sending packets somewhere. As an example is the test case sending <message                     /> packet. You can set the destination address for the packet. Mind, normally every test expects some response for the data sent so make sure the destination end-point will send back the data expected by the test case.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_33_-_Experimental.asciidoc",
    "content": "= Experimental\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe guide contains description of non-standard or experimental functionality of the server. Some of them are based on never published extensions, some of them are just test implementation for new ideas or performance improvements.\n\n- xref:dynamicRosters[Dynamic Rosters]\n- xref:mobileoptimizations[Mobile Optimizations]\n- xref:boshsessioncashe[Bosh Session Cache]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_34_-_Dynamic_Rosters.asciidoc",
    "content": "[[dynamicRosters]]\n= Dynamic Rosters\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-27 18:10\n\n\n== Problem Description\nNormal roster contacts stored and created as *dynamic roster parts* are delivered to the end user transparently. The XMPP client doesn't really know what contacts come from its own *static* roster created manually by the user and what contacts come from a *dynamic* roster part; contacts and groups generated dynamically by the server logic.\n\nSome specialized clients need to store extra bits of information about roster contacts. For the normal user *static* roster information can be stored as private data and is available only to this single user. In some cases however, clients need to store information about contacts from the dynamic roster part and this information must be available to all users accessing *dynamic* roster part.\n\nThe protocol defined here allows the exchange of information, saving and retrieving extra data about the contacts.\n\n== Syntax and Semantics\nExtra contact data is accessed using IQ stanzas, specifically by means of a child element qualified by the *jabber:iq:roster-dynamic* namespace. The child element MAY contain one or more children, each describing a unique contact item. Content of the element is not specified and is implementation dependent. From Tigase's point of view it can contain any valid XML data. Whole element is passed to the DynamicRoster implementation class as is and without any verification. Upon retrieving the contact extra data the DynamicRoster implementation is supposed to provide a valid XML element with all the required data for requested *jid*.\n\nThe *jid* attribute specifies the Jabber Identifier (JID) that uniquely identifies the roster item. Inclusion of the *jid* attribute is *REQUIRED*.\n\nFollowing actions on the extra contact data are allowed:\n\n- *set* - stores extra information about the contact\n- *get* - retrieves extra information about the contact\n\n== Retrieving Contact Data\nUpon connecting to the server and becoming an active resource, a client can request the extra contact data. This request can be made either before or after requesting the user roster. The client's request for the extra contact data is *OPTIONAL*.\n\nExample: Client requests contact extra data from the server using *get* request:\n\n[source,xml]\n-----\n<iq type='get' id='rce_1'>\n<query xmlns='jabber:iq:roster-dynamic'>\n<item jid='archimedes@eureka.com'/>\n</query>\n</iq>\n-----\n\nExample: Client receives contact extra data from the server, but there was either no extra information for the user, or the user was not found in the dynamic roster:\n\n[source,xml]\n-----\n<iq type='result' id='rce_1'>\n<query xmlns='jabber:iq:roster-dynamic'>\n<item jid='archimedes@eureka.com'/>\n</query>\n</iq>\n-----\n\nExample: Client receives contact extra data from the server, and there was some extra information found about the contact:\n\n[source,xml]\n-----\n<iq type='result' id='rce_1'>\n<query xmlns='jabber:iq:roster-dynamic'>\n<item jid='archimedes@eureka.com'>\n<phone>+12 3234 322342</phone>\n<note>This is short note about the contact</note>\n<fax>+98 2343 3453453</fax>\n</item>\n</query>\n</iq>\n-----\n\n== Updating/Saving Extra Information About the Contact\nAt any time, a client *MAY* update extra contact information on the server.\n\nExample: Client sends contact extra information using *set* request.\n\n[source,xml]\n-----\n<iq type='set' id='a78b4q6ha463'>\n<query xmlns='jabber:iq:roster-dynamic'>\n<item jid='archimedes@eureka.com'>\n<phone>+22 3344 556677</phone>\n<note>he is a smart guy, he knows whether the crown is made from pure gold or not.</note>\n</item>\n</query>\n</iq>\n-----\n\nClient responds to the server:\n\n[source,xml]\n-----\n<iq type='result' id='a78b4q6ha463'/>\n-----\n\nA client *MAY* update contact extra information for more than a single item in one request:\n\nExample: Client sends contact extra information using *set* request with many +<item/>+ elements.\n\n[source,xml]\n-----\n<iq type='set' id='a78b4q6ha464'>\n<query xmlns='jabber:iq:roster-dynamic'>\n<item jid='archimedes@eureka.com'>\n<phone>+22 3344 556677</phone>\n<note>he is a smart guy, he knows whether the crown is made from pure gold or not.</note>\n</item>\n<item jid='newton@eureka.com'>\n<phone>+22 3344 556688</phone>\n<note>He knows how heavy I am.</note>\n</item>\n<item jid='pascal@eureka.com'>\n<phone>+22 3344 556699</phone>\n<note>This guy helped me cure my sickness!</note>\n</item>\n</query>\n</iq>\n-----\n\nClient responds to the server:\n\n[source,xml]\n-----\n<iq type='result' id='a78b4q6ha464'/>\n-----\n\n== Configuration\nDynamicRoster implementation class should be configured in the *init.properties* file. As it's an extension to the *PresenceState*, *PresenceSubscription* and *Roster* plugins classes should be configured either for each plugin:\n[source,bash]\n-----\nsess-man/plugins-conf/jabber\\:iq\\:roster/dynamic-roster-classes=<class list>\nsess-man/plugins-conf/presence-state/dynamic-roster-classes=<classes list>\nsess-man/plugins-conf/presence-subscription/dynamic-roster-classes=<classes list>\n-----\nor globally:\n\n[source,bash]\n-----\nsess-man/plugins-conf/dynamic-roster-classes=<classes list>\n-----\n\n*<classes list>* is a comma separated list of classes.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_35_-_Mobile_Optimizations.asciidoc",
    "content": "[[mobileoptimizations]]\n= Mobile Optimizations\n:author: Andrzej Wojcik <andrzejw@tigase.org>\n:version: v2.1, January 2015: Added info about MobileV3\n:oldversion: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2012-05-22 17:57\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n== Problem Description\nIn default configuration stanzas are sent to the client when processing is finished, but in mobile environment sending or receiving data drains battery due to use of the radio.\n\nTo save energy data should be sent to client only if it is important or client is waiting for it.\n\n== Solution\nWhen mobile client is entering inactive state it notifies server about it by sending following stanza:\n\n[source,xml]\n-----\n<iq type=\"set\" id=\"xx\">\n<mobile\n  xmlns=\"http://tigase.org/protocol/mobile#v3\"\n  enable=\"true\"/>\n</iq>\n-----\n\nAfter receiving stanza server starts queuing stanza which should be send to mobile client. What kind of queued stanzas depends on the plugins used and in case of *Mobile v3* presence stanzas are queued as well as message stanzas which are Message Carbons. Any other stanza (such as iq or plain messenge) is sent immediately to the client and every stanza from queue is also sent at this time.\n\nWhen mobile client is entering active state it notifies server by sending following stanza:\n\n[source,xml]\n-----\n<iq type=\"set\" id=\"xx\">\n<mobile\n  xmlns=\"http://tigase.org/protocol/mobile#v3\"\n  enable=\"false\"/>\n</iq>\n-----\n\nAfter receiving stanza server sends all queued stanzas to the client.\n\nAlso all stanzas from queue will be sent if number of stanzas in queue will reach queue size limit. By default this limit is set to 50.\n\n== Queuing Algorithms\nThere are three mobile optimization plugins for Tigase:\n\n- *Mobile v1* - all presence stanzas are kept in queue\n- *Mobile v2* - only last presence from each source is kept in queue\n- *Mobile v3* - only last presence from each source is kept in queue, also Message Carbons are queued\n\n\nIf you wish to activate you Mobile v1 plugin you need to send presented above with xmlns attribute value replaced with _http://tigase.org/protocol/mobile#v1_\n\nIf you wish to activate you Mobile v2 plugin you need to send presented above with xmlns attribute value replaced with _http://tigase.org/protocol/mobile#v2_\n\n== Configuration\nMentioned plugins are not activated by default thus additional entries in the init.properties are required:\n\n+--sm-plugins=+mobile_v1,+mobile_v2,+mobile_v3\n\n*Only one of these plugins should be enabled*\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_36_-_Bosh_Session_Cache.asciidoc",
    "content": "[[boshsessioncache]]\n= Bosh Session Cache\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n== Problem Description\nWeb clients have no way to store any data locally, on the client side. Therefore after a web page reload the web clients loses all the context it was running in before the page reload.\n\nSome elements of the context can be retrieved from the server like the roster and all contacts presence information. Some other data however, can not be restored easily like opened chat windows and the chat windows contents. Even if the roster restoring is possible, this operation is very expensive in terms of time and resources on the server side.\n\nOn of possible solutions is to allow web client to store some data in the Bosh component cache on the server side for the time while the Bosh session is active. After the page reloads, if the client can somehow retrieve SID (stored in cookie or provided by the web application running the web client) it is possible to reload all the data stored in the Bosh cache to the client.\n\nBosh session context data are: roster, contacts presence information, opened chat windows, chat windows content and some other minor data. Ideally the web client should be able to store any data in the Bosh component cache it wants.\n\n== Bosh Session Cache Description\nThe Bosh Session Cache is divided into 2 parts - automatic cache and dynamic cache.\n\nThe reason for splitting the cache into 2 parts is that some data can be collected automatically by the Bosh component and it would be very inefficient to require the client to store the data in the Bosh cache. The best example for such data is the Roster and contacts presence information.\n\n- *automatic cache* - is the cache part which is created automatically by the Bosh component without any interaction with the client. The client, however, can access the cache at any time. I would say this is a read-only cache but I don't want to stop client from manipulating the cache if it needs. The client usually, only retrieves data from this part of the cache as all changes should be automatically updated by the Bosh component. The general idea for the automatic cache is that the data stored there are accessible in the standard XMPP form. So no extra code is needed for processing them.\n- *dynamic cache* - is the cache part which is or can be modified at any time by the client. Client can store, retrieve, delete and modify data in this part of the cache.\n\n== Cache Protocol\nAll the Bosh Session Cache actions are executed using additional +<body/>+ element attributes: +cache+ and +cache-id+. Attribute cache stores the action performed on the Bosh +cache+ and the +cache-id+ attribute refers to the +cache+ element if the action attribute needs it. +cache-id+ is optional. There is a default cache ID (empty one) associated with the elements for which the +cache-id+ is not provided.\n\nIf the +<body/>+ element contains the cache attribute it means that all data included in the +<body/>+ refer to the cache action. It is not allowed, for example to send a message in the body and have the cache action set to *get*. The +<body/>+ element with cache action *get*, *get_all*, *on*, *off*, *remove* must be empty. The +<body/>+ element with actions *set* or *add* must contain data to store in the cache.\n\n=== Cache Actions\n- *on* or *off* - the client can switch the cache on or off at any time during the session. It is recommended, however that the client switches the cache *on* in the first body packet, otherwise some information from the automatic cache may be missing. The automatic cache is created from the stream of data passing the Bosh component. Therefore if the cache is switched on after the roster retrieval is completed then the roster information will be missing in the cache. If the cache is set to *off* (the default value) all requests to the cache are ignored. This is to ensure backward compatibility with the original Bosh specification and to make sure that in a default environment the Bosh component doesn't consume any extra resources for cache processing and storing as the cache wouldn't be used by the client anyway.\n- *get* - retrieves the cache element pointing by the cache-id from the Bosh cache. Note there is no *result* cache action. The +<body/>+ sent as a response from the server to the client may contain cache results for a given cache-id and it may also contain other data received by the Bosh component for the client. It may also happen that large cached data are split into a few parts and each part can be sent in a separate +<body/>+ element. It may usually happen for the Roster data.\n- *get_all* - retrieves all the elements kept in the Bosh cache. That action can can be performed after the page reload. The client doesn't have to request every single cached item one by one. It can retrieve all cache items in one go. It doesn't mean however the whole cache is sent to the client in a single +<body/>+ element. The cache content will be divided into a smaller parts of a reasonable size and will be sent to the client in a separate +<body/>+ elements. It may also happen that the +<body/>+ element contain the cache elements as well as the new requests sent to the user like new messages or presence information.\n- *set* - sends data to the Bosh Session cache for later retrieval. The client can store any data it wants in the cache. The Bosh components stores in the cache under the selected ID all the data inside the +<body/>+ element. The only restriction is that the cached data must be a valid XML content. The data are returned to the client in exactly the same form as they were received from the server. The *set* action replaces any previously stored data under this ID.\n- *add* - adds new element to the cache under the given ID. This action might be useful for storing data for the opened chat window. The client can add new elements for the chat window, like new messages, icons and so on...\n- *remove* - removes the cached element for the given cache ID.\n\n=== Cache ID\nCache ID can be an any character string. There might be some IDs reserved for a special cases, like for the Roster content. To avoid any future ID conflicts reserved ID values starts with: *bosh* - string.\n\nThere is a default cache ID - en empty string. Thus cache-id attribute can be omitted and then the requests refers to data stored under the default (empty) ID.\n\n=== Reserved Cache ID Names\nHere is a list of reserved Cache IDs:\n\n- *bosh-roster* - The user roster is cached in the Bosh component in exactly the same form as it was received from the core server. The Bosh Cache might or might not do optimizations on the roster like removing elements from the cached roster if the roster *remove* has been received or may just store all the roster requests and then send them all to the client. There is a one mandatory optimization the Bosh Cache must perform. It must remember the last (and only the last) presence status for each roster item. Upon roster retrieving from the cache the Bosh component must send the roster item first and then the presence for the item. If the presence is missing it means an offline presence. If the roster is small it can be sent to the client in a single packet but for a large roster it is recommended to split contact lists to batches of max 100 elements. The Bosh component may send all roster contacts first and then all presences or it can send a part of the roster, presences for sent items, next part of the roster, presences for next items and so on.\n\n- *bosh-resource-bind* - The user resource bind is also cached to allow the client quickly retrieve information about the full JID for the established Bosh session.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_37_-_Old_Stuff.asciidoc",
    "content": "[[oldStuff]]\n= Old Stuff\n:author: Daniel Wisnewski\n:version: v1.0 July 2015\n:date: 2015-27-07 19:43\n\nThis contains sections on old features, or information pertaining to old builds of Tigase.  It is kept here for archival purposes.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_38_-_Tigase_DB_Schema_Explained.asciidoc",
    "content": "[[tigaseDBSchema]]\n= Tigase DB Schema Explained\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2011-07-12 00:56\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe schema basics, how it looks like and brief explanation to all rows can be found in the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/database/mysql-schema-4-schema.sql[schema creation script]. However, this is hardly enough to understand how it works and how all the data is accessed. There are only 3 basic tables which actually keep all the Tigase server users' data: *tig_users*, *tig_nodes* and *tig_pairs*. Therefore it is not clear at first how Tigase's data is organized.\n\nBefore you can understand the Tigase XMPP Server database schema, how it works and how to use it, is it essential to know what were the goals of it's development and why it works that way. Let's start with the API as this gives you the best introduction.\n\nSimplified access can be made through methods:\n\n[source,java]\n-----\nvoid setData(BareJID user, String key, String value);\nString getData(BareJID user, String key);\n-----\n\nAnd more a complex version:\n\n[source,java]\n-----\nvoid setData(BareJID user, String subnode, String key, String value);\nString getData(BareJID user, String subnode, String key, String def);\n-----\nEven though the API contains more methods, the rest is more or less a variation of presented above. A complete API description for all access methods is available in JavaDoc documentation in the link:https://projects.tigase.org/projects/tigase-server/repository/entry/trunk/src/main/java/tigase/db/UserRepository.java[UserRepository] interface. So we are not going into too much detail here except for the main idea.\n\nTigase operates on <*key*, *value*> pairs for the individual user data. The idea behind this was to make the API very simple and also at the same time very flexible, so adding a new plugin or component would not require a database schema change, adding new tables, or conversion of the DB schema to a new version.\n\nAs a result the *UserRepository* interface is exposed to all of Tigase's code, mainly the components and plugins (let's call all of them modules). These modules simply call set/get methods to store or access module specific data.\n\nAs plugins or components are developed independently it may easily happen that developer choses the same key name to store some information. To avoid key name conflicts in the database a 'node' concept has been introduced. Therefore, most modules when set/get key value they also provide a subnode part, which in most cases is just XMLNS or some other unique string.\n\nThe 'node' thing is a little bit like directory in a file system, it may contain subnodes which makes the Tigase database behave like a hierarchical structure. And the notation is also similar to file systems, you use just */* to separate node levels. In practice you can have the database organized like this:\n\n[source,sql]\n-----\nuser-name@domain  --> (key, value) pairs\n                   |\n               roster -->\n                       |\n                     item1 --> (key1, value1) pairs.\n                       |\n                     item2 --> (key1, value1) pairs.\n-----\n\nSo to access item's 1 data from the roster you could call method like this:\n\n[source,java]\n-----\ngetData(\"user-name@domain\", \"roster/item1\", key1, def1);\n-----\n\nThis is huge convenience for the developer, as he can focus on the module logic instead of worrying about data storage implementation and organization. Especially at the prototype phase it speeds development up and allows for a quick experiments with different solutions. In practice, accessing user's roster in such a way would be highly inefficient so the roster is stored a bit differently but you get the idea. Also there is a more complex API used in some places allowing for more direct access to the database and store data in any format optimized for the scenario.\n\nRight now such a hierarchical structure is implemented on top of SQL databases but initially Tigase's database was implemented as an XML structure, so it was natural and simple.\n\nIn the SQL database we simulate hierarchical structure with three tables:\n\n. *tig_users* - with main users data, user id (JID), optional password, active flag, creation time and some other basic properties of the account. All of them could be actually stored in tig_pairs but for performance reasons they are in one place to quickly access them with a single, simple query.\n. *tig_nodes* - is a table where the hierarchy is implemented. When Tigase was storing data in XML database the hierarchy was quite complex. However, in a SQL database it resulted in a very slow access to the data and a now more flat structure is used by most components. Please note, every user's entry has something called root node, which is represented by 'root' string;\n. *tig_pairs* - this is the table where all the user's information is stored in form of the <key, value> pairs.\n\nSo we now know how the data is organized. Now we are going to learn how to access the data directly in the database using SQL queries.\n\nLet's assume we have a user 'admin@test-d' for whom we want to retrieve the roster. We could simply execute query:\n\n[source,sql]\n-----\nselect pval\n  from tig_users, tig_pairs\n  where user_id = 'admin@test-d' and\n        tig_users.uid = tig_pairs.uid and\n        pkey = 'roster';\n-----\n\nHowever, if multiple modules store data under the key 'roster' for a single user, we would receive multiple results. To access the correct 'roster' we also have to know the node hierarchy for this particular key. The main users roster is stored under the 'root' node, so the query would look like:\n\n[source,sql]\n-----\nselect pval\n  from tig_users, tig_nodes, tig_pairs\n  where user_id = 'admin@test-d' and\n            tig_users.uid = tig_nodes.uid and\n            node = 'root' and\n            tig_users.uid = tig_pairs.uid and\n           pkey = 'roster';\n-----\n\nHow exactly the information is stored in the *tig_pairs* table depends on the particular module. For the roster it looks a bit like XML content:\n\n[source,xml]\n-----\n<contact jid=\"all-xmpp-test@test-d\" subs=\"none\" preped=\"simple\" name=\"all-xmpp-test\"/>\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_39_-_Why_the_Most_Recent_JDK.asciidoc",
    "content": "[[whyRecentJDK]]\n= Why the most recent JDK?\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThere are many reasons but the main is that we are a small team working on source code. So the whole approach is to make life easier for us, make the project easier to maintain, and development more efficient.\n\nHere is the list:\n\n- *Easy to maintain* - No third-party libraries are used for the project which makes this project much easier to maintain. This simplifies issues of compatibility between particular versions of libraries. This also unifies coding with a single library package without having to rely on specific versions that may not be supported.\n- *Easy to deploy* -  Another reason to not use third-party tools is to make it easier for end-users to install and use the server.\n- *Efficient development* -  As no third-party libraries are used, Tigase needs either to implement many things on its own or use as much as possible of JDK functionality. We try to use as much as possible of existing library provided with JDK and the rest is custom coded.\n\nWhat features of JDK-1.5 are critical for Tigase development? Why I can't simply re-implement some code to make it compatible with earlier JDK versions?\n\n- *Non-blocking I/O for SSL/TLS* -  This is functionality which can't be simply re-implemented in JDK-1.4. As the whole server uses NIO it doesn't make sense to use blocking I/O for SSL and TLS.\n- *SASL* -  This could be re-implemented for JDK-1.4 without much effort.\n- *Concurrent package* -  This could be re-implemented for JDK-1.4 but takes a lot of work. This is a critical part of the server as it uses multi-threading and concurrent processing.\n- *Security package* -  There number of extensions to the security package which otherwise would not work as easily with earlier versions of JDK.\n\nI think above list is enough to decide to use JDK-1.5. But why JDK-1.6?\n\n- *LinkedHashMap* -  in JDK-1.6 is a basement for the Tigase cache implementation.\n- *Light HTTP server* -  JDK-1.6 offers built-in light HTTP server which is needed to implement HTTP binding (JEP-0124) and HTTP user interface to monitor server activity and work with the server configuration.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_40_-_Generating_Tigase_Installer.asciidoc",
    "content": "[[genTigaseInstaller]]\n= Generating Tigase Installer\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nTo generate installer:\n\n. Install chosen version of link:http://izpack.org/[IzPack] including source code.\n. In order to compile custom Tigase panels you need to first compile link:http://izpack.org/[IzPack] classes. You can use the included +build.xml+ which is in the src directory of link:http://izpack.org/[IzPack] install. Just enter this dir and type:\n\n[source,bash]\nant all\n\n. Depending on the IzPack version classes will be compiled directly into the +src/lib+ directory or +_build+ directory of link:http://izpack.org/[IzPack]. You may need to tweak the +build.xml+ file which is in the same dir as the +readme+ and point to the directory where link:http://izpack.org/[IzPack] compiled classes reside.\n\n[source,java]\n-----\n<!-- fragment -->\n<classpath>\n  <pathelement location=\"java\"/>\n\n  <!-- tweak below fragment -->\n  <pathelement location=\"${installer.path}/_build\"/>\n\n  <pathelement location=\"${installer.path}/bin/panels/TargetPanel.jar\"/>\n</classpath>\n-----\n. Make sure that the bin/panels directory of link:http://izpack.org/[IzPack] is writable by +generate-installer.sh+ script. Compiled custom panels will be placed here before running installer compiler.\n. Modify the +script/generate-installer.sh+. Change the +IZPACK_DIR+ variable to point to the link:http://izpack.org/[IzPack] instalation directory e.g.\n+\n[source,bash]\n-----\nIZPACK_DIR=\"/usr/local/IzPack421\"\n-----\n. To start the installation process run the +scripts/generate-installer.sh+ file you will find in the main server source code directory. You should start it from the server root dir.\n. Generated files (jar and exe) will be placed in the packages dir of Tigase codebase.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_41_-_API_Description_for_Virtual_Domains_Management_in_the_Tigase_Server.asciidoc",
    "content": "[[apiVirtualDomain]]\n= API Description for Virtual Domains Management in the Tigase Server\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nThe purpose of this guide is to introduce vhost management in Tigase server. Please refer to the JavaDoc documentation for all specific details not covered in this guide. All interfaces are well documented and you can use existing implementation as an example code base and reference point. The VHost management files are located in the repository and you can browse them using the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/show/src/main/java/tigase/vhosts[project tracker].\n\nVirtual hosts management in Tigase can be adjusted in many ways through the flexible API. The core elements of the virtual domains management is interface link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostManager.java[VHostManager] class. They are responsible for providing the virtual hosts information to the rest of the Tigase server components. In particular to the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/server/MessageRouter.java[MessageRouter] class which controls how XMPP packets flow inside the server.\n\nThe class you most likely want to re-implement is link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostJDBCRepository.java[VHostJDBCRepository] used as a default virtual hosts storage and implementing the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostRepository.java[VHostRepository] interface. You might need to have your own implementation in order to store and access virtual hosts in other than Tigase's own data storage. This is especially important if you are going to modify the virtual domains list through systems other than Tigase.\n\nThe very basic virtual hosts storage is provided by link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostItem.java[VHostItem] class. This is read only storage and provides the server a bootstrap vhosts data at the first startup time when the database with virtual hosts is empty or is not accessible. Therefore it is advised that all link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostItem.java[VHostItem] implementations extend this class. The example code is provided in the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostJDBCRepository.java[VHostJDBCRepository] file.\n\nAll components which may need virtual hosts information or want to interact with virtual hosts management subsystem should implement the link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostListener.java[VHostListener] interface. In some cases implementing this interface is necessary to receive packets for processing.\n\nVirtual host information is carried out in 2 forms inside the Tigase server:\n\n. As a *String* value with the domain name\n. As a *link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostItem.java[VHostItem]* which contains all the domain information including the domain name, maximum number of users for this domain, whether the domain is enabled or disabled and so on. The JavaDoc documentation contains all the details about all available fields and usage.\n\nHere is a complete list of all interfaces and classes with a brief description for each of them:\n\n[[vhostManIfc]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostManagerIfc.java[VHostManagerIfc] - is an interface used to access virtual hosts information in all other server components. There is one default implementation of the interface: xref:vhostMgr[VHostManager].\n[[vhostListen]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostListener.java[VHostListener] - is an interface which allows components to interact with the xref:vhostMgr[VHostManager]. The interaction is in both ways. The VHostManager provides virtual hosts information to components and components provide some control data required to correctly route packets to components.\n[[vhostrepo]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostRepository.java[VHostRepository] - is an interface used to store and load virtual domains list from the database or any other storage media. There are 2 implementations for this interface: link:http://projects.tigase.org/server/trac/browser/trunk/src/main/java/tigase/vhosts/VhostConfigRepository.java[VHostConfigRepository] which loads vhosts information for the configuration file and provides read-only storage and - xref:vhostJDBC[VHostJDBCRepository] class which extends link:http://projects.tigase.org/server/trac/browser/trunk/src/main/java/tigase/vhosts/VhostConfigRepository.java[VHostConfigRepository] and allows for both - reading and saving virtual domains list. +VHostJDBCRepository+ is loaded as a default repository by Tigase server.\n[[vhostItem]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostItem.java[VHostItem] - is a class which allows for keeping all the virtual domain properties. Sometimes the domain name is not sufficient for data processing. The domain may be temporarily disabled, may have a limited number of users and so on. Instances of this class keep all the information about the domain which might be needed by the server components.\n[[vhostMgr]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostManager.java[VHostManager] - the default implementation of the VHostManagerIfc interface. It provides components with the virtual hosts information and manages the virtual hosts list. Processes ad-hoc commands for reloading, updating and removing domains.\n[[vhostConfig]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VhostConfigRepository.java[VHostConfirRepository] - a very basic implementation of the link:http://projects.tigase.org/server/trac/browser/trunk/src/main/java/tigase/vhosts/VHostRepository.java[VHostRepository] for loading domains list from the configuration file.\n[[vhostJDCB]]\n. link:https://projects.tigase.org/projects/tigase-server/repository/revisions/master/entry/src/main/java/tigase/vhosts/VHostJDBCRepository.java[VHostJDBCRepository] - the default implementation of the link:http://projects.tigase.org/server/trac/browser/trunk/src/main/java/tigase/vhosts/VHostRepository.java[VHostRepository] loaded by Tigase server. It allows to read and store virtual domains list in the database accessible through UserRepository.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_42_-_Cluster_Map_Interface.asciidoc",
    "content": "[[clusterMapInterface]]\n= Cluster Map Interface\n\n:author: Bartosz Malkowski & Daniel Wisnewski\n:date: 2015-12-22 13:46\n:version: v1.0 December 2015\n\n:toc:\n:numbered:\n:website:\n\nStarting with v7.1.0, a cluster map interface has been implemented.  The cluster map is aided by use of the distributed event bus system to communicate between all clusters.\n\n== Requirements\nAny full distribution of Tigase will support the Cluster Map API so long as the eventbus component is not disabled.  JDK v1.8 is required for this feature, however since Tigase v1.7.0 requires this, you should already have it installed.\n\nThe cluster map is stored in memory and follows the map.util.interface java standards can be used to improve cluster connections, and help clustered servers keep track of each other.\n\n\n== Map creation\nMap must be created with the following command:\n\n[source,java]\n----\njava.util.Map<String, String> map = ClusterMapFactory.get().createMap(\"type\",String.class,String.class,\"1\",\"2\",\"3\" )\n----\nWhere \"type\" is the map ID.  This creates the map locally and then fires an event to all clustered servers.  Each cluster server has an event handler waiting for, in this case, +NewMapCreate+ event.\nMap Key class and Map Value class are used to type conversion.\nArrays of strings are parameters, for example ID of user session.\n\nOnce received, the distributed eventbus will create a local map.\n[source,java]\n-----\neventBus.addHandler(MapCreatedEventHandler.MapCreatedEvent.class, new MapCreatedEventHandler() {\n    @Override\n    public void onMapCreated(Map map, String type, String... parameters) {\n    }\n});\n-----\n\nA brief example of a map creation is shown here:\n[source,java]\n-----\njava.util.Map<String, String> map = ClusterMapFactory.get().createMap(\"Very_Important_Map_In_User_Session\",JID.class,Boolean.class,\"user-session-identifier-123\");\n-----\nThis will fire event MapCreatedEvent on all other cluster nodes. Strings \"Very_Important_Map_In_User_Session\" and \"user-session-identifier-123\" are given as parameters in onMapCreated() method.\nThe event consumer code must know what to do with map with type \"Very_Important_Map_In_User_Session\". It may retrieve user session \"user-session-identifier-123\" and put this map in this session.\nIt should be used to tell other nodes how to treat the event with a newly created map, and it should be stored in user session.\n\nMap Changes\n-----------\nChanges to the map on one cluster will trigger +AddValue+ or +RemoveValue+ events in eventbus.  Stanzas sent betweeen clusters will look something like this:\n[source,xml]\n-----\n<ElementAdd xmlns=\"tigase:clustered:map\">\n  <uid>1-2-3</uid>\n  <item>\n    <key>xKEY</key>\n    <value>xVALUE</value>\n  </item>\n  <item>\n    <key>yKEY</key>\n    <value>yVALUE</value>\n  </item>\n</ElementAdd>\n-----\nCode to handle adding an item:\n[source,java]\n-----\neventBus.addHandler(ElementAdd, tigase:clustered:map, new EventHandler() {\n  @Override\n  public void onEvent(String name, String xmlns, Element event) {\n  });\n-----\n\nWhere the element 'event' is the UID, and the name string is the name of the map key/value pair.\n\n\nThis example removes an element from the cluster map.  Removal of items look similar:\n[source,xml]\n-----\n<ElementRemove xmlns=\"tigase:clustered:map\">\n  <uid>1-2-3</uid>\n  <item>\n    <key>xKEY</key>\n    <value>xVALUE</value>\n  </item>\n</ElementRemove>\n-----\nwith the code also being similar:\n[source,java]\n-----\neventBus.addHandler(ElementRemove, tigase:clustered:map, new EventHandler() {\n  @Override\n  public void onEvent(String name, String xmlns, Element name) {\n  });\n-----\n\n== Map Destruction\nJava Garbage Collector will normally remove a local map if it is no longer used.  Clustered maps however are not removed in this manner.\nThese maps must be destroyed manually if they are no longer used:\n[source,java]\n-----\nClusterMapFactory.get().destroyMap(clmap);\n-----\n\nCalling this, the map named clmap will be destroyed on each cluster node.\n\nThe event handler will catch event when map is destroyed on another cluster node:\n[source,java]\n-----\neventBus.addHandler(MapDestroyedEventHandler.MapDestroyedEvent.class, new MapDestroyedEventHandler() {\n    @Override\n    public void onMapDestroyed(Map mapX, String type) {\n    }\n});\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_43_-_EventBus_API.asciidoc",
    "content": "[[eventBus]]\n= EventBus API in Tigase\n:author: Bartosz Małkowski <bmalkowski@tigase.pl>\n:version: v1.0, December 2015.\n:date: 2015-12-29\n:revision: v1.0\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nEventBus is a custom publish-subscribe mechanism which allows for the use of Event Listener within Tigase Server.  EventBus consists of two separated parts: Distributed EventBus and Local EventBus.\nLocal EventBus is only concerned with local event listener, and will operate events locally.  Distributed EventBus is designed to distribute events among cluster nodes.\nFor a more detailed overview of EventBus and it's features, please visit link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/#eventBus[The Administration Guide].\n\n== EventBus API\nTo create instance of EventBus use the following code:\n[source, xml]\n-------\nEventBus eventBus = EventBusFactory.getInstance();\n-------\n\n*NOTE:* Remember, that EventBus is asynchronous. All handlers are called in a different thread than the thread that initially fired the event.\n\n== Distributed EventBus\nDistributed EventBus is designed to distribute events among cluster nodes.\nEvents must extends `tigase.xml.Element`:\n\n[source, xml]\n-------\n<EventName xmlns=\"tigase:demo\">\n  <sample_value>1</sample_value>\n</EventName>\n-------\nEvents are identified by two elements: name of event and namespace.\n\n\n=== Registering events handlers\nTo catch and handle an event published in any node of cluster, EventsHandler must be registered first.\n\n[source, java]\n-------\nEventHandler handler = new EventHandler() {\n    @Override\n    public void onEvent(String name, String xmlns, Element event) {\n        // TODO\n    }\n};\n\neventBus.addHandler(\"EventName\", \"tigase:demo\", handler);\n\n-------\n\nIt is possible to register handler for all events with a specific xmlns such as tigase:demo below:\n\n[source, java]\n-------\neventBus.addHandler(null, \"tigase:demo\", handler);\n-------\n\nEvents created on others cluster node, will have attribute `remote` set to `true` and attribute `source` set to event creator node name:\n\n[source, xml]\n-------\n<EventName xmlns=\"tigase:demo\" remote=\"true\" source=\"node1.example\">\n  <sample_value>1</sample_value>\n</EventName>\n-------\n\n=== Publishing events\n\nThe only limitation for events are the requirements of name and xmlns. Internal structure may be defined by programmer.\n\n[source, java]\n-------\nElement event = new Element(\"EventName\", new String[]{\"xmlns\"}, new String[]{\"tigase:demo\"});\nevent.addChild(new Element(\"sample_value\", \"1\"));\n\neventBus.fire(event);\n-------\n\nThis event will be received by all handlers that are registered for exactly this event, or all events usint the *tigase:demo* namespace on all cluster nodes. It is possible to limit event delivery only to the current Tigase instance (current cluster node), by setting the attribute `local`:\n\n[source, java]\n-------\nElement event = new Element(\"EventName\", new String[]{\"xmlns\", \"local\"}, new String[]{\"tigase:demo\", \"true\"});\nevent.addChild(new Element(\"sample_value\", \"1\"));\n\neventBus.fire(event);\n-------\n\n== Local EventBus\n\nLocal EventBus is the mechanism to distribute events to all listeners on the same instance of Tigase Server.  Local EventBus uses Java Objects as events and allows for the transmission instance of object (for example `Map` or `Set`).\n\n=== Defining events and handlers classes\nLocal EventBus uses own structures of events and handlers.\n\n[source, java]\n.SampleEvent.java\n-------\npublic static class SampleEvent implements Event {\n\n    private final String data;\n\n    public SampleEvent(String data) {\n        this.data = data;\n    }\n\n    public String getData() {\n        return data;\n    }\n\n}\n-------\n\n=== Registering events handlers\n\nTo catch an event, `EventHandler` must be registered in EventBus:\n\n[source, java]\n-------\nEventHandler handler = new EventHandler() {\n    @Override\n    public void onEvent(Event event) {\n\n    }\n};\n\neventBus.addHandler(SampleEvent.class, handler);\n-------\n\nThe other way to register a handler is by using annotations. Event consumer class must contain the method with a single parameter, and its type must be equal to expected event type.\n\n[source, java]\n.SampleConsumer.java\n-------\npublic static class SampleConsumer {\n\n\t@HandleEvent\n\tpublic void onCatchSomeNiceEvent(SampleEvent event) {\n\t}\n\n\t@HandleEvent\n\tpublic void onEvent01(ImportantEvent event) {\n\t}\n}\n-------\n\nThe instance of class must be registered in Eventbus:\n\n[source, java]\n-------\neventBus.registerAll(consumer);\n-------\n\nOnce this is in place, EventBus will be added as the event handler for two different events.\n\n=== Publishing events\nPublishing events is simple:\n\n[source, java]\n-------\nSampleEvent event = new SampleEvent(\"data\");\neventBus.fire(event);\n-------\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_44_-_Stanza_Limitations.asciidoc",
    "content": "[[stanzaLimitations]]\n= Stanza Limitations\n:author: Daniel Wisnewski <daniel.wisnewski@tigase.com>\n:version: v1.0, Janurary 2016\n:date: 2016-20-01\n:revision: v1.0\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nAlthough XMPP is robust and can process stanzas of any size in bytes, there are some limitations to keep in mind for Tigase server.\n\nPlease keep these in mind when using default Tigase settings and creating custom stanzas.\n\n- Limit to number of attributes of single element = 50 attributes\n- Limit to number of elements = 1024 elements\n- Limit to length of element name = 1024 characters\n- Limit to length of attribute name = 1024 characters\n- Limit to length of attribute value = 10240 characters\n- Limit to length of content of single element CDATA = 1048576b or 1Mb\n\nThese values may be changed.\n\n*Note that these limitations are to elements and attributes that may be within a stanza, but do not limit the overall stanza length.*\n\n\n== Escape Characters\nThere are special characters that need to be escaped if they are included in the stanza to avoid conflicts. The rules are similar to normal XML escaping.\nThe following is a list of characters that need to be escaped and what to use to escape them:\n[source]\n-----\n&    &amp;\n<    &lt;\n>    &gt;\n\"    &quot;\n'    &apos;\n-----\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/asciidoc/text/Development_Guide_XX_-_Hack_Tigase_Jabber-XMPP_Server_in_Eclipse.asciidoc",
    "content": "[[codingTigase]]\n= Hack Tigase Jabber/XMPP Server in Eclipse\n:author: Bartosz Malkowski <bmalkowski@tigase.pl>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2010-04-06 21:22\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\nlink:files/tigase-server.psf[tigase-server.psf  424 bytes]\n\nlink:files/eclipse-config.tar_.gz[eclipse-config.tar_.gz  1.01 KB]\n\n\nIf you want to write code for *Tigase* server we recommend the use of link:http://www.eclipse.org/[Eclipse]. Here is a guide how to start working on source code using this IDE.\n\nAll you need to start is:\n\n. Installed and working copy of link:http://www.eclipse.org/[Eclipse]\n. Installed and working copy of link:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[Java Development Kit (JDK)].\n. Installed and working link:http://subclipse.tigris.org/[Subclipse] plugin for Eclipse.\n\n\n== JDK-1.6.0 Setup\nAfter installation JDK-1.6.0 in your operating system, run Eclipse and select Window/Preferences.\n\nimage:images/preferences-jre.png[]\n\nIn section Java/Installed JREs press *Add* button. In the new opened window enter path to installed JDK-6. In this case it is */opt/jdk1.6.0*. It also good to set name to *sun-jdk-1.6.0*.\n\nimage:images/preferences-jre-add.png[]\n\n== Subclipse Installation\nAs Eclipse doesn't contain built-in support for Subversion repositories you have to add the Subclipse plugin.  Detailed instruction for Subclipse installation is on page:\n\nlink:http://subclipse.tigris.org/install.html[subclipse.tigris.org/install.html].\n\nAlternatively you may use the link:http://marketplace.eclipse.org/marketplace-client-intro[Eclipse Marketplace Client].\n\n== Project Import\nFrom menu File in Eclipse execute *Import*. Next, highlight section *Team/Team\nProject Set* and press *Next*.\n\nimage:images/import-project.png[]\n\nEnter file name *tigase-server.psf* in field *File* and press *Finish*.\n\nThe file is attached to this article.\n\nYou will have to add and manipulate Eclipse configuration files on your own as we do not maintain those on the file repository.\n\nThat's it. Start hacking now!\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/devguide/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../../..</dist_path>\n\t\t<guide_name>Development</guide_name>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-docs-devel</artifactId>\n\t<name>Tigase XMPP Server Documentation - ${guide_name} Guide</name>\n\n\t<packaging>pom</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-docs</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t</parent>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-docbook</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.agilejava.docbkx</groupId>\n\t\t\t\t<artifactId>docbkx-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-pdf</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-webhelp</id>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-epub3</id>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>Remove *.fo file</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../..</dist_path>\n\t\t<guide_path>${dist_path}/docs/${guide_name}_Guide</guide_path>\n\t\t<guide_filename>index</guide_filename>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-docs</artifactId>\n\t<name>Tigase XMPP Server Documentation</name>\n\n\t<packaging>pom</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-master</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t\t<relativePath>../master</relativePath>\n\t</parent>\n\n\t<modules>\n\t\t<module>adminguide</module>\n\t\t<module>devguide</module>\n\t\t<module>propertiesguide</module>\n\t\t<module>userguide</module>\n\t</modules>\n\n\t<build>\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t\t<version>1.5.0</version>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>output-html</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>process-asciidoc</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<sourceHighlighter>coderay</sourceHighlighter>\n\t\t\t\t\t\t\t\t<backend>html5</backend>\n\t\t\t\t\t\t\t\t<preserveDirectories>true</preserveDirectories>\n\t\t\t\t\t\t\t\t<outputDirectory>${guide_path}/html</outputDirectory>\n\t\t\t\t\t\t\t\t<attributes>\n\t\t\t\t\t\t\t\t\t<toc>left</toc>\n\t\t\t\t\t\t\t\t\t<sectanchors>true</sectanchors>\n\t\t\t\t\t\t\t\t\t<linkcss>true</linkcss>\n\t\t\t\t\t\t\t\t\t<imagesdir>.</imagesdir>\n\t\t\t\t\t\t\t\t</attributes>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>output-docbook</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>process-asciidoc</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<preserveDirectories>true</preserveDirectories>\n\t\t\t\t\t\t\t\t<outputDirectory>${project.build.directory}/docbook/</outputDirectory>\n\t\t\t\t\t\t\t\t<backend>docbook</backend>\n\t\t\t\t\t\t\t\t<doctype>book</doctype>\n\t\t\t\t\t\t\t\t<attributes>\n\t\t\t\t\t\t\t\t\t<linkcss>true</linkcss>\n\t\t\t\t\t\t\t\t\t<imagesdir>.</imagesdir>\n\t\t\t\t\t\t\t\t</attributes>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<gemPath>gems-provided</gemPath>\n\t\t\t\t\t\t<sourceDirectory>./asciidoc</sourceDirectory>\n\t\t\t\t\t\t<sourceDocumentName>${guide_filename}.asciidoc</sourceDocumentName>\n\t\t\t\t\t\t<attributes>\n\t\t\t\t\t\t\t<endpoint-url>http://docs.tigase.org</endpoint-url>\n\t\t\t\t\t\t</attributes>\n\t\t\t\t\t\t<headerFooter>true</headerFooter>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>com.agilejava.docbkx</groupId>\n\t\t\t\t\t<artifactId>docbkx-maven-plugin</artifactId>\n\t\t\t\t\t<version>2.0.16</version>\n\t\t\t\t\t<dependencies>\n\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t<groupId>net.sf.docbook</groupId>\n\t\t\t\t\t\t\t<artifactId>docbook-xml</artifactId>\n\t\t\t\t\t\t\t<version>5.0-all</version>\n\t\t\t\t\t\t\t<classifier>resources</classifier>\n\t\t\t\t\t\t\t<type>zip</type>\n\t\t\t\t\t\t\t<scope>runtime</scope>\n\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t<groupId>net.sf.xslthl</groupId>\n\t\t\t\t\t\t\t<artifactId>xslthl</artifactId>\n\t\t\t\t\t\t\t<version>2.0.1</version>\n\t\t\t\t\t\t\t<scope>runtime</scope>\n\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t<groupId>net.sf.offo</groupId>\n\t\t\t\t\t\t\t<artifactId>fop-hyph</artifactId>\n\t\t\t\t\t\t\t<version>1.2</version>\n\t\t\t\t\t\t\t<scope>runtime</scope>\n\t\t\t\t\t\t</dependency>\n\t\t\t\t\t</dependencies>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>generate-webhelp</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>generate-webhelp</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<targetDirectory>${guide_path}/webhelp/</targetDirectory>\n\t\t\t\t\t\t\t\t<!--<imgSrcPath>../html/</imgSrcPath>-->\n\t\t\t\t\t\t\t\t<ignoreImageScaling>true</ignoreImageScaling>\n\t\t\t\t\t\t\t\t<postProcess>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/webhelp/css\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/css\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/webhelp/images\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/images\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/webhelp/files\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/files\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t</postProcess>\n\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>generate-pdf</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>generate-pdf</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<targetDirectory>${guide_path}/pdf/</targetDirectory>\n\t\t\t\t\t\t\t\t<imgSrcPath>${project.build.directory}/docbook/</imgSrcPath>\n\t\t\t\t\t\t\t\t<ignoreImageScaling>true</ignoreImageScaling>\n\t\t\t\t\t\t\t\t<fopLogLevel>OFF</fopLogLevel>\n\t\t\t\t\t\t\t\t<!--<defaultImageWidth>3cm</defaultImageWidth>-->\n\t\t\t\t\t\t\t\t<!--<ignoreImageScaling>true</ignoreImageScaling>-->\n\t\t\t\t\t\t\t\t<postProcess>\n\t\t\t\t\t\t\t\t\t<move file=\"${guide_path}/pdf/index.pdf\" tofile=\"${guide_path}/pdf/${guide_name}Guide.pdf\" failonerror=\"false\" />\n\t\t\t\t\t\t\t\t</postProcess>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>generate-html</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>generate-html</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<chunkedOutput>true</chunkedOutput>\n\t\t\t\t\t\t\t\t<targetDirectory>${guide_path}/html_chunk/</targetDirectory>\n\t\t\t\t\t\t\t\t<targetsFilename>true</targetsFilename>\n\t\t\t\t\t\t\t\t<useIdAsFilename>true</useIdAsFilename>\n\t\t\t\t\t\t\t\t<cssDecoration>true</cssDecoration>\n\t\t\t\t\t\t\t\t<annotationCss>true</annotationCss>\n\t\t\t\t\t\t\t\t<htmlStylesheet>css/docbook-xsl.css</htmlStylesheet>\n\t\t\t\t\t\t\t\t<postProcess>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/html_chunk/css\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/css\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/html_chunk/images\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/images\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${guide_path}/html_chunk/files\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/files\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t</postProcess>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>generate-epub3</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>generate-epub3</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<targetDirectory>${project.build.directory}/epub3/</targetDirectory>\n\t\t\t\t\t\t\t\t<targetsFilename>true</targetsFilename>\n\t\t\t\t\t\t\t\t<useIdAsFilename>true</useIdAsFilename>\n\t\t\t\t\t\t\t\t<cssDecoration>true</cssDecoration>\n\t\t\t\t\t\t\t\t<annotationCss>true</annotationCss>\n\t\t\t\t\t\t\t\t<preProcess>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${project.build.directory}/epub3/css\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/css\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${project.build.directory}/epub3/images\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/images\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t\t<copy todir=\"${project.build.directory}/epub3/files\">\n\t\t\t\t\t\t\t\t\t\t<fileset dir=\"asciidoc/files\"></fileset>\n\t\t\t\t\t\t\t\t\t</copy>\n\t\t\t\t\t\t\t\t</preProcess>\n\t\t\t\t\t\t\t\t<postProcess>\n\t\t\t\t\t\t\t\t\t<move file=\"${project.build.directory}/index.epub\"\n\t\t\t\t\t\t\t\t\t\t\t\ttofile=\"${guide_path}/epub/${guide_name}Guide.epub\"\n\t\t\t\t\t\t\t\t\t\t\t\tfailonerror=\"false\" />\n\t\t\t\t\t\t\t\t</postProcess>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<chunkedOutput>true</chunkedOutput>\n\t\t\t\t\t\t<sourceDirectory>${project.build.directory}/docbook/</sourceDirectory>\n\t\t\t\t\t\t<includes>${guide_filename}.xml</includes>\n\t\t\t\t\t\t<!--<imgSrcPath>../html/</imgSrcPath>-->\n\t\t\t\t\t\t<highlightSource>1</highlightSource>\n\t\t\t\t\t\t<!--<foCustomization>src/docbkx/docbook-fo.xsl</foCustomization>-->\n\t\t\t\t\t\t<hyphenate>true</hyphenate>\n\t\t\t\t\t\t<hyphenateVerbatim>true</hyphenateVerbatim>\n\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\n\t\t\t\t<plugin>\n\t\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t\t<version>2.6</version>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>Remove *.fo file</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>clean</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<filesets>\n\t\t\t\t\t\t\t<fileset>\n\t\t\t\t\t\t\t\t<directory>${guide_path}/pdf/</directory>\n\t\t\t\t\t\t\t\t<followSymlinks>false</followSymlinks>\n\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t<include>*.fo</include>\n\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t</fileset>\n\t\t\t\t\t\t</filesets>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<version>2.6</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>Remove docs</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>clean</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<filesets>\n\t\t\t\t\t\t\t\t<fileset>\n\t\t\t\t\t\t\t\t\t<directory>${guide_path}</directory>\n\t\t\t\t\t\t\t\t\t<followSymlinks>false</followSymlinks>\n\t\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t\t<include>**/*</include>\n\t\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t\t</fileset>\n\t\t\t\t\t\t\t</filesets>\n\t\t\t\t\t\t\t<!--<verbose>true</verbose>-->\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<version>2.8.2</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<pluginRepositories>\n\t\t<pluginRepository>\n\t\t\t<id>sonatype.snapshots</id>\n\t\t\t<name>Maven Plugin Snapshots</name>\n\t\t\t<url>https://oss.sonatype.org/content/repositories/snapshots/</url>\n\t\t\t<releases>\n\t\t\t\t<enabled>false</enabled>\n\t\t\t</releases>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t</snapshots>\n\t\t</pluginRepository>\n\t</pluginRepositories>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/css/docbook-xsl.css",
    "content": "/*\n  CSS stylesheet for XHTML produced by DocBook XSL stylesheets.\n*/\n\nbody {\n  font-family: Georgia,serif;\n}\n\ncode, pre {\n  font-family: \"Courier New\", Courier, monospace;\n}\n\nspan.strong {\n  font-weight: bold;\n}\n\nbody blockquote {\n  margin-top: .75em;\n  line-height: 1.5;\n  margin-bottom: .75em;\n}\n\nhtml body {\n  margin: 1em 5% 1em 5%;\n  line-height: 1.2;\n}\n\nbody div {\n  margin: 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\n\ndiv.toc p:first-child,\ndiv.list-of-figures p:first-child,\ndiv.list-of-tables p:first-child,\ndiv.list-of-examples p:first-child,\ndiv.example p.title,\ndiv.sidebar p.title\n{\n  font-weight: bold;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n  margin-bottom: 0.2em;\n}\n\nbody h1 {\n  margin: .0em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h2 {\n  margin: 0.5em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h3 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h4 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h5 {\n  margin: .8em 0 0 -2%;\n  line-height: 1.3;\n}\n\nbody h6 {\n  margin: .8em 0 0 -1%;\n  line-height: 1.3;\n}\n\nbody hr {\n  border: none; /* Broken on IE6 */\n}\ndiv.footnotes hr {\n  border: 1px solid silver;\n}\n\ndiv.navheader th, div.navheader td, div.navfooter td {\n  font-family: Arial,Helvetica,sans-serif;\n  font-size: 0.9em;\n  font-weight: bold;\n  color: #527bbd;\n}\ndiv.navheader img, div.navfooter img {\n  border-style: none;\n}\ndiv.navheader a, div.navfooter a {\n  font-weight: normal;\n}\ndiv.navfooter hr {\n  border: 1px solid silver;\n}\n\nbody td {\n  line-height: 1.2\n}\n\nbody th {\n  line-height: 1.2;\n}\n\nol {\n  line-height: 1.2;\n}\n\nul, body dir, body menu {\n  line-height: 1.2;\n}\n\nhtml {\n  margin: 0; \n  padding: 0;\n}\n\nbody h1, body h2, body h3, body h4, body h5, body h6 {\n  margin-left: 0\n} \n\nbody pre {\n  margin: 0.5em 10% 0.5em 1em;\n  line-height: 1.0;\n  color: navy;\n}\n\ntt.literal, code.literal {\n  color: navy;\n}\n\n.programlisting, .screen {\n  border: 1px solid silver;\n  background: #f4f4f4;\n  margin: 0.5em 10% 0.5em 0;\n  padding: 0.5em 1em;\n}\n\ndiv.sidebar {\n  background: #ffffee;\n  margin: 1.0em 10% 0.5em 0;\n  padding: 0.5em 1em;\n  border: 1px solid silver;\n}\ndiv.sidebar * { padding: 0; }\ndiv.sidebar div { margin: 0; }\ndiv.sidebar p.title {\n  margin-top: 0.5em;\n  margin-bottom: 0.2em;\n}\n\ndiv.bibliomixed {\n  margin: 0.5em 5% 0.5em 1em;\n}\n\ndiv.glossary dt {\n  font-weight: bold;\n}\ndiv.glossary dd p {\n  margin-top: 0.2em;\n}\n\ndl {\n  margin: .8em 0;\n  line-height: 1.2;\n}\n\ndt {\n  margin-top: 0.5em;\n}\n\ndt span.term {\n  font-style: normal;\n  color: navy;\n}\n\ndiv.variablelist dd p {\n  margin-top: 0;\n}\n\ndiv.itemizedlist li, div.orderedlist li {\n  margin-left: -0.8em;\n  margin-top: 0.5em;\n}\n\nul, ol {\n    list-style-position: outside;\n}\n\ndiv.sidebar ul, div.sidebar ol {\n    margin-left: 2.8em;\n}\n\ndiv.itemizedlist p.title,\ndiv.orderedlist p.title,\ndiv.variablelist p.title\n{\n  margin-bottom: -0.8em;\n}\n\ndiv.revhistory table {\n  border-collapse: collapse;\n  border: none;\n}\ndiv.revhistory th {\n  border: none;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\ndiv.revhistory td {\n  border: 1px solid silver;\n}\n\n/* Keep TOC and index lines close together. */\ndiv.toc dl, div.toc dt,\ndiv.list-of-figures dl, div.list-of-figures dt,\ndiv.list-of-tables dl, div.list-of-tables dt,\ndiv.indexdiv dl, div.indexdiv dt\n{\n  line-height: normal;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n/*\n  Table styling does not work because of overriding attributes in\n  generated HTML.\n*/\ndiv.table table,\ndiv.informaltable table\n{\n    margin-left: 0;\n    margin-right: 5%;\n    margin-bottom: 0.8em;\n}\ndiv.informaltable table\n{\n    margin-top: 0.4em\n}\ndiv.table thead,\ndiv.table tfoot,\ndiv.table tbody,\ndiv.informaltable thead,\ndiv.informaltable tfoot,\ndiv.informaltable tbody\n{\n    /* No effect in IE6. */\n    border-top: 3px solid #527bbd;\n    border-bottom: 3px solid #527bbd;\n}\ndiv.table thead, div.table tfoot,\ndiv.informaltable thead, div.informaltable tfoot\n{\n    font-weight: bold;\n}\n\ndiv.mediaobject img {\n    margin-bottom: 0.8em;\n}\ndiv.figure p.title,\ndiv.table p.title\n{\n  margin-top: 1em;\n  margin-bottom: 0.4em;\n}\n\ndiv.calloutlist p\n{\n  margin-top: 0em;\n  margin-bottom: 0.4em;\n}\n\na img {\n  border-style: none;\n}\n\n@media print {\n  div.navheader, div.navfooter { display: none; }\n}\n\nspan.aqua { color: aqua; }\nspan.black { color: black; }\nspan.blue { color: blue; }\nspan.fuchsia { color: fuchsia; }\nspan.gray { color: gray; }\nspan.green { color: green; }\nspan.lime { color: lime; }\nspan.maroon { color: maroon; }\nspan.navy { color: navy; }\nspan.olive { color: olive; }\nspan.purple { color: purple; }\nspan.red { color: red; }\nspan.silver { color: silver; }\nspan.teal { color: teal; }\nspan.white { color: white; }\nspan.yellow { color: yellow; }\n\nspan.aqua-background { background: aqua; }\nspan.black-background { background: black; }\nspan.blue-background { background: blue; }\nspan.fuchsia-background { background: fuchsia; }\nspan.gray-background { background: gray; }\nspan.green-background { background: green; }\nspan.lime-background { background: lime; }\nspan.maroon-background { background: maroon; }\nspan.navy-background { background: navy; }\nspan.olive-background { background: olive; }\nspan.purple-background { background: purple; }\nspan.red-background { background: red; }\nspan.silver-background { background: silver; }\nspan.teal-background { background: teal; }\nspan.white-background { background: white; }\nspan.yellow-background { background: yellow; }\n\nspan.big { font-size: 2em; }\nspan.small { font-size: 0.6em; }\n\nspan.underline { text-decoration: underline; }\nspan.overline { text-decoration: overline; }\nspan.line-through { text-decoration: line-through; }\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/files/.gitignore",
    "content": "# Placeholder"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/images/.gitignore",
    "content": "# Placeholder"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/index.asciidoc",
    "content": "[[propertiesGuide]]\n= Tigase Properties Guide\n:toc:\n:numbered:\n\n:leveloffset: 1\n\ninclude::text/Properties_Guide_01_-_--admins.asciidoc[]\n\ninclude::text/Properties_Guide_02_-_--auth-db.asciidoc[]\n\ninclude::text/Properties_Guide_03_-_--auth-db-uri.asciidoc[]\n\ninclude::text/Properties_Guide_04_-_--auth-domain-repo-pool.asciidoc[]\n\ninclude::text/Properties_Guide_05_-_--auth-repo-pool.asciidoc[]\n\ninclude::text/Properties_Guide_06_-_--auth-repo-pool-size.asciidoc[]\n\ninclude::text/Properties_Guide_07_-_--bind-ext-hostnames.asciidoc[]\n\ninclude::text/Properties_Guide_08_-_--bosh-close-connection.asciidoc[]\n\ninclude::text/Properties_Guide_09_-_--bosh-extra-headers-file.asciidoc[]\n\ninclude::text/Properties_Guide_10_-_--cl-conn-repo-class.asciidoc[]\n\ninclude::text/Properties_Guide_11_-_--client-access-policy-file.asciidoc[]\n\ninclude::text/Properties_Guide_12_-_--cluster-connect-all.asciidoc[]\n\ninclude::text/Properties_Guide_13_-_--cluster-mode.asciidoc[]\n\ninclude::text/Properties_Guide_14_-_--cluster-nodes.asciidoc[]\n\ninclude::text/Properties_Guide_15_-_--cm-ht-traffic-throttling.asciidoc[]\n\ninclude::text/Properties_Guide_16_-_--cm-see-other-host.asciidoc[]\n\ninclude::text/Properties_Guide_17_-_--cm-traffic-throttling.asciidoc[]\n\ninclude::text/Properties_Guide_18_-_--cmpname-ports.asciidoc[]\n\ninclude::text/Properties_Guide_19_-_--comp-class.asciidoc[]\n\ninclude::text/Properties_Guide_20_-_--comp-name.asciidoc[]\n\ninclude::text/Properties_Guide_21_-_--cross-domain-policy-file.asciidoc[]\n\ninclude::text/Properties_Guide_22_-_--data-repo-pool-size.asciidoc[]\n\ninclude::text/Properties_Guide_23_-_--debug.asciidoc[]\n\ninclude::text/Properties_Guide_24_-_--debug-packages.asciidoc[]\n\ninclude::text/Properties_Guide_25_-_--domain-filter-policy.asciidoc[]\n\ninclude::text/Properties_Guide_26_-_--elements-number-limit.asciidoc[]\n\ninclude::text/Properties_Guide_27_-_--ext-comp.asciidoc[]\n\ninclude::text/Properties_Guide_28_-_--extcomp-repo-class.asciidoc[]\n\ninclude::text/Properties_Guide_29_-_--external.asciidoc[]\n\ninclude::text/Properties_Guide_30_-_--hardened-mode.asciidoc[]\n\ninclude::text/Properties_Guide_31_-_--max-queue-size.asciidoc[]\n\ninclude::text/Properties_Guide_32_-_--monitoring.asciidoc[]\n\ninclude::text/Properties_Guide_33_-_--net-buff-high-throughput.asciidoc[]\n\ninclude::text/Properties_Guide_34_-_--net-buff-standard.asciidoc[]\n\ninclude::text/Properties_Guide_35_-_--new-connections-throttling.asciidoc[]\n\ninclude::text/Properties_Guide_36_-_--nonpriority-queue.asciidoc[]\n\ninclude::text/Properties_Guide_37_-_--queue-implementation.asciidoc[]\n\ninclude::text/Properties_Guide_38_-_--roster-implementation.asciidoc[]\n\ninclude::text/Properties_Guide_39_-_--s2s-ejabberd-bug-workaround-active.asciidoc[]\n\ninclude::text/Properties_Guide_40_-_--s2s-secret.asciidoc[]\n\ninclude::text/Properties_Guide_41_-_--s2s-skip-tls-hostnames.asciidoc[]\n\ninclude::text/Properties_Guide_42_-_--script-dir.asciidoc[]\n\ninclude::text/Properties_Guide_43_-_--sm-cluster-strategy-class.asciidoc[]\n\ninclude::text/Properties_Guide_44_-_--sm-plugins.asciidoc[]\n\ninclude::text/Properties_Guide_45_-_--sm-threads-pool.asciidoc[]\n\ninclude::text/Properties_Guide_46_-_--ssl-certs-location.asciidoc[]\n\ninclude::text/Properties_Guide_47_-_--ssl-container-class.asciidoc[]\n\ninclude::text/Properties_Guide_48_-_--ssl-def-cert-domain.asciidoc[]\n\ninclude::text/Properties_Guide_49_-_--stats-archiv.asciidoc[]\n\ninclude::text/Properties_Guide_50_-_--stats-history.asciidoc[]\n\ninclude::text/Properties_Guide_51_-_--stringprep-processor.asciidoc[]\n\ninclude::text/Properties_Guide_52_-_--test.asciidoc[]\n\ninclude::text/Properties_Guide_53_-_--tigase-config-repo-class.asciidoc[]\n\ninclude::text/Properties_Guide_54_-_--tigase-config-repo-uri.asciidoc[]\n\ninclude::text/Properties_Guide_55_-_--tls-jdk-nss-bug-workaround-active.asciidoc[]\n\ninclude::text/Properties_Guide_56_-_--trusted.asciidoc[]\n\ninclude::text/Properties_Guide_57_-_--user-db.asciidoc[]\n\ninclude::text/Properties_Guide_58_-_--user-db-uri.asciidoc[]\n\ninclude::text/Properties_Guide_59_-_--user-domain-repo-pool.asciidoc[]\n\ninclude::text/Properties_Guide_60_-_--user-repo-pool.asciidoc[]\n\ninclude::text/Properties_Guide_61_-_--user-repo-pool-size.asciidoc[]\n\ninclude::text/Properties_Guide_62_-_--vhost-anonymous-enabled.asciidoc[]\n\ninclude::text/Properties_Guide_63_-_--vhost-disable-dns-check.asciidoc[]\n\ninclude::text/Properties_Guide_64_-_--vhost-max-users.asciidoc[]\n\ninclude::text/Properties_Guide_65_-_--vhost-message-forward-jid.asciidoc[]\n\ninclude::text/Properties_Guide_66_-_--vhost-presence-forward-jid.asciidoc[]\n\ninclude::text/Properties_Guide_67_-_--vhost-register-enabled.asciidoc[]\n\ninclude::text/Properties_Guide_68_-_--vhost-tls-required.asciidoc[]\n\ninclude::text/Properties_Guide_69_-_--virt-hosts.asciidoc[]\n\ninclude::text/Properties_Guide_70_-_--watchdog_delay.asciidoc[]\n\ninclude::text/Properties_Guide_71_-_--watchdog_ping_type.asciidoc[]\n\ninclude::text/Properties_Guide_72_-_--watchdog_timeout.asciidoc[]\n\ninclude::text/Properties_Guide_74_-_--ws-allow-unmasked-frames.asciidoc[]\n\ninclude::text/Properties_Guide_73_-_-config-type.asciidoc[]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_01_-_--admins.asciidoc",
    "content": "[[admins]]\n= --admins\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 07:42\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* none\n\n*Example:* +--admins = admin@domain.com+\n\n*Possible values:* +user1@domain,user2@domain2+\n\n*Description:* 'Specifies a list of administrator accounts.'\n\n*Possible values:* list of admin accounts: +user1@domain,user2@domain2+\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_02_-_--auth-db.asciidoc",
    "content": "[[authDb]]\n= --auth-db\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 07:50\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase-custom+\n\n*Example:* +--auth-db = db-type+\n\n*Possible values:* +mysql|pgsql|ldap|drupal|tigase-auth|tigase-custom|class name+\n\n*Description:* Specifies authentication repository, where +db-type+ can be one of possible values: +mysql, pgsql, drupal, wp, tigase-auth+ and +tigase-custom+ (if omitted: +user-db+ is used in versions up to 5.0 and +tigase-custom+ is the new default value starting from version 5.1 ) or the class name. For SQL database this is normally: +tigase.db.jdbc.JDBCRepository+.\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_03_-_--auth-db-uri.asciidoc",
    "content": "[[authDbUri]]\n= --auth-db-uri\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 20:55\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass+\n\n*Example:* +--auth-db-uri = jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass+\n\n*Possible values:* +db connection-uri+.\n\n*Description:* +connection-uri+ is a full resource uri for user repository data source. (If omitted xref:userDbUri[+user-db-uri+] settings are used.)\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_04_-_--auth-domain-repo-pool.asciidoc",
    "content": "[[authDomainRepoPool]]\n= --auth-domain-repo-pool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:01\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.db.AuthRepositoryMDImpl+\n\n*Example:* +--auth-domain-repo-pool = tigase.db.AuthRepositoryMDImpl+\n\n*Possible values:* 'class implementing AuthRepository.'\n\n*Description:* Allows to specify an implementation for per-domain +AuthRepository+ implementation. This is used only if the implementation provided by a default Tigase server package is not sufficient in the particular deployment. The implementation provides a DB (AuthRepository to be more specific) connection pool where each connection (AuthRepository) handles data for a different DNS domain (VHost). This allows for database (user data) sharing to improve the system performance and better balance the load.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_05_-_--auth-repo-pool.asciidoc",
    "content": "[[authRepoPool]]\n= --auth-repo-pool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 20:59\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.db.AuthRepositoryPool+\n\n*Example:* +--auth-repo-pool = tigase.db.AuthRepositoryPool+\n\n*Possible values:* 'class implementing AuthRepository.'\n\n*Description:* Allows you to specify an implementation for the authentication repository connection pool. This is used only if the implementation provided by a default Tigase server package is not sufficient in a deployment. The implementation provides a DB (AuthRepository to be more specific) connection pool to improve the data access performance. The repository pool can offer data caching for improved performance or any other features necessary.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_06_-_--auth-repo-pool-size.asciidoc",
    "content": "[[authRepoPoolSize]]\n= --auth-repo-pool-size\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-05-28 04:24\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +10+\n\n*Example:* +--auth-repo-pool-size = 25+\n\n*Possible values:* 'Number of db connections as integer.'\n\n*Description:* The property allows to set the database connections pool size for the AuthRepository.\n*Please note* if this value is not specified, there are some cases where instead of a default for this property, the setting for --data-repo-pool-size can be used. This depends on the repository implementation and the way it is initialized.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_07_-_--bind-ext-hostnames.asciidoc",
    "content": "[[bindExtHostnames]]\n= --bind-ext-hostnames\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:06\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* none\n\n*Example:* +--bind-ext-hostnames = pubsub.host.domain+\n\n*Possible values:* 'comma separated list of domains.'\n\n*Description:* This property enables setting a list of domains to be bound to the external component connection. Let's say we have a Tigase instance with only MUC and PubSub components loaded and we want to connect this instance to the main server via external component protocol. Using xref:external[--external property] we can define a domain (perhaps muc.devel.tigase.org), password, TCP/IP port, remote host address, connection type, etc... This would make one of our components (MUC) visible on the remote server.\n\nTo make the second component (PubSub) visible we would need to open another connection with the domain name (pubsub.devel.tigase.org) for the other component. Of course the second connection is redundant as all communication could go through a single connection. This is what this property is used. In our example with 2 components you can just put the 'pubsub.devel.tigase.org' domain as a value to this property and it will bind the second domain to a single connection on top of the domain which has been authenticated during protocol handshaking.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_08_-_--bosh-close-connection.asciidoc",
    "content": "[[boshCloseConnection]]\n= --bosh-close-connection\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-20 00:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--bosh-close-connection = true+\n\n*Possible values:* +true|false+\n\n*Description:* This property globally disables Bosh keep-alive support for Tigase server. It causes the Bosh connection manager to force close the HTTP connection each time data is sent to the Bosh client. To continue communication the client must open a new HTTP connection.\n\nThis setting is rarely required but on installations where the client cannot control/disable keep-alive Bosh connections and keep-alive does not work correctly for some reason.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_09_-_--bosh-extra-headers-file.asciidoc",
    "content": "[[boshExtraHeadersFile]]\n= --bosh-extra-headers-file\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-20 01:00\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +etc/bosh-extra-headers.txt+\n\n*Example:* +--bosh-extra-headers-file = /path/to/file.txt+\n\n*Possible values:* 'path to a file on the filesystem.'\n\n*Description:* This property allows you to specify a path to a text file with additional HTTP headers which will be sent to a Bosh client with each request. This gives some extra flexibility for Bosh clients running on some systems with special requirements for the HTTP headers and some additional settings.\n\nBy default a file distributed with the installation contains following content:\n\n[source,bash]\n-----\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: GET, POST, OPTIONS\nAccess-Control-Allow-Headers: Content-Type\nAccess-Control-Max-Age: 86400\n-----\n\nThis can be modified, removed or replaced with a different content on your installation.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_10_-_--cl-conn-repo-class.asciidoc",
    "content": "[[clConnRepoClass]]\n= --cl-conn-repo-class\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-28 14:02\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.cluster.repo.ClConSQLRepository+\n\n*Example:* +--cl-conn-repo-class = tigase.cluster.repo.ClConDirRepository+\n\n*Possible values:* 'class implementing ComponentRepository.'\n\n*Description:* This property allows setting of the class controlling cluster connections repository. The cluster connections repository is responsible for discovering cluster nodes which are part of the installation. Tigase in cluster mode establishes TCP/IP connections between cluster nodes to allow for user communication and exchanging cluster state metadata.\n\nFrom Tigase XMPP Server version 5.2.0 the server supports cluster auto-configuration so no action, configuring, or any maintenance action is required to add a new cluster node.\n\nAs everything in Tigase, it is also a pluggable system so it is possible to implement/add new ways to synchronize information about cluster nodes on the system. Currently following cluster connection repositories are implemented:\n\n. *ClConSQLRepository* a default implementation which synchronizes cluster nodes information through SQL database. By default it uses the same database as the main Tigase DB, that is the UserRepository database. All the cluster nodes need an access to the same database for cluster nodes information synchronization.\n\n*For backward compatibility this mode reads the list of the cluster nodes from a configuration file (+init.properties+) as well. However, this is used only as an initial setup and, after startup time the cluster nodes are synchronized through the database.*\n\nIt is recommended however, that the xref:clusterNode[--cluster-nodes] property is not used (should be removed or commented out) when the automatic reconfiguration mode is used. This is because we found out that when the network configuration and DNS names are not perfect than automatic mode may conflict with manual settings.\n\nBy default the same database as for the user repository is used for the cluster automatic cluster mode but, a different, separate database can be used as well. A DB URI for a different SQL database can be set using following configuration property:\n\n[source,bash]\n-----\ncl-comp/repo-uri=jdbc:mysql://localhost/tigasedb?user=user&password=mypass\n-----\n. *ClConDirRepository* an alternative way to synchronize information about cluster nodes on the installation through filesystem. This might be used in case where DB is not accessible by the clustering code for some reason or synchronization through DB is not desired.\nTo make use of the filesystem based cluster nodes synchronization you need to mount a directory via some network filesystem mechanism (like NFS for example) and point Tigase to the directory. The rest works the same way as through the DB. However, instead of writing cluster node metadata to some DB table, each node writes it's metadata to a separate file in the given directory.\nThis mode is also compatible with the manual nodes configuration through --cluster-nodes but the same precautions and suggestions as for DB based automatic node hold.\n+\nA default location of the directory is probably not very useful, as it points to etc/ directory, therefore, normally a correct location has to be set through the repo-uri property in a following way:\n+\n[source,bash]\n-----\ncl-comp/repo-uri=/mount/tigase-cluster-repo\n-----\n. *ClConConfigRepository* is an implementation which allows you to revert back to the previous and manual cluster configuration through cluster nodes. However, since version *5.2.0*  xref:clusterNodes[+--cluster-nodes+] has been extended with ability to set password and port number for each cluster node.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_11_-_--client-access-policy-file.asciidoc",
    "content": "[[clientAccessPolicyFile]]\n= --client-access-policy-file\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-20 01:09\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +etc/client-access-policy.xml+\n\n*Example:* +--client-access-policy-file = /path/to/access-policy-file.xml+\n\n*Possible values:* 'path to a file on the filesystem.'\n\n*Description:* The --client-access-policy-file property allows control of the cross domain access policy for Silverlight based web applications. The cross domain policy is controlled via XML file which contains the policy and rules.\n\nBy default Tigase is distributed with an example policy file which allows for full access from all sources to the whole installation. This is generally okay for most Bosh server installations. The configuration through the property and XML files allows for a very easy and flexible modification of the policy on any installation.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_12_-_--cluster-connect-all.asciidoc",
    "content": "[[clusterConnectAll]]\n= --cluster-connect-all\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:25\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--cluster-connect-all = true+\n\n*Possible values:* +true|false+\n\n*Description:* The --cluster-connect-all property is used to open active connections to all nodes listed in the xref:clusterNodes[+--cluster-nodes+] configuration property. This property should be used only on the node which is added to the live cluster at later time. Normally this new cluster node is not listed in the configuration of the existing cluster nodes. This is why they can not open connections the new node. The new node opens connection to all existing nodes instead. False is the default value and you can skip this option if you want to have it switched off.\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_13_-_--cluster-mode.asciidoc",
    "content": "[[clusterMode]]\n= --cluster-mode\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:27\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--cluster-mode = true+\n\n*Possible values:* +true|false+\n\n*Description:* The property is used to switch cluster mode on. The default value is 'false' so you can normally skip the parameter if you don't want the server to run in the cluster mode. You can run the server in the cluster mode even if there is only one node running. The performance impact is insignificant and you will have the opportunity to connect mode cluster nodes at any time without restarting the server.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_14_-_--cluster-nodes.asciidoc",
    "content": "[[clusterNodes]]\n= --cluster-nodes\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:30\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* none\n\n*Example:* +--cluster-nodes = node1.domain,node2.domain,node3.domain+\n\n*Possible values:* 'a comma separated list of hostnames.'\n\n*Description:* The property is used to specify a list of cluster nodes running on your installation.\nThe node is the full DNS name of the machine running the node. Please note the proper DNS configuration is critical for the cluster to work correctly. Make sure the 'hostname' command returns a full DNS name on each cluster node. Nodes don't have to be in the same network although good network connectivity is also a critical element for an effective cluster performance.\n\n[source,bash]\n-----\n--cluster-nodes=host-a.domain.com:pass:port,host-b.domain.com:pass:port,host-c.domain.com:pass:port\n-----\n\nAll cluster nodes must be connected with each other to maintain user session synchronization and exchange packets between users connected to different nodes. Therefore each cluster node opens a 'cluster port' on which it is listening for connections from different cluster nodes. As there is only one connection between each two nodes Tigase server has to decide which nodes to connect to and which has to accept the connection. If you put the same list of cluster nodes in the configuration for all nodes this is not a problem. Tigase server has a way to find and void any conflicts that are found. If you however want to add a new node later on, without restarting and changing configuration on old nodes, there is no way the old nodes will try to establish a connection to the new node they don't know them. To solve this particular case the next parameter is used.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_15_-_--cm-ht-traffic-throttling.asciidoc",
    "content": "[[cmHtTrafficThrottling]]\n= --cm-ht-traffic-throttling\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:38\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +xmpp:25k:0:disc,bin:200m:0:disc+\n\n*Example:* +--cm-ht-traffic-throttling = xmpp:25k:0:disc,bin:200m:0:disc+\n\n*Possible values:* 'comma separated list of traffic limits settings.'\n\n*Description:* This property is used to specify traffic limit of non-user connections, that is s2s, external components and other high traffic server connections. The meaning of the property and values encoded are in the same way as for the xref:cmTrafficThrottling[--cm-traffic-throttling property].\n\n*Available since:* 5.1.3\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_16_-_--cm-see-other-host.asciidoc",
    "content": "[[cmSeeOtherHost]]\n= --cm-see-other-host\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-06-11 10:12\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.server.xmppclient.SeeOtherHostHashed+\n\n*Example:* +--cm-see-other-host=tigase.server.xmppclient.SeeOtherHostHashed+\n\n*Possible values:* ''none'' 'or class implementing SeeOtherHostIfc.'\n\n*Description:* Allows you to specify a load balancing mechanism by specifying SeeOtherHostIfc implementation. More details about functionality and implementation details can be found in Tigase Load Balancing documentation.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_17_-_--cm-traffic-throttling.asciidoc",
    "content": "[[cmTrafficThrottling]]\n= --cm-traffic-throttling\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:35\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +xmpp:2500:0:disc,bin:20m:0:disc+\n\n*Example:* +--cm-traffic-throttling = xmpp:2500:0:disc,bin:20m:0:disc+\n\n*Possible values:* 'comma separated list of traffic limits settings.'\n\n*Description:* The --cm-traffic-throttling property allows you to limit traffic on user connections. These limits are applied to each user connection and if a limit is exceeded then a specified action is applied.\n\nThe property value is a comma separated list of traffic limits settings. For example the first part: +xmpp:2500:0:disc+ specifies traffic limits for XMPP data to 2,500 packets allowed within last minute either sent to or received from a user and unlimited (0) total traffic on the user connection, in case any limit is exceeded the action is to *disconnect* the user.\n\n- *[xmpp|bin]* traffic type, xmpp - XMPP traffic, that is limits refer to a number of XMPP packets transmitted, bin - binary traffic, that is limits refer to a number of bytes transmitted.\n- *2500* maximum traffic allowed within 1 minute. 0 means unlimited, or no limits.\n- *0* maximum traffic allowed for the life span of the connection. 0 means unlimited or no limits.\n- *[disc|drop]* action performed on the connection if limits are exceeded. disc - means disconnect, drop - means drop data.\n\n*Available since:* 5.1.3\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_18_-_--cmpname-ports.asciidoc",
    "content": "[[cmpnamePorts]]\n= --cmpname-ports\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:42\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'depends on component.'\n\n*Example:* +--s2s-ports=5269,5270,5271+\n\n*Possible values:* 'comma separate list of TCP/IP port numbers.'\n\n*Description:* The --cmpname-ports property is used to set a ports list for a connection manager. 'cmpname' is a component name of the connection manager you want to change ports numbers for. 'list of ports' is a comma separated list of ports numbers. For example for the server to server connection manager named s2s the property would like like the example below:\n\n[source,bash]\n-----\n--s2s-ports=5269,5270,5271\n-----\n\n*Available since:* 3.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_19_-_--comp-class.asciidoc",
    "content": "[[compClass]]\n= --comp-class\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'depends on component.'\n\n*Example:* +--comp-class-1 = tigase.muc.MUCComponent+\n\n*Possible values:* 'class name.'\n\n*Description:* This property is used to load an extra component to the server.  Normally this parameter is used if you want to load a component which is not included in the +config-type+ you use. You can, of course, load more than just one component using parameters: +--comp-class-2+, +--comp-class-3+ and so on....\nLet's say you want to load the MUC component and the class name for the component is: +tigase.muc.MUCService+. The line in the properties file should look like:\n\n[source,bash]\n-----\n--comp-class-1 = tigase.muc.MUCComponent\n-----\n\n*Available since:* 3.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_20_-_--comp-name.asciidoc",
    "content": "[[compName]]\n= --comp-name\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:54\n:version: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'custom string.'\n\n*Example:* +--comp-name-1 = muc+\n\n*Possible values:* 'XMPP localnode string.'\n\n*Description:* The --comp-name property is used to assign name 'name' to the non-standard component which is loaded by the server. It is normally used when you want to load components which are not loaded by the +config-type+ you use. Together with +--comp-class-1+ it allows you to load any extra component to your server configuration. Of course you can load more than just one component, just use +--comp-name-2+, +--comp-name-3+ and so on... Let's say you want to load the MUC component. You can then put give it a name: +muc+ and the setting would look like:\n\n[source,bash]\n-----\n--comp-name-1 = muc\n-----\n\n*Available since:* 3.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_21_-_--cross-domain-policy-file.asciidoc",
    "content": "[[crossDomainPolicyFile]]\n= --cross-domain-policy-file\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-20 01:14\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +etc/cross-domain-policy.xml+\n\n*Example:* +--cross-domain-policy-file = /path/to/cross-domain-policy.xml+\n\n*Possible values:* 'path to a file on the filesystem.'\n\n*Description:* This property allows you to set a path to a file with cross domain access policy for flash based clients. This is a standard XML file which is sent to the flash client upon request.\n\nA default file distributed with Tigase installations allows for full access for all. This is good enough for most use cases but it can be changed by simply editing the file.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_22_-_--data-repo-pool-size.asciidoc",
    "content": "[[dataRepoPoolSize]]\n= --data-repo-pool-size\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-05-28 04:19\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +10+\n\n*Example:* +--data-repo-pool-size = 25+\n\n*Possible values:* 'Number of db connections as integer.'\n\n*Description:* +DataRepository+ is an abstraction layer between any higher level data access repositories such as +UserRepository+ or +AuthRepository+ and SQL database or JDBC driver to be more specific. Many implementations use +DataRepository+ for DB connections and in fact on many installations they also share the same DataRepository instance if they connect to the same DB. In this case it is desired to use a specific connection pool on this level to an avoid excessive number of connections to the database.\n\nIt recommended to control the number of DB connections using this property rather than xref:userRepoPoolSize[--user-repo-pool-size] or xref:authRepoPoolSize[--auth-repo-pool-size].\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_23_-_--debug.asciidoc",
    "content": "[[debug]]\n= --debug\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 21:57\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--debug = server,xmpp.impl+\n\n*Possible values:* 'comma separated list of Tigase\\'s package names.'\n\n*Description:* The +--debug+ property is used to turn on the debug log for the selected Tigase package. For example if you want to turn debug logs on for the +tigase.server+ package, then you have to use the +--debug server+ parameter. If you have any problems with your server the best way to get help from the Tigase team is to generate configuration with '--debug = server' and run the server. Then from the +logs/tigase-console.log+ log file I can provide the best information for us to provide assistance. More details about server logging and adjusting logging level is described in the Debugging Tigase article in the admin guide.\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_24_-_--debug-packages.asciidoc",
    "content": "[[debugPackages]]\n= --debug-packages\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:00\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--debug-packages = com.company.CustomPlugin,com.company.custom+\n\n*Possible values:* 'comma separated list of Java packages or classes.'\n\n*Description:* This property is used to turn debugging on for any package not located within the default Tigase packages.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_25_-_--domain-filter-policy.asciidoc",
    "content": "[[domainFilterPolicy]]\n= --domain-filter-policy\n:author: not known\n:version: v1.0 initial release\n:date: 2015-07-15 17:08\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n*Default value:* +ALL+\n\n*Example:* +--domain-filter-policy = LOCAL+\n\n*Possible values:* +ALL|LOCAL|OWN|BLOCK|LIST=domain1;domain2|BLACKLIST=domain1;domain2+\n\n*Description:* The +--domain-filter-policy+ property is a global setting for setting communication filtering for vhosts. This function is kind of an extension of the same property which could be set on a single user level. However, in many cases it is desired to control users communication not on per user-level but on the domain level. Domain filtering (communication filtering) allows you to specify with whom users can communicate for a particular domain. It enables restriction of communications for a selected domain or for the entire installation. A default value +ALL+ renders users for the domain (by default for all domains) able to communicate with any user on any other domains. Other possible values are:\n\n. `ALL` a default value allowing users to communicate with anybody on any other domain, including external servers.\n. `LOCAL` allows users to communicate with all users on the same installation on any domain. It only blocks communication with external servers.\n. `OWN` allows users to communicate with all other users on the same domain. Plus it allows users to communicate with subdomains such as *muc.domain*, *pubsub.domain*, etc…\n. `BLOCK` value completely blocks communication for the domain or for the user with anybody else. This could be used as a means to temporarily disable account or domain.\n. `LIST` property allows to set a list of domains (users' JIDs) with which users on the domain can communicate (i.e. _whitelist_).\n. `BLACKLIST` - user can communicate with everybody (like `ALL`), except contacts on listed domains.\n\nThis is a global property which is overridden by settings for particular vhosts and settings for particular users.\n\nA default settings for all virtual hosts for which the configuration is not defined. This settings is useful mostly for installations with many virtual hosts listed in the init.property file for which there is no individual settings specified. It allows default value for all of servers, instead of having to provide individual configuration for each vhost.\n\n+ALL+ is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_26_-_--elements-number-limit.asciidoc",
    "content": "[[elementsNumberLimit]]\n= --elements-number-limit\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-11-27 10:48\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +1000+\n\n*Example:* +--elements-number-limit=20000+\n\n*Possible values:* 'any integer.'\n\n*Description:* +elements-number-limit+ configuration property allows configuring a Denial of Service protection mechanism which limits number of elements sent in stanza. It can be configured on a per ConnectionManager basis with the following configuration:\n\n[source,bash]\n-----\n<ConnectionManager component>/elements-number-limit[I]=integer_number\n-----\n\nfor example (for ClusterConnectionManager):\n\n[source,bash]\n-----\ncl-comp/elements-number-limit[I]=100000\n-----\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_27_-_--ext-comp.asciidoc",
    "content": "[[extComp]]\n= --ext-comp\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:05\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* --ext-comp = +localdomain,remotedomain,port,passwd,plain,accept+\n\n*Possible values:* 'external connection definition string.' connection string +localdomain,remotedomain,port,passwd,(plain|ssl),(accept|connect),routing+\n\n*Description:* Deprecated in favor of xref:external[+--external+]. _Support for this property is no longer maintained, please update your installation for the new way to connect external components._\n\nThe +--ext-comp+ property creates a connection over an external component protocol - link:http://xmpp.org/extensions/xep-0114.html[XEP-0114]. The connection can be made to/from any XEP-0114 application such as IM transort, MUC, PubSub and others. It is also possible to separate Tigase internal components onto separate instances connected via XEP-0114 connections.\n\n*Note:* It is also possible to generate a configuration for many external components. To do so use +--ext-comp_1 parameters+, +--ext-comp_2 parameters+ and so on...\n\n*Available since:* 2.0.0\n*Discontiuned since* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_28_-_--extcomp-repo-class.asciidoc",
    "content": "[[extcompRepoClass]]\n= --extcomp-repo-class\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:13\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.server.ext.CompConfigRepository+\n\n*Example:* +--extcomp-repo-class = tigase.server.ext.CompConfigRepository+\n\n*Possible values:* 'a class name implementing tigase.db.comp.ComponentRepository.'\n\n*Description:* This can be used when xref:external[+--external+] is used to connect external components. The component responsible for maintaining external components connections can be reconfigured during run-time and can store configuration in a separate place, configuration file, database or any other data source. This property specifies implementation for this data source.\n\nThe property sets a class managing the component repository. There are 3 available now and you can implement and use your own. They are:\n\n- 'tigase.server.ext.CompConfigRepository' which reads settings for external components from configuration only. It works well with ad-hoc commands, you can add, remove and update external component settings but your changes are not saved to any permanent storage.\n- 'tigase.server.ext.CompDBRepository' which reads settings for external components from configuration and from a database. As a database backend it uses UserRepository. It works well with ad-hoc commands and your changes are stored in DB and are loaded after server restart. All data are cached in memory so it doesn't cause a significant load on database. As it uses UserRepository data are stored in a format hard for direct modifications in database and because of caching in memory all the data it is also not a good choice in cluster environment as changes made on one node are not quickly propagated to other nodes - a reload ad-hoc command must be called on all nodes.\n- 'tigase.server.ext.CompSQLRepository' which reads initial settings from configuration and also stores data in SQL database. It automatically creates a dedicated DB table with a simple structure suitable for direct modification with SQL commands. It also doesn't cache any data. External component details are read from DB on demand when the component tries to authenticate. As it doesn't cache any data, each authentication request requires DB access therefore it may put some load on the DB. On the other hand it allows for easy external component management from a separate application connecting directly to DB and all changes are instantly picked up by all cluster nodes.\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_29_-_--external.asciidoc",
    "content": "[[external]]\n= --external\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:40\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--external = muc1.devel.tigase.org:passwd1:connect:5270:devel.tigase.org:accept:lb-class+\n\n*Possible values:* 'external domains parameters list.'\n\n*Description:* This property defines parameters for external component connections.\n\nThe component is loaded the same way as all other Tigase components. In your +init.properties+ file you need to add 2 lines:\n\n[source,bash]\n-----\n--comp-name-1 = ext\n--comp-class-1 = tigase.server.ext.ComponentProtocol\n-----\n\nThis will load the component with an empty configuration and is practically useless. You have to tell the component on what port to listen to (or on what port to connect to) and external domains list with passwords.\n\nAs a value you have to put comma separated list of external domains settings. Each domain settings consist of a few, colon separated parameters. For example:\n\n[source,bash]\n-----\n--external = muc1.devel.tigase.org:passwd1,muc2.devel.tigase.org:passwd2\n-----\n\nThis sets passwords for 2 external domains but does not say anything about port number or connection. The above list is a simplified syntax. The full syntax looks like this:\n\n[source,bash]\n-----\n--external = muc1.devel.tigase.org:passwd1:listen:5270\n-----\nor\n[source,bash]\n-----\n--external = muc1.devel.tigase.org:passwd1:connect:5270:devel.tigase.org:accept:lb-class\n-----\n\nDefinition of each colon separated part:\n\n. external component *domain*;\n. *password* for this domain;\n. *connection type* - 'listen' for incoming connections or 'connect' for the remote server;\n. *port number* for the TCP/IP connection (listening on or connecting to);\n. *remote hostname address(es)* - if the connection type is 'connect' then the the remote hostname address should be here. For 'listen' connection type this parameter can be skipped. The first item on the list is always the remote domain name, if there are more entries, the rest is just addresses to connect to for this domain separated by a semicolon (;)\n. *protocol* - if the connection type is 'connect' then the protorol is defined here - 'accept' for XEP-0114, 'client' for XEP-0225, possibly others in the future. It can be skipped for 'listen' connection types.\n. *lb-class* - is a class name for a load-balancer plugin. This is used only where there are multiple connections from the external component and you want to spread the resource load among them. More details and examples are in this guide.\n\nOnly 2 first parts are mandatory, the rest is optional. The simplified form is used to provide a list of domains:password elements for external components connections.\n\nThe settings on the server side may most likely looks like this:\n\n[source,bash]\n-----\n--external=muc1.devel.tigase.org:passwd1:listen:5270,muc2.devel.tigase.org:passwd2,muc3.devel.tigase.org:passwd3\n-----\n\nIt specifies 3 domains with passwords and one TCP/IP port to listen to. On the other hand you can specify a configuration which would establish the connection to the server:\n\n[source,bash]\n-----\n--external = muc1.devel.tigase.org:passwd1:connect:5270:devel.tigase.org:accept\n-----\n\nWe use one of the domains configured on the server side, the same port number and the server address. (Assuming the main server works at devel.tigase.org address).\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_30_-_--hardened-mode.asciidoc",
    "content": "[[hardenedMode]]\n= --hardened-mode\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2014-01-07 09:04\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--hardened-mode=true+\n\n*Possible values:* +true|false+\n\n*Description:* Enabling hardened mode affects handling of security aspects within Tigase. It turns off workarounds for SSL issues, turns off SSLv2 and forces enabling more secure ciphers suites. It also forces requirement of StartTLS.\n\nEnabling it requires link:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[UnlimitedJCEPolicyJDK] installed. We prefer to use OracleJDK as our tests revealed that using OpenJDK in hardened mode may cause issues with some clients on some platforms.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_31_-_--max-queue-size.asciidoc",
    "content": "[[maxQueueSize]]\n= --max-queue-size\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:45\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'depends on RAM size.'\n\n*Example:* +--max-queue-size = 10000+\n\n*Possible values:* 'integer number.'\n\n*Description:* The +--max-queue-size+ property sets internal queues maximum size to a specified value. By default Tigase sets the queue size depending on the maximum available memory to the Tigase server process. It set's 1000 for each 100MB memory assigned for JVM. This is enough for most cases. If you have however, an extremely busy service with Pubsub or MUC component generating huge number of packets (presence or messages) this size should be equal or bigger to the maximum expected number of packets generated by the component in a single request. Otherwise Tigase may drop packets that it is unable to process.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_32_-_--monitoring.asciidoc",
    "content": "[[monitoring]]\n= --monitoring\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 22:48\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--monitoring = jmx:9050,http:9080,snmp:9060+\n\n*Possible values:* 'list of monitoring protocols with port numbers.'\n\n*Description:* This property activates monitoring interfaces through selected protocols on selected TCP/IP port numbers. For more details please refer to the monitoring guide in the user guide for details.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_33_-_--net-buff-high-throughput.asciidoc",
    "content": "[[netBuffHighThroughput]]\n= --net-buff-high-throughput\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 23:05\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +64k+\n\n*Example:* +--net-buff-high-throughput = 256k+\n\n*Possible values:* 'network buffer size as integer.'\n\n*Description:* The +--net-buff-high-throughput+ property sets the network buffer for high traffic connections like s2s or connections between cluster nodes. The default is +64k+ and is optimal for medium traffic websites. If your cluster installation can not cope with traffic between nodes try to increase this number.\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_34_-_--net-buff-standard.asciidoc",
    "content": "[[netBuffStandard]]\n= --net-buff-standard\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 23:06\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +2k+\n\n*Example:* +--net-buff-standard = 16k+\n\n*Possible values:* 'network buffer size as integer.'\n\n*Description:* This property sets the network buffer for standard (usually c2s) connections, default value is 2k and is optimal for most installations.\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_35_-_--new-connections-throttling.asciidoc",
    "content": "[[newConnectionsThrottling]]\n= --new-connections-throttling\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 23:08\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +5222:200,5223:50,5269:100,5280:1000+\n\n*Example:* +--new-connections-throttling = 5222:100+\n\n*Possible values:* 'a list of port numbers with throttling thresholds as integer.'\n\n*Description:* The property allows you to limit how many new users' connection per second the server accepts on a particular port. Connections established within the limit are processed normally, all others are simply disconnected. This allows you to avoid server overload in case there is a huge number of users trying to connect at the same time. Mostly this happens after a server restart.\n\nThe property value is a list of comma separated port settings. Each port setting is formatted in a following way: +PORT_NO:LIMIT_VAL+\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_36_-_--nonpriority-queue.asciidoc",
    "content": "[[nonpriorityQueue]]\n= --nonpriority-queue\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 23:10\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--nonpriority-queue =  true+\n\n*Possible values:* +true|false+\n\n*Description:* The +--nonpriority+ property can be used to switch to non-priority queues usage in Tigase server (value set to 'true'). Using non-priority queues prevents packets reordering. By default Tigase uses priority queues which means that packets with highest priority may take over packets with lower priority (presence updates) which may result in packets arriving out of order.\n\nThis may happen however only for packets of different types. That is, messages may take over presence packets. However, one message never takes over another message for the same user. Therefore, out of order packet delivery is not an issue for the most part.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_37_-_--queue-implementation.asciidoc",
    "content": "[[queueImplementation]]\n= --queue-implementation\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 23:16\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.util.PriorityQueueRelaxed+\n\n*Example:* +--queue-implementation = tigase.util.PriorityQueueStrict+\n\n*Possible values:* 'class name extending +tigase.util.PriorityQueueAbstract+.'\n\n*Description:* The +--queue-implementation+ property sets Tigase's internal queue implementation. You can choose between already available and ready to use or you can create own queue implementation and let Tigase load it instead of the default one.\nCurrently following queue implementations are available:\n\n. *tigase.util.PriorityQueueRelaxed* - specialized priority queue designed to efficiently handle very high load and prevent packets loss for higher priority queues. This means that sometimes, under the system overload packets may arrive out of order in cases when they could have been dropped. Packets loss (drops) can typically happen for the lowest priority packets (presences) under a very high load.\n. *tigase.util.PriorityQueueStrict* - specialized priority queue designed to efficiently handle very high load but prefers packet loss over packet reordering. It is suitable for systems with a very high load where the packets order is the critical to proper system functioning. This means that the packets of the same priority with the same source and destination address are never reordered. Packets loss (drops) can typically happen for all packets with the same probability, depending which priority queue is overloaded.\n. *tigase.util.NonpriorityQueue* - specialized non-priority queue. All packets are stored in a single physical collection, hence they are never reordered. Packets are not prioritized, hence system critical packets may have to wait for low priority packets to be processed. This may impact the server functioning and performance in many cases. Therefore this queue type should be choosen very carefully. Packets of the same type are never reordered. Packets loss (drops) can typically happen for all packets which do not fit into the single queue.\n\n*Please note!* _Since the packets are processed by plugins in the SessionManager component and each plugin has own thread-pool with own queues packet reordering may happen regardless what queue type you set. The reordering may only happen, however between different packet types. That is 'message' may take over 'iq' packet or 'iq' packet may take over 'presence' packet and so on... This is unpredictable._\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_38_-_--roster-implementation.asciidoc",
    "content": "[[rosterImplementation]]\n= --roster-implementation\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-04-24 20:44\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +RosterFlat.class.getCanonicalName()+\n\n*Example:* +--roster-implementation=my.pack.CustomRosterImpl+\n\n*Possible values:* 'Class extending tigase.xmpp.impl.roster.RosterAbstract.'\n\n*Description:* The +--roster-implementation+ property allows you to specify a different RosterAbstract implementation. This might be useful for a customized roster storage, extended roster content, or in some cases for some custom logic for certain roster elements.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_39_-_--s2s-ejabberd-bug-workaround-active.asciidoc",
    "content": "[[s2sEjabberdBugWorkaroundActive]]\n= --s2s-ejabberd-bug-workaround-active\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 00:58\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--s2s-ejabberd-bug-workaround-active = true+\n\n*Possible values:* +true|false+\n\n*Description:* This property activates a workaround for a bug in EJabberd in it's s2s implementation. EJabberd does not send dialback in stream features after TLS handshaking even if the dialback is expected/needed. This results in unusable connection as EJabberd does not accept any packets on this connection either. The workaround is enabled by default right now until the EJabberd version without the bug is popular enough. A disadvantage of the workaround is that dialback is always performed even if the SSL certificate is fully trusted and in theory this dialback could be avoided.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_40_-_--s2s-secret.asciidoc",
    "content": "[[s2sSecret]]\n= --s2s-secret\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-03-28 14:55\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +<null>+\n\n*Example:* +--s2s-secret = some-s2s-secret+\n\n*Possible values:* 'ascii string.'\n\n*Description:* This property is a global setting for s2s secrets to generate dialback keys on the Tigase installation. By default it is null, which means the secret is automatically generated for each s2s connection and handshake.\n\nThis is a global property which is overridden by settings for each vhost.\n\nA default settings for all virtual hosts for which the configuration is not defined. This settings is useful mostly for installations with many virtual hosts listed in the init.property file for which there is no individual settings specified. It allows to configure a default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_41_-_--s2s-skip-tls-hostnames.asciidoc",
    "content": "[[s2sSkipTlsHostnames]]\n= --s2s-skip-tls-hostnames\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 00:59\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--s2s-skip-tls-hostnames =  domain1,domain2+\n\n*Possible values:* 'comma separated list of domains.'\n\n*Description:* The +--s2s-skip-tls-hostnames+ property disables TLS handshaking for s2s connections to selected remote domains. Unfortunately some servers (certain versions of Openfire - [link:http://community.igniterealtime.org/thread/36206[1]] or [link:http://community.igniterealtime.org/thread/30578[2]]) have problems with TLS handshaking over s2s which prevents establishing a usable connection. This completely blocks any communication to these servers. As a workaround you can disable TLS for these domains to get communication back.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_42_-_--script-dir.asciidoc",
    "content": "[[scriptDir]]\n= --script-dir\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:01\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +scripts/admin+\n\n*Example:* +--script-dir = /opt/admin-scripts+\n\n*Possible values:* 'path to a directory on the filesystem.'\n\n*Description:* This property sets the directory where all administrator scripts for ad-hoc command are stored.\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_43_-_--sm-cluster-strategy-class.asciidoc",
    "content": "[[smClusterStrategyClass]]\n= --sm-cluster-strategy-class\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-08-06 11:20\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.cluster.strategy.SMNonCachingAllNodes+\n\n*Example:* +--sm-cluster-strategy-class=tigase.cluster.strategy.SMNonCachingAllNodes+\n\n*Possible values:* 'any class implementing +tigase.cluster.strategy.ClusteringStrategyIfc+ interface.'\n\n*Description:* The +--sm-cluster-strategy-class+ property allows users to specify Clustering Strategy class which should be used for handling clustering environment; by default +SMNonCachingAllNodes+ is used.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_44_-_--sm-plugins.asciidoc",
    "content": "[[smPlugins]]\n= --sm-plugins\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:04\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--sm-plugins = -jabber:iq:register,+ +your-plugin+\n\n*Possible values:* 'comma separated list of plugins IDs.'\n\n*Description:* The +--sm-plugins+ property allows users to specify a list of plugins which should be loaded or disabled on the server. Normally you don't have to specify this. Tigase server loads a default list of plugins automatically. The default list contains all available plugins. Sometimes however you might want to load only some plugins. Typical use case is when user accounts are managed on a third-party system that Tigase server is integrated with. Then you might not want to allow users to register new accounts via the XMPP service. You can then load a list of plugins without the user registration plugin. Another case when you usually have to use this option is when you have your own plugins which replace function of the Tigase default plugins like vCard, roster management, and so on....\n\nTo prevent the plugin from loading add '-' before its ID, to load the plugin add '+' (which is optional). For example, the following setting would switch user registration off, while adding a new plugin: 'your-plugin':\n\n[source,bash]\n-----\n--sm-plugins=-jabber:iq:register,+your-plugin\n-----\n\nThere is more. Each plugin is running in one or more separate threads. Most plugins which deal with databases have a number of threads equal to the number of CPUs or CPU cores. Sometimes this is not enough. If the database is slow or there is a specific kind of traffic at a high level you might want to adjust the number of threads for the plugin. To set a different number of threads, just add '=N' where 'N' is the number of threads you want. The previous example has been modified to assign 8 threads for your plugin and 16 threads for authentication plugin:\n\n[source,bash]\n-----\n--sm-plugins=-jabber:iq:register,+your-plugin=8,jabber:iq:auth=16\n-----\n\n*Available since:* 3.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_45_-_--sm-threads-pool.asciidoc",
    "content": "[[smThreadsPool]]\n= --sm-threads-pool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:06\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +default+\n\n*Example:* +--sm-threads-pool = custom:100+\n\n*Possible values:* +default|custom:NN+\n\n*Description:* The +--sm-threads-pool+ property allows you to fine-tune the SM plugin's (processors) thread pool. With the default settings every plugin gets his own thread pool. This guarantees the best performance and optimal resource usage. The downside of this setting is that packets can arrive out of order if they are processed within different thread pools.\n\nIf you really need or want to preserve the order for packets processed by different plugins then the solution is to use the 'custom' thread pool. In this case packets processed by all plugins are handled within a single thread pool. This guarantees that the packets are processed and delivered in the exact order they arrive. The number after the colon ':' specifies the thread pool size.\n\nWe can even fine tune this packet processing. Let's say you want most of the plugins to be executed within a single thread pool to preserve packet ordering for them, but for some selected plugins that should execute within separate thread pools to improve performance.  Let's say, authentication packets and user registration can be actually executed in a separate thread pools as we do not worry about an order for them. Users cannot send or receive anything else before they authenticates anyway. The solution is to specify a number of threads for the selected plugins in the +--sm-plugins+ property as described above. For example, setting a common thread pool for all plugins but registration and authentication can be done with following configuration:\n\n[source,bash]\n-----\n--sm-threads-pool=custom:100\n--sm-plugins=jabber:iq:register=8,jabber:iq:auth=16,urn:ietf:params:xml:ns:xmpp-sasl=16\n-----\n\nAvailable since: 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_46_-_--ssl-certs-location.asciidoc",
    "content": "[[sslCertsLocation]]\n= --ssl-certs-location\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:11\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +certs/+\n\n*Example:* +--ssl-certs-location = /etc/vhost-certs+\n\n*Possible values:* 'location of SSL certificates directory on the filesystem.'\n\n*Description:* This option allows you to specify the location where SSL certificates are stored. The meaning of this property depends on the SSL container xref:sslContainerClass[class implementation]. By default it just points to the directory where the server SSL certificates are stored in files in PEM format.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_47_-_--ssl-container-class.asciidoc",
    "content": "[[sslContainerClass]]\n= --ssl-container-class\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\nv2.0, June 2014: Reformatted for AsciiDoc.\n:toc:\n:numbered:\n:website: http://tigase.net/\n:Date: 2013-02-10 01:11\n\n*Default value:* +tigase.io.SSLContextContainer+\n\n*Example:* +--ssl-container-class =+\n\n*Possible values:* a class implementing tigase.io.SSLContectContainerIfc.\n\n*Description:* The +--ssl-container-class+ property allows you to specify a class implementing storage for SSL/TLS certificates. The class presented in the example to this description allows for loading certificates from PEM files which is a common storage used on many systems.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_48_-_--ssl-def-cert-domain.asciidoc",
    "content": "[[sslDefCertDomain]]\n= --ssl-def-cert-domain\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:13\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +default+\n\n*Example:* +--ssl-def-cert-domain =+\n\n*Possible values:* 'DNS domain name.'\n\n*Description:* This property allows you to specify a default alias/domain name for certificate. It is mostly used to load certificates for unknown domain names during the SSL negotiation. Unlike in TLS protocol where the domain name is known at the handshaking time, for SSL domain name is not known, therefore, the server does not know which certificate to use. Specifying a domain name in this property allows you to use a certificate for a specific domain in such case. This property value is also sometimes used if there is no certificate for one of virtual domains and the container does not automatically generate a self-signed certificate, then it can use a default one.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_49_-_--stats-archiv.asciidoc",
    "content": "[[statsArchiv]]\n= --stats-archiv\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2014-06-10 18:21\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'By default, --stats-archiv is not listed in the init.properties file'\n\n*Example:* +--stats-archiv=tigase.stats.CounterDataFileLogger:stats-file-logger:60,tigase.stats.CounterDataLogger:stats-logger:60+\n\n*Possible values:* 'comma separated list of statistics archivers:' +<class>:<name>:<frequency>+\n\n*Description:* +--stats-archiv+ configuration property allow enabling and configuring components responsible for storing statistic information. As a parameter, it takes comma separated list of all archivers that we want to enable. Each entry follows same pattern: <class>:<name>:<frequency>, where:\n\n- <class> - is the class of any archiver implementing +tigase.stats.StatisticsArchivizerIfc+ interface\n- <name> - is the name of particular archiver under which it will be identified in Tigase\n- <frequency> - is the time interval between subsequent execution of the archiver +.execute()+ method (in seconds).\n\nCurrently following archivers classes are available:\n\n- +tigase.stats.CounterDataArchivizer+ - every execution put current basic server metrics (CPU usage, memory usage, number of user connections, uptime) into database (overwrites previous entry);\n- +tigase.stats.CounterDataLogger+ - every execution insert new row with new set of number of server statistics (CPU usage, memory usage, number of user connections per connector, number of processed packets of different types, uptime, etc) into the database\n- +tigase.stats.CounterDataFileLogger+ - every execution store all server statistics into separate file.\n\nIt's possible to configure each archiver by adding following entry to the +etc/init.properties+ file:\n\n[source,bash]\n-----\n<statistics_component_name>/stats-archiv/<name>/<property>=<value>\n-----\n\nFor example, if we want to enable CounterDataFileLogger that stores statistics every 60 seconds:\n\n[source,bash]\n-----\n--stats-archiv=tigase.stats.CounterDataFileLogger:stats-file-logger:60\n-----\n\nWe can configure it further with following options:\n\n[source,bash]\n-----\nstats/stats-archiv/stats-file-logger/stats-directory=logs/server_statistics\nstats/stats-archiv/stats-file-logger/stats-filename=stat\nstats/stats-archiv/stats-file-logger/stats-unixtime=false\nstats/stats-archiv/stats-file-logger/stats-datetime=true\nstats/stats-archiv/stats-file-logger/stats-datetime-format=HH:mm:ss\nstats/stats-archiv/stats-file-logger/stats-level=FINE\n-----\n\nwhich configures accordingly: directory to which files should be saved, filename prefix, whether to include or not unix timestamp in filename, whether to include or not datetime timestamp, control format of timestamp (using java DateFormat pattern) and also set level of the statistics we want to save (using java Logger.Level)\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_50_-_--stats-history.asciidoc",
    "content": "[[statsHistory]]\n= --stats-history\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-04-15 20:55\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--stats-history=2160,10+\n\n*Possible values:* +SIZE-NUM,INTERVAL_NUM+\n\n*Description:* Tigase XMPP Server can store server statistics internally for a given period of time. This allows you to connect to a running system and collect all the server metrics along with historic data which are stored on the server.\n\nThis is very useful when something happens on your production system you can connect and see when exactly this happened and what other metrics looked around this time.\n\nThe property value consists of comma separated, 2 integer numbers. The first is a size of the buffer. That is how many complete sets of historic metrics to store in memory. The second specified how often to probe metrics on the server.\n\nPlease be aware that Tigase XMPP Server produces about 1,000 different metrics of the system. Therefore caching large number of statistics sets requires lots of memory.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_51_-_--stringprep-processor.asciidoc",
    "content": "[[stringprepProcessor]]\n= --stringprep-processor\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:29\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +simple+\n\n*Example:* +--stringprep-processor = libidn+\n\n*Possible values:* +simple|libidn|empty+\n\n*Description:* The +--stringprep-processor+ property sets the stringprep processor for all JIDs handled by Tigase. The default 'simple' implementation uses regular expressions to parse and check the user JID. It does not fulfill the RFC-3920 requirements but also puts much less stress on the server CPU, hence impact on the performance is very low.\n\nOther possible values are:\n\n'libidn' - provides full stringprep processing exactly as described in the RFC-3920. It requires lots of CPU power and significantly impacts performance.\n\n'empty' - doesn't do anything to JIDs. JIDs are accepted in the form they are received. No impact on the performance and doesn't use any CPU. This is suitable for use in automated systems where JIDs are generated by some algorithm, hence there is no way incorrect JIDs may enter the system.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_52_-_--test.asciidoc",
    "content": "[[test]]\n= --test\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:34\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--test+\n\n*Possible values:* +true|false|empty-string+\n\n*Description:* This property sets the server for test mode, which means that all logging is turned off, offline message storage is off, and possibly some other changes to the system configuration are being made.\n\nThe idea behind this mode is to test Tigase XMPP Server with minimal performance impact from environment such as hard drive, database and others...\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_53_-_--tigase-config-repo-class.asciidoc",
    "content": "[[tigaseConfigRepoClass]]\n= --tigase-config-repo-class\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:37\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.conf.ConfigurationCache+\n\n*Example:* +--tigase-config-repo-class = tigase.conf.ConfigXMLRepository+\n\n*Possible values:* 'name of class implementing +tigase.conf.ConfigRepositoryIfc+'\n\n*Description:* This property is a parameter which allows loading of different configuration storage engines. The default setting stores configuration in memory only.\nOther possible are: +tigase.conf.ConfigXMLRepository+ which keeps configuration in the old XML file and +tigase.conf.ConfigSQLRepository+ which stores configuration in SQL database.\n*Please note* in all cases the +init.properties+ file can still be read and works the same way - provides an initial settings for Tigase at startup.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_54_-_--tigase-config-repo-uri.asciidoc",
    "content": "[[tigaseConfigRepoUri]]\n= --tigase-config-repo-uri\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:38\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* 'none'\n\n*Example:* +--tigase-config-repo-uri = jdbc:mysql://localhost/tigase?user=root&amp;password=mypass+\n\n*Possible values:* 'DB connection URI string.'\n\n*Description:* The +--tigase-config-repo-uri+ property is a parameter which allows to provide database connection string for configuration storage engines which keep server settings in a database.\n\n*Available since:* 5.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_55_-_--tls-jdk-nss-bug-workaround-active.asciidoc",
    "content": "[[tlsJdkNssBugWorkaroundActive]]\n= --tls-jdk-nss-bug-workaround-active\n:author: Andrzej Wojcik <andrzejw@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 03:57\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--tls-jdk-nss-bug-workaround-active = true+\n\n*Possible values:* +true|false+\n\n*Description:* This is a workaround for TLS/SSL bug in new JDK7 using the native library for keys generation and connection encryption used with new version of nss library.\n\nThis caused a number of problems with Tigase installed on systems with JDK7 and the new library installed, such as hanging connections, or broken SSL/TLS. There is some information on our link:https://projects.tigase.org/projects/tigase-server/wiki/Tigase_with_OpenJDK7_with_OpenSSL_101[wiki page]. Our earlier suggestion was to avoid using either JDK7 or the problematic native library. Now we have a proper fix/workaround which allows you to run Tigase with JDK7.\n\n- http://stackoverflow.com/q/10687200/427545\n- http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=b509d9cb5d8164d90e6731f5fc44?bug_id=6928796\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_56_-_--trusted.asciidoc",
    "content": "[[trusted]]\n= --trusted\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:40\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +none+\n\n*Example:* +--trusted = user@domain.com,user-2@domain2.com+\n\n*Possible values:* 'comma separated list of user bare JIDs.'\n\n*Description:* The +--trusted+ property allows users to specify a list of accounts which are considered as trusted, thus whom can perform some specific actions on the server. They can execute some commands, send a broadcast message, set MOTD and so on. The configuration is similar to xref:admins[--adimins] setting.\n\n*Available since:* 3.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_57_-_--user-db.asciidoc",
    "content": "[[userdb]]\n= --user-db\n:admin: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:45\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +mysql+\n\n*Example:* +--user-db = ldap+\n\n*Possible values:* 'UserRepository implementation class name or predefined string.'\n\n*Description:* The +--user-db+ property allows to specify UserRepository implementation - a storage where all users' data are located. Users' data include contact list (roster), privacy lists, vCards, and similar; everything except user authentication information. The implementation can be defined by one of possible values: +mysql, pgsql, xml+ or the class name. For a SQL database this is normally: +tigase.db.jdbc.JDBCRepository+.\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_58_-_--user-db-uri.asciidoc",
    "content": "[[userDbUri]]\n= --user-db-uri\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:47\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +jdbc:mysql://localhost/tigase?user=root&password=mypass+\n\n*Example:* +--user-db-uri = jdbc:postgresql://localhost/tigase?user=tigase+\n\n*Possible values:* 'Database connection URI.'\n\n*Description:* The +--user-db-uri+ property specify database connection string - +connection-uri+, where +connection-uri+ is a full resource uri for user repository data source. If you skip this parameter, the default value is used depending on database type you selected:\n\n- jdbc:mysql://localhost/tigase?user=root&password=mypass\n- jdbc:postgresql://localhost/tigase?user=tigase\n- user-repository.xml\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_59_-_--user-domain-repo-pool.asciidoc",
    "content": "[[userDomainRepoPool]]\n= --user-domain-repo-pool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:50\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/0\n\n*Default value:* +tigase.db.UserRepositoryMDImpl+\n\n*Example:* +--user-domain-repo-pool = tigase.db.UserRepositoryMDImpl+\n\n*Possible values:* 'Name of class implementing UserRepository.'\n\n*Description:* This property allows you to specify an implementation for per-domain UserRepository implementation. This is used only if the implementation provided by a default Tigase server package is not sufficient in the particular deployment. The implementation provides a DB (UserRepository to be more specific) connection pool where each connection (UserRepository) handles data for a different DNS domain (VHost). This allows for database (user data) sharing to improve the system performance and better balance the resource load.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_60_-_--user-repo-pool.asciidoc",
    "content": "[[userRepoPool]]\n= --user-repo-pool\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:49\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +tigase.db.UserRepositoryPool+\n\n*Example:* +--user-repo-pool = tigase.db.UserRepositoryPool+\n\n*Possible values:* 'Name of class implementing UserRepository.'\n\n*Description:* The +--user-repo-pool+ property provides an ability to specify an implementation for the repository connection pool. This is used only if the implementation provided by a default Tigase server package is not sufficient in a particular deployment. The implementation provides a DB (UserRepository to be more specific) connection pool to improve the data access performance. The repository pool can offer data caching for improved performance or any other features necessary.\n\n*Available since:* 5.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_61_-_--user-repo-pool-size.asciidoc",
    "content": "[[userRepoPoolSize]]\n= --user-repo-pool-size\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-10 01:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +10+\n\n*Example:* +--user-repo-pool-size = 25+\n\n*Possible values:* 'Number of db connections as integer.'\n\n*Description:* This property allows setting the database connections pool size for the +UserRepository+.\n\n*Please note* if not specified than in some cases instead of default for this property setting for xref:dataRepoPoolSize[+--data-repo-pool-size+] can be used. This depends on the repository implementation and the way it is initialized.\n\n*Available since:* 4.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_62_-_--vhost-anonymous-enabled.asciidoc",
    "content": "[[vhostAnonymousEnabled]]\n= --vhost-anonymous-enabled\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 02:37\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +true+\n\n*Example:* +--vhost-anonymous-enabled = false+\n\n*Possible values:* +true|false+\n\n*Description:* The +--vhost-anonymous-enabled+ property specifies whether anonymous user logins are allowed for the installation for all vhosts.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nDefault settings for all virtual hosts are used when this property is not defined. This settings is useful mostly for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It allows the configuration of default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_63_-_--vhost-disable-dns-check.asciidoc",
    "content": "[[vhostDisableDnsCheck]]\n= --vhost-disable-dns-check\n:author: Daniel Wisnewski <daniel.wisnewski@tigase.net>\n:version: v1.0, October 2015\n:date: 2015-07-10\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--vhost-disable-dns-check = true+\n\n*Possible values:* +true|false+\n\n*Description:* This property disables DNS validation when adding or editing vhosts in Tigase server. This also exempts administrative accounts from validation.\nWith this property enabled, you will not benefit from seeing if proper SRV records are set so other people can connect to specific vhosts from outside your network.\n\n*Available since:* 7.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_64_-_--vhost-max-users.asciidoc",
    "content": "[[vhostMaxUsers]]\n= --vhost-max-users\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 02:44\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +0+\n\n*Example:* +--vhost-max-users = 1000+\n\n*Possible values:* 'integer number.'\n\n*Description:* The +--vhost-max-users+ property specifies how many user accounts can be registered on the installations for all vhosts.\n\n*0 - zero* means unlimited and this is a default. Otherwise greater than zero value specifies accounts number limit.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nThe default setting is used for all virtual hosts for which the configuration is not defined. This settings is most useful for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It provides an ability to use default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_65_-_--vhost-message-forward-jid.asciidoc",
    "content": "[[vhostMessageForwardJid]]\n= --vhost-message-forward-jid\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 02:52\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +<null>+\n\n*Example:* +--vhost-message-forward-jid = archive@domain.com+\n\n*Possible values:* 'valid JID'\n\n*Description:* This is a global property for message forwarding for the installation. This property is normally specified on the vhost configuration level, however if you want to forward all messages on your installation and you have many virtual domains this property allows to set message forwarding for all of them. A valid JID must be specified as the forwarding destination. Also a message forwarding plugin must be loaded and activated on the installation for the message forwarding to work.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nThe null value is used as a default when no configuration is set. This setting is mostly useful for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It provides the ability to configure a default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_66_-_--vhost-presence-forward-jid.asciidoc",
    "content": "[[vhostPresenceForwardJid]]\n= --vhost-presence-forward-jid\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 02:57\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +<null>+\n\n*Example:* +--vhost-presence-forward-jid = presence-collector@domain.com+\n\n*Possible values:* 'valid JID.'\n\n*Description:* This is a global property for presence forwarding function for the installation. All user status presences will be forwarded to given XMPP address which can be a component or any other XMPP entity. If the destination entity is a bot connected via c2s connection it probably should be addressed via full JID (with resource part) or the standard XMPP presence processing would refuse to deliver presences from users who are not in the contact list.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nThe null value is used as a default when no configuration is set. This settings is useful for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It enables the ability to configure default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_67_-_--vhost-register-enabled.asciidoc",
    "content": "[[vhostRegisterEnabled]]\n= --vhost-register-enabled\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 03:00\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +true+\n\n*Example:* +--vhost-register-enabled = false+\n\n*Possible values:* +true|false+\n\n*Description:* +--vhost-register-enabled+ is a global property which allows you to switch on/off user registration on the installation. Setting this property to +false+ does not disable the registration plugin on the server. You can enable registration for selected domains in the domain configuration settings.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nThe +true+ value is used as a default when no configuration is set. This settings is useful for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It allows admins to configure default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_68_-_--vhost-tls-required.asciidoc",
    "content": "[[vhostTlsRequired]]\n= --vhost-tls-required\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-22 03:05\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--vhost-tls-required = true+\n\n*Possible values:* +true|false+\n\n*Description:* This property is a global settings to switch on/off TLS required mode on the Tigase installation. Setting this property to +false+ does not turn TLS off. The TLS is still available on the server but as an option and this is the client's decision whether to use encryption or not. If the property is set to true the server will not allow for user authentication or sending any other user data before TLS handshaking is completed.\n\nThis is a global property which is overridden by settings for particular vhost.\n\nThe +false+ value is used as a default when no configuration is set. This settings is useful for installations with many virtual hosts listed in the +init.property+ file for which there is no individual settings specified. It allows admins to configure default values for all of them, instead of having to provide individual configuration for each vhost.\n\nIt is also applied as a default value for all new vhosts added at run-time.\n\n*Available since:* 5.2.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_69_-_--virt-hosts.asciidoc",
    "content": "[[virtHosts]]\n= --virt-hosts\n:author: not known\n:version: v1.0 initial release\n:Date: 2013-02-10 01:53\n\n*Default value:* 'hostname'\n\n*Example:* +--virt-hosts = domain1,domain2,domain3+\n\n*Possible values:* 'comma separated list of domains.'\n\n*Description:* The +--virt-hosts+ property allows to set a list of virtual domains served by the installation. This is just a list of virtual domains loaded at the startup time. Domains can be added, removed, disabled or updated at runtime. All the actual domain metadata are stored in the database.\n\nSome metadata for vhosts can be also provided in the +init.properties+ configuration file using this property. Domain is separated with ':' from its metadata. For boolean values '-' in front of the parameter means the feature is *off*. `+` or nothing  means it is *on*. If a parameter requires some additional settings it is provided in form: +param=val+.\n\nHere is an example:\n\n[source,bash]\n-----\n--virt-hosts=domain1:-anon:register:-tls-required:s2s-secret=s2spasswd:\\\n  domain-filter=LOCAL:max-users=1000,domain2,\\\n  domain3:c2s-ports-allowed=5222;5223;5280;5290\n  domain3:domain-filter=LIST=whitedomain1;whitedomain2;whitedomain3\n-----\n\n*Available since:* 4.3.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_70_-_--watchdog_delay.asciidoc",
    "content": "[[watchdogDelay]]\n= --watchdog_delay\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2014-02-07 18:07\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +600000+\n\n*Example:* +--watchdog_delay=30000+\n\n*Possible values:* 'any integer.'\n\n*Description:* +--watchdog_delay+ configuration property allows configuring delay (in miliseconds) between subsequent checks that ConnectionManager Watchdog (service responsible for detecting broken connections and closing them) will use to verify the connection. In addition to global configuration presented above a per component configuration is possible:\n\n[source,bash]\n-----\n<ConnectionManager component>/watchdog_delay[L]=60000\n-----\n\nfor example (for ClusterConnectionManager):\n\n[source,bash]\n-----\ncl-comp/watchdog_delay[L]=150000\n-----\n\nAll related configuration options:\n\n- --watchdog_ping_type\n- --watchdog_delay\n- --watchdog_timeout\n\n*Available since:* 5.2.1\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_71_-_--watchdog_ping_type.asciidoc",
    "content": "[[watchdogPingType]]\n= --watchdog_ping_type\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2014-02-07 18:05\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +whitespace+\n\n*Example:* +--watchdog_ping_type=xmpp+\n\n*Possible values:* +whitespace,xmpp+\n\n*Description:* +watchdog_ping_type+ configuration property allows configuring the type of ping that ConnectionManager Watchdog (service responsible for detecting broken connections and closing them) will use to check the connection. In addition to global configuration presented above a per component configuration is possible:\n\n[source,bash]\n-----\n<ConnectionManager component>/watchdog_ping_type[S]=xmpp\n-----\n\nfor example (for ClusterConnectionManager):\n\n[source,bash]\n-----\ncl-comp/watchdog_ping_type[S]=xmpp\n-----\n\nAll related configuration options:\n\n- --watchdog_ping_type\n- --watchdog_delay\n- --watchdog_timeout\n\n*Available since:* 5.2.1\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_72_-_--watchdog_timeout.asciidoc",
    "content": "[[watchdogTimeout]]\n= --watchdog_timeout\n:author: Wojciech Kapcia <wojciech.kapcia@tigase.org>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2014-02-07 18:13\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +1740000+\n\n*Example:* +--watchdog_timeout=60000+\n\n*Possible values:* 'any integer.'\n\n*Description:* The +watchdog_timeout+ property allows for fine-tuning ConnectionManager Watchdog (service responsible for detecting broken connections and closing them). Timeout property relates to the amount of time (in miliseconds) after which lack of response/activity on a given connection will considered such connection as broken an close it. In addition to global configuration presented above a per component configuration is possible:\n\n[source,bash]\n-----\n<ConnectionManager component>/watchdog_timeout[L]=60000\n-----\n\nfor example (for ClusterConnectionManager):\n\n[source,bash]\n-----\ncl-comp/watchdog_timeout[L]=150000\n-----\n\nAll related configuration options:\n\n- --watchdog_ping_type\n- --watchdog_delay\n- --watchdog_timeout\n\n*Available since:* 5.2.1\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_73_-_-config-type.asciidoc",
    "content": "[[configType]]\n= -config-type\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2013-02-09 07:22\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +-config-type:--gen-config-def+\n\n*Possible values:* +--gen-config-def|--gen-config-all|--gen-config-sm|--gen-config-cs|--gen-config-comp+\n\n*Description:* Probably the only such a property not starting with double hyphen. It sets the server type and determines what components are included in the generated XML file. Possible values are listed below:\n\n- '--gen-config-all' - creating configuration file with all available components. That is: session manager, client-to-server connection manager, server-to-server connection manager, one external component connection manager, stanza sender and stanza receiver.\n- '--gen-config-def' - creating default configuration file. That is configuration which is most likely needed for a typical installation. Components included in configuration are: session manager, client-to-server connection manager and server-to-server connection manager.\n- '--gen-config-sm' - creating configuration for instance with session manager and external component only. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: +sm+ and +ext2s+.\n- '--gen-config-cs' - creating configuration for instance with components managing network connections. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: +c2s+, +s2s+, +ext2s+.\n- '--gen-config-comp' - generating a configuration with only one component - component managing external components connection, either XEP-0114 or XEP-0225. This is used to deploy a Tigase instance as external component connecting to the main server. You have to add more components handled by this instance, usually these are MUC, PubSub or any other custom components. You have to refer to description for xref:compName[--comp-name] and xref:compClass[--comp-class] properties to learn how to add components to the Tigase instance. You also have to configure the external component connection, domain name, password, port, etc... Please look for a description for --external and --bind-ext-hostnames properties.\n\n*Available since:* 2.0.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/asciidoc/text/Properties_Guide_74_-_--ws-allow-unmasked-frames.asciidoc",
    "content": "[[wsAllowUnmaskedFrames]]\n= --ws-allow-unmasked-frames\n:author: Daniel Wisnewski (Daniel@tigase.net)\n:version: v1.0, April 2016\n:date: 2016-04-04 10:03\n\n:toc:\n:numbered:\n:website: http://tigase.net/\n\n*Default value:* +false+\n\n*Example:* +--ws-allow-unmasked-frames = true+\n\n*Possible values:* +true|false+\n\n*Description:* RFC 6455 specifies that all clients must mask frames that it sends to the server over Websocket connections.  If unmasked frames are sent, regardless of any encryption, the server must close the connection.  Some clients however, may not support masking frames, or you may wish to bypass this security measure for development purposes. This setting, when enabled true, will allow connections over websocket to be unmasked to the server, and may operate without Tigase closing that connection.\n\n*Available since:* 7.1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/propertiesguide/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../../..</dist_path>\n\t\t<guide_name>Properties</guide_name>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-docs-properties</artifactId>\n\t<name>Tigase XMPP Server Documentation - ${guide_name} Guide</name>\n\n\t<packaging>pom</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-docs</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t</parent>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-docbook</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.agilejava.docbkx</groupId>\n\t\t\t\t<artifactId>docbkx-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-pdf</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-webhelp</id>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-epub3</id>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>Remove *.fo file</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/css/docbook-xsl.css",
    "content": "/*\n  CSS stylesheet for XHTML produced by DocBook XSL stylesheets.\n*/\n\nbody {\n  font-family: Georgia,serif;\n}\n\ncode, pre {\n  font-family: \"Courier New\", Courier, monospace;\n}\n\nspan.strong {\n  font-weight: bold;\n}\n\nbody blockquote {\n  margin-top: .75em;\n  line-height: 1.5;\n  margin-bottom: .75em;\n}\n\nhtml body {\n  margin: 1em 5% 1em 5%;\n  line-height: 1.2;\n}\n\nbody div {\n  margin: 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\n\ndiv.toc p:first-child,\ndiv.list-of-figures p:first-child,\ndiv.list-of-tables p:first-child,\ndiv.list-of-examples p:first-child,\ndiv.example p.title,\ndiv.sidebar p.title\n{\n  font-weight: bold;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n  margin-bottom: 0.2em;\n}\n\nbody h1 {\n  margin: .0em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h2 {\n  margin: 0.5em 0 0 -4%;\n  line-height: 1.3;\n  border-bottom: 2px solid silver;\n}\n\nbody h3 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h4 {\n  margin: .8em 0 0 -3%;\n  line-height: 1.3;\n}\n\nbody h5 {\n  margin: .8em 0 0 -2%;\n  line-height: 1.3;\n}\n\nbody h6 {\n  margin: .8em 0 0 -1%;\n  line-height: 1.3;\n}\n\nbody hr {\n  border: none; /* Broken on IE6 */\n}\ndiv.footnotes hr {\n  border: 1px solid silver;\n}\n\ndiv.navheader th, div.navheader td, div.navfooter td {\n  font-family: Arial,Helvetica,sans-serif;\n  font-size: 0.9em;\n  font-weight: bold;\n  color: #527bbd;\n}\ndiv.navheader img, div.navfooter img {\n  border-style: none;\n}\ndiv.navheader a, div.navfooter a {\n  font-weight: normal;\n}\ndiv.navfooter hr {\n  border: 1px solid silver;\n}\n\nbody td {\n  line-height: 1.2\n}\n\nbody th {\n  line-height: 1.2;\n}\n\nol {\n  line-height: 1.2;\n}\n\nul, body dir, body menu {\n  line-height: 1.2;\n}\n\nhtml {\n  margin: 0; \n  padding: 0;\n}\n\nbody h1, body h2, body h3, body h4, body h5, body h6 {\n  margin-left: 0\n} \n\nbody pre {\n  margin: 0.5em 10% 0.5em 1em;\n  line-height: 1.0;\n  color: navy;\n}\n\ntt.literal, code.literal {\n  color: navy;\n}\n\n.programlisting, .screen {\n  border: 1px solid silver;\n  background: #f4f4f4;\n  margin: 0.5em 10% 0.5em 0;\n  padding: 0.5em 1em;\n}\n\ndiv.sidebar {\n  background: #ffffee;\n  margin: 1.0em 10% 0.5em 0;\n  padding: 0.5em 1em;\n  border: 1px solid silver;\n}\ndiv.sidebar * { padding: 0; }\ndiv.sidebar div { margin: 0; }\ndiv.sidebar p.title {\n  margin-top: 0.5em;\n  margin-bottom: 0.2em;\n}\n\ndiv.bibliomixed {\n  margin: 0.5em 5% 0.5em 1em;\n}\n\ndiv.glossary dt {\n  font-weight: bold;\n}\ndiv.glossary dd p {\n  margin-top: 0.2em;\n}\n\ndl {\n  margin: .8em 0;\n  line-height: 1.2;\n}\n\ndt {\n  margin-top: 0.5em;\n}\n\ndt span.term {\n  font-style: normal;\n  color: navy;\n}\n\ndiv.variablelist dd p {\n  margin-top: 0;\n}\n\ndiv.itemizedlist li, div.orderedlist li {\n  margin-left: -0.8em;\n  margin-top: 0.5em;\n}\n\nul, ol {\n    list-style-position: outside;\n}\n\ndiv.sidebar ul, div.sidebar ol {\n    margin-left: 2.8em;\n}\n\ndiv.itemizedlist p.title,\ndiv.orderedlist p.title,\ndiv.variablelist p.title\n{\n  margin-bottom: -0.8em;\n}\n\ndiv.revhistory table {\n  border-collapse: collapse;\n  border: none;\n}\ndiv.revhistory th {\n  border: none;\n  color: #527bbd;\n  font-family: Arial,Helvetica,sans-serif;\n}\ndiv.revhistory td {\n  border: 1px solid silver;\n}\n\n/* Keep TOC and index lines close together. */\ndiv.toc dl, div.toc dt,\ndiv.list-of-figures dl, div.list-of-figures dt,\ndiv.list-of-tables dl, div.list-of-tables dt,\ndiv.indexdiv dl, div.indexdiv dt\n{\n  line-height: normal;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n/*\n  Table styling does not work because of overriding attributes in\n  generated HTML.\n*/\ndiv.table table,\ndiv.informaltable table\n{\n    margin-left: 0;\n    margin-right: 5%;\n    margin-bottom: 0.8em;\n}\ndiv.informaltable table\n{\n    margin-top: 0.4em\n}\ndiv.table thead,\ndiv.table tfoot,\ndiv.table tbody,\ndiv.informaltable thead,\ndiv.informaltable tfoot,\ndiv.informaltable tbody\n{\n    /* No effect in IE6. */\n    border-top: 3px solid #527bbd;\n    border-bottom: 3px solid #527bbd;\n}\ndiv.table thead, div.table tfoot,\ndiv.informaltable thead, div.informaltable tfoot\n{\n    font-weight: bold;\n}\n\ndiv.mediaobject img {\n    margin-bottom: 0.8em;\n}\ndiv.figure p.title,\ndiv.table p.title\n{\n  margin-top: 1em;\n  margin-bottom: 0.4em;\n}\n\ndiv.calloutlist p\n{\n  margin-top: 0em;\n  margin-bottom: 0.4em;\n}\n\na img {\n  border-style: none;\n}\n\n@media print {\n  div.navheader, div.navfooter { display: none; }\n}\n\nspan.aqua { color: aqua; }\nspan.black { color: black; }\nspan.blue { color: blue; }\nspan.fuchsia { color: fuchsia; }\nspan.gray { color: gray; }\nspan.green { color: green; }\nspan.lime { color: lime; }\nspan.maroon { color: maroon; }\nspan.navy { color: navy; }\nspan.olive { color: olive; }\nspan.purple { color: purple; }\nspan.red { color: red; }\nspan.silver { color: silver; }\nspan.teal { color: teal; }\nspan.white { color: white; }\nspan.yellow { color: yellow; }\n\nspan.aqua-background { background: aqua; }\nspan.black-background { background: black; }\nspan.blue-background { background: blue; }\nspan.fuchsia-background { background: fuchsia; }\nspan.gray-background { background: gray; }\nspan.green-background { background: green; }\nspan.lime-background { background: lime; }\nspan.maroon-background { background: maroon; }\nspan.navy-background { background: navy; }\nspan.olive-background { background: olive; }\nspan.purple-background { background: purple; }\nspan.red-background { background: red; }\nspan.silver-background { background: silver; }\nspan.teal-background { background: teal; }\nspan.white-background { background: white; }\nspan.yellow-background { background: yellow; }\n\nspan.big { font-size: 2em; }\nspan.small { font-size: 0.6em; }\n\nspan.underline { text-decoration: underline; }\nspan.overline { text-decoration: overline; }\nspan.line-through { text-decoration: line-through; }\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/files/.gitignore",
    "content": "# Placeholder"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/index.asciidoc",
    "content": "= Tigase User Guide\nTigase Team <team@tigase.com>\n:toc:\n:numbered:\n:website: http://tigase.net\n\n:leveloffset: 1\n:no title:\n:no author:\n\ninclude::text/User_Guide_01_Jabber_XMPP_Introduction.asciidoc[]\n\ninclude::text/User_Guide_02_Installing_Minichat_on_your_Website.asciidoc[]\n\ninclude::text/User_Guide_03_How_to_use_Tigase_Service.asciidoc[]\n\ninclude::text/User_Guide_04_Psi_Initial_Configuration.asciidoc[]\n\n//MSNTransport removed due to JETI missing from website, is this still supported?\n//include::text/User_Guide_05_Tigase_Service_and_MSN_Transport_from_Client_Side.asciidoc[]\n\n//include::text/User_Guide_06_Jeti_and_MSN_Transport_on_tigase.org.asciidoc[]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/UserGuide.asciidoc",
    "content": "= Jabber/XMPP introduction\nArtur Hefczyc <artur.hefczyc@tigase.net>\nv2.0, June 2014: Reformatted for AsciiDoc.\n:toc:\n:numbered:\n:website: http://tigase.net\n:Date: 2009-11-25 20:51\n\n== Jabber/XMPP is Instant Messaging Technology\nAll federated *Jabber/XMPP* servers are connected in one global communications network allowing you to send messages to friends who have accounts on other Jabber servers.\n\nThis is very much like sending e-mail but the difference between Jabber and e-mail is the same as the difference between sending a traditional mail and talking on the phone.\n\nAll messages sent through Jabber are sent instantly and you also receive responses instantly. More over you can see whether your mate is online and available for talking or not.\n\nThere exists similar technologies to Jabber like Yahoo, MSN, and ICQ. There are, however, quite a few differences.\n\nJabber is an open standard which means everybody can know how it works, everybody can implement their own software connecting to the network both client and server side.\n\nThe server side is actually the biggest difference and advantage. Many companies have offices in different locations, and such instant messaging technology could be very useful to employees for communication. Companies are not inclined to allow confidential discussions to go outside the company's network. Especially if it is not very secure to leave such information on third party public servers.\n\nJabber on the other hand, allows you to deploy server software on your own company network. Employees can then talk securely and all information remains on the company's secure network. Of course if offices are located in different locations or countries then all messages are transmitted over the public network - the Internet. This is not a problem since Jabber supports SSL/TLS - secure encrypted connections which helps you protect your discussion.\n\nThen if your employees need to contact customers outside your company, the whole discussion can go through your server and a server located on the customer side.\n\nThere are many other scenarios and use cases but I hope this brief introduction gives you an idea of the differences and advantages of Jabber technology.\n\n\n[[X2]]\n== Installing Minichat on Your Website\nWe have made Minichat available to demonstrate new projects we are working on, to run some tests, and collect your opinions. The feedback we've recieved has exceeded our expectations. The most common question was: _Can I/how can I install this on my website?_\n\nInstalling Minichat on your website is very simple so I am providing instructions here for all of you that want to include the Minichat client on your website and allow visitors to chat with you.\n\n_Just to remind you - this code is under development and will be updated and changed frequently. It may even stop working temporarily or permanently.  We can and will intentionally block certain users or IP addresses if we discover any abuse. If you are ready for this and still want to use it continue reading..._\n\nFirst thing to know: Minichat will only work with the *tigase.org* Jabber/XMPP server right now.  _This is not because of some limitations in the code or special non-standard implementation. This is to simplify deployment of the service. If you wanted Minichat to connect to a different domain/Jabber server the installation would be much more difficult, involving Apaches proxy_mod installation, configuration and possibly Bosh component/server deployment._\n\nSecond thing to know: Minichat connects to the server as anonymous user. To avoid sending spam the anonymous user can only send messages to users within the single Jabber/XMPP server. It means that although you can configure Minichat to send messages to user@jabber.org, Tigase server won't deliver those messages.\n\n=== Instructions:\n. Register an account on the tigase.org website. For purposes of this guide let's say the account name is: *your-account*. The Jabber ID will be: your-account@tigase.org.  *Note!* There seems to be some confusion so let me clarify this. You create an account on the http://tigase.org[www.tigase.org] website but your Jabber account domain is: *tigase.org*.\n. Setup the Jabber/XMPP client of your choice to connect to the Tigase server in domain: *tigase.org*. Note you must allow plain text login. TLS is supported so the connection is secure and your password is still safe.\n. There are a few ways for adding the client to the website but you always use startup parameters as URL query to the client link. Following parameters are possible:\n\n - *jid=your-account@tigase.org* tells the client who you want website visitors talk to. Normally you put your own account here.\n - *name=YourName* screen name (displayed name) of your account.\n - *domain=tigase.org* domain name you want Minichat to connect to. At the moment only tigase.org is allowed.\n - *autologin=true* determines whether the Minichat client automatically connects to the server when the page is loaded or waits for the visitor to click on the title bar.\n\n\n1. The first way described is to put the client in exactly the same way as it is on the http://tigase.org[www.tigase.org] website. The chat window is always visible but the client is not connected to the server until someone clicks on the Minichat title bar. Include in your page following code:\n+\n----\n<iframe\n  src=\"http://minichat.tigase.org/MesComp.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n----\n+\n2. Very similar to the first option. The only difference is that the client automatically connects to the server and is ready for chatting without need to click on the title bar. Include following code:\n+\n----\n<iframe\n  src=\"http://minichat.tigase.org/MesComp.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org&autologin=true\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n----\n+\n3. The third option is the least intrusive but the most complex to install. It puts a small, clickable image with text on your page: *Click to chat with....* When the website visitor clicks a new window pops up with the Minichat which automatically connects to the server. You need to put some code in the web page header:\n+\n----\n<link rel=\"stylesheet\" type=\"text/css\"\n  href=\"http://minichat.tigase.org/minichat.css\"/>\n<link rel=\"stylesheet\" type=\"text/css\"\n  href=\"http://minichat.tigase.org/mygwt-all.css\" />\n----\n+\nAnd similar to other configurations code in the web page body:\n+\n----\n<iframe\n  src=\"http://minichat.tigase.org/Runner.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n----\n\n_Enjoy and send us your comments..._\n\n[[X3]]\n== How to Use Tigase Service\n=== This Article Describes How to use *tigase.org* Service for Instant Communications.\n\nYou have to install and run a Jabber client application to use the service.\n\n==== *Short instructions:*\nUsually you just need to enter Jabber user name of the form: user@tigase.org. Your Jabber client should take care of all other things as our service doesn't need any special settings.  If you don't have an account on tigase.org server yet just tick the option to register new account. That's it!\n\n==== *Long Instructions:*\nGood news is that there are many programs to choose from which allow you to communicate through our server. So you can pick up your favorite application or use an existing one that is compatible and start using our service.\n\nAll clients presented below support multiple accounts on Jabber servers. What this means is that you can have a few Jabber accounts on different Jabber servers and you can still use just one program to connect to all of them at the same time.\n\nFull list of all known Jabber clients is very long. You can obviously try them all but below is a selection which is recommended by Tigase team.  The selected programs might not be the best choice for you but these programs have been tested and we can offer help with using them.  Here is a list of recommended instant messaging clients:\n\n- http://psi-im.org/about[Psi]\nPure Jabber client. Although it supports only Jabber network it is a very user friendly and comfortable program. It works on most popular operating systems like Linux, MS Windows, and Apple MacOS X.\n- http://www.gajim.org/[Gajim]\nThis is another Jabber only client. Very user friendly and works on most of Linux distributions, FreeBSD, and MS Windows.\n- http://www.pidgin.im/[Pidgin] (previously http://gaim.sourceforge.net/[Gaim])\nThis is not just a Jabber client. This type of application is called multicommunicator as apart from Jabber it supports many other instant messagin networks/protocols such as: AIM/ICQ, MSN, Yahoo, Gadu-Gadu, IRC, and a few others. So it is especially convenient if you have friends using other messaging networks. Pidgin works on most Linux distributions, and on MS Windows.\n- http://kopete.kde.org/[Kopete]\nThis is a http://www.kde.org/[KDE] component and although it only works on Linux based system it also supports many of the most popular instant messaging protocols apart from Jabber like: AIM, Gadu-Gadu, ICQ, IRC, MSN, Yahoo.\n\nInstall the Jabber client of your choice and set up for a Tigase account:\n\n\n[[X4]]\n== Configuration instructions for Psi\n=== Psi - Initial configuration\nThe first time you run Psi you see a screen like this:\n\nimage:images/psi-first-run.png[Psi First Run]\n\nTo connect to tigase.org server we need to configure the program. Below are step-by-step instructions for novice users on how to setup Psi.\n\n1. Psi can connect to many Jabber servers at the same time so we have to identify each connection somehow. The first thing to do is assign a name to the connection we just created. As we are going to define connection to tigase.org server let's just name it: *Tigase*.\n+\nimage:images/psi-add-account.png[Psi Add Account]\n+\n*Note!* At the moment you can register an account through the Web site only.  This is a single account for both services: The Drupal website and Jabber/XMPP service on the tigase.org domain. If you want to have a Jabber account on the tigase.org server go to the registration page, un-tick \"Register new account\", and go to the point no 5. You can use guide points 2-4 to register a Jabber account on any other Jabber server.\n\n2. When you press the Add button you will see next window where you can enter your Jabber account details:\n+\nimage:images/psi-register-account-empty.png[Psi Empty Account]\n\n3. Invent your user name for the account on Tigase server. Let's assume your user name is: *frank*. Jabber ID's however consist of 2 parts - your user name and server address. Exactly the same as an e-mail address. As you are registering an account on tigase.org server, you will have to enter in this field: *frank@tigase.org*. Next enter the password of your choice and click the Register button.\n+\nimage:images/psi-register-account-nossl.png[Psi Register Account]\n\n4. On successful registration you will receive a confirmation message and you should see a window like this:\n+\nimage:images/psi-register-account-success.png[Register Account Success]\n+\nIt may happen that somebody earlier registered an account with the same name you've selected for yourself. If so, you will receive error message. You will then have to select another user name and try to register again.\n\n5. After clicking the *OK* button you will see a window with your connection and account setup. You can stick with default values for now.\n+\nimage:images/psi-after-registration.png[PSI After Registration]\n+\nJust click the *Save* button and this window closes.\n\n6. Now you have your account configured and ready to use but you are still off-line. You can find out whether you are on-line or off-line by looking at the bottom of main Psi window. There you can see *Offline* text.\n+\nClick on this *Offline* text and you will see a list of possible options. Just select *Online*.\n+\nimage:images/psi-connected.png[PSI Connected]\n+\nNow you are connected!\n\n\nWell, you are now connected but how to talk to other people? How to add friends to the contact list?  You can send a message to your friends stright away using the *Psi menu* option *New blank message*. It is much more convenient however, if you could see which of your friends is online and available for chatting and if you could start talking to your friend just by clicking on his name.\n\n=== Short Instructions How to Add Your First Contact\n1. Click on Psi menu - the button next to the *Online* text. You will see something like this:\n+\nimage:images/psi-menu.png[PSI Menu]\n+\nFrom all menu options select the top one - Add a contact:\n+\nimage:images/psi-menu-add-contact.png[PSI Menu add Contact]\n\n2. The next window will display where you can enter your contact details:\n+\nimage:images/psi-add-user-empty.png[PSI Add User Empty]\n+\nYou have to know the Jabber ID of the person you want to add to your contact list. Let's assume, for example, you want to add Tigase server administrator's Jabber ID to your contact list. So, after you enter these details the window will look like this:\n+\nimage:images/psi-add-user-filled.png[PSI Add User Filled]\n+\nClick the *Add* button.\n\n3. Now you will see a confirmation window that a new person has been added to your contact list:\n+\nimage:images/psi-kobit-added.png[PSI Kobit Added]\n+\nBut there is more behind the scenes. Adding a contact to your *Roster* (contact list) usually means you can see whether the person is online and available to talk or not. The person however, may not wish you to see his presence. So, to make sure the other person accepts you as a friend Psi sent a request to the address you just entered with the question of whether he agrees to show his presence to you.\n+\nYou won't be able to see the users availability until he sends confirmation.\n\n4. Once the other user sends confirmation back, you will usually receive 2 system events:\n+\nimage:images/psi-kobit-auth-received.png[PSI Kobit Auth Received]\n\n5. Click on the contact to see a window with these messages:\n+\nimage:images/psi-authorized-window.png[PSI Authorized Window]\n\n6. One message just says you have been authorized by the other user:\n+\nimage:images/psi-authorized-window-2.png[PSI Authorized Window 2]\n+\nSo you simply click *Next* to see the second message.\n\n7. The second message is a bit more interesting. It contains the question of whether you also authorize the other user to see your presence. If you want to accept this request just click *Add/Auth*.\n+\nimage:images/psi-authorized-window-3.png[PSI Authorized Window 3]\n\n8. Finally main Psi window with your new contact:\n+\nimage:images/psi-kobit-added-authorized.png[PSI Kobit Added Authorized]\n\n\nWell done!\n\nYou are ready to start Jabbering. Good luck.\n\nWhere to go next? For detailed Psi documentation refer to the program Wiki page: http://psi-im.org/wiki/Main_Page\n\n\n[[X5]]\n== Tigase service and MSN transport from client side\nMSN transport is a separate module which allows you to connect to your MSN account and contact other people on the MSN network from your Jabber client.  We use http://delx.cjb.net/pymsnt/[PyMSN-t] application as a MSN transport which is a separate project from Tigase server. Both applications integrate very well and detailed configuration instructions are available in http://www.tigase.org/node/1191[this guide].\n\nimage:images/tigase-register-2-s.png[Tigase Register]\n\nAt the moment the MSN transport installed on *tigase.org* server is available for local users only.  You also need an account on http://get.live.com/mail/options[Hotmail's] server and a Jabber/XMPP client of your choice:\n\n- http://psi-im.org/[Psi]\n- http://www.pidgin.im/[Pidgin]\n- http://coccinella.im/[Coccinella]\n- http://jeti-im.org/[Jeti] - Also available on Tigase Website.\n- http://jwchat.sourceforge.net/[JWChat] - Also available on Tigase Website.\n\nThere are many other clients available...\n\nHere are instructions on how to use the MSN transport on *tigase.org* with different Jabber/XMPP clients.\n\nThe first and most important thing to note is that you can not register an account on *tigase.org* server using your Jabber client. You have to create a new account using http://www.tigase.org/user/register[Tigase website]. This is because Tigase website (which runs on http://drupal.org/[Drupal]) shares account information with the Jabber service and all account management is done via the website interface.\n\nAll Jabber/XMPP capable clients can use MSN transport as it needs very basic Jabber/XMPP protocol features. Unfortunately, some clients, especially multi-protocol clients like http://www.pidgin.im/[Pidgin] don't fully support the protocol and cannot initialize MSN transport properly. There is a workaround though. Again, using what Tigase Website offers, you can initialize MSN transport and then switch back to your favorite client.\n\nLet's say we have already requested a *test* account on\nhttp://www.tigase.org/user/register[Tigase website] with password \\*\\*\\*\\**\nand we also have a MSN account: kobit12@hotmail.com with password: \\*\\*\\*\\******.\n\n=== Jeti\nJeti is described as the first client because it might be needed for users of some other clients to initialize MSN transport for your account.\n\n=== Pidgin\nAs I mentioned earlier, Pidgin doesn't support all Jabber extensions needed for registering to MSN transport. So unfortunately you have to use a different client to add this transport to your roster. Ideally you should use one of the native Jabber stand-alone clients like http://psi-im.org/[Psi], or http://coccinella.im/[Coccinella]. However, If you don't want to install any other clients you can use http://jeti-im.org/[Jeti] which is available on Tigase website preinstalled and preconfigured for use. Please refer to http://www.tigase.org/node/1343[this guide] for details on how to use Jeti client to get MSN transport working.\n\nOk, now as you probably have MSN transport activated for you account you can start using http://www.pidgin.im/[Pidgin] to communicate with either Jabber users or MSN users.  First thing to do is basic Pidgin configuration to connect to your Jabber account on *tigase.org* server. Click *Accounts* in your main menu and then *Add/Edit* to get to the window with all your accounts listing. There is a button Add. After you press it you get to a window as below.\n\nimage:images/pidgin-add-account-m.png[Pidgin Add Account]\n\nPlease enter all your login details as on the example screenshot. Your user name, Screen name, and Password will be different but Domain should be the same: *tigase.org*. After you fill in all fields *don't* press Register. You have to press *Save*.\n\nimage:images/pidgin-no-hotmail-budy-m.png[Pidgin no Hotmail]\n\nOk. Assuming everything was enterred correctly and you have configured Pidgin to login automatically, your main window should look like the one on the left hand side. Your buddy list might be empty if you didn't add anybody to your list yet or, if you didn't register to MSN transport yet.\n\nIf MSN transport is not activated yet, please disconnect Pidgin from *tigase.org* server and use a different client as described above.\n\nOn the other hand if you did everything already, and you have an old MSN account with lots of contacts, your buddy list may look completely different as all the contacts you have will be automatically pulled into your Jabber roster and should show on the list.\n\nI have created a completely new MSN account for the purpose of writing this guide and I don't have any MSN contacts yet. So my list is quite simple - a single Jabber contact and MSN transport which shows as a normal contact. Remember Pidgin can't distinguish between transports and regular accounts.\n\nIn such a case one of the first things I should do is add a new MSN contact to be able to communicate with somebody and see whether he/she is on-line or not.\n\nAdding new contact is simple as long as Pidgin thinks it is normal Jabber contact. So we cannot actually enter: user_name@hotmail.com in the *Add buddy* window because this is a Hotmail account which is not directly available.  After the @ character you have to put a valid Jabber domain, not MSN.\n\nIf you look at the image below it should become clear now.\n\nimage:images/pidgin-add-hotmail-budy-m.png[Pidgin add Hotmail]\n\nThe whole MSN account address is a user name for Jabber identifier purposes and you have to replace @ with %. Then you add @ and MSN transport address. As an *alias* you can use anything. I have used a real Hotmail address to make it easier later on to see what the account is.\n\nEnter everything carefuly and press *Add*.\n\nAfter you press the *Add* button the contact you are adding should receive a subscription request as well receiving a subscription request yourself. The Pidgin window should look similar to the example below.\n\nimage:images/pidgin-autorize-hotmail-budy-m.png[Pidgin Authorize Hotmail]\n\nOf course you need to press the *Authorize* button on both sides (or your mate on MSN network accepts your subscription request) and now the final window should look like the one below. The new buddy is on your list and you can click on his/her name and start chatting.\n\nimage:images/pidgin-hotmail-budy-added-m.png[Pidgin Hotmail Buddy Added]\n\nOne final funny discovery I made during writing this guide.  I have created a new MSN account just for my tests and I have also used my old MSN account for subscribing and adding the account to buddy list on both sides. Moreover, I access both MSN accounts through MSN transport and in my tests I was communicating from one Jabber client (Psi) through MSN gateway to the MSN server and back through my MSN gateway back to other Jabber client (Pidgin) to the other account.  Apparently MSN transport spotted this and knowing how silly such a use case this is, sends me one extra message to my chat window. Have a look at the last screenshot and have fun. Remember to not communicate between 2 Jabber accounts using your 2 MSN accounts as this might be discovered by the smart, open source software.\n\nimage:images/pidgin-hotmail-chat-m.png[Pidgin Hotmail Chat]\n\n[[X6]]\n== Jeti and MSN Transport on tigase.org\n*Make sure you are not connected to the *Tigase* server account with another Jabber client at the same time as this may affect your transport configuration.*\n\nJeti is available on Tigase website, preinstalled and preconfigured. You can run it by clicking on http://www.tigase.org/content/jeti-and-msn-transport-tigaseorg[this link].  Enter you user name and password to login. In my case this is test and \\*\\*\\*.  Click *Login* and go to next page...\n\nimage:images/jeti-login-m.png[Jeti Login]\n\nYou are now logged in. You may see some contacts on the buddy list or an empty list if you have no contacts. You can add somebody or just start chatting, but in this guide we will focus on the MSN transport configuration.\n\nNow click the *Jeti* button and select Manage Services menu option...\n\nimage:images/jeti-services-menu-cut-m.png[Jeti Services Menu]\n\nAs a result you will get the windows with all *tigase.org* services.\n\nimage:images/jeti-change-server.png[Jeti Change Server]\n\nThis version of Jeti client doesn't support service browsing yet so you have to enter the correct address of MSN transport: msn.tigase.org.\n\nClick *Change server* and you will get to another window which looks like this one.\n\nimage:images/jeti-msn-transport.png[Jeti MSN Transport]\n\nNow single click on the *PyMSNt Commands* text to open another window where you have to enter you MSN user name and password.\n\nimage:images/jeti-hotmail-registration-m.png[Jeti Hotmail Registration]\n\nMake sure you enter your full MSN account name here including the _hotmail.com_ part or any other domain name you use for you MSN account.\n\nNow click OK.\n\nWell, you clicked OK and nothing really happened. The main *Jeti* windows looks just as it looked before, the same. Possibly empty buddy list, and no track of MSN transport. Unfortunately this Jeti version doesn't refresh the transport list properly and you have to re-login to see the transport. Jeti's author is aware of this problem and it will be addressed in next release.  So please close the Jeti window and start the application again entering you Tigase user name and password.\n\nimage:images/jeti-logged-with-msn-offline-m.png[Jeti Logged with MSN Offline]\n\nAs you can see the MSN transport is available now but it is grayed out, which means you are not logged into the MSN service.\n\nTo activate (login) to the MSN service, right click on the MSN Transport to get connect menu. Select Log On...\n\nimage:images/jeti-msn-login-cut-m.png[Jeti MSN Login Cut]\n\nIf everything was entered correctly, and if the MSN service is available, you should be logged into the transport and it should show in green color. All of your MSN contacts should be automatically pulled into your application.  For the Jabber client, there is now no difference between MSN contacts and Jabber contacts. So, you can simply continue to use Jeti or close it and login with another Jabber client.\n\nimage:images/jeti-logged-with-msn-online-m.png[Jeti Logged With MSN Online]\n\nYou can now communicate with all people regardless if they are available through XMPP or MSN.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_01_Jabber_XMPP_Introduction.asciidoc",
    "content": "= Jabber/XMPP introduction\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2009-11-25 15:51\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n== Jabber/XMPP is Instant Messaging Technology\nAll federated *XMPP* servers are connected in one global communications network allowing you to send messages to friends who have accounts on other Jabber servers.\n\nThis is very much like sending e-mail but the difference between Jabber and e-mail is the same as the difference between sending a traditional mail and talking on the phone.\n\nAll messages sent through Jabber are sent instantly and you also receive responses instantly. More over you can see whether your mate is online and available for talking or not.\n\nThere exists similar technologies to Jabber like Yahoo, MSN, and ICQ. There are, however, quite a few differences.\n\nXMPP is an open standard which means everybody can know how it works, everybody can implement their own software connecting to the network both client and server side.\n\nThe server side is actually the biggest difference and advantage. Many companies have offices in different locations, and such instant messaging technology could be very useful to employees for communication. Companies are not inclined to allow confidential discussions to go outside the company's network. Especially if it is not very secure to leave such information on third party public servers.\n\nXMPP servers on the other hand, allows you to deploy server software on your own company network. Employees can then talk securely and all information remains on the company's secure network. Of course if offices are located in different locations or countries then all messages are transmitted over the public network - the Internet. This is not a problem since XMPP supports SSL/TLS - secure encrypted connections which helps you protect your discussion.\n\nThen if your employees need to contact customers outside your company, the whole discussion can go through your server and a server located on the customer side.\n\nThere are many other scenarios and use cases but I hope this brief introduction gives you an idea of the differences and advantages of XMPP technology.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_02_Installing_Minichat_on_your_Website.asciidoc",
    "content": "= Installing Minichat on Your Website\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2009-11-25 15:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nWe have made Minichat available to demonstrate new projects we are working on, to run some tests, and collect your opinions. The feedback we've recieved has exceeded our expectations. The most common question was: _Can I/how can I install this on my website?_\n\nInstalling Minichat on your website is very simple so I am providing instructions here for all of you that want to include the Minichat client on your website and allow visitors to chat with you.\n\n_Just to remind you - this code is under development and will be updated and changed frequently. It may even stop working temporarily or permanently.  We can and will intentionally block certain users or IP addresses if we discover any abuse. If you are ready for this and still want to use it continue reading..._\n\nFirst thing to know: Minichat will only work with the *tigase.org* XMPP server right now.  _This is not because of some limitations in the code or special non-standard implementation. This is to simplify deployment of the service. If you wanted Minichat to connect to a different domain or XMPP server the installation would be much more difficult, involving Apaches proxy mod installation, configuration and possibly Bosh component/server deployment._\n\nSecond thing to know: Minichat connects to the server as anonymous user. To avoid sending spam the anonymous user can only send messages to users within the XMPP server. It means that although you can configure Minichat to send messages to *user@jabber.org*, Tigase server won't deliver those messages.\n\n== Instructions:\n1. link:http://www.tigase.org/user/register[Register an account] on the link:http://www.tigase.org[tigase.org] website. For purposes of this guide let's say the account name is: *your-account*. The Jabber ID will be: *your-account@tigase.org*.\n+\n*Note!* There seems to be some confusion so let me clarify this. You create an account on the link:http://tigase.org[www.tigase.org] website but your Jabber account domain is: *tigase.org*.\n+\n2. Setup the Jabber/XMPP client of your choice to connect to the Tigase server in domain: *tigase.org*. Note you must allow plain text login. TLS is supported so the connection is secure and your password is still safe.\n3. There are a few ways for adding the client to the website but you always use startup parameters as URL query to the client link. Following parameters are possible:\n+\n - *jid=your-account@tigase.org* tells the client who you want website visitors talk to. Normally you put your own account here.\n - *name=YourName* screen name (displayed name) of your account.\n - *domain=tigase.org* domain name you want Minichat to connect to. At the moment only *tigase.org* is allowed.\n - *autologin=true* determines whether the Minichat client automatically connects to the server when the page is loaded or waits for the visitor to click on the title bar.\n - The first way described is to put the client in exactly the same way as it is on the link:http://tigase.org[www.tigase.org] website. The chat window is always visible but the client is not connected to the server until someone clicks on the Minichat title bar. Include in your page following code:\n+\n[source,html]\n-----\n<iframe\n  src=\"http://minichat.tigase.org/MesComp.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n-----\n - By adding a single bit of code: +autologin=true+ the client automatically connects to the server and is ready for chatting without need to click on the title bar.\n+\n[source,html]\n-----\n<iframe\n  src=\"http://minichat.tigase.org/MesComp.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org&autologin=true\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n-----\n - A third option is the least intrusive but the most complex to install. It puts a small, clickable image with text on your page: *Click to chat with....* When the website visitor clicks a new window pops up with the Minichat which automatically connects to the server. You need to put some code in the web page header:\n+\n[source,html]\n-----\n<link rel=\"stylesheet\" type=\"text/css\"\n  href=\"http://minichat.tigase.org/minichat.css\"/>\n<link rel=\"stylesheet\" type=\"text/css\"\n  href=\"http://minichat.tigase.org/mygwt-all.css\" />\n-----\n+\nAnd similar to other configurations code in the web page body:\n+\n[source,html]\n-----\n<iframe\n  src=\"http://minichat.tigase.org/Runner.html?jid=your-account@tigase.org&name=YourName&domain=tigase.org\"\n  width=\"220px\" height=\"250px\" frameborder=\"0\"></iframe>\n-----\n\n_Enjoy and send us your comments..._\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_03_How_to_use_Tigase_Service.asciidoc",
    "content": "= How to Use Tigase Service\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2009-11-25 15:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\n== This Article Describes How to use *tigase.org* Service for Instant Communications\nYou have to install and run a Jabber client application to use the service.\n\n=== Short instructions:\n\nUsually you just need to enter the user name of the form: user@tigase.org. Your XMPP client should take care of all other things as our service doesn't need any special settings.  If you don't have an account on tigase.org server yet just tick the option to register new account. That's it!\n\n=== Long Instructions:\nThe good news is that there are many programs to choose from which allow you to communicate through our server. So you can pick up your favorite application or use an existing one that is compatible and start using our service.\n\nAll clients presented below support multiple accounts on Jabber or XMPP servers. What this means is that you can have a few Jabber accounts on different servers and you can still use just one program to connect to all of them at the same time.\n\nThe full list of all known XMPP clients is very long. You can obviously try them all but below is a selection which is recommended by the Tigase team.  The selected programs might not be the best choice for you, but these programs have been tested and we can offer help with using them.  Here is a list of recommended instant messaging clients:\n\n- http://psi-im.org/about[Psi]\nPure XMPP client. Although it supports only Jabber networks it is a very user friendly and comfortable program. It works on most popular operating systems like Linux, MS Windows, and Apple MacOS X.\n- http://www.gajim.org/[Gajim]\nThis is another Jabber only client. Very user friendly and works on most of Linux distributions, FreeBSD, and MS Windows.\n- http://www.pidgin.im/[Pidgin] (previously http://gaim.sourceforge.net/[Gaim])\nThis is not just a Jabber client. This type of application is called multicommunicator as apart from Jabber it supports many other instant messagin networks/protocols such as: AIM/ICQ, MSN, Yahoo, Gadu-Gadu, IRC, and a few others. So it is especially convenient if you have friends using other messaging networks. Pidgin works on most Linux distributions, and on MS Windows.\n- http://kopete.kde.org/[Kopete]\nThis is a http://www.kde.org/[KDE] component and although it only works on Linux based system it also supports many of the most popular instant messaging protocols apart from Jabber like: AIM, Gadu-Gadu, ICQ, IRC, MSN, Yahoo.\n\nInstall the XMPP client of your choice and set up for a Tigase account.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_04_Psi_Initial_Configuration.asciidoc",
    "content": "= Configuration Instructions for Psi\n\n== Psi - Initial Configuration\n\nThe first time you run Psi you see a screen like this:\n\nimage:images/psi-first-run.png[Psi First Run]\n\nTo connect to tigase.org server we need to configure the program. Below are step-by-step instructions for novice users on how to setup Psi.\n\n1. Psi can connect to many servers at the same time so we have to identify each connection. The first thing to do is assign a name to the connection we just created. As we are going to define connection to tigase.org server let's just name it: *Tigase*.\n+\nimage:images/psi-add-account.png[Psi Add Account]\n+\n*Note!* _At the moment you can register an account through link:http://www.tigase.org/user/register[the Web site only].  This is a single account for both services: The Drupal website and XMPP service on the tigase.org domain. If you want to have a Jabber account on the *tigase.org* server go to the link:http://www.tigase.org/user/register[registration page], un-tick \"Register new account\", and go to the point no *5*. You can use guide points 2-4 to register a Jabber account on any other Jabber server._\n\n2. When you press the *Add* button you will see next window where you can enter your Jabber account details:\n+\nimage:images/psi-register-account-empty.png[Psi Empty Account]\n\n3. Invent your user name for the account on Tigase server. Let's assume your user name is: *frank*. Jabber ID's however consist of 2 parts - your user name and server address. Exactly the same as an e-mail address. As you are registering an account on tigase.org server, you will have to enter in this field: *frank@tigase.org*. Next enter your password and click the *Register* button.\n+\nimage:images/psi-register-account-nossl.png[Psi Register Account]\n\n4. On successful registration you will receive a confirmation message and you should see a window like this:\n+\nimage:images/psi-register-account-success.png[Register Account Success]\n+\nIt is possible that somebody may have already registered your chosen username. If so, you will receive error message and will then have to select another user name and try to register again.\n\n5. After clicking the *OK* button you will see a window with your connection and account setup. You can stick with default values for now.\n+\nimage:images/psi-account-properties-basic.png[]\n+\nJust click the *Save* button and this window closes.\n\n6. Now you have your account configured and ready to use but you are still off-line. You can find out whether you are on-line or off-line by looking at the bottom of main Psi window. There you can see *Offline* text.\n+\nimage:images/psi-after-registration.png[PSI After Registration]\n+\nClick on this *Offline* text and you will see a list of possible options. Just select *Online*.\n+\nimage:images/psi-connected.png[PSI Connected]\n+\nNow you are connected!\n\nThe box also allows you to choose other online statuses which can tell other users if you are away or busy.\n\n\nWell, you are now connected but how to talk to other people? How to add friends to the contact list?\n\nYou can send a message to your friends stright away using the *Psi menu* option *New blank message*. It is much more convenient however, if you could see which of your friends is online and available for chatting and if you could start talking to your friend just by clicking on his name.\n\n== Short Instructions How to Add Your First Contact\n\n1. Click on Psi menu - the button next to the *Online* text. You will see something like this:\n+\nimage:images/psi-menu.png[PSI Menu]\n+\nFrom all menu options select the top one - *Add a contact*:\n+\nimage:images/psi-menu-add-contact.png[PSI Menu add Contact]\n\n2. The next window will display where you can enter your contact details:\n+\nimage:images/psi-add-user-empty.png[PSI Add User Empty]\n+\nYou have to know the Jabber ID of the person you want to add to your contact list. Let's assume, for example, you want to add Tigase server administrator's Jabber ID to your contact list. So, after you enter these details the window will look like this:\n+\nimage:images/psi-add-user-filled.png[PSI Add User Filled]\n+\nClick the *Add* button.\n\n3. Now you will see a confirmation window that a new person has been added to your contact list:\n+\nimage:images/psi-kobit-added.png[PSI Kobit Added]\n+\nBut there is more behind the scenes. Adding a contact to your *Roster* (contact list) usually means you can see whether the person is online and available to talk or not. The person however, may not wish you to see his presence. So, to make sure the other person accepts you as a friend Psi sent a request to the address you just entered with the question of whether he agrees to show his presence to you.\n+\nYou won't be able to see the users availability until he sends confirmation.\n\n4. Once the other user sends confirmation back, you will usually receive 2 system events:\n+\nimage:images/psi-kobit-auth-received.png[PSI Kobit Auth Received]\n\n5. Click on the contact to see a window with these messages:\n+\nimage:images/psi-authorized-window.png[PSI Authorized Window]\n\n6. One message just says you have been authorized by the other user:\n+\nimage:images/psi-authorized-window-2.png[PSI Authorized Window 2]\n+\nSo you simply click *Next* to see the second message.\n\n7. The second message is a bit more interesting. It contains the question of whether you also authorize the other user to see your presence. If you want to accept this request just click *Add/Auth*.\n+\nimage:images/psi-authorized-window-3.png[PSI Authorized Window 3]\n\n8. Finally main Psi window with your new contact:\n+\nimage:images/psi-kobit-added-authorized.png[PSI Kobit Added Authorized]\n\n\nWell done!\n\nYou are ready to start Jabbering. Good luck.\n\nWhere to go next? For detailed Psi documentation refer to the program Wiki page: http://psi-im.org/wiki/Main_Page\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_05_Tigase_Service_and_MSN_Transport_from_Client_Side.asciidoc",
    "content": "= Tigase Service and MSN Transport From Client Side\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2009-11-25 15:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nMSN transport is a separate module which allows you to connect to your MSN account and contact other people on the MSN network from your XMPP client.  We use link:http://delx.cjb.net/pymsnt/[PyMSN-t] application as a MSN transport which is a separate project from Tigase server. Both applications integrate very well and detailed configuration instructions are available in the link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/[*Admin Guide*].\n\nimage:images/tigase-register-2-s.png[Tigase Register]\n\nAt the moment the MSN transport installed on *tigase.org* server is available for local users only.\n\nYou also need an account on http://get.live.com/mail/options[Microsoft Live's] server and an XMPP client of your choice:\n\n- link:http://psi-im.org/[Psi]\n- link:http://www.pidgin.im/[Pidgin]\n- link:http://coccinella.im/[Coccinella]\n- link:http://jeti-im.org/[Jeti] - Also available on Tigase Website.\n- link:http://jwchat.sourceforge.net/[JWChat] - Also available on Tigase Website.\n\nThere are many other clients available, but we cannot offer support on those clients.\n\nHere are instructions on how to use the MSN transport on *tigase.org* with the recommended XMPP clients.\n\nThe first and most important thing to note is that you can not register an account on *tigase.org* server using your XMPP client. You have to create a new account using link:http://www.tigase.org/user/register[Tigase website]. This is because the Tigase website (which runs on link:http://drupal.org/[Drupal]) shares account information with the XMPP service and all account management is done via the website interface.\n\nAll XMPP capable clients can use a MSN transport as it needs very basic XMPP protocol features. Unfortunately, some clients, especially multi-protocol clients like http://www.pidgin.im/[Pidgin] don't fully support the protocol and cannot initialize the MSN transport properly. There is a workaround though. Again, using what Tigase Website offers, you can initialize MSN transport and then switch back to your favorite client.\n\nLet's say we have already requested a *test* account on link:http://www.tigase.org/user/register[Tigase website] with password \\*\\** and we also have a MSN account:\nkobit12@hotmail.com with password: \\*\\*\\*\\*\\*\\*\\***.\n\n== Jeti\nJeti is described as the first client because it might be needed for users of some other clients to initialize MSN transport for your account.\n\nDue to the number of images used in the Jeti guide it has been moved to a xref:jetiMSN[separate page].\n\n== Pidgin\nAs mentioned earlier, Pidgin doesn't support all XMPP extensions needed for registering to MSN transport. So unfortunately you have to use a different client to add this transport to your roster. Ideally you should use one of the native XMPP stand-alone clients like link:http://psi-im.org/[Psi], or link:http://coccinella.im/[Coccinella]. However, If you don't want to install any other clients you can use http://jeti-im.org/[Jeti] which is available on Tigase's website preinstalled and preconfigured for use. Please refer to separate guide for details on how to use xref:jetiMSN[Jeti client] to get MSN transport working.\n\nOk, now as you probably have MSN transport activated for you account you can start using link:http://www.pidgin.im/[Pidgin] to communicate with either Jabber users or MSN users.\n\nFirstly, configure Pidgin to connect to your Jabber account on the *tigase.org* server. Click *Accounts* in your main menu and then *Add/Edit* to get to the window with all your accounts listing. There is a button Add. After you press it you get to a window as below.\n\nimage:images/pidgin-add-account-m.png[Pidgin Add Account]\n\nPlease enter all your login details as on the example screenshot. Your user name, screen name, and password will be different but the Domain should be the same: *tigase.org*. After you fill in all fields *DO NOT* click Register. Click *Save* instead.\n\nimage:images/pidgin-no-hotmail-budy-m.png[Pidgin no Hotmail]\n\nAssuming everything was entered correctly, and you have configured Pidgin to login automatically, your main window should look like the one on the left hand side. Your buddy list might be empty if you didn't add anybody to your list yet or, if you didn't register to MSN transport yet.\n\nIf MSN transport is not activated yet, please disconnect Pidgin from *tigase.org* server and use a different client as described above.\n\nOn the other hand if you did everything already, and you have an old MSN account with lots of contacts, your buddy list may look completely different as all the contacts you have will be automatically pulled into your roster and should show on the list.\n\nI have created a completely new MSN account for the purpose of writing this guide and as such there are no MSN contacts yet. As a result the list is quite simple - a single Jabber contact and MSN transport which shows as a normal contact. Remember Pidgin can't distinguish between transports and regular accounts.\n\nOnce you get to this point, one of the first things you should do is add a new MSN contact to be able to communicate with somebody and see whether he/she is on-line or not.\n\nAdding new contact is simple as long as Pidgin thinks it is normal Jabber contact. So we cannot actually enter: user_name@hotmail.com in the *Add buddy* window because this is a Hotmail account which is not directly available.  After the @ character you have to put a valid Jabber domain, not MSN.\n\nThe below image should clarify things.\n\nimage:images/pidgin-add-hotmail-budy-m.png[Pidgin add Hotmail]\n\nThe whole MSN account address is a user name for Jabber identifier purposes and you have to replace @ with %. Then you add @ and MSN transport address. As an *alias* you can use anything. I have used a real Hotmail address to make it easier later on to see what the account is.\n\nEnter everything carefuly and click *Add*.\n\nAfter you click the *Add* button the contact you are adding should receive a subscription request as well receiving a subscription request yourself. The Pidgin window should look similar to the example below.\n\nimage:images/pidgin-autorize-hotmail-budy-m.png[Pidgin Authorize Hotmail]\n\nOf course both parties need to *Authorize* the request on both sides (or your mate on MSN network accepts your subscription request) and now the final window should look like the one below. The new buddy is on your list and you can click on his/her name and start chatting.\n\nimage:images/pidgin-hotmail-budy-added-m.png[Pidgin Hotmail Buddy Added]\n\nOne final funny discovery I made during writing this guide.\n\nI have created a new MSN account just for my tests and I have also used my old MSN account for subscribing and adding the account to buddy list on both sides. Moreover, I access both MSN accounts through MSN transport and in my tests I was communicating from one Jabber client (Psi) through MSN gateway to the MSN server and back through my MSN gateway back to other Jabber client (Pidgin) to the other account.\n\nApparently MSN transport spotted this and knowing how silly such a use case this is, sends me one extra message to my chat window. Have a look at the last screenshot and have fun. Remember to not communicate between 2 Jabber accounts using your 2 MSN accounts as this might be discovered by the smart, open source software.\n\nimage:images/pidgin-hotmail-chat-m.png[Pidgin Hotmail Chat]\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/asciidoc/text/User_Guide_06_Jeti_and_MSN_Transport_on_tigase.org.asciidoc",
    "content": "[[jetiMSN]]\n= Jeti and MSN Transport on tigase.org\n:author: Artur Hefczyc <artur.hefczyc@tigase.net>\n:version: v2.0, June 2014: Reformatted for AsciiDoc.\n:date: 2009-11-25 15:51\n:revision: v2.1\n\n:toc:\n:numbered:\n:website: http://tigase.net\n\nMake sure you are not connected to the *Tigase* server account with a Jabber client as this may affect the transport configuration.\n\nJeti is available on Tigase website, preinstalled and preconfigured. You can run it by clicking on http://www.tigase.org/content/jeti-and-msn-transport-tigaseorg[this link].  Enter you user name and password to login. In my case this is test and \\*\\*\\*.  Click *Login* and go to next page...\n\nimage:images/jeti-login-m.png[Jeti Login]\n\nYou are now logged in. You may see some contacts on the buddy list or an empty list if you have no contacts. You can add somebody or just start chatting, but in this guide we will focus on the MSN transport configuration.\n\nNow click the *Jeti* button and select Manage Services menu option...\n\nimage:images/jeti-services-menu-cut-m.png[Jeti Services Menu]\n\nAs a result you will get the windows with all *tigase.org* services.\n\nimage:images/jeti-change-server.png[Jeti Change Server]\n\nThis version of Jeti client doesn't support service browsing yet so you have to enter the correct address of MSN transport: +msn.tigase.org+.\n\nClick *Change server* and you will get to another window which looks like this one.\n\nimage:images/jeti-msn-transport.png[Jeti MSN Transport]\n\nNow single click on the *PyMSNt Commands* text to open another window where you have to enter you MSN user name and password.\n\nimage:images/jeti-hotmail-registration-m.png[Jeti Hotmail Registration]\n\nMake sure you enter your full MSN account name here including the _hotmail.com_ part or any other domain name you use for you MSN account.\n\nNow click *OK*.\n\nWell, you clicked *OK* and nothing really happened. The main *Jeti* windows looks just as it looked before, the same. Possibly empty buddy list, and no track of MSN transport. Unfortunately this Jeti version doesn't refresh the transport list properly and you have to re-login to see the transport. Jeti's author is aware of this problem and it will be addressed in next release.\n\nSo please close the Jeti window and start the application again entering you Tigase user name and password.\n\nimage:images/jeti-logged-with-msn-offline-m.png[Jeti Logged with MSN Offline]\n\nAs you can see the MSN transport is available now but it is grayed out, which means you are not logged into the MSN service.\n\nTo activate (login) to the MSN service, right click on the *MSN Transport* to get connect menu. Select *Log On...*\n\nimage:images/jeti-msn-login-cut-m.png[Jeti MSN Login Cut]\n\nIf everything was entered correctly, and if the MSN service is available, you should be logged into the transport and it should show in green color. All of your MSN contacts should be automatically pulled into your application.\n\nFor the Jabber client, there is now no difference between MSN contacts and Jabber contacts. So, you can simply continue to use Jeti or close it and login with another Jabber client.\n\nimage:images/jeti-logged-with-msn-online-m.png[Jeti Logged With MSN Online]\n\nYou can now communicate with all people regardless if they are available through XMPP or MSN.\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/documentation/userguide/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>pom</packaging.type>\n\t\t<dist_path>../../..</dist_path>\n\t\t<guide_name>User</guide_name>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-docs-user</artifactId>\n\t<name>Tigase XMPP Server Documentation - ${guide_name} Guide</name>\n\n\t<packaging>pom</packaging>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-docs</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t</parent>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>output-docbook</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.agilejava.docbkx</groupId>\n\t\t\t\t<artifactId>docbkx-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-pdf</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-html</id>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-webhelp</id>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>generate-resources</phase>\n\t\t\t\t\t\t<id>generate-epub3</id>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-clean-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>Remove *.fo file</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/modules/master/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<slf4j.version>1.7.5</slf4j.version>\n\t\t<packet.version>7.1.0</packet.version>\n\t\t<packaging.type>bundle</packaging.type>\n\t\t<dir>target</dir>\n\t\t<maven.build.timestamp.format>yyyy-MM-dd/HH:mm:ss</maven.build.timestamp.format>\n\n\t\t<sign-keystore>/path/to/jks.keystore</sign-keystore>\n\t\t<sign-alias>alias</sign-alias>\n\t\t<sign-storepass>storepass</sign-storepass>\n\t\t<sign-keypass>keypass</sign-keypass>\n\t\t<sign-skip>true</sign-skip>\n\t\t<verbose-log>false</verbose-log>\n\t</properties>\n\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server-master</artifactId>\n\t<version>7.1.0-SNAPSHOT</version>\n\t\n\t<name>Tigase XMPP Server Master project</name>\n\n\t<packaging>pom</packaging>\n\n\t<url>http://www.tigase.org/</url>\n\t<issueManagement>\n\t\t<system>Redmine</system>\n\t\t<url>https://projects.tigase.org/projects/tigase-server</url>\n\t</issueManagement>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<id>kobit</id>\n\t\t\t<name>Artur Hefczyc</name>\n\t\t\t<email>kobit@tigase.org</email>\n\t\t\t<url>http://www.tigase.org/</url>\n\t\t\t<roles>\n\t\t\t\t<role>architect</role>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t</developer>\n\t</developers>\n\n\t<licenses>\n\t\t<license>\n\t\t\t<name>GNU Affero General Public License GPLv3</name>\n\t\t\t<url>http://www.gnu.org/licenses/agpl.txt</url>\n\t\t</license>\n\t</licenses>\n\n\t<scm>\n\t\t<connection>scm:git:https://repository.tigase.org/git/tigase-server.git</connection>\n\t\t<developerConnection>scm:git:https://repository.tigase.org/git/tigase-server.git</developerConnection>\n\t\t<url>https://projects.tigase.org/projects/tigase-server/repository</url>\n\t</scm>\n\n\t<organization>\n\t\t<name>\"Tigase, Inc.\"</name>\n\t\t<url>http://www.tigase.org</url>\n\t</organization>\n\n\t<modules>\n\t\t<module>../../</module>\n\t</modules>\n\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>doc</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>doc</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<modules>\n\t\t\t\t<module>../documentation</module>\n\t\t\t</modules>\n\t\t\t<properties>\n\t\t\t\t<maven.javadoc.skip>false</maven.javadoc.skip>\n\t\t\t\t<packaging.type>bundle</packaging.type>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>dist</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>dist</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<modules>\n\t\t\t\t<module>../distribution</module>\n\t\t\t</modules>\n\t\t\t<properties>\n\t\t\t\t<packaging.type>bundle</packaging.type>\n\t\t\t</properties>\n\t\t</profile>\n\t</profiles>\n\n\t<build>\n\n\t\t<directory>${dir}</directory>\n\t\t<finalName>${project.artifactId}-${gitVersion}</finalName>\n\t\t<!--<finalName>tigase-server-${project.version}-b${gitVersion}</finalName>-->\n\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-release-plugin</artifactId>\n\t\t\t\t<version>2.5.1</version>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>buildnumber-maven-plugin</artifactId>\n\t\t\t\t<version>1.2</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<timestampFormat>{0,date} {0,time}</timestampFormat>\n\t\t\t\t\t<doCheck>false</doCheck>\n\t\t\t\t\t<doUpdate>false</doUpdate>\n\t\t\t\t\t<getRevisionOnlyOnce>true</getRevisionOnlyOnce>\n\t\t\t\t\t<shortRevisionLength>8</shortRevisionLength>\n\t\t\t\t\t<autoVersionSubmodules>true</autoVersionSubmodules>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>create</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>2.5.1</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>1.8</source>\n\t\t\t\t\t<target>1.8</target>\n\t\t\t\t\t<encoding>UTF-8</encoding>\n\t\t\t\t\t<showDeprecation>true</showDeprecation>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-assembly-plugin</artifactId>\n\t\t\t\t<version>2.3</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>prod</id>\n\t\t\t\t\t\t<phase>none</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.gmaven</groupId>\n\t\t\t\t<artifactId>gmaven-plugin</artifactId>\n\t\t\t\t<version>1.5</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>gitver</id>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>execute</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<providerSelection>2.0</providerSelection>\n\t\t\t\t\t\t\t<properties>\n\t\t\t\t\t\t\t\t<script>git rev-list HEAD --count</script>\n\t\t\t\t\t\t\t</properties>\n\t\t\t\t\t\t\t<source>\n\t\t\t\t\t\t\t\tdef version\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tdef command = project.properties.script\n\t\t\t\t\t\t\t\t\tdef process = command.execute()\n\t\t\t\t\t\t\t\t\tprocess.waitFor()\n\n\t\t\t\t\t\t\t\t\tversion = process.in.text.trim()\n\t\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\t\tversion = '0'\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tprintln \"setting revision to: \" + version\n\n\t\t\t\t\t\t\t\tproject.properties.setProperty( 'gitVersion' , version )\n\n\t\t\t\t\t\t\t</source>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<version>2.9.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<quiet>true</quiet>\n\t\t\t\t\t\t\t<reportOutputDirectory>${project.reporting.outputDirectory}/docs/javadoc</reportOutputDirectory>\n\t\t\t\t\t\t\t<destDir>docs/javadoc</destDir>\n\t\t\t\t\t\t\t<maxmemory>512m</maxmemory>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\n\t\t<extensions>\n\t\t\t<extension>\n\t\t\t\t<groupId>org.apache.maven.wagon</groupId>\n\t\t\t\t<artifactId>wagon-ssh-external</artifactId>\n\t\t\t\t<version>2.10</version>\n\t\t\t</extension>\n\t\t\t<extension>\n\t\t\t\t<groupId>org.apache.maven.wagon</groupId>\n\t\t\t\t<artifactId>wagon-ssh</artifactId>\n\t\t\t\t<version>2.10</version>\n\t\t\t</extension>\n\t\t</extensions>\n\t</build>\n\n\t<repositories>\n\t\t<repository>\n\t\t\t<id>tigase</id>\n\t\t\t<name>Tigase repository</name>\n\t\t\t<url>http://maven.tigase.org</url>\n\t\t</repository>\n\t\t<repository>\n\t\t\t<id>tigase-snapshot</id>\n\t\t\t<name>Tigase repository</name>\n\t\t\t<url>http://build.xmpp-test.net/maven/</url>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t</snapshots>\n\t\t</repository>\n\t</repositories>\n\t<distributionManagement>\n\t\t<repository>\n\t\t\t<id>tigase</id>\n\t\t\t<name>Tigase repository</name>\n\t\t\t<url>scp://maven.tigase.org:/home/webapp/maven-repository</url>\n\t\t</repository>\n\t\t<snapshotRepository>\n\t\t\t<id>tigase-snapshot</id>\n\t\t\t<name>Tigase snapshot repository</name>\n\t\t\t<url>scp://build.xmpp-test.net:/home/maven/repository</url>\n\t\t</snapshotRepository>\n\t</distributionManagement>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/package-list/package-list",
    "content": "java.applet\njava.awt\njava.awt.color\njava.awt.datatransfer\njava.awt.dnd\njava.awt.event\njava.awt.font\njava.awt.geom\njava.awt.im\njava.awt.im.spi\njava.awt.image\njava.awt.image.renderable\njava.awt.print\njava.beans\njava.beans.beancontext\njava.io\njava.lang\njava.lang.annotation\njava.lang.instrument\njava.lang.management\njava.lang.ref\njava.lang.reflect\njava.math\njava.net\njava.nio\njava.nio.channels\njava.nio.channels.spi\njava.nio.charset\njava.nio.charset.spi\njava.rmi\njava.rmi.activation\njava.rmi.dgc\njava.rmi.registry\njava.rmi.server\njava.security\njava.security.acl\njava.security.cert\njava.security.interfaces\njava.security.spec\njava.sql\njava.text\njava.util\njava.util.concurrent\njava.util.concurrent.atomic\njava.util.concurrent.locks\njava.util.jar\njava.util.logging\njava.util.prefs\njava.util.regex\njava.util.zip\njavax.accessibility\njavax.activity\njavax.crypto\njavax.crypto.interfaces\njavax.crypto.spec\njavax.imageio\njavax.imageio.event\njavax.imageio.metadata\njavax.imageio.plugins.bmp\njavax.imageio.plugins.jpeg\njavax.imageio.spi\njavax.imageio.stream\njavax.management\njavax.management.loading\njavax.management.modelmbean\njavax.management.monitor\njavax.management.openmbean\njavax.management.relation\njavax.management.remote\njavax.management.remote.rmi\njavax.management.timer\njavax.naming\njavax.naming.directory\njavax.naming.event\njavax.naming.ldap\njavax.naming.spi\njavax.net\njavax.net.ssl\njavax.print\njavax.print.attribute\njavax.print.attribute.standard\njavax.print.event\njavax.rmi\njavax.rmi.CORBA\njavax.rmi.ssl\njavax.security.auth\njavax.security.auth.callback\njavax.security.auth.kerberos\njavax.security.auth.login\njavax.security.auth.spi\njavax.security.auth.x500\njavax.security.cert\njavax.security.sasl\njavax.sound.midi\njavax.sound.midi.spi\njavax.sound.sampled\njavax.sound.sampled.spi\njavax.sql\njavax.sql.rowset\njavax.sql.rowset.serial\njavax.sql.rowset.spi\njavax.swing\njavax.swing.border\njavax.swing.colorchooser\njavax.swing.event\njavax.swing.filechooser\njavax.swing.plaf\njavax.swing.plaf.basic\njavax.swing.plaf.metal\njavax.swing.plaf.multi\njavax.swing.plaf.synth\njavax.swing.table\njavax.swing.text\njavax.swing.text.html\njavax.swing.text.html.parser\njavax.swing.text.rtf\njavax.swing.tree\njavax.swing.undo\njavax.transaction\njavax.transaction.xa\njavax.xml\njavax.xml.datatype\njavax.xml.namespace\njavax.xml.parsers\njavax.xml.transform\njavax.xml.transform.dom\njavax.xml.transform.sax\njavax.xml.transform.stream\njavax.xml.validation\njavax.xml.xpath\norg.ietf.jgss\norg.omg.CORBA\norg.omg.CORBA.DynAnyPackage\norg.omg.CORBA.ORBPackage\norg.omg.CORBA.TypeCodePackage\norg.omg.CORBA.portable\norg.omg.CORBA_2_3\norg.omg.CORBA_2_3.portable\norg.omg.CosNaming\norg.omg.CosNaming.NamingContextExtPackage\norg.omg.CosNaming.NamingContextPackage\norg.omg.Dynamic\norg.omg.DynamicAny\norg.omg.DynamicAny.DynAnyFactoryPackage\norg.omg.DynamicAny.DynAnyPackage\norg.omg.IOP\norg.omg.IOP.CodecFactoryPackage\norg.omg.IOP.CodecPackage\norg.omg.Messaging\norg.omg.PortableInterceptor\norg.omg.PortableInterceptor.ORBInitInfoPackage\norg.omg.PortableServer\norg.omg.PortableServer.CurrentPackage\norg.omg.PortableServer.POAManagerPackage\norg.omg.PortableServer.POAPackage\norg.omg.PortableServer.ServantLocatorPackage\norg.omg.PortableServer.portable\norg.omg.SendingContext\norg.omg.stub.java.rmi\norg.w3c.dom\norg.w3c.dom.bootstrap\norg.w3c.dom.events\norg.w3c.dom.ls\norg.xml.sax\norg.xml.sax.ext\norg.xml.sax.helpers\n"
  },
  {
    "path": "tigase-server 7.1.0/package.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t\t<title>Tigase XMPP (Jabber) server ver ${APP_VER}</title>\n\t</head>\n\t<body bgcolor=\"white\">\n\t\t<h2>About</h2>\n\n\t\t<p>Copyright &copy; 2004-2013 Tigase.org. &lt;http://www.tigase.org/&gt;</p>\n\n\t\t<p>The <strong>Tigase Jabber/XMPP Server</strong> is <strong>Open Source and Free (AGPLv3)</strong> <a href=\"http://java.sun.com\">Java</a> based server.</p>\n\n\t\t<p>The server offers complete implementation of the XMPP protocol with a long list\n\t\tof extensions. Effcient, reliable and very extensible can be easily integrated\n\t\tit with your systems.</p>\n\n\t\t<p>The unique features of the Tigase server are</p>\n\n\t\t<ol>\n\t\t\t<li>High performance and scalability. Was tested with up to 500 000 concurrent\n\t\t\t users connected to a single machine and in cluster with over 1mln online users.</li>\n\t\t\t<li>High reliability. Tries to run as long as possible and tried to automaticaly\n\t\t\t recover from detected problems.</li>\n\t\t\t<li>Built-in many self monitoring functions. You can check your systems statistics\n\t\t\t via XMPP, JMX, HTTP, SNMP or you can automatically receive notifications about\n\t\t\t possible problems.</li>\n\t\t\t<li>Scripting support - scripts can be loaded/reloaded at run time.\n\t\t\t Many scripting languages are supported</li>\n\t\t\t<li>Virtual hosts support. You can have virtually unlimited virtual hosts which\n\t\t\t can be added/removed at runtime. You can temporarily block vhost or limit\n\t\t\t number of users per vhost.</li>\n\t\t\t<li>There is much more... check the official change log and the project website.</li>\n\t\t</ol>\n\n\t\t<p>People who contributed to the project in alphabetical order:</p>\n\t\t<ul>\n\t\t\t<li>Artur Hefczyc (kobit)</li>\n\t\t\t<li>Bartosz Małkowski (bmalkow)</li>\n\t\t\t<li>Mateusz Fiołka</li>\n\t\t\t<li>Tomasz Sterna (smoku)</li>\n\t\t\t<li>... and many others.</li>\n\t\t</ul>\n\n\t\t<h2>Installtion, configuration and compilation</h2>\n\n\t\t<p>The most recent documentation on all these topics is always available in the\n\t\tproject website: <a href=\"http://www.tigase.org/\">www.tigase.org</a>. Please\n\t\trefer to the website for all the details and always up to date guides.</p>\n\n\t\t<p>You would probably want to start with Quick Start:\n\t\t<a href=\"http://www.tigase.org/content/quick-start\">http://www.tigase.org/content/quick-start</a> documentation.</p>\n\n\t\t<p>The website also contains lots of other useful information like load tests\n\t\tresults, user discussions and online support and help always available to\n\t\tyou.</p>\n\n\t\t<p>This is ${APP_VER} release of the server. Please include the exact version\n\t\tnumber in all correspondence regarding the server.</p>\n\n\n\t\t<img src=\"Tiger.image\"/>\t<img src=\"JavaPowered.image\"/>\t<img src=\"SolarisReady.image\"/>\n </body>\n</html>\n"
  },
  {
    "path": "tigase-server 7.1.0/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<properties>\n\t\t<packaging.type>bundle</packaging.type>\n\t\t<tests.excludeGroups>tigase.tests.SlowTest</tests.excludeGroups>\n\t</properties>\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>tigase</groupId>\n\t<artifactId>tigase-server</artifactId>\n\t<name>Tigase XMPP Server</name>\n\t<packaging>${packaging.type}</packaging>\n\t<description>Tigase XMPP Server - OSGi bundle</description>\n\n\t<parent>\n\t\t<groupId>tigase</groupId>\n\t\t<artifactId>tigase-server-master</artifactId>\n\t\t<version>7.1.0-SNAPSHOT</version>\n\t\t<relativePath>modules/master</relativePath>\n\t</parent>\n\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>osgi</id>\n\t\t\t<activation>\n\t\t\t\t<activeByDefault>true</activeByDefault>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<packaging.type>bundle</packaging.type>\n\t\t\t\t<maven.javadoc.skip>true</maven.javadoc.skip>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>jar</id>\n\t\t\t<properties>\n\t\t\t\t<packaging.type>jar</packaging.type>\n\t\t\t\t<maven.javadoc.skip>true</maven.javadoc.skip>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>dist</id>\n\t\t\t<properties>\n\t\t\t\t<packaging.type>bundle</packaging.type>\n\t\t\t\t<maven.javadoc.skip>false</maven.javadoc.skip>\n\t\t\t\t<tests.excludeGroups></tests.excludeGroups>\n\t\t\t</properties>\n\t\t</profile>\n\t</profiles>\n\n\t<licenses>\n\t\t<license>\n\t\t\t<name>GNU Affero General Public License GPLv3</name>\n\t\t\t<url>http://www.gnu.org/licenses/agpl.txt</url>\n\t\t</license>\n\t</licenses>\n\t<build>\n\t\t<finalName>${project.artifactId}</finalName>\n\t\t\n\t\t\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<!--This plugin's configuration is used to store Eclipse m2e settings only. \n\t\t\t\t\tIt has no influence on the Maven build itself. -->\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.eclipse.m2e </groupId>\n\t\t\t\t\t<artifactId>lifecycle-mapping</artifactId>\n\t\t\t\t\t<version>1.0.0</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<lifecycleMappingMetadata>\n\t\t\t\t\t\t\t<pluginExecutions>\n\t\t\t\t\t\t\t\t<pluginExecution>\n\t\t\t\t\t\t\t\t\t<pluginExecutionFilter>\n\t\t\t\t\t\t\t\t\t\t<groupId>\n\t\t\t\t\t\t\t\t\t\t\torg.codehaus.gmaven\n\t\t\t\t\t\t\t\t\t\t</groupId>\n\t\t\t\t\t\t\t\t\t\t<artifactId>\n\t\t\t\t\t\t\t\t\t\t\tgmaven-plugin\n\t\t\t\t\t\t\t\t\t\t</artifactId>\n\t\t\t\t\t\t\t\t\t\t<versionRange>\n\t\t\t\t\t\t\t\t\t\t\t[1.5,)\n\t\t\t\t\t\t\t\t\t\t</versionRange>\n\t\t\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t\t\t<goal>execute</goal>\n\t\t\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t\t</pluginExecutionFilter>\n\t\t\t\t\t\t\t\t\t<action>\n\t\t\t\t\t\t\t\t\t\t<ignore></ignore>\n\t\t\t\t\t\t\t\t\t</action>\n\t\t\t\t\t\t\t\t</pluginExecution>\n\t\t\t\t\t\t\t</pluginExecutions>\n\t\t\t\t\t\t</lifecycleMappingMetadata>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\t\t\n\t\t\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t\t<artifactId>maven-bundle-plugin</artifactId>\n\t\t\t\t<version>2.4.0</version>\n\t\t\t\t<extensions>true</extensions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<instructions combine.inherited=\"append\">\n\t\t\t\t\t\t<manifestLocation>src/main/resources/META-INF/MANIFEST.MF</manifestLocation>\n\t\t\t\t\t\t<Implementation-Title>${project.name}</Implementation-Title>\n\t\t\t\t\t\t<Implementation-Version>${project.version}-b${gitVersion}/${buildNumber} (${maven.build.timestamp})</Implementation-Version>\n\t\t\t\t\t\t<Implementation-Build>${gitVersion}/${buildNumber} (${maven.build.timestamp})</Implementation-Build>\n\t\t\t\t\t\t<Tigase-Version>${project.version}-b${gitVersion}</Tigase-Version>\n\t\t\t\t\t\t<Bundle-Activator>tigase.osgi.Activator</Bundle-Activator>\n\t\t\t\t\t\t<Export-Package>gnu.inet.encoding.*;version=${packet.version},tigase.*;version=${packet.version};-split-package:=merge-first</Export-Package>\n\t\t\t\t\t\t<Import-Package>!junit.*,!sun.*,!com.sun.*,*</Import-Package>\n\t\t\t\t\t\t<DynamicImport-Package>*</DynamicImport-Package>\n\t\t\t\t\t\t<inlinedArtifacts>\n\t\t\t\t\t\t\t<inlinedArtifact>tigase-utils</inlinedArtifact>\n\t\t\t\t\t\t\t<inlinedArtifact>tigase-xmltools</inlinedArtifact>\n\t\t\t\t\t\t</inlinedArtifacts>\n\t\t\t\t\t\t<Embed-Dependency>*;scope=compile|runtime;artifactId=!junit|org.osgi.core|slf4j-api|tigase-utils|tigase-xmltools</Embed-Dependency>\n\t\t\t\t\t\t<Bundle-SymbolicName>${project.artifactId};singleton=true</Bundle-SymbolicName>\n\t\t\t\t\t\t<Private-Package>tigase.annotations.*,tigase.auth.*,tigase.cluster.*,tigase.conf.*,tigase.db.*,tigase.disco.*,tigase.http.*,tigase.io.*,tigase.net.*,tigase.server.*,tigase.stats.*,tigase.sys.*,tigase.util.*,tigase.vhosts.*,tigase.xmpp.*</Private-Package>\n\t\t\t\t\t</instructions>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<version>2.9.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<source>1.8</source>\n\t\t\t\t\t\t\t<quiet>true</quiet>\n\t\t\t\t\t\t\t<aggregate>true</aggregate>\n\t\t\t\t\t\t\t<includeDependencySources>true</includeDependencySources>\n\t\t\t\t\t\t\t<dependencySourceIncludes>\n\t\t\t\t\t\t\t\t<dependencySourceInclude>tigase:*</dependencySourceInclude>\n\t\t\t\t\t\t\t</dependencySourceIncludes>\n\n\t\t\t\t\t\t\t<reportOutputDirectory>${project.reporting.outputDirectory}/docs/javadoc</reportOutputDirectory>\n\t\t\t\t\t\t\t<destDir>docs/javadoc</destDir>\n\n\t\t\t\t\t\t\t<finalName>${project.artifactId}-${project.version}-b${gitVersion}</finalName>\n\t\t\t\t\t\t\t<jarOutputDirectory>pack</jarOutputDirectory>\n\n\t\t\t\t\t\t\t<additionalparam>-Xdoclint:none</additionalparam>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<version>2.17</version>\n\t\t\t\t<dependencies>\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.apache.maven.surefire</groupId>\n\t\t\t\t\t\t<artifactId>surefire-junit47</artifactId>\n\t\t\t\t\t\t<version>2.17</version>\n\t\t\t\t\t</dependency>\n\t\t\t\t</dependencies>\n\t\t\t\t<configuration>\n\t\t\t\t\t<excludedGroups>${tests.excludeGroups}</excludedGroups>\n\t\t\t\t\t<parallel>methods</parallel>\n\t\t\t\t\t<threadCount>10</threadCount>\t\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jarsigner-plugin</artifactId>\n\t\t\t\t<version>1.4</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>sign</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>sign</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archiveDirectory>${project.basedir}</archiveDirectory>\n\t\t\t\t\t<includes>\n\t\t\t\t\t\t<include>target/tigase*.?ar</include>\n\t\t\t\t\t\t<include>jars/tigase*.?ar</include>\n\t\t\t\t\t</includes>\n\t\t\t\t\t<processMainArtifact>false</processMainArtifact>\n\t\t\t\t\t<processAttachedArtifacts>false</processAttachedArtifacts>\n\t\t\t\t\t<tsa>http://timestamp.comodoca.com/rfc3161</tsa>\n\t\t\t\t\t<skip>${sign-skip}</skip>\n\n\t\t\t\t\t<keystore>${sign-keystore}</keystore>\n\t\t\t\t\t<alias>${sign-alias}</alias>\n\t\t\t\t\t<storepass>${sign-storepass}</storepass>\n\t\t\t\t\t<keypass>${sign-keypass}</keypass>\n\t\t\t\t\t<verbose>${verbose-log}</verbose>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-utils</artifactId>\n\t\t\t<version>3.5.0</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>tigase</groupId>\n\t\t\t<artifactId>tigase-xmltools</artifactId>\n\t\t\t<version>3.5.0</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.felix</groupId>\n\t\t\t<artifactId>org.osgi.core</artifactId>\n\t\t\t<version>1.4.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>jul-to-slf4j</artifactId>\n\t\t\t<version>${slf4j.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<version>4.11</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t\n\t</dependencies>\n</project>\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/AddUser.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User add script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#add-user\n\n AS:Description: Add user\n AS:CommandId: http://jabber.org/protocol/admin#add-user\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\ndef PASSWORD = \"password\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef userPass = Command.getFieldValue(packet, PASSWORD)\n\nif (userJid == null || userPass == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Adding a User\")\n\tCommand.addInstructions(result, \"Fill out this form to add a user.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the account to be added\")\n\tCommand.addFieldValue(result, PASSWORD, userPass ?: \"\", \"text-private\",\n\t\t\t\"The password for this account\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tauth_repo.addUser(bareJID, userPass)\n\t\tCommand.addTextField(result, \"Note\", \"1\");\n//\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"0\");\n//\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to create account for this domain.\");\n\t}\n} catch (UserExistsException ex) {\n\tCommand.addTextField(result, \"Note\", \"2\");\n//\tCommand.addTextField(result, \"Note\", \"User already exists, can't be added.\");\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"3\");\n//\tCommand.addTextField(result, \"Note\", \"Problem accessing database, user not added.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/AddUserTracker.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Activate on the server user tracking mechanisms to aid in problem resolution.\n AS:Description: Activate log tracker for a user\n AS:CommandId: http://jabber.org/protocol/admin#add-user-tracker\n AS:Component: sess-man\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\nimport java.util.logging.*\n\ndef JID = \"accountjid\"\ndef FILE_NAME = \"file-name\"\ndef FILE_LIMIT = 25000000\ndef FILE_COUNT = 5\n\ndef p = (Packet)packet\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef fileName = Command.getFieldValue(packet, FILE_NAME)\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Adding a User Log Tracker\")\n\tCommand.addInstructions(result, \"Fill out this form to add a user log tracker.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the account to be tracked\")\n\tCommand.addFieldValue(result, FILE_NAME, fileName ?: \"\", \"text-single\",\n\t\t\t\"File name to write user's log entries\")\n\n\treturn result\n}\n\n// Remove the old tracker if there is any active for that user\ndef hand = null\n\nHandler[] handlers = Logger.getLogger(\"\").getHandlers()\nhandlers.each {\n\tFilter filt = it.getFilter()\n\tif (filt != null && filt.class == LogUserFilter && ((LogUserFilter)filt).getId() == userJid) {\n\t\thand = it\n\t}\n}\nif (hand != null) {\n\tLogger.getLogger(\"\").removeHandler(hand)\n\thand.close()\n\tCommand.addTextField(result, \"Note\", \"Operation successful, tracker removed for \" + userJid);\n}\n\n// Ok now we can setup a new tracker\ndef result = p.commandResult(Command.DataType.result)\n\ndef users_sessions = (Map)userSessions\nbareJID = BareJID.bareJIDInstance(userJid)\n\nXMPPSession session = users_sessions.get(bareJID)\n\nif (fileName == null || fileName == \"\") {\n\tfileName = \"logs/\" + userJid\n}\nLogUserFilter filter = new LogUserFilter(bareJID, users_sessions)\n\nFileHandler handler = new FileHandler(fileName, FILE_LIMIT, FILE_COUNT)\nhandler.setLevel(Level.ALL)\nhandler.setFilter(filter)\nLogger.getLogger(\"\").addHandler(handler)\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addTextField(result, \"Note\", \"Tracking user \" + userJid)\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/BoshPreBindSession.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\n/*\nAS:Description: Pre-Bind BOSH user session\nAS:CommandId: pre-bind-bosh-session\nAS:Component: bosh\n */\n\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.bosh.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ntry {\n\n\tdef USER_JID = \"from\";\n\tdef RID = \"rid\"\n\tdef HOLD = \"hold\"\n\tdef WAIT = \"wait\"\n\tdef SID = \"sid\"\n\tdef HOSTNAME = \"hostname\"\n\n\tdef p = (Iq)packet\n\n\tdef vhost_man = (VHostManagerIfc)vhostMan\n\tdef admins = (Set)adminsSet\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID()\n\tdef isServiceAdmin = admins.contains(stanzaFromBare)\n\n\tdef userJid = Command.getFieldValue(p, USER_JID)\n\tdef rid = 0\n\tdef hold = Command.getFieldValue(p,HOLD)\n\tdef wait = Command.getFieldValue(p,WAIT)\n\n\tif (userJid == null || userJid.isEmpty() ) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form);\n\t\tCommand.addTitle(res, \"Pre-bind BOSH user session\")\n\t\tCommand.addInstructions(res, \"Fill out this form to create and pre-bind BOSH user session.\")\n\n\t\tCommand.addFieldValue(res, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\n\t\tCommand.addFieldValue(res, USER_JID, \"\", \"jid-single\", \"JID of the user for which session should be created - either BareJID or FullJID, the former will result in randomly generated resource\")\n\t\tCommand.addFieldValue(res, HOLD, hold ?: \"1\",\"text-single\", \"HOLD value (optional)\")\n\t\tCommand.addFieldValue(res, WAIT, wait ?: \"60\",\"text-single\", \"WAIT value (optional)\")\n\n\t\treturn res\n\t}\n\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\n\tdef result = (Iq)p.commandResult(Command.DataType.result)\n\n\tif (vhost == null ) {\n\t\tCommand.addTextField(result, \"Error\", \"Domain of the JID doesn't exists\");\n\t} else if (isServiceAdmin ||\n\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n\t\tMap args = new HashMap();\n\t\tif (userJid != null && !userJid.isEmpty()) {\n\t\t\targs.put(USER_JID,userJid)\n\t\t}\n\t\tif (hold != null && !hold.isEmpty()) args.put(HOLD,hold)\n\t\tif (wait != null && !wait.isEmpty()) args.put(WAIT,wait)\n\n\t\targs = boshCM.preBindSession(args)\n\n\t\trid = args.get(RID);\n\t\tdef sid = args.get(SID);\n\t\tdef hostname = args.get(HOSTNAME)\n\t\tuserJid = args.get(USER_JID)\n\n\t\tif (hostname != null ) {\n\t\tCommand.addFieldValue(result, USER_JID, userJid,\"jid-single\",  \"JID\")\n\t\tCommand.addFieldValue(result, HOSTNAME, hostname,\"jid-single\",  \"hostname\")\n\t\tCommand.addFieldValue(result, RID, rid, \"text-single\", \"RID\")\n\t\tCommand.addFieldValue(result, SID, sid, \"text-single\", \"SID\")\n\t\tCommand.addFieldValue(result, HOLD, hold, \"text-single\", \"HOLD\")\n\t\tCommand.addFieldValue(result, WAIT, wait, \"text-single\", \"WAIT\")\n\t\t} else {\n\t\t\tCommand.addTextField(result, \"Error\", \"Error processing request, provided data is invalid\");\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions\");\n\t}\n\treturn result\n\n}  catch (Exception ex) { ex.printStackTrace(); }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/BroadcastToOnline.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\n4.23 Send Announcement to Online Users as described in XEP-0133:\nhttp://xmpp.org/extensions/xep-0133.html#announce\n\nAS:Description: Send Announcement to Online Users\nAS:CommandId: http://jabber.org/protocol/admin#announce\nAS:Component: sess-man\nAS:Group: Notifications\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.cluster.*;\nimport tigase.cluster.api.*;\nimport tigase.cluster.strategy.*;\n\n\ndef FROM_JID = \"from-jid\"\ndef SUBJECT = \"subject\"\ndef MSG_TYPE = \"msg-type\"\ndef MSG_BODY = \"announcement\"\n\ndef p = (Iq)packet\n\ndef fromJid = Command.getFieldValue(p, FROM_JID)\ndef subject = Command.getFieldValue(p, SUBJECT)\ndef msg_type = Command.getFieldValue(p, MSG_TYPE)\ndef body = Command.getFieldValues(p, MSG_BODY)\n\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\nif (fromJid == null || subject == null || msg_type == null || body == null) {\n\tdef res = (Iq)p.commandResult(Command.DataType.form);\n  Command.addTitle(res, \"Message to online users\")\n  Command.addInstructions(res, \"Fill out this form to make an announcement to all active users of this service.\")\n\n  Command.addFieldValue(res, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\n  Command.addFieldValue(res, FROM_JID, fromJid ?: p.getStanzaFrom().getDomain().toString(), \"jid-single\", \"From address\")\n\n  Command.addFieldValue(res, SUBJECT, subject ?: \"Message from administrators\", \"Subject\")\n\n  def msg_types = [\"normal\", \"headline\", \"chat\" ]\n  Command.addFieldValue(res, MSG_TYPE, msg_type ?: msg_types[0], \"Type\", (String[])msg_types, (String[])msg_types)\n\n  if (body == null) {\n     body = [\"\"]\n  }\n\n\tCommand.addFieldMultiValue(res, MSG_BODY, body)\n\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(res, NOTIFY_CLUSTER, true.toString())\n\t}\n\n\n\treturn res\n}\n\nQueue results = new LinkedList()\nif \t( clusterMode && notifyCluster ) {\n\tif ( null != clusterStrategy ) {\n\t\tdef cluster = (ClusteringStrategyIfc) clusterStrategy\n\t\tList<JID> cl_conns = cluster.getAllNodes()\n\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\tcl_conns.each { node ->\n\n\t\t\t\tdef forward = p.copyElementOnly();\n\t\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\t\tforward.setPacketTo( node );\n\t\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\t\tresults.offer(forward)\n\t\t\t}\n\t\t}\n\t}\n}\n\n\ndef jidFrom = JID.jidInstanceNS(fromJid)\ndef type = StanzaType.valueOf(msg_type)\ndef msg_body = body.join('\\n')\n\ndef msg = Message.getMessage(null, null, type, msg_body, subject, null, \"admin\")\ndef result = p.commandResult(Command.DataType.result)\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nresults += result\ndef conns = (Map)userConnections\nconns.each { key, value ->\n  if (value.isAuthorized()) {\n\t\tdef res = msg.copyElementOnly()\n\t\tres.initVars(jidFrom, value.getJID())\n\t\tres.setPacketTo(key)\n\t\tresults += res\n\t}\n\n}\n\nreturn (Queue)results\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ChangeUserPassword.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User change password script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#\n AS:Description: Change user password\n AS:CommandId: http://jabber.org/protocol/admin#change-user-password\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\ndef PASSWORD = \"password\"\n//def PASSWORD_VERIFY = \"password-verify\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef userPass = Command.getFieldValue(packet, PASSWORD)\n//def userPassVer = Command.getFieldValue(packet, PASSWORD_VERIFY)\n\nif (userJid == null || userPass == null /*|| userPassVer == null*/) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Changing a User Password\")\n\tCommand.addInstructions(result, \"Fill out this form to change a user's password.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for this account\")\n\tCommand.addFieldValue(result, PASSWORD, userPass ?: \"\", \"text-private\",\n\t\t\t\"The password for this account\")\n//\tCommand.addFieldValue(result, PASSWORD_VERIFY, userPassVer ?: \"\", \"text-private\",\n//\t\t\t\"Retype password\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tif (user_repo.userExists(bareJID)) {\n\t\t\tauth_repo.updatePassword(bareJID, userPass)\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t}\n\t\telse {\n\t\t\tCommand.addTextField(result, \"Note\", \"User not exists, can't change password.\");\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to change account password for this domain.\");\n\t}\n} catch (UserNotFoundException ex) {\n\tCommand.addTextField(result, \"Note\", \"User not exists, can't change password.\");\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, password not changed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CompManager.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nManage active server components\n\nAS:Description: Manage active server components\nAS:CommandId: comp-manager\nAS:Component: basic-conf\nAS:Group: Configuration\n */\n\npackage tigase.admin\n\nimport tigase.conf.ConfigRepositoryIfc\nimport tigase.conf.Configurable;\nimport tigase.conf.Configurator;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.*\n\ntry {\n\n\tdef ACTION = \"action\";\n\tdef ACTION_ADD = \"Add\";\n\tdef ACTION_EDIT = \"Edit\";\n\tdef ACTION_REMOVE = \"Remove\";\n\tdef ACTION_LIST = \"List\";\n\n\tdef COMP_NAME = \"comp-name\";\n\tdef COMP_CLASS = \"comp-class\";\n\n\tdef SUBMIT = \"submit\";\n\n\tdef getComponentProperties = { comp_name, comp_class ->\n\t\tdef conf = XMPPServer.getConfigurator();\n\t\tdef prop = conf.getProperties(comp_name);\n\t\ttry {\n\t\t\tdef comp = ModulesManagerImpl.getInstance().getServerComponent(comp_class);\n\t\t\tif (!comp) {\n\t\t\t\tdef INTERNAL_COMPONENTS = [];\n\t\t\t\tINTERNAL_COMPONENTS.addAll(MessageRouterConfig.COMPONENT_CLASSES.values());\n\t\t\t\tINTERNAL_COMPONENTS.addAll(MessageRouterConfig.COMP_CLUS_MAP.values());\n\t\t\t\t\n\t\t\t\tif (!XMPPServer.isOSGi() || INTERNAL_COMPONENTS.contains(comp_class)) {\n\t\t\t\t\tcomp = XMPPServer.class.getClassLoader().loadClass(comp_class).newInstance()\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (comp) {\n\t\t\t\tcomp.setName(comp_name)\n\t\t\t\tdef defProp = comp.getDefaults(conf.getDefConfigParams() ?: [:])  ?: [:];\n\t\t\t\tdefProp.putAll(prop);\n\t\t\t\treturn defProp;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn [:];\n\t\t\t}\n\t\t}\n\t\tcatch(Exception ex) {\n\t\t\tex.printStackTrace();\n\t\t\treturn [:];\n\t\t}\n\t};\n\n\tdef prepareComponentConfigForAdHoc = { res, comp_name, comp_class ->\n\t\tdef prop = getComponentProperties(comp_name, comp_class);\n\t\tdef keys = [];\n\t\tkeys.addAll(prop.keySet());\n\t\tkeys.sort { it }.each { key ->\n\t\t\tdef val = prop[key];\n\t\t\tif (val.getClass().isArray()) {\n\t\t\t\tdef tmp = [];\n\t\t\t\tfor (def x : val) {\n\t\t\t\t\ttmp.add(String.valueOf(x));\n\t\t\t\t}\n\t\t\t\tval = tmp.join(',');\n\t\t\t}\n\t\t\tif (!(val instanceof String)) {\n\t\t\t\tval = val.toString();\n\t\t\t}\n\t\t\tCommand.addFieldValue(res, key, val);\n\t\t}\n\t};\n\n\tdef getConfigFromAdHoc = { p, comp_name, comp_class ->\n\t\tdef defProp = getComponentProperties(comp_name, comp_class);\n        \n\t\tdef props = [:];\n\t\tdefProp.each { key, defVal ->\n\t\t\tdef val = Command.getFieldValue(p, key);\n                \n\t\t\tdef tmpVal = defVal;\n\t\t\tif (tmpVal.getClass().isArray()) {\n\t\t\t\tdef tmp = [];\n\t\t\t\tfor (def x : tmpVal) {\n\t\t\t\t\ttmp.add(String.valueOf(x));\n\t\t\t\t}\n\t\t\t\ttmpVal = tmp.join(',');\n\t\t\t}\n\n\t\t\tif (val && !val.equals(tmpVal)) {\n\t\t\t\tdef cls = defVal.getClass();\n\t\t\t\tif (val == \"null\") val = null;\n\t\t\t\tif (cls == Long[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(Long.parseLong(it))};\n\t\t\t\t\tval = (out as Long[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == Integer[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(Integer.parseInt(it))};\n\t\t\t\t\tval = (out as Integer[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == String[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(it)};\n\t\t\t\t\tval = (out as String[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == Long.class) {\n\t\t\t\t\tval = Long.parseLong(val);\n\t\t\t\t}\n\t\t\t\telse if (cls == Integer.class) {\n\t\t\t\t\tval = Integer.parseInt(val);\n\t\t\t\t}\n\t\t\t\telse if (cls == Boolean.class) {\n\t\t\t\t\tval = Boolean.parseBoolean(val);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tprintln \"unknown convertion for key = \" + key + \" , \" + cls.getName()\n\t\t\t\t}\n                                                \n\t\t\t\tprops.put(key, val);\n\t\t\t}\n\t\t}\n        \n\t\treturn props;\n\t};\n\n\n\tdef conf_repo = (ConfigRepositoryIfc)comp_repo\n\tdef p = (Iq)packet\n\n\t// check permission\n\tdef admins = (Set)adminsSet\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID()\n\tdef isServiceAdmin = admins.contains(stanzaFromBare)\n\n\tif (!isServiceAdmin) {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n\t\treturn result\n\t}\n\n\n\tdef comp_name = Command.getFieldValue(p, COMP_NAME)\n\tdef action = Command.getFieldValue(p, ACTION);\n\tdef submit = Command.getFieldValue(p, SUBMIT);\n\n\tif (action == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef actions = [ACTION_LIST, ACTION_ADD, ACTION_EDIT, ACTION_REMOVE];\n\t\tCommand.addFieldValue(res, ACTION, actions[0], \"Action\",\n\t\t\t(String[]) actions, (String[]) actions)\n\t\treturn res;\n\t}\n\n\tif (action == ACTION_ADD && comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(res, COMP_NAME, \"\", \"text-single\", \"Component name\");\n\t\tCommand.addFieldValue(res, COMP_CLASS, \"\", \"text-single\", \"Component class\");\n\t\tCommand.addHiddenField(res, ACTION, ACTION_ADD);\n\t\treturn res;\n\t}\n\telse if ( action == ACTION_LIST && comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef compNames = []\n\t\tdef conf = XMPPServer.getConfigurator();\n\n\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\tcompNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n\t\tcompNames += mrProps.get(MessageRouterConfig.REGISTRATOR_NAMES_PROP_KEY).toList();\n\n\t\tcompNames.each {\n\t\t\tdef mr = conf.getComponent( it );\n\t\t\tif (mr) {\n\t\t\t\tCommand.addFieldMultiValue(res, it, Arrays.asList( mr.getComponentInfo().toString() ))\n\t\t\t}\n\t\t}\n\t\tCommand.addHiddenField(res, ACTION, action);\n\t\treturn res\n\t}\n\telse if (comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef compNames = []\n\t\tdef conf = XMPPServer.getConfigurator();\n\t\tconf_repo.getCompNames().findAll{ conf.getComponent(it) != null }.each { compNames += it }\n\t\tcompNames.sort();\n\t\tCommand.addFieldValue(res, COMP_NAME, comp_name ?: compNames[0], \"Components\",\n\t\t\t(String[])compNames, (String[])compNames)\n\t\tCommand.addHiddenField(res, ACTION, action ?: \"\");\n\t\treturn res\n\t}\n\telse {\n\t\tif (action == ACTION_REMOVE) {\n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.result)\n\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\tdef suffix = null;\n\t\t\tinitProps.each {\n\t\t\t\tsuffix = it.key.substring(Configurable.GEN_COMP_NAME.length());\n\t\t\t}\n\t\t\tconf.getDefConfigParams().remove(Configurable.GEN_COMP_NAME + suffix);\n\t\t\tconf.getDefConfigParams().remove(Configurable.GEN_COMP_CLASS + suffix);\n\n\t\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\t\tdef compNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n                        \n\t\t\tif (compNames.contains(comp_name)) {\n\t\t\t\tcompNames.remove(comp_name);\n\t\t\t}\n                        \n\t\t\tmrProps = [:];\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY, (compNames as String[]));\n\t\t\tconf.putProperties(\"message-router\", mrProps);\n                        \n\t\t\t((Configurator) XMPPServer.getConfigurator()).updateMessageRouter();\n\t\t\tCommand.addTextField(res, \"Note\", \"Operation successful.\")\n\n\t\t\treturn res;\n\t\t}\n\t\telse if (!submit) {\n\t\t\tdef comp_class = Command.getFieldValue(p, COMP_CLASS);\n                \n\t\t\tif (comp_class == null) {\n\t\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\t\tdef suffix = null;\n\t\t\t\tinitProps.each {\n\t\t\t\t\tsuffix = it.key.substring(Configurable.GEN_COMP_NAME.length());\n\t\t\t\t}\n\t\t\t\tcomp_class = conf.getDefConfigParams().get(Configurable.GEN_COMP_CLASS + suffix);\n\n\t\t\t\tif (!comp_class) comp_class = MessageRouterConfig.COMPONENT_CLASSES.get(comp_name);\n\t\t\t\tif (!comp_class) comp_class = MessageRouterConfig.COMP_CLUS_MAP.get(comp_name);\n\t\t\t\tif (!comp_class && comp_name == \"basic-conf\") comp_class = XMPPServer.getConfigurator().getClass().getCanonicalName();\n\t\t\t\tif (!comp_class) throw new Exception(\"Could not find component class for component: \" + comp_name);\n\t\t\t}\n                        \n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\t\tCommand.addFieldValue(res, COMP_NAME, comp_name, \"fixed\", \"Component name\");\n\t\t\tCommand.addHiddenField(res, COMP_CLASS, comp_class);\n\t\t\tCommand.addHiddenField(res, ACTION, action);\n\t\t\tCommand.addHiddenField(res, SUBMIT, SUBMIT);\n        \n\t\t\tprepareComponentConfigForAdHoc(res, comp_name, comp_class);\n         \n\t\t\treturn res;\n\t\t}\n\t\telse if (submit) {\n\t\t\tdef comp_class = Command.getFieldValue(p, COMP_CLASS);\n\n\t\t\t// here we should apply results of new or edit\n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.result)\n\t\t\tdef props = getConfigFromAdHoc(p, comp_name, comp_class);\n                \n\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\tconf.putProperties(comp_name, props);\n                \n\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\tif (initProps.isEmpty()) {\n\t\t\t\tdef suffix = 1;\n\t\t\t\twhile (!(conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.key.endsWith(\"-\"+suffix); }.isEmpty())) {\n\t\t\t\t\tsuffix += 1;\n\t\t\t\t}\n\t\t\t\tconf.getDefConfigParams().put(Configurable.GEN_COMP_NAME+\"-\"+suffix, comp_name);\n\t\t\t\tconf.getDefConfigParams().put(Configurable.GEN_COMP_CLASS+\"-\"+suffix, comp_class);\n\t\t\t}\n\n\t\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\t\tdef compNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n                        \n\t\t\tif (!compNames.contains(comp_name)) {\n\t\t\t\tcompNames.add(comp_name);\n\t\t\t}\n                        \n\t\t\tmrProps = [:];\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY, (compNames as String[]));\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_PROP_KEY + comp_name + \".class\", comp_class)\n\t\t\tconf.putProperties(\"message-router\", mrProps);\n                        \n\t\t\t((Configurator) XMPPServer.getConfigurator()).updateMessageRouter();\n\t\t\tCommand.addTextField(res, \"Note\", \"Operation successful.\");\n\t\t\treturn res;\n\t\t}\n\t}\n\n\n                \n                \n}\ncatch(Exception ex) {\n\tex.printStackTrace();\n\tthrow ex;\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CompRepoItemAdd.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nAdd an item in a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Add new item\nAS:CommandId: comp-repo-item-add\nAS:Component: vhost-man,ext\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef MARKER = \"command-marker\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Iq)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef item = repo.getItemInstance()\ndef marker = Command.getFieldValue(p, MARKER)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\n\nif (marker == null) {\n  def result = p.commandResult(Command.DataType.form)\n  item.addCommandFields(result)\n\tCommand.addHiddenField(result, MARKER, MARKER)\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t}\n\treturn result\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\nitem.initFromCommand(p)\ndef oldItem = item.getKey() != null ? repo.getItem(item.getKey()) : null;\ndef result = p.commandResult(Command.DataType.result)\nif (oldItem == null) {\n\tdef validateResult = repo.validateItem(item)\n\tif (validateResult == null || (isServiceAdmin && !item.getKey().isEmpty())) {\n\t\trepo.addItem(item)\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful.\")\n\t\tif (validateResult != null) {\n\t\t\tCommand.addTextField(result, \"Note\", \"   \")\n\t\t\tCommand.addTextField(result, \"Warning\", validateResult)\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"The item did not pass validation checking.\")\n\t\tCommand.addTextField(result, \"Note\", \"   \")\n\t\tCommand.addTextField(result, \"Warning\", validateResult)\n\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"The item is already added, you can't add it twice.\")\n}\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CompRepoItemRemove.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nRemove an item from a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Remove an item\nAS:CommandId: comp-repo-item-remove\nAS:Component: vhost-man,ext\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef ITEMS = \"item-list\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, ITEMS)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, ITEMS, itemsStr[0], \"List of items\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\tif \t( clusterMode  ) {\n\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t}\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Note\", \"There are no items on the list\");\n\t\treturn result\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\ndef item = repo.getItem(itemKey)\nif (item == null) {\n\tCommand.addTextField(result, \"Error\", \"No such item, deletion impossible.\");\n} else {\n  if (isServiceAdmin || item.isOwner(stanzaFromBare.toString())) {\n\t\trepo.removeItem(itemKey)\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\")\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You are not the Item owner or you have no \"\n\t\t\t+ \"enough permission to remove the item.\")\n\t}\n}\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CompRepoItemUpdate.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nUpdate an item in a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Update item configuration\nAS:CommandId: comp-repo-item-update\nAS:Component: vhost-man,ext,basic-conf\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef MARKER = \"command-marker\"\ndef ITEMS = \"item-list\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, ITEMS)\ndef marker = Command.getFieldValue(packet, MARKER)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, ITEMS, itemsStr[0], \"List of items\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Error\", \"There are no items on the list\");\n\t\treturn result\n\t}\n}\n\nif (marker == null) {\n\tdef item = repo.getItem(itemKey)\n\tif (item == null) {\n\t\tCommand.addTextField(result, \"Error\", \"No such item, update impossible.\");\n\t} else {\n\t\tif (isServiceAdmin || item.isOwner(stanzaFromBare.toString()) || item.isAdmin(stanzaFromBare.toString())) {\n\t\t\tdef result = p.commandResult(Command.DataType.form)\n\t\t\titem.addCommandFields(result)\n\t\t\tCommand.addHiddenField(result, MARKER, MARKER)\n\t\t\tCommand.addHiddenField(result, ITEMS, itemKey)\n\t\t\tif \t( clusterMode  ) {\n\t\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t\t}\n\t\t\treturn result\n\t\t} else {\n\t\t\tdef result = p.commandResult(Command.DataType.result)\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this item.\")\n\t\t\treturn result\n\t\t}\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\n\ndef item = repo.getItemInstance()\nitem.initFromCommand(packet)\ndef oldItem = repo.getItem(item.getKey())\n\nif (oldItem == null) {\n\tCommand.addTextField(result, \"Error\", \"The item you try to update does not exist.\");\n} else {\n\tif (isServiceAdmin || oldItem.isOwner(stanzaFromBare.toString())\n\t\t// we allow changes by admins, except for changing the owner of the domain.\n\t\t|| oldItem.isAdmin(stanzaFromBare.toString()) && oldItem.getOwner().equals(item.getOwner())\n\t) {\n\t\trepo.addItem(item)\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You are not the Item owner or you have no \"\n\t\t\t+ \"enough permission to change the item.\")\n\n\t}\n}\n\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CompRepoReload.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nReload a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Reload component repository\nAS:CommandId: comp-repo-reload\nAS:Component: vhost-man,ext\n*/\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\n\ndef repo = (ComponentRepository)comp_repo\nrepo.reload()\n\ndef result = \"Reloaded items - \" + repo.size() + \":\\n\"\ndef items = repo.allItems()\nif (items.size() > 0) {\n\titems.each { result += \"\\n\" + it.getKey() }\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ConfigList.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nList server/component configuration\n\nAS:Description: List server/component configuration\nAS:CommandId: config-list\nAS:Component: basic-conf\nAS:Group: Configuration\n*/\n\npackage tigase.admin\n\nimport tigase.conf.*\nimport tigase.server.*\n\ndef COMP_NAME = \"comp-name\"\ndef PARAMS_SET = \"params-set\"\n\ndef conf_repo = (ConfigRepositoryIfc)comp_repo\ndef p = (Iq)packet\ndef comp_name = Command.getFieldValue(p, COMP_NAME)\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n    def result = p.commandResult(Command.DataType.result)\n    Command.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n    return result\n}\n\nif (comp_name == null) {\n\tdef res = (Iq)p.commandResult(Command.DataType.form)\n  def compNames = []\n  conf_repo.getCompNames().each { compNames += it }\n\tCommand.addFieldValue(res, COMP_NAME, comp_name ?: compNames[0], \"Components\",\n\t\t(String[])compNames, (String[])compNames)\n\treturn res\n}\n\ndef params_set = Command.getFieldValue(p, PARAMS_SET)\n\nif (params_set == null) {\n\tdef res = (Iq)p.commandResult(Command.DataType.result)\n  def compNames = []\n  conf_repo.getCompNames().each { compNames += it }\n\tCommand.addTextField(res, COMP_NAME, comp_name ?: compNames[0])\n  Command.addHiddenField(res, PARAMS_SET, PARAMS_SET)\n\tconf_repo.getItemsForComponent(comp_name).each {\n\t\tCommand.addFieldValue(res, it.getKey(), it.getConfigValToString())\n\t}\n\treturn res\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ConnectionTime.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Calculates maximum and average connection time for all connected users\n AS:Description: Connections time\n AS:CommandId: connection-time\n AS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport tigase.conf.*\nimport tigase.server.*\nimport tigase.xmpp.*\n\ndef user_connections = (Map)userConnections\ndef p = (Iq)packet\n\ndef total_time = 0\ndef max_time = 0\ndef start_time = System.currentTimeMillis()\nuser_connections.entrySet().each {\n\tif (!it.getKey().toString().startsWith(\"sess-man\")) {\n\t\tdef session = (XMPPResourceConnection) it.getValue()\n\t\tdef creation_time = start_time - session.getCreationTime()\n\t\ttotal_time += creation_time\n\t\tif (creation_time  > max_time) {\n\t\t\tmax_time = creation_time\n\t\t}\n\t}\n}\ndef average_time = total_time / user_connections.size()\n\n\ndef res = (Iq)p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(res, \"Connections time: \",\n\t\t[\n\t\t\t\"Longest connection: \" + (max_time / 1000),\n\t\t\t\"Average connection time:\" + (average_time / 1000)\n\t\t])\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/CreateNode.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Create PubSub node\n\n AS:Description: Create node\n AS:CommandId: create-node\n AS:Component: pubsub\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.pubsub.*\nimport tigase.pubsub.repository.IPubSubRepository\nimport tigase.pubsub.exceptions.PubSubException\nimport tigase.pubsub.modules.NodeCreateModule.NodeCreateHandler.NodeCreateEvent;\n\ndef NODE = \"node\"\ndef OWNER = \"owner\";\n\nIPubSubRepository pubsubRepository = component.pubsubRepository\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef node = Command.getFieldValue(packet, NODE)\ndef owner = Command.getFieldValue(packet, OWNER);\n\nif (node == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Creating a node\")\n\tCommand.addInstructions(result, \"Fill out this form to create a node.\")\n\n\tCommand.addFieldValue(result, NODE, node ?: \"\", \"text-single\",\n\t\t\t\"The node to create\")\t\n\tCommand.addFieldValue(result, OWNER, owner ?: \"\", \"jid-single\",\n\t\t\t\"Owner JID\")\n\t\n\tdef nodeConfig = new LeafNodeConfig(null);\n\tList<Element> fields = nodeConfig.getFormElement().getChildren();\n\tElement x = Command.getData(result, \"x\",\"jabber:x:data\");\n\tx.addChildren(fields);\n\t//Command.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t//\t\t\"hidden\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tif (isServiceAdmin) {\n\t\tdef toJid = p.getStanzaTo().getBareJID();\n\n\t\tdef nodeConfig = pubsubRepository.getNodeConfig(toJid, node);\n\n\t\tif (nodeConfig != null) {\n\t\t\tthrow new PubSubException(Authorization.CONFLICT, \"Node \" + node + \" already exists\");\n\t\t}\n\t\t\n\t\tdef nodeTypeStr = Command.getFieldValue(p, \"pubsub#node_type\");\n\t\tdef nodeType = nodeTypeStr ? NodeType.valueOf(nodeTypeStr) : NodeType.leaf;\n\t\tnodeConfig = (nodeType == NodeType.leaf) ? new LeafNodeConfig(node, component.defaultNodeConfig) : new CollectionNodeConfig(node);\n\t\t\n\t\tCommand.getData(p, \"x\", \"jabber:x:data\").getChildren().each { fieldEl ->\n\t\t\tdef var = fieldEl.getAttribute(\"var\");\t\t\t\n\t\t\tdef field = nodeConfig.getForm().get(var);\n\t\t\tdef value = fieldEl.getChildCData( \"/field/value\")\n\t\t\tif (!field) return;\n\t\t\tif (field.getType().name().endsWith(\"-multi\")) {\n\t\t\t\tnodeConfig.setValues(field.getVar(), value.tokenize());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnodeConfig.setValue(field.getVar(), value);\n\t\t\t}\n\t\t};\n\t\t\n\t\tdef collection = nodeConfig.getCollection();\n\t\tCollectionNodeConfig colNodeConfig = null;\n\t\t\n\t\tif (collection != '') {\n\t\t\tAbstractNodeConfig absNodeConfig = pubsubRepository.getNodeConfig(toJid, collection);\n\n\t\t\tif (absNodeConfig == null) {\n\t\t\t\tthrow new PubSubException(p.getElement(), Authorization.ITEM_NOT_FOUND);\n\t\t\t} else if (absNodeConfig.getNodeType() == NodeType.leaf) {\n\t\t\t\tthrow new PubSubException(p.getElement(), Authorization.NOT_ALLOWED);\n\t\t\t}\n\t\t\tcolNodeConfig = (CollectionNodeConfig) absNodeConfig;\n\t\t}\t\t\n\t\t\t\n\t\tif (owner == null || owner.isEmpty()) { \n\t\t\towner = p.getStanzaFrom().getBareJID();\n\t\t} else {\n\t\t\towner = BareJID.bareJIDInstance(owner);\n\t\t}\n\t\tpubsubRepository.createNode(toJid, node, owner,\n\t\t\tnodeConfig, nodeType, collection);\n\t\t\n\t\tdef nodeaAffiliations  = pubsubRepository.getNodeAffiliations(toJid, node);\n\n\t\tnodeaAffiliations.addAffiliation(owner,Affiliation.owner);\n\t\tpubsubRepository.update(toJid, node, nodeaAffiliations);\n\t\tif (colNodeConfig == null) {\n\t\t\tpubsubRepository.addToRootCollection(toJid, node);\n\t\t} else {\n\t\t\tcolNodeConfig.addChildren(node);\n\t\t\tpubsubRepository.update(toJid, collection, colNodeConfig);\n\t\t}\n\t\t\n\t\tNodeCreateEvent event = new NodeCreateEvent(packet, node);\t\t\n\t\tcomponent.getEventBus().fire(event);\n\n\t\tif (collection != '') {\n\t\t\tdef colNodeSubscriptions =\n\t\t\t\tpubsubRepository.getNodeSubscriptions(toJid, collection);\n\t\t\tdef colNodeAffiliations =\n\t\t\t\tpubsubRepository.getNodeAffiliations(toJid, collection);\n\t\t\tElement colE = new Element(\"collection\");\n\t\t\tcolE.setAttribute(\"node\", collection);\n\t\t\tElement associateEl = new Element(\"associate\");\n\t\t\tassociateEl.setAttribute(\"node\", node);\n\t\t\tcolE.addChild(associateEl);\n\t\t\tdef results = (component.publishNodeModule.sendNotifications(colE,\n\t\t\t\t\t\t\tpacket.getStanzaTo(), collection, nodeConfig,\n\t\t\t\t\t\t\tcolNodeAffiliations, colNodeSubscriptions));\n\t\t\tresults.each { packet -> \n\t\t\t\tcomponent.addOutPacket(packet);\n\t\t\t}\n\t\t}\t\t\n\t\t\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\t//Command.addTextField(result, \"Error\", \"You do not have enough permissions to publish item to a node.\");\n\t\tthrow new PubSubException(Authorization.FORBIDDEN, \"You do not have enough \" + \n\t\t\t\t\"permissions to publish item to a node.\");\n\t}\n} catch (PubSubException ex) {\n\tCommand.addTextField(result, \"Error\", ex.getMessage())\n\tif (ex.getErrorCondition()) {\n\t\tdef error = ex.getErrorCondition();\n\t\tElement errorEl = new Element(\"error\");\n\t\terrorEl.setAttribute(\"type\", error.getErrorType());\n\t\tElement conditionEl = new Element(error.getCondition(), ex.getMessage());\n\t\tconditionEl.setXMLNS(Packet.ERROR_NS);\n\t\terrorEl.addChild(conditionEl);\n\t\tElement pubsubCondition = ex.pubSubErrorCondition?.getElement();\n\t\tif (pubsubCondition)\n\t\t\terrorEl.addChild(pubsubCondition);\n\t\tresult.getElement().addChild(errorEl);\t\n\t}\t\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, node not created.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/DNSQuery.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User add script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#add-user\n AS:Description: DNS Query\n AS:CommandId: query-dns\n AS:Component: vhost-man\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\n\n\ndef DOMAIN = \"domain-name\"\n\ndef p = (Packet)packet\n\ndef domain = Command.getFieldValue(packet, DOMAIN)\n\nif (domain == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Provide domain name\")\n\tCommand.addInstructions(result, \"Fill out this form to query DNS for domain.\")\n\n\tCommand.addFieldValue(result, DOMAIN, domain ?: \"\", \"text-single\",\n\t\t\t\"Domain name to query DNS\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ndef response_data = []\ntry {\n\tresponse_data += \"IP: \" + DNSResolver.getHostIP(domain)\n} catch (Exception ex) {\n\tresponse_data += \"IP: \" + ex.toString()\n}\ntry {\n\tDNSEntry[] entries = DNSResolver.getHostSRV_Entries(domain)\n\tint cnt = 1\n\tentries.each {\n\t\tresponse_data += \"SRV \" + (cnt++) + \": \" + it.toString()\n\t}\n\tresponse_data += \"Selected SRV: \" + DNSResolver.getHostSRV_Entry(domain).toString()\n\tresponse_data += \"Selected SRV IP: \" + DNSResolver.getHostSRV_IP(domain)\n\n\n\tCommand.addFieldMultiValue(result, \"DNS Response \", response_data);\n} catch (Exception ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem querying DNS for domain: \" + domain);\n\t// There is a new API to pass exception, for now we have to do it manually\n\t//Command.addFieldMultiValue(result, \"Exception: \", ex)\n\tdef stes = []\n\tstes += ex.toString()\n\tex.getStackTrace().each {\n\t\tstes += it.toString()\n\t}\n\tCommand.addFieldMultiValue(result, \"Exception: \", stes);\n\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/DeleteNode.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Delete PubSub node\n\n AS:Description: Delete node\n AS:CommandId: delete-node\n AS:Component: pubsub\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.pubsub.*\nimport tigase.pubsub.repository.IPubSubRepository\nimport tigase.pubsub.exceptions.PubSubException\nimport tigase.pubsub.modules.NodeDeleteModule.NodeDeleteHandler.NodeDeleteEvent;\n\ndef NODE = \"node\"\n\nIPubSubRepository pubsubRepository = component.pubsubRepository\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef node = Command.getFieldValue(packet, NODE)\n\nif (node == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Deleting a node\")\n\tCommand.addInstructions(result, \"Fill out this form to delete a node.\")\n\n\tCommand.addFieldValue(result, NODE, node ?: \"\", \"text-single\",\n\t\t\t\"The node to delete\")\t\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tif (isServiceAdmin) {\n\t\tdef toJid = p.getStanzaTo().getBareJID();\n\t\t\n\t\tAbstractNodeConfig nodeConfig = pubsubRepository.getNodeConfig(toJid, node);\n\n\t\tif (nodeConfig == null) {\n\t\t\tthrow new PubSubException(Authorization.ITEM_NOT_FOUND, \"Node \" + node + \" cannot \" + \n\t\t\t\t\"be deleted as it not exists yet.\");\n\t\t}\n\n\t\tList<Packet> results = [];\n\t\t\n\t\tif (nodeConfig.isNotify_config()) {\n\t\t\tdef nodeSubscriptions = pubsubRepository.getNodeSubscriptions(toJid, node);\n\t\t\tElement del = new Element(\"delete\");\n\t\t\tdel.setAttribute(\"node\", node);\n\n\t\t\tresults.addAll(component.publishNodeModule.prepareNotification(del, p.getStanzaTo(), node,\n\t\t\t\t\t\t\tnodeConfig, nodeAffiliations, nodeSubscriptions));\n\t\t}\t\t\n\n\n\t\tfinal String parentNodeName                 = nodeConfig.getCollection();\n\t\tCollectionNodeConfig parentCollectionConfig = null;\n\t\t\n\t\tif ((parentNodeName != null) &&!parentNodeName.equals(\"\")) {\n\t\t\tparentCollectionConfig =\n\t\t\t(CollectionNodeConfig) pubsubRepository.getNodeConfig(toJid, parentNodeName);\n\t\t\tif (parentCollectionConfig != null) {\n\t\t\t\tparentCollectionConfig.removeChildren(node);\n\t\t\t}\n\t\t} else {\n\t\t\tpubsubRepository.removeFromRootCollection(toJid, node);\n\t\t}\n\t\tif (nodeConfig instanceof CollectionNodeConfig) {\n\t\t\tCollectionNodeConfig cnc     = (CollectionNodeConfig) nodeConfig;\n\t\t\tfinal String[] childrenNodes = cnc.getChildren();\n\t\t\t\n\t\t\tif ((childrenNodes != null) && (childrenNodes.length > 0)) {\n\t\t\t\tfor (String childNodeName : childrenNodes) {\n\t\t\t\t\tAbstractNodeConfig childNodeConfig = pubsubRepository.getNodeConfig(toJid, childNodeName);\n\t\t\t\t\t\n\t\t\t\t\tif (childNodeConfig != null) {\n\t\t\t\t\t\tchildNodeConfig.setCollection(parentNodeName);\n\t\t\t\t\t\tpubsubRepository.update(toJid, childNodeName, childNodeConfig);\n\t\t\t\t\t}\n\t\t\t\t\tif (parentCollectionConfig != null) {\n\t\t\t\t\t\tparentCollectionConfig.addChildren(childNodeName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpubsubRepository.addToRootCollection(toJid, childNodeName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (parentCollectionConfig != null) {\n\t\t\tpubsubRepository.update(toJid, parentNodeName, parentCollectionConfig);\n\t\t}\n\t\t\n\t\tpubsubRepository.deleteNode(toJid, node);\n\t\t\t\n\t\tNodeDeleteEvent event = new NodeDeleteEvent(packet, node);\n\t\tcomponent.getEventBus().fire(event);\n\t\t\n\t\tresults.each { packet ->\n\t\t\tcomponent.addOutPacket(packet);\n\t\t}\n\t\t\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\t//Command.addTextField(result, \"Error\", \"You do not have enough permissions to publish item to a node.\");\n\t\tthrow new PubSubException(Authorization.FORBIDDEN, \"You do not have enough \" + \n\t\t\t\t\"permissions to publish item to a node.\");\n\t}\n} catch (PubSubException ex) {\n\tCommand.addTextField(result, \"Error\", ex.getMessage())\n\tif (ex.getErrorCondition()) {\n\t\tdef error = ex.getErrorCondition();\n\t\tElement errorEl = new Element(\"error\");\n\t\terrorEl.setAttribute(\"type\", error.getErrorType());\n\t\tElement conditionEl = new Element(error.getCondition(), ex.getMessage());\n\t\tconditionEl.setXMLNS(Packet.ERROR_NS);\n\t\terrorEl.addChild(conditionEl);\n\t\tElement pubsubCondition = ex.pubSubErrorCondition?.getElement();\n\t\tif (pubsubCondition)\n\t\t\terrorEl.addChild(pubsubCondition);\n\t\tresult.getElement().addChild(errorEl);\t\n\t}\t\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, node not deleted.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/DeleteUser.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User delete script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#delete-user\n AS:Description: Delete user\n AS:CommandId: http://jabber.org/protocol/admin#delete-user\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JIDS = \"accountjids\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef user_sessions = (Map)userSessions;\n\ndef userJids = Command.getFieldValues(packet, JIDS)\n\nif (userJids == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Deleting a User\")\n\tCommand.addInstructions(result, \"Fill out this form to delete a user.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JIDS, userJids ?: \"\", \"jid-multi\",\n\t\t\t\"The Jabber ID(s) to delete\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ndef results = new LinkedList<Packet>();\nresults.offer(result);\ndef msgs = [];\ndef errors = [];\nfor (userJid in userJids) {\n\ttry {\n\t\tdef bareJID = BareJID.bareJIDInstance(userJid)\n\t\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\t\tif (isServiceAdmin ||\n\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\t\tif (user_repo.userExists(bareJID)) {\n\t\t\t\tauth_repo.removeUser(bareJID)\n\t\t\t\ttry {\n\t\t\t\t\tuser_repo.removeUser(bareJID)\n\t\t\t\t} catch (UserNotFoundException ex) {\n\t\t\t\t\t// We ignore this error here. If auth_repo and user_repo are in fact the same\n\t\t\t\t\t// database, then user has been already removed with the auth_repo.removeUser(...)\n\t\t\t\t\t// then the second call to user_repo may throw the exception which is fine.\n\t\t\t\t}\n\t\t\t\tdef sess = user_sessions.get(bareJID);\n\t\t\t\tif (sess != null) {\n\t\t\t\t\tdef conns = sess.getConnectionIds();\n\t\t\t\t\tfor (conn in conns) {\n\t\t\t\t\t\tdef res = sess.getResourceForConnectionId(conn);\n\t\t\t\t\t\tif (res != null) {\n\t\t\t\t\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), conn,\n\t\t\t\t\t\t\t\t StanzaType.set, res.nextStanzaId());\n\t\t\t\t\t\t\tresults.offer(commandClose);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmsgs.add(\"Operation successful for user \"+userJid);\n\t\t\t}\n\t\t\telse {\n\t\t\t\terrors.add(\"User \"+userJid+\" not found, can't be deleted.\");\n\t\t\t}\n\t\t} else {\n\t\t\terrors.add(\"You do not have enough permissions to delete accounts for domain \"+bareJID.getDomain()+\".\");\n\t\t}\n\t} catch (UserNotFoundException ex) {\n\t\terrors.add(\"User \"+userJid+\" not exists, can't be deleted.\");\n\t} catch (TigaseDBException ex) {\n\t\terrors.add(\"Problem accessing database, user \"+userJid+\" not deleted.\");\n\t}\n}\n\nif (!msgs.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Notes\", msgs);\n\nif (!errors.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Errors\", errors);\nreturn results\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ForceStopServiceForKey.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nForce stop IOService for a given key.\n\nAS:Description: Force stop service\nAS:CommandId: force-stop-service\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.net.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef KEY = \"key\"\n\ndef key = Command.getFieldValue(packet, KEY)\n\nif (key == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n  Command.addTitle(result, \"Force-stopping IOService for a given key\")\n\tCommand.addInstructions(result, \"Provide a key for IOService you wish to stop.\")\n\tCommand.addFieldValue(result, KEY, key ?: \"\", \"text-single\",  \"Key\")\n\n\treturn result\n}\n\nMap services = (Map)servicesMap\n\nIOService serv = services.get(key)\n\nif (serv == null) {\n\treturn \"IOService for key: ${key} not found!\"\n} else {\n  serv.forceStop()\n\treturn \"Stopped IOService for key: ${key}.\"\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetAnyFile.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet any file\n\nAS:Description: Get any file\nAS:CommandId: get-any-file\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport java.io.File;\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.conf.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef FILE_PATH = \"file\";\n\ndef filepath = Command.getFieldValue(p, FILE_PATH);\n\ndef result = p.commandResult(filepath ? Command.DataType.result : Command.DataType.form);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\n\nelse if (filepath == null) {\n\tCommand.addFieldValue(result, FILE_PATH, \"\", \"text-single\", \"File\");\n}\nelse {\n\tif (filepath == null) {\n\t\tCommand.addTextField(result, \"Error\", \"File not specified\");\n\t}\n\telse {\n\t\tdef file = new File(filepath);\n\t\tif (file.exists()) {\n\t\t\tdef lines = [];\n\t\t\tfile.eachLine { line -> lines += line; };\n\t\t\tCommand.addFieldMultiValue(result, \"Content\", lines);\n\t\t}\n\t\telse {\n\t\t\tCommand.addTextField(result, \"Error\", \"File not found\");\n\t\t}\n\t}\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetConfigFile.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet configuration file\n\nAS:Description: Get configuration file\nAS:CommandId: get-config-file\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport java.io.File;\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.conf.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef CFGFILE_TYPE = \"config-file\";\ndef CFGFILE_OPTIONS = [\"init.properties\", \"tigase.conf\"];\n\ndef cfgfile = Command.getFieldValue(p, CFGFILE_TYPE);\n\ndef result = p.commandResult(cfgfile ? Command.DataType.result : Command.DataType.form);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\nelse if (cfgfile == null) {\n\tdef filesArray = CFGFILE_OPTIONS.toArray(new String[CFGFILE_OPTIONS.size()]);\n\tCommand.addFieldValue(result, CFGFILE_TYPE, \"init.properties\", \"File\", filesArray, filesArray);\n}\nelse {\n\tdef filepath = null;\n\tswitch (cfgfile) {\n\t\tcase \"init.properties\":\n\t\t\tfilepath = initProperties.get(ConfiguratorAbstract.PROPERTY_FILENAME_PROP_KEY).tokenize(',');\n\t\t\tbreak;\n\n\t\tcase \"tigase.conf\":\n\t\t\tdef filenames = [\"/etc/default/tigase\", \"/etc/tigase/tigase.conf\", \"etc/tigase.conf\"];\n\t\t\tfilenames.each { it ->\n\t\t\t\tdef file = new File(it);\n\t\t\t\tif (!filepath && file.exists()) {\n\t\t\t\t\tfilepath = it;\n\t\t\t\t}\n\t\t\t};\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (filepath == null) {\n\t\tCommand.addTextField(result, \"Error\", \"Config file not specified\");\n\t}\n\telse {\n\t\tfilepath.each{ it ->\n\t\t\tdef file = new File(it);\n\t\t\tdef lines = [];\n\t\t\tfile.eachLine { line -> lines += line; };\n\t\t\tCommand.addFieldMultiValue(result, \"Content\", lines);\n\t\t}\n\t}\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetInitPropertiesFromMemory.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet init.properties configuration from memory.\n\nAS:Description: Get init.properties configuration\nAS:CommandId: get-init-properties\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.cert.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef result = p.commandResult(Command.DataType.result);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\nelse {\n\tdef lines = [];\n\tinitProperties.each { key, value ->\n\t\tlines += key + \"=\" + value;\n\t}\n\n\tCommand.addFieldMultiValue(result, \"init.properties\", lines);\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetListOfActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-active-users-list\n\n AS:Description: Get list of active users\n AS:CommandId: http://jabber.org/protocol/admin#get-active-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting List of Active Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the active users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of active users\", vhostsArr, vhostsArr);\n//\t}\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == true) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list active accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, active users not listed.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetListOfClusterNodes.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of all connected cluster nodes\n\n AS:Description: Get list of all connected cluster nodes\n AS:CommandId: cluster-nodes-list\n AS:Component: cl-comp\n AS:Group: Configuration\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.cluster.repo.ClusterRepoItem\nimport tigase.db.*\nimport tigase.db.comp.ComponentRepository\nimport tigase.xml.*\n\ndef p = (Packet)packet\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef repo = (ComponentRepository<ClusterRepoItem>)comp_repo;\n\tdef nodes = repo.allItems().collect { return it.getHostname() };\n\tCommand.addFieldMultiValue(result, \"Cluster nodes:\", nodes);\n} catch (Exception ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem with retrieving list of all connected cluster nodes: \" + ex.getMessage());\n}\nreturn result\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetListOfIdleUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-idle-users-list\n\n AS:Description: Get list of idle users\n AS:CommandId: http://jabber.org/protocol/admin#get-idle-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting List of Idle Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the idle users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of idle users\", vhostsArr, vhostsArr);\n//\t}\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == false) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list idle accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, idle users not listed.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetListOfOnlineUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-online-users-list\n\n AS:Description: Get list of online users\n AS:CommandId: http://jabber.org/protocol/admin#get-online-users-list\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\n\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Requesting List of Online Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the online users\\nof this service.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of online users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tvhosts = vhosts.sort();\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of online users\", vhostsArr, vhostsArr);\n//\t}\n\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\n\t\t\t\t\tusers_list += user;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list online accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, online users not listed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetNumberOfActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-active-users-num\n\n AS:Description: Get number of active users\n AS:CommandId: http://jabber.org/protocol/admin#get-active-users-num\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\nif (domainJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting Number of Active Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the number of active users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the number of active users\", vhostsArr, vhostsArr);\n//\t}\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\t//if (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == true) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t//}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldValue(result, \"activeusersnum\", String.valueOf(users_list.size()), \"fixed\", \"The number of active users\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to get number of active accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, active users not counted.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetNumberOfIdleUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-idle-users-num\n\n AS:Description: Get number of idle users\n AS:CommandId: http://jabber.org/protocol/admin#get-idle-users-num\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\nif (domainJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting Number of Idle Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the number of idle users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the number of idle users\", vhostsArr, vhostsArr);\n//\t}\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\t//if (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == false) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t//}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldValue(result, \"idleusersnum\", String.valueOf(users_list.size()), \"fixed\", \"The number of idle users\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to get number of idle accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, idle users not counted.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetRegisteredUserList.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Get registered user list script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-registered-users-list\n\n AS:Description: Get registered user list\n AS:CommandId: http://jabber.org/protocol/admin#get-registered-users-list\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\n\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Requesting List of Registered Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the registered users \\n of this service.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of online users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tvhosts = vhosts.sort();\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of registered users\", vhostsArr, vhostsArr);\n//\t}\n\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tdef domain_user_repo = (user_repo instanceof tigase.db.UserRepositoryMDImpl) ? user_repo.getRepo(bareJID.getDomain()) : user_repo;\n\t\tdef users =  domain_user_repo.getUsers();\n\t\tfor (user in users) {\n\t\t\tif (!user.getDomain().equals(bareJID.getDomain()))\n\t\t\t\tcontinue;\n\n\t\t\tusers_list.add(user.toString());\n\t\t\tif (maxItems && users_list.size() > maxItems)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, users not listed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetTopActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Retrieves from the server specified number of top active users\n AS:Description: Get top active users\n AS:CommandId: http://jabber.org/protocol/admin#get-top-active-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\n\ndef TOP_NUM = \"top-num\"\n\ndef p = (Packet)packet\n\ndef topNum = Command.getFieldValue(packet, TOP_NUM)\n\nif (topNum == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get top active users\")\n\tCommand.addInstructions(result, \"Fill out this form to get top active users.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, TOP_NUM, topNum ?: \"10\", \"text-single\",\n\t\t\t\"Number of top active users to show\")\n\n\treturn result\n}\n\ndef user_sessions = (Map)userSessions\n\ndef mc= [\n\t\t\tcompare: {XMPPSession a, XMPPSession b->\n\t\t\t\ta.getPacketsCounter() == b.getPacketsCounter() ? 0: a.getPacketsCounter()>b.getPacketsCounter()? -1: 1\n\t\t\t}\n\t\t] as Comparator\n\ndef sessions = []\n// TODO: this is memory inefficient way to do it. We need to find a more memory friendly way\nuser_sessions.entrySet().each {\n\tif (!it.getKey().toString().startsWith(\"sess-man\")) {\n\t\tsessions += it.getValue()\n\t}\n}\n\nsessions.sort(mc)\ndef max = topNum.toInteger()\nif (max > sessions.size() ) {\n\tmax = sessions.size()\n}\n\ndef usr_list = []\n\nsessions[0..(max-1)].each { XMPPSession it ->\n\tusr_list += it.getJIDs()[0].toString() + \" online \" + (it.getLiveTime()/1000) + \" sec, \" + it.getPacketsCounter() + \" packets\"\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Top active users \", usr_list);\nreturn result\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/GetUserRoster.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nObtaining User Statistics as described in in XEP-0133:\nhttp://xmpp.org/extensions/xep-0133.html#get-user-roster\n\nAS:Description: Get User Roster\nAS:CommandId: http://jabber.org/protocol/admin#get-user-roster\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.xmpp.impl.roster.*\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n        Command.addTitle(result, \"Getting a User's Roster\")\n        Command.addInstructions(result, \"Fill out this form to get a user's roster.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n        Command.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for which to retrieve roster\")\n\n\treturn result\n}\n\nbareJID = BareJID.bareJIDInstance(userJid)\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\ndef result = p.commandResult(Command.DataType.result)\n\nif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n            Command.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for which to retrieve roster\")\n\n            XMPPSession session = sessions.get(BareJID.bareJIDInstanceNS(userJid))\n\n\t    Element query = new Element(\"query\");\n\t    query.setXMLNS(\"jabber:iq:roster\");\n\t    if (session == null) {\n\t\tString rosterStr = repository.getData(bareJID, null,\n\t\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\troster.values().each {\n\t\t    query.addChild(it.getRosterItem());\n\t\t}\n    \t    } else {\n\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\tquery.addChildren(rosterUtil.getRosterItems(session.getActiveResources().get(0)));\n    \t    }\n\t    if (query != null) {\n\t\tresult.getElement().getChild(\"command\").getChild(\"x\", \"jabber:x:data\").addChild(query);\n\t    }\n\t} else {\n\t    Command.addTextField(result, \"Error\", \"You do not have enough permissions to retrieve roster for user in this domain.\");\n\t}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ListCommands.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of available adhoc commands with additional metadata.\n\n AS:Description: Get list available commands\n AS:CommandId: list-commands\n AS:Group: Scripts\n AS:ComponentClass: tigase.server.BasicComponent\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xml.Element\nimport tigase.xmpp.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef result = p.commandResult(Command.DataType.form)\nCommand.addTitle(result, \"Retrieving list of commands\");\n\ndef type = Command.getFieldValue(p, \"type\");\nif (!type) {\t\n\tCommand.addInstructions(result, \"Select a informations to retrieve\")\n\tCommand.addFieldValue(result, \"type\", \"\", \"Informations to retrive\", [\"Groups\", \"Commands\"].toArray(new String[2]), [\"groups\", \"commands\"].toArray(new String[2]));\n\treturn result;\n}\nelse if (type == \"groups\") {\n\tdef groups = [];\n\tCommand.addInstructions(result, \"Select a group for which to retrieve commands\");\n\tCommand.addFieldValue(result, \"type\", \"commands\", \"hidden\");\n\tadminCommands.each { id, script -> \n\t\tif (!component.canCallCommand(p.getStanzaFrom(), id))\n\t\t\treturn;\n\t\t\n\t\tdef group = script.getGroup();\n\t\tif (group == null) {\n\t\t\tgroup = \"--\";\n\t\t}\n\t\tif (!groups.contains(group))\n\t\t\tgroups.add(group);\n\t}\n\tCommand.addFieldValue(result, \"group\", \"\", \"Group\", groups.toArray(new String[groups.size()]), groups.toArray(new String[groups.size()]));\n\treturn result;\n}\nelse if (type == \"commands\") {\n\tdef group = Command.getFieldValue(p, \"group\");\n\tCommand.addInstructions(result, \"Following commands are available\" + (group ? \" for group $group\" : \"\"));\n\tdef x = Command.getData(result).find { it.getName() == \"x\" && it.getXMLNS() };\n\tdef reported = new Element(\"reported\");\n\tdef fields = [\"node\", \"group\", \"name\", \"jid\"];\n\treported.addChildren(fields.collect {\n\t\tnew Element(\"field\", [\"var\"].toArray(new String[1]), [it].toArray(new String[1]));\t\n\t});\n\tx.addChild(reported);\n\tdef scripts = [];\n\tadminCommands.each { id, script -> \n\t\tif (!component.canCallCommand(p.getStanzaFrom(), id))\n\t\t\treturn;\n\t\t\t\n\t\tif (group && !group.equals(script.getGroup()))\n\t\t\treturn;\n\t\t\t\n\t\tdef item = new Element(\"item\");\n\t\tfields.each {\n\t\t\tdef value = new Element(\"value\");\n\t\t\tdef field = new Element(\"field\");\n\t\t\tfield.setAttribute(\"var\", it);\n\t\t\tfield.addChild(value);\n\t\t\titem.addChild(field);\n\t\t\t\n\t\t\tif (it == \"node\") {\n\t\t\t\tvalue.setCData(id);\n\t\t\t} else if (it == \"group\") {\n\t\t\t\tvalue.setCData(script.getGroup());\n\t\t\t} else if (it == \"name\") {\n\t\t\t\tvalue.setCData(script.getDescription());\n\t\t\t} else if (it == \"jid\") {\n\t\t\t\tvalue.setCData(packet.getStanzaTo().toString());\n\t\t\t}\n\t\t}\n\t\tx.addChild(item);\n\t\t\n\t\tscripts.add([id:id, name:script.getDescription()]);\n\t}\t\n\t\n\tCommand.addFieldValue(result, \"commands\", \"\", \"Commands\", scripts.collect{ it.name }.toArray(new String[scripts.size()]), scripts.collect{ it.id }.toArray(new String[scripts.size()]));\n\treturn result;\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/ListServiceKeys.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nList all keys for active IOServices from the connection manager.\n\nAS:Description: List Service Keys\nAS:CommandId: service-keys\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\nMap services = (Map)servicesMap\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\nreturn services.keySet().toString()\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/LoadErrors.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nLoad errors caught by the server during execution:\n\nAS:Description: Load errors\nAS:CommandId: load-errors\nAS:Component: monitor\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef result = []\n\ndef size = LogFormatter.errors.size()\nif (size > 0) {\n\tLogFormatter.errors.each {\n\t\tdef entry = it.getValue()\n\t\tresult += \"\";\n\t\tresult += entry.getMessage() + \": \" + entry.getCounter()\n\t\tentry.getRecord().split(\"\\n\").each {\n\t\t\tresult += it\n\t\t}\n\t}\n} else {\n\tresult += \"No errors so far!\"\n}\n\ndef res = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(res, \"Errors: \" + size, result)\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/OAuthCredentials.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nAdHoc Command for setting OAuth credentials for JabberIQRegister\n\nAS:Description: OAuth credentials\nAS:CommandId: oauth-credentials\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\n\ndef p = (Packet)packet\n\ndef oauthTokenKey = Command.getFieldValue(packet, \"oauthTokenKey\")\ndef oauthTokenSecret = Command.getFieldValue(packet, \"oauthTokenSecret\")\ndef signedFormRequired = Command.getFieldValue(packet, \"signedFormRequired\")\n\nif (signedFormRequired == null) {\n\tdef res = p.commandResult(Command.DataType.form)\n\tCommand.addTitle(res, \"OAuth Credentials\")\n\tCommand.addInstructions(res, \"It allows to set new OAuth credentials and enable or disable requirement of registration with Signed Form.\")\n\tCommand.addFieldValue(res, \"oauthTokenKey\", \"\", \"text-single\", \"OAuth Token Key\")\n\tCommand.addFieldValue(res, \"oauthTokenSecret\", \"\", \"text-single\", \"OAuth Token Secret\")\n\tCommand.addFieldValue(res, \"signedFormRequired\", Boolean.toString(JabberIqRegister.isSignedFormRequired()), \"boolean\", \"Signed Form required to registration\") \n\treturn res\n} else {\n\tJabberIqRegister.setOAuthCredentials(oauthTokenKey, oauthTokenSecret)\n\tJabberIqRegister.setSignedFormRequired(signedFormRequired.equals(\"1\") || signedFormRequired.equals(\"true\"))\n\t\n\tdef res = p.commandResult(Command.DataType.result)\n\tCommand.addTitle(res, \"OAuth Credentials\")\n\tCommand.addInstructions(res, \"Credentials set.\")\n\treturn res\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/PluginManager.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nManage active server plugins\n\nAS:Description: Manage active server plugins\nAS:CommandId: plugin-manager\nAS:Component: basic-conf\nAS:Group: Configuration\n */\n\npackage tigase.admin\n\nimport tigase.conf.ConfigRepositoryIfc\nimport tigase.conf.Configurable;\nimport tigase.conf.Configurator;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.*\n\ntry {\n\ndef SUBMIT = \"submit\";\n        \ndef p = (Iq)packet\n\n// check permission\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n        def result = p.commandResult(Command.DataType.result)\n        Command.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n        return result\n}\n\n        \ndef submit = Command.getFieldValue(p, SUBMIT);\n\nif (!submit) {\n        def res = (Iq)p.commandResult(Command.DataType.form)\n                \n        def pluginsAll = [];\n\t\tif (XMPPServer.isOSGi()) {\n\t\t\tpluginsAll.addAll(ModulesManagerImpl.getInstance().plugins.keySet());\n\t\t}\n\t\telse {\n\t\t\tpluginsAll.addAll(tigase.xmpp.ProcessorFactory.processors.keySet());\n\t\t}\n        def conf = XMPPServer.getConfigurator();\n        def pluginsEnabled = [];\n        pluginsEnabled.addAll(tigase.server.xmppsession.SessionManagerConfig.PLUGINS_FULL_PROP_VAL);\n        \n        def pluginsStr = conf.getDefConfigParams().get(Configurable.GEN_SM_PLUGINS);\n        if (pluginsStr) {\n                pluginsStr.split(\",\").each { tmp ->\n                        def id = tmp;\n                        switch (tmp.charAt(0)) {\n                                case '+':\n                                        id = tmp.substring(1);\n                                        if (!pluginsAll.contains(id)) {\n                                                pluginsAll.add(id);\n                                        }\n                                        if (!pluginsEnabled.contains(id)) {\n                                                pluginsEnabled.add(id);\n                                        }\n                                        break;\n                                case '-':\n                                        id = tmp.substring(1);\n                                        if (!pluginsAll.contains(id)) {\n                                                pluginsAll.add(id);\n                                        }\n                                        pluginsEnabled.remove(id);\n                                        break;\n                                default:\n                                        pluginsEnabled.add(id);\n                                        break;\n                        }\n                }\n        }\n        \n        Command.addHiddenField(res, SUBMIT, SUBMIT);\n                \n        pluginsAll.sort();\n        pluginsAll.each { id ->\n                Command.addCheckBoxField(res, id, pluginsEnabled.contains(id));\n        }\n        \n        return res;\n}\nelse {\n        def pluginsEnabled = [];\n        pluginsEnabled.addAll(tigase.server.xmppsession.SessionManagerConfig.PLUGINS_FULL_PROP_VAL);\n        \n        def str = \"\";\n                \n        def data = Command.getData(p, \"x\", \"jabber:x:data\");\n        data.getChildren().each { child ->\n                if (child.getName() != 'field') return;\n                if (child.getAttribute(\"value\") == SUBMIT) return;\n                def id = tigase.xml.XMLUtils.escape(child.getAttribute(\"var\"));\n                def enable = Command.getCheckBoxFieldValue(p, id);\n                if (enable && pluginsEnabled.contains(id)) return;\n                if (!enable && !pluginsEnabled.contains(id)) return;\n                if (enable && !pluginsEnabled.contains(id)) {\n                        if (!str.isEmpty()) str += \",\";\n                        str += \"+\" + id;\n                        pluginsEnabled.add(id);\n                }\n                else if (!enable && pluginsEnabled.contains(id)) {\n                        if (!str.isEmpty()) str += \",\";\n                        str += \"-\" + id;\n\t\t\t\t\t\tpluginsEnabled.remove(id);\n                }\n        }\n\n        def conf = XMPPServer.getConfigurator();\n        conf.getDefConfigParams().put(Configurable.GEN_SM_PLUGINS, str.isEmpty() ? null : str);\n\t\n        def props = [:];\n        props[tigase.server.xmppsession.SessionManagerConfig.PLUGINS_PROP_KEY] = (pluginsEnabled as String[]);\n        conf.putProperties(\"sess-man\", props);\n                \n        ((Configurator) XMPPServer.getConfigurator()).updateMessageRouter();\n\t\t\n        def res = (Iq)p.commandResult(Command.DataType.result)\n\n        Command.addTextField(res, \"Note\", \"Operation successful.\");\n                \n        return res;\n}        \n\n}\ncatch (Exception ex) {\n        ex.printStackTrace();\n        throw ex;\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/PublishItem.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Publish item to PubSub node\n\n AS:Description: Publish item to node\n AS:CommandId: publish-item\n AS:Component: pubsub\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.pubsub.*\nimport tigase.pubsub.repository.IPubSubRepository\nimport tigase.pubsub.exceptions.PubSubException\nimport tigase.pubsub.exceptions.PubSubErrorCondition\nimport tigase.pubsub.modules.PublishItemModule.ItemPublishedHandler\n\n\ntry {\ndef NODE = \"node\"\ndef ID = \"item-id\";\ndef ENTRY = \"entry\";\n\nIPubSubRepository pubsubRepository = component.pubsubRepository\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef node = Command.getFieldValue(packet, NODE)\ndef id = Command.getFieldValue(packet, ID);\ndef entry = Command.getFieldValues(packet, ENTRY);\n\nif (!node || !entry) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Publish item to a node\")\n\tCommand.addInstructions(result, \"Fill out this form to publish item to a node.\")\n\n\tCommand.addFieldValue(result, NODE, node ?: \"\", \"text-single\",\n\t\t\t\"The node to publish to\")\n\tCommand.addFieldValue(result, ID, id ?: \"\", \"text-single\",\n\t\t\t\"ID of item\")\n\tCommand.addFieldValue(result, ENTRY, entry ?: \"\", \"text-multi\",\n\t\t\t\"Entry\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tif (isServiceAdmin) {\n\t\tdef toJid = p.getStanzaTo().getBareJID();\n\n\t\tdef nodeConfig = pubsubRepository.getNodeConfig(toJid, node);\n\t\tif (nodeConfig == null) {\n\t\t\tthrow new PubSubException(Authorization.ITEM_NOT_FOUND, \"Node \" + node + \" needs \" +\n\t\t\t\t\"to be created before an item can be published.\");\n\t\t}\n\t\tif (nodeConfig.getNodeType() == NodeType.collection) {\n\t\t\tthrow new PubSubException(Authorization.FEATURE_NOT_IMPLEMENTED,\n\t\t\t\t\t\tnew PubSubErrorCondition(\"unsupported\", \"publish\"));\n\t\t}\n\n\t\tdef nodeAffiliations = pubsubRepository.getNodeAffiliations(toJid, node);\n\t\tdef nodeSubscriptions = pubsubRepository.getNodeSubscriptions(toJid, node);\n\n\t\tElement item = new Element(\"item\");\n\t\tif (!id) id = UUID.randomUUID().toString();\n\t\titem.setAttribute(\"id\", id);\n\n\t\tdef data = entry.join(\"\\n\")\n\t\tdata = ((String) data).toCharArray();\n\n\t\tdef handler = new DomBuilderHandler();\n\t\tdef parser = SingletonFactory.getParserInstance();\n\t\tparser.parse(handler, data, 0, data.length);\n\t\titem.addChildren(handler.getParsedElements());\n\n\t\tdef items = new Element(\"items\");\n\t\titems.setAttribute(\"node\", node);\n\t\titems.addChild(item);\n\n\t\tdef results = [];\n\t\t\tcomponent.publishNodeModule.sendNotifications(items, packet.getStanzaTo(),\n\t\t\tnode, pubsubRepository.getNodeConfig(toJid, node),\n\t\t\tnodeAffiliations, nodeSubscriptions)\n\n\t\tdef parents = component.publishNodeModule.getParents(toJid, node);\n\n\t\tif (!parents) {\n\t\t\tparents.each { collection ->\n\t\t\t\tdef headers = [Collection:collection];\n\n\t\t\t\tAbstractNodeConfig colNodeConfig    = pubsubRepository.getNodeConfig(toJid, collection);\n\t\t\t\tdef colNodeSubscriptions =\n\t\t\t\t\tpubsubRepository.getNodeSubscriptions(toJid, collection);\n\t\t\t\tdef colNodeAffiliations =\n\t\t\t\t\tpubsubRepository.getNodeAffiliations(toJid, collection);\n\n\t\t\t\t\tcomponent.publishNodeModule.sendNotifications(items, packet.getStanzaTo(),\n\t\t\t\t\t\t\t\t\tnode, headers, colNodeConfig,\n\t\t\t\t\t\t\t\t\tcolNodeAffiliations, colNodeSubscriptions)\n\t\t\t}\n\t\t}\n\n\t\tif (nodeConfig.isPersistItem()) {\n\t\t\tdef nodeItems = pubsubRepository.getNodeItems(toJid, node);\n\n\t\t\tnodeItems.writeItem(System.currentTimeMillis(), id,\n\t\t\t\t\tp.getAttributeStaticStr(\"from\"), item);\n\n\t\t\tif (nodeConfig.getMaxItems() != null) {\n\t\t\t\tcomponent.publishNodeModule.trimItems(nodeItems, nodeConfig.getMaxItems());\n\t\t\t}\n\t\t}\n\n\t\tresults.each { packet ->\n\t\t\tcomponent.addOutPacket(packet);\n\t\t}\n\n\t\t\tcomponent.getEventBus().fire(\n\t\t\t\tnew ItemPublishedHandler.ItemPublishedEvent(packet.getStanzaTo().getBareJID(), node, itemsToSend));\n\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\t//Command.addTextField(result, \"Error\", \"You do not have enough permissions to publish item to a node.\");\n\t\tthrow new PubSubException(Authorization.FORBIDDEN, \"You do not have enough \" +\n\t\t\t\t\"permissions to publish item to a node.\");\n\t}\n} catch (PubSubException ex) {\n\tCommand.addTextField(result, \"Error\", ex.getMessage())\n\tif (ex.getErrorCondition()) {\n\t\tdef error = ex.getErrorCondition();\n\t\tElement errorEl = new Element(\"error\");\n\t\terrorEl.setAttribute(\"type\", error.getErrorType());\n\t\tElement conditionEl = new Element(error.getCondition(), ex.getMessage());\n\t\tconditionEl.setXMLNS(Packet.ERROR_NS);\n\t\terrorEl.addChild(conditionEl);\n\t\tElement pubsubCondition = ex.pubSubErrorCondition?.getElement();\n\t\tif (pubsubCondition)\n\t\t\terrorEl.addChild(pubsubCondition);\n\t\tresult.getElement().addChild(errorEl);\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, item not published to node.\");\n}\n\nreturn result\n\n} catch (Exception ex) {\n\tex.printStackTrace();\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/RemoveUserTracker.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Activate on the server user tracking mechanisms to aid in problem resolution.\n AS:Description: Remove log tracker for a user\n AS:CommandId: http://jabber.org/protocol/admin#remove-user-tracker\n AS:Component: sess-man\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\nimport java.util.logging.*\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Removing a User Log Tracker\")\n\t//Command.addInstructions(result, \"Fill out this form to add a user log tracker.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the tracker to be removed\")\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\n\ndef hand = null\n\nHandler[] handlers = Logger.getLogger(\"\").getHandlers()\nhandlers.each {\n\tFilter filt = it.getFilter()\n\tif (filt != null && filt.class == LogUserFilter && ((LogUserFilter)filt).getId() == userJid) {\n\t\thand = it\n\t}\n}\n\nif (hand != null) {\n\tLogger.getLogger(\"\").removeHandler(hand)\n\thand.close()\n\tCommand.addTextField(result, \"Note\", \"Operation successful, tracker removed for \" + userJid);\n} else {\n\tCommand.addTextField(result, \"Note\", \"No tracker found for user \" + userJid)\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/RosterFixer.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\n\nThe roster fixer scripts is used in a case if for whatever reason user's roster got\nbroken, lost or otherwise messed up. If we know the user's contact list, this script\ncan be used to restore the contact list. It adds missing entries to the user's roster.\nIf the user is online, he gets a roster push with updated entries to make sure\nhe is up to date with all the changes.\nThe script accepts a user JID, action (update or remove) and a list of buddies in\na following format:\nbuddy_jid,buddy_name,subscription\nbuddy_jid is a JID (bare JID)\nbuddy_name is just a string, it is optional, if omit, localpart of the JID is used\nsubscription is one of following (none, from, to, both), it is optional, if omit 'both' is used\n\n\nAS:Description: Fixes user's roster\nAS:CommandId: roster-fixer\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\ndef ROSTER_BUDDY_LIST = \"roster-buddy-list\"\n\ndef ROSTER_ACTION = \"roster-action\"\n\ndef UPDATE = \"update\"\ndef REMOVE = \"remove\"\ndef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\ndef actions = [UPDATE, REMOVE]\ndef actions_descr = [\"Add/Update item\", \"Remove item\"]\n//def notify_cluster = [\"no\", \"yes\"]\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\n\ndef stanzaFromBare = p.getStanzaFrom().getBareJID();\ndef isServiceAdmin = admins.contains(stanzaFromBare);\n\ndef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\ndef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\ndef rosterBuddyList = Command.getFieldValues(packet, ROSTER_BUDDY_LIST)\n\n//def rosterNotifyCluster = Command.getFieldValue(packet, ROSTER_NOTIFY_CLUSTER)\n\nif (rosterOwnerJid == null || rosterBuddyList == null ||\n\trosterAction == null) {\n\tdef res = p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\",\n    \"jid-single\", \"Roster owner JID\")\n\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0],\n    \"Action\", (String[])actions_descr, (String[])actions)\n\n\tif (rosterBuddyList == null) {\n\t\trosterBuddyList = [\"\"]\n\t}\n\tCommand.addFieldMultiValue(res, ROSTER_BUDDY_LIST, rosterBuddyList)\n\n//\tCommand.addFieldValue(res, ROSTER_NOTIFY_CLUSTER, notify_cluster[0],\n//    \"Notify cluster\", (String[])notify_cluster, (String[])notify_cluster)\n\n\treturn res\n}\n\ndef remove_item = rosterAction == REMOVE\n\ndef Queue<Packet> results = new LinkedList<Packet>()\n\ndef res_report = []\n\ndef updateRoster = { sess, online, jid, i_jid, i_name, i_subscr ->\n\n\tif (online) {\n//\t\tsess.getActiveResources().each{ conn ->\n\t\tdef conn = sess.getActiveResources()[0]\n\t\t  // Update online\n\t\t  RosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t  if (remove_item) {\n\t\t\t  rosterUtil.removeBuddy(conn, i_jid)\n  \t\t  Element item = new Element(\"item\",\n\t  \t\t  (String[])[\"jid\", \"subscription\"], (String[])[i_jid, \"remove\"])\n  \t\t  rosterUtil.updateBuddyChange(conn, results, item)\n\t\t\t  res_report += \"Buddy: \"+ i_jid + \" removed\"\n\t\t  } else {\n\t\t\t  if (rosterUtil.containsBuddy(conn, i_jid)) {\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n\t\t\t\t} else {\n  \t\t\t  rosterUtil.addBuddy(conn, i_jid, i_name, null, null)\n\t  \t\t  rosterUtil.setBuddySubscription(conn,\n\t\t  \t\t  RosterAbstract.SubscriptionType.valueOf(i_subscr), i_jid)\n\t\t\t    item = rosterUtil.getBuddyItem(conn, i_jid)\n    \t\t  rosterUtil.updateBuddyChange(conn, results, item)\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n\t\t\t\t}\n\t\t  }\n//\t\t}\n\t} else {\n\t\t// Update offline\n\t\tString rosterStr = repository.getData(jid.getBareJID(), null,\n\t\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\tif (remove_item) {\n\t\t\troster.remove(i_jid.getBareJID())\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" removed\"\n\t\t} else {\n      if (roster.get(i_jid.getBareJID()) == null) {\n\t\t\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, null, null)\n\t\t\t\t  rel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\t    roster.put(i_jid, rel)\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n      } else {\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n      }\n\t\t}\n\t\tStringBuilder sb = new StringBuilder(200)\n\t\tfor (RosterElement relem: roster.values())\n\t\t\tsb.append(relem.getRosterElement().toString())\n\t\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\t}\n}\n\ndef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid);\n\nPacket result = p.commandResult(Command.DataType.result)\ndef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\nif (vhost == null ||\n\t(!isServiceAdmin &&\n\t !vhost.isOwner(stanzaFromBare.toString()) &&\n\t !vhost.isAdmin(stanzaFromBare.toString()))) {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\tresults.add(result);\n\treturn results;\n}\n\ndef rosterItemJid = null\ndef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID());\ndef conn = sess != null ? sess.getActiveResources().get(0) : null;\ndef online = true\nif (conn) {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is online, updating database and online connections\"\n} else {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is offline, updating database only\"\n\tonline = false\n}\n\nrosterBuddyList.each {\n  def\tbuddy = it.split(\",\")\n\tif (it.contains(';')) {\n  \tbuddy = it.split(\";\")\n\t}\n\trosterItemJid = buddy[0]\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid)\n\tdef rosterItemName = (buddy as List)[1] ?: jidRosterItemJid.getLocalpart()\n\tdef rosterItemSubscr = (buddy as List)[2] ?: \"both\"\n\n  updateRoster(sess, online, jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemSubscr)\n\n\t\tif (!remove_item) {\n\n\t\t\tElement pres = new Element(\"presence\",\n\t\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterOwnerJid, rosterItemJid,\n\t\t\t\t\t\"probe\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t\tpres = new Element(\"presence\",\n\t\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterItemJid, rosterOwnerJid,\n\t\t\t\t\t\"probe\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t}\n\n}\n\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addFieldMultiValue(result, \"Report: \", res_report)\nresults.add(result)\n\nreturn results\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/RosterFixerCluster.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\nThe roster fixer scripts is used in a case if for whatever reason user's roster got\nbroken, lost or otherwise messed up. If we know the user's contact list, this script\ncan be used to restore the contact list. It adds missing entries to the user's roster.\nIf the user is online, he gets a roster push with updated entries to make sure\nhe is up to date with all the changes.\nThe script accepts a user JID, action (update or remove) and a list of buddies in\na following format:\nbuddy_jid,buddy_name,subscription\nbuddy_jid is a JID (bare JID)\nbuddy_name is just a string, it is optional, if omit, localpart of the JID is used\nsubscription is one of following (none, from, to, both), it is optional, if omit 'both' is used\nAS:Description: Fixes user's roster on Tigase cluster\nAS:CommandId: roster-fixer-cluster\nAS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport java.util.Set;\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.cluster.strategy.*\n\ndef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\ndef ROSTER_BUDDY_LIST = \"roster-buddy-list\"\n\ndef ROSTER_ACTION = \"roster-action\"\n\ndef DISCONNECTED_PHASE = \"disconnected-phase\"\n\ndef UPDATE = \"update\"\ndef REMOVE = \"remove\"\ndef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\ndef actions = [UPDATE, REMOVE]\ndef actions_descr = [\"Add/Update item\", \"Remove item\"]\n//def notify_cluster = [\"no\", \"yes\"]\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\n\ndef stanzaFromBare = p.getStanzaFrom().getBareJID();\ndef isServiceAdmin = admins.contains(stanzaFromBare);\n\ndef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\ndef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\ndef rosterBuddyList = Command.getFieldValues(packet, ROSTER_BUDDY_LIST)\n\n//def rosterNotifyCluster = Command.getFieldValue(packet, ROSTER_NOTIFY_CLUSTER)\n\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\n\nif (rosterOwnerJid == null || rosterBuddyList == null ||\n\trosterAction == null) {\n\tdef res = p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\",\n\t\t\t\"jid-single\", \"Roster owner JID\")\n\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0],\n\t\t\t\"Action\", (String[])actions_descr, (String[])actions)\n\n\tif (rosterBuddyList == null) {\n\t\trosterBuddyList = [\"\"]\n\t}\n\tCommand.addFieldMultiValue(res, ROSTER_BUDDY_LIST, rosterBuddyList)\n\n\t//\tCommand.addFieldValue(res, ROSTER_NOTIFY_CLUSTER, notify_cluster[0],\n\t//    \"Notify cluster\", (String[])notify_cluster, (String[])notify_cluster)\n\n\treturn res\n}\n\ndef remove_item = rosterAction == REMOVE\ndef res_report = []\ndef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid)\ndef Queue<Packet> results = new LinkedList<Packet>()\n\nPacket result = p.commandResult(Command.DataType.result)\ndef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\nif (vhost == null ||\n\t(!isServiceAdmin &&\n\t\t!vhost.isOwner(stanzaFromBare.toString()) &&\n\t\t!vhost.isAdmin(stanzaFromBare.toString()))) {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\tresults.offer(result);\n\treturn results;\n}\n\ndef disconnected = Command.getFieldValue(p, DISCONNECTED_PHASE)\n\n// Disconnecting all user's connections on the whole cluster\n\nif (!disconnected) {\n\n\tdef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID())\n\tdef online = false\n\n\tif (sess && sess.getActiveResourcesSize() > 0) {\n\t\tsess.getActiveResources().each{ conn ->\n\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), conn.getConnectionId(),\n\t\t\t\tStanzaType.set, conn.nextStanzaId())\n\t\t\tresults.offer(commandClose)\n\t\t\tres_report += \"User: \" + conn.getjid() + \" is online, disconnected.\"\n\t\t}\n\t\tonline = true\n\t}\n\n\tif \t( clusterMode ) {\n\t\tif ( null != clusterStrategy ) {\n\t\t\tdef cluster = (ClusteringStrategyIfc)clusterStrategy\n\t\t\tSet<ConnectionRecord> cl_conns = cluster.getConnectionRecords(jidRosterOwnerJid.getBareJID())\n\t\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\t\tcl_conns.each {\n\t\t\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), it.getConnectionId(),\n\t\t\t\t\t\tStanzaType.set, \"77\")\n\t\t\t\t\tresults.offer(commandClose)\n\t\t\t\t\tres_report += \"User: \" + it.getUserJid() + \" is online on node: \" + it.getNode() + \", disconnected.\"\n\n\t\t\t\t}\n\t\t\t\tonline = true\n\t\t\t}\n\t\t}\n\t}\n\n\tif (online) {\n\t\tCommand.addFieldMultiValue(p, \"Report: \", res_report)\n\t\tCommand.addHiddenField(p, DISCONNECTED_PHASE, DISCONNECTED_PHASE)\n\t\tresults.offer(p)\n\n\t\treturn results\n\t}\n} else {\n\n\tCommand.getFieldValues(packet, \"Report: \").each {\n\t\tres_report += it\n\t}\n}\n\n// Waiting 2 secs\n\nsleep(2000)\n\n// Updating user's roster in DB\n\ndef updateRoster = { sess, online, jid, i_jid, i_name, i_subscr ->\n\n\t// Update offline\n\tString rosterStr = repository.getData(jid.getBareJID(), null,\n\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\tif (remove_item) {\n\t\troster.remove(i_jid.getBareJID())\n\t\tres_report += \"Buddy: \"+ i_jid + \" removed\"\n\t} else {\n\t\tif (roster.get(i_jid.getBareJID()) == null) {\n\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, null, null)\n\t\t\trel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\troster.put(i_jid, rel)\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n\t\t} else {\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n\t\t}\n\t}\n\tStringBuilder sb = new StringBuilder(200)\n\tfor (RosterElement relem: roster.values())\n\tsb.append(relem.getRosterElement().toString())\n\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\n}\n\n\ndef rosterItemJid = null\ndef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID());\ndef conn = sess != null ? sess.getActiveResources().get(0) : null;\ndef online = true\nif (conn) {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is online, updating database and online connections\"\n} else {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is offline, updating database only\"\n\tonline = false\n}\n\nrosterBuddyList.each {\n\tdef\tbuddy = it.split(\",\")\n\tif (it.contains(';')) {\n\t\tbuddy = it.split(\";\")\n\t}\n\trosterItemJid = buddy[0]\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid)\n\tdef rosterItemName = (buddy as List)[1] ?: jidRosterItemJid.getLocalpart()\n\tdef rosterItemSubscr = (buddy as List)[2] ?: \"both\"\n\n\tupdateRoster(sess, online, jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemSubscr)\n\n\tif (!remove_item) {\n\n\t\tElement pres = new Element(\"presence\",\n\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterOwnerJid, rosterItemJid,\n\t\t\t\t\t\"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t\tpres = new Element(\"presence\",\n\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterItemJid, rosterOwnerJid,\n\t\t\t\t\t\"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t}\n\n}\n\n// Finishing the work and completing script\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addFieldMultiValue(result, \"Report: \", res_report)\nresults.add(result)\n\nreturn results\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/S2SBadConnectionStates.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Script tries to find S2S connection in a bad state and reports connection details.\n AS:Description: S2S Bad State Connections\n AS:CommandId: s2s-bad-state-conns\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef p = (Packet)packet\ndef cidConns = (Map)cidConnections\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef conns = []\n\nconns += \"Total count: \" + cidConns.size()\n\ncidConns.entrySet().each {\n\tCIDConnections con = it.getValue()\n\tif (con.getWaitingCount() > 0) {\n\t\tconns += it.getKey().toString() +\n\t\t\t\t\", out in progress: \" + con.getOutgoingInProgress() +\n\t\t\t\t\", waiting: \" + con.getWaitingCount() +\n\t\t\t\t\", control: \" + con.getWaitingControlCount() +\n\t\t\t\t\", incoming: \" + con.getIncomingCount() +\n\t\t\t\t\", outgoing: \" + con.getOutgoingCount() +\n\t\t\t\t\", out-handshaking: \" + con.getOutgoingHandshakingCount()\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Connections with waiting packets\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/S2SCIDState.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Returns S2S connection state for given CID\n AS:Description: S2S get CID connection state\n AS:CommandId: s2s-get-cid-connection\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef CID_KEY = \"cid\"\n\ndef cid = Command.getFieldValue(packet, CID_KEY)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\nif (cid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get S2S connection state\")\n\tCommand.addInstructions(result, \"Fill out this form to get S2S connection state\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, CID_KEY, cid ?: \"\", \"text-single\",\n\t\t\t\"S2S connection CID\")\n\n\treturn result\n}\n\ndef conns = []\ndef cidConns = (Map)cidConnections\n\nCID c = new CID(cid)\nCIDConnections con = cidConns.get(c)\n\nif (con == null) {\n\tconns += \"No such CID connection found\"\n} else {\n\tconns += cid\n\tconns += \"out in progress: \" + con.getOutgoingInProgress()\n\tconns += \"waiting: \" + con.getWaitingCount()\n\tconns += \"control: \" + con.getWaitingControlCount()\n\tconns += \"incoming: \" + con.getIncomingCount()\n\tconns += \"outgoing: \" + con.getOutgoingCount()\n\tconns += \"out-handshaking: \" + con.getOutgoingHandshakingCount()\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"S2S connection\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/S2SResetBadConnections.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Script tries to find S2S connection in a bad state and resets their state\n AS:Description: S2S Reset Bad State Connections\n AS:CommandId: s2s-reset-bad-state-conns\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef cidConns = (Map)cidConnections\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\ndef conns = []\n\nconns += \"Total count: \" + cidConns.size()\n\ncidConns.entrySet().each {\n\tCIDConnections con = it.getValue()\n\t// Bad state is when the OutgoingInProgress is set to true but there is no outgoing\n\t// or outgoing handshaking connections.\n\tif (con.getOutgoingInProgress() && (con.getOutgoingCount() == 0) &&\n\t(con.getOutgoingHandshakingCount() == 0)) {\n\t\tconns += it.getKey().toString() + \", waiting: \" + con.getWaitingCount()\n\t\tcon.resetOutgoingInProgress()\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Reset connections\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/SSLCertificateAdd.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nAdd an SSL certificate for a given domain.\n\nAS:Description: Add SSL Certificate\nAS:CommandId: ssl-certificate-add\nAS:Component: vhost-man\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.cert.*\nimport tigase.io.*\nimport tigase.xmpp.JID\nimport tigase.cluster.*\nimport tigase.conf.ConfiguratorAbstract;\n\ndef MARKER = \"command-marker\"\n//def ITEMS = \"item-list\"\n\ndef VHOST = \"VHost\"\ndef CERTIFICATE = \"Certificate in PEM format\"\ndef SAVE_TO_DISK = \"Save to disk\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, VHOST)\ndef marker = Command.getFieldValue(packet, MARKER)\ndef pemCertVals = Command.getFieldValues(packet, CERTIFICATE)\ndef saveToDisk = Command.getCheckBoxFieldValue(packet, SAVE_TO_DISK)\n\nQueue results = new LinkedList()\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\n// The first step - provide a list of all vhosts for the user\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, VHOST, itemsStr[0], \"List of VHosts\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Note\", \"You have no VHosts to manage\");\n\t\treturn result\n\t}\n}\n\n// The second step - provide a form to fill be by the user for selected vhost\nif (marker == null) {\n\tdef item = repo.getItem(itemKey)\n\tif (item == null) {\n\t\tCommand.addTextField(result, \"Error\", \"No such VHost, adding SSL Certificate impossible.\");\n\t} else {\n\t\tif (isServiceAdmin || item.isOwner(stanzaFromBare.toString()) || item.isAdmin(stanzaFromBare.toString())) {\n\t\t\tdef result = p.commandResult(Command.DataType.form)\n      Command.addFieldValue(result, VHOST, itemKey, \"text-single\")\n\t\t\tCommand.addFieldMultiValue(result, CERTIFICATE, [\"\"])\n\t\t\tCommand.addCheckBoxField(result, SAVE_TO_DISK, true)\n\t\t\tCommand.addHiddenField(result, MARKER, MARKER)\n\t\t\tif \t( clusterMode  ) {\n\t\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t\t}\n\t\t\treturn result\n\t\t} else {\n\t\t\tdef result = p.commandResult(Command.DataType.result)\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this VHost.\")\n\t\t\treturn result\n\t\t}\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\n// The last step - process the form submitted by the user\ndef result = p.commandResult(Command.DataType.result)\ndef item = repo.getItem(itemKey)\n\nif (item == null) {\n\tCommand.addTextField(result, \"Error\", \"No such VHost, loading SSL certificate impossible.\")\n} else {\n  if (isServiceAdmin || item.isOwner(stanzaFromBare.toString())) {\n\t\tdef pemCert = pemCertVals.join('\\n')\n    // Basic certificate checks\n\t\t// For XMPP service nonAdmins (domain owners) the alias must match CN name in the certificate\n\t\tCertificateEntry certEntry = CertificateUtil.parseCertificate(new CharArrayReader(pemCert.toCharArray()))\n\t\tif (certEntry.getPrivateKey() == null) {\n\t\t\tCommand.addTextField(result, \"Error\", \"Missing private key or private key encoded in uknown format.\")\n\t\t\tCommand.addTextField(result, \"Note\", \"Private key cannot be encoded with a password.\")\n\t\t\t//println(pemCert);\n\t\t} else {\n\t\t\tdef certCName = CertificateUtil.getCertCName(certEntry.getCertChain()[0])\n\t\t\tdef subjectAltName = CertificateUtil.getCertAltCName(certEntry.getCertChain()[0])\n\t\t\tif (certCName != itemKey && !subjectAltName.contains(itemKey) && !isServiceAdmin) {\n\t\t\t\tCommand.addTextField(result, \"Error\", \"Neither certificate CName nor any of SubjectAlternativeNames match the domain name!\")\n\t\t\t} else {\n\t\t\t\tdef params = new HashMap()\n\t\t\t\tparams.put(SSLContextContainerIfc.PEM_CERTIFICATE_KEY, pemCert)\n\t\t\t\tparams.put(SSLContextContainerIfc.CERT_ALIAS_KEY, itemKey)\n\t\t\t\tparams.put(SSLContextContainerIfc.CERT_SAVE_TO_DISK_KEY, saveToDisk.toString())\n\t\t\t\tTLSUtil.addCertificate(params)\n\t\t\t\tCommand.addTextField(result, \"Note\", \"SSL Certificate for domain: \" + itemKey + \" loaded successfully\")\n\t\t\t}\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You are not the VHost owner or you have no \"\n\t\t\t+ \"enough permission to change the VHost.\")\n\t}\n}\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/SimServiceStopped.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nSimulate service stopped uncontrolled execution to help with testing weird network\nproblems.\n\nAS:Description: Simulate serviceStopped method call\nAS:CommandId: sim-serv-stopped\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.net.*\nimport tigase.cluster.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef KEY = \"key\"\n\ndef key = Command.getFieldValue(packet, KEY)\n\nif (key == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n  Command.addTitle(result, \"Simulate serviceStopped method call\")\n\tCommand.addInstructions(result, \"Provide a key for IOService you wish to test.\")\n\tCommand.addFieldValue(result, KEY, key ?: \"\", \"text-single\",  \"Key\")\n\n\treturn result\n}\n\nMap services = (Map)servicesMap\n\nIOService serv = services.get(key)\n\nif (serv == null) {\n\treturn \"IOService for key: ${key} not found!\"\n} else {\n  ClusterConnectionManager clCM = (ClusterConnectionManager)clusterCM\n\tclCM.serviceStopped(serv)\n\treturn \"serviceStopped called for IOService for key: ${key}.\"\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/SubscribeNode.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Subscribe to PubSub node\n\n AS:Description: Subscribe to node\n AS:CommandId: subscribe-node\n AS:Component: pubsub\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.pubsub.*\nimport tigase.pubsub.repository.IPubSubRepository\nimport tigase.pubsub.exceptions.PubSubException\n\ndef NODE = \"node\"\ndef JIDS = \"jids\";\n\nIPubSubRepository pubsubRepository = component.pubsubRepository\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef node = Command.getFieldValue(packet, NODE)\ndef jids = Command.getFieldValues(packet, JIDS);\n\nif (node == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Subscribe to a node\")\n\tCommand.addInstructions(result, \"Fill out this form to subscribe to a node.\")\n\n\tCommand.addFieldValue(result, NODE, node ?: \"\", \"text-single\",\n\t\t\t\"The node to subscribe to\")\t\n\tCommand.addFieldValue(result, JIDS, jids ?: \"\", \"jid-multi\",\n\t\t\t\"JIDs to subscribe\")\n\t\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tif (isServiceAdmin) {\n\t\tdef toJid = p.getStanzaTo().getBareJID();\n\t\t\n\t\tAbstractNodeConfig nodeConfig = pubsubRepository.getNodeConfig(toJid, node);\n\n\t\tif (nodeConfig == null) {\n\t\t\tthrow new PubSubException(Authorization.ITEM_NOT_FOUND, \"Node \" + node + \" needs \" + \n\t\t\t\t\"to be created before anyone will be able to subscribe to a node.\");\n\t\t}\n\t\t\n\t\tdef nodeAffiliations  = pubsubRepository.getNodeAffiliations(toJid, node);\n\t\tdef nodeSubscriptions = pubsubRepository.getNodeSubscriptions(toJid, node);\n\t\t\n\t\tjids.each { jidStr ->\n\t\t\tdef jid = BareJID.bareJIDInstance(jidStr);\n\t\t\tdef subscription = nodeSubscriptions.getSubscription(jid)\n\t\t\tdef affiliation = nodeAffiliations.getSubscriberAffiliation(jid).getAffiliation();\n\t\t\t\n\t\t\taffiliation = affiliation.getWeight() > Affiliation.member.getWeight() ? affiliation : Affiliation.member;\n\t\t\tString subid = nodeSubscriptions.getSubscriptionId(jid);\n\t\t\t\n\t\t\tif (subid == null) {\n\t\t\t\tsubid = nodeSubscriptions.addSubscriberJid(jid, Subscription.subscribed);\n\t\t\t\tnodeAffiliations.addAffiliation(jid, affiliation);\n\t\t\t} else {\n\t\t\t\tnodeSubscriptions.changeSubscription(jid, Subscription.subscribed);\n\t\t\t\tnodeAffiliations.changeAffiliation(jid, affiliation);\n\t\t\t}\n\n\t\t\t// repository.setData(config.getServiceName(), nodeName, \"owner\",\n\t\t\t// JIDUtils.getNodeID(element.getAttribute(\"from\")));\n\t\t\tif (nodeSubscriptions.isChanged()) {\n\t\t\t\tpubsubRepository.update(toJid, node, nodeSubscriptions);\n\t\t\t}\n\t\t\tif (nodeAffiliations.isChanged()) {\n\t\t\t\tpubsubRepository.update(toJid, node, nodeAffiliations);\n\t\t\t}\n\n\t\t}\n\t\t\t\t\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\t//Command.addTextField(result, \"Error\", \"You do not have enough permissions to publish item to a node.\");\n\t\tthrow new PubSubException(Authorization.FORBIDDEN, \"You do not have enough \" + \n\t\t\t\t\"permissions to publish item to a node.\");\n\t}\n} catch (PubSubException ex) {\n\tCommand.addTextField(result, \"Error\", ex.getMessage())\t\n\tif (ex.getErrorCondition()) {\n\t\tdef error = ex.getErrorCondition();\n\t\tElement errorEl = new Element(\"error\");\n\t\terrorEl.setAttribute(\"type\", error.getErrorType());\n\t\tElement conditionEl = new Element(error.getCondition(), ex.getMessage());\n\t\tconditionEl.setXMLNS(Packet.ERROR_NS);\n\t\terrorEl.addChild(conditionEl);\n\t\tElement pubsubCondition = ex.pubSubErrorCondition?.getElement();\n\t\tif (pubsubCondition)\n\t\t\terrorEl.addChild(pubsubCondition);\n\t\tresult.getElement().addChild(errorEl);\t\n\t}\t\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, not subscribed to node.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/UnsubscribeNode.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Unsubscribe from PubSub node\n\n AS:Description: Unsubscribe fromo node\n AS:CommandId: unsubscribe-node\n AS:Component: pubsub\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.pubsub.*\nimport tigase.pubsub.repository.IPubSubRepository\nimport tigase.pubsub.exceptions.PubSubException\n\ndef NODE = \"node\"\ndef JIDS = \"jids\";\n\nIPubSubRepository pubsubRepository = component.pubsubRepository\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef node = Command.getFieldValue(packet, NODE)\ndef jids = Command.getFieldValues(packet, JIDS);\n\nif (node == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Unsubscribe from a node\")\n\tCommand.addInstructions(result, \"Fill out this form to unsubscribe from a node.\")\n\n\tCommand.addFieldValue(result, NODE, node ?: \"\", \"text-single\",\n\t\t\t\"The node to unsubscribe from\")\t\n\tCommand.addFieldValue(result, JIDS, jids ?: \"\", \"jid-multi\",\n\t\t\t\"JIDs to unsubscribe\")\n\t\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tif (isServiceAdmin) {\n\t\tdef toJid = p.getStanzaTo().getBareJID();\n\t\t\n\t\tAbstractNodeConfig nodeConfig = pubsubRepository.getNodeConfig(toJid, node);\n\n\t\tif (nodeConfig == null) {\n\t\t\tthrow new PubSubException(Authorization.ITEM_NOT_FOUND, \"Node \" + node + \" needs \" + \n\t\t\t\t\"to be created before anyone will be able to subscribe or unsubscribe.\");\n\t\t}\n\t\t\n\t\tdef nodeAffiliations  = pubsubRepository.getNodeAffiliations(toJid, node);\n\t\tdef nodeSubscriptions = pubsubRepository.getNodeSubscriptions(toJid, node);\n\t\t\n\t\tjids.each { jidStr ->\n\t\t\tdef jid = BareJID.bareJIDInstance(jidStr);\n\t\t\tdef subscription = nodeSubscriptions.getSubscription(jid)\n\t\t\tif (!subscription || subscription == Subscription.none)\n\t\t\t\treturn;\n\t\t\t\t\n\t\t\tnodeSubscriptions.changeSubscription(jid, Subscription.none);\n\t\t\t\n\t\t\tif (nodeSubscriptions.isChanged()) {\n\t\t\t\tpubsubRepository.update(toJid, node, nodeSubscriptions);\n\t\t\t}\t\t\t\n\t\t}\n\t\t\t\t\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\t//Command.addTextField(result, \"Error\", \"You do not have enough permissions to publish item to a node.\");\n\t\tthrow new PubSubException(Authorization.FORBIDDEN, \"You do not have enough \" + \n\t\t\t\t\"permissions to publish item to a node.\");\n\t}\n} catch (PubSubException ex) {\n\tCommand.addTextField(result, \"Error\", ex.getMessage())\t\n\tif (ex.getErrorCondition()) {\n\t\tdef error = ex.getErrorCondition();\n\t\tElement errorEl = new Element(\"error\");\n\t\terrorEl.setAttribute(\"type\", error.getErrorType());\n\t\tElement conditionEl = new Element(error.getCondition(), ex.getMessage());\n\t\tconditionEl.setXMLNS(Packet.ERROR_NS);\n\t\terrorEl.addChild(conditionEl);\n\t\tElement pubsubCondition = ex.pubSubErrorCondition?.getElement();\n\t\tif (pubsubCondition)\n\t\t\terrorEl.addChild(pubsubCondition);\n\t\tresult.getElement().addChild(errorEl);\t\n\t}\t\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, not unsubscribed from node.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/UserDomainFilter.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nAS:Description: Change user inter-domain communication permission.\nAS:CommandId: user-domain-perm\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.xmpp.impl.DomainFilter\nimport tigase.vhosts.filter.DomainFilterPolicy\nimport tigase.db.UserRepository\nimport tigase.db.UserNotFoundException\n\nimport tigase.vhosts.*\n\ndef vhost_man = (VHostManagerIfc)vhostMan\n\ndef JID = \"jid\"\ndef DOMAIN = \"domain\"\ndef DOMAIN_LIST = \"domainList\"\n\ndef p = (Iq)packet\ndef jid = Command.getFieldValue(p, JID)\ndef domain = Command.getFieldValue(p, DOMAIN)\ndef domainList = Command.getFieldValue(p, DOMAIN_LIST)\n\nif (jid == null || domain == null ||\n\t(domain == DomainFilterPolicy.LIST.name() && domainList == null)) {\n\tdef res = (Iq)p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, JID, jid ?: \"\", \"jid-single\", \"User JID\")\n\tdef domainStr = []\n  DomainFilterPolicy.values().each { domainStr += it.name() }\n\tCommand.addFieldValue(res, DOMAIN, domain ?: domainStr[0], \"List of domains\",\n\t\t(String[])domainStr, (String[])domainStr)\n\tCommand.addFieldValue(res, DOMAIN_LIST, domainList ?: \"\", \"text-single\", \"Domains List\")\n\treturn res\n}\n\njid = JIDUtils.getNodeID(jid)\n\nbareJID = BareJID.bareJIDInstance(jid)\n\ndef repo = (UserRepository)userRepository\n\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\nif ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this domain\");\n\treturn result\n}\n\n\ntry {\n\tdef old_value = repo.getData(bareJID, null,\n\t\tDomainFilter.ALLOWED_DOMAINS_KEY, null)\n\tdef old_value_domains = \"\";\n\n\tif (old_value ==  DomainFilterPolicy.LIST.name()\n\t\t|| old_value ==  DomainFilterPolicy.BLACKLIST.name()) {\n\t\told_value_domains = repo.getData(bareJID, null,\n\t\t\tDomainFilter.ALLOWED_DOMAINS_LIST_KEY, null)\n\t}\n\n\tdef new_value = domain\n\tif (domain == DomainFilterPolicy.LIST.name()\n\t\t|| domain == DomainFilterPolicy.BLACKLIST.name()) {\n//\t\tnew_value = domainList\n\t\t\trepo.setData(bareJID, null, DomainFilter.ALLOWED_DOMAINS_LIST_KEY, domainList)\n\t}\n\trepo.setData(bareJID, null, DomainFilter.ALLOWED_DOMAINS_KEY, new_value)\n\n\treturn \"Changed an old value: $old_value (domains list: $old_value_domains) to a new value: $new_value (domains list: $domainList) for user: $jid\"\n} catch (e) {\n  if (e in UserNotFoundException)\t{\n\t\treturn \"The user $jid was not found in the user repository\"\n\t} else {\n\t\treturn \"Unexpected error: \" + e\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/UserRosterManagement.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nUpdate user roster entry.\n\nAS:Description: Update user roster entry\nAS:CommandId: user-roster-management\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.db.UserRepository\nimport tigase.vhosts.*\n\nclass Field { String name; String label; String type; String defVal = \"\"}\n\nclass RosterChangesControler {\n\tUserRepository repository\n\tVHostManagerIfc vhost_man\n\tSet<BareJID> admins\n\n\n\tMap<String, XMPPSession> sessions\n\n\tField addOperation = new Field(name: \"addJid\", label: \"Add\")\n\tField removeOperation = new Field(name: \"removeJid\", label: \"Remove\")\n\tList<Field> operationTypes = [addOperation, removeOperation]\n\n\tField subscriptionNone = new Field(name: \"none\", label: \"None\")\n\tField subscriptionFrom = new Field(name: \"from\", label: \"From\")\n\tField subscriptionTo = new Field(name: \"to\", label: \"To\")\n\tField subscriptionBoth = new Field(name: \"both\", label: \"Both\")\n\tList<Field> subscriptionTypes = [subscriptionNone, subscriptionFrom, subscriptionTo, subscriptionBoth]\n\n\tField ownerJid = new Field(name: \"rosterOwnerJID\", label: \"Roster owner JID\", type: \"jid-single\")\n\tField jidToChange= new Field(name: \"jidToManipulate\", label: \"JID to manipulate\", type: \"jid-single\")\n\tField groups = new Field(name: \"groups\", label: \"Comma separated groups\", type: \"text-single\")\n\tField operationType = new Field(name: \"operationType\", label: \"Operation type\",\n\t\t\tdefVal: addOperation.name)\n\tField subscriptionType = new Field(name: \"subscriptionType\",\n\t\t\tlabel: \"Subscription type\", defVal: subscriptionBoth.name)\n\tList<Field> formFields = [ownerJid, jidToChange, groups, operationType, subscriptionType]\n\n\tdef addField(Packet form, Field field, List<Field> listFields = []) {\n\t\tif (listFields != null && listFields.size() == 0)\n\t\t\tCommand.addFieldValue(form, field.name, field.defVal, field.type, field.label)\n\t\telse {\n\t\t\tdef listValues = (listFields.collect { it.name }).toArray(new String[0])\n\t\t\tdef listLabels = (listFields.collect { it.label }).toArray(new String[0])\n\t\t\tCommand.addFieldValue(form, field.name, field.defVal, field.label, listLabels, listValues)\n\t\t}\n\t}\n\n\tdef getFieldValue(Packet form, Field field) { return Command.getFieldValue(form, field.name) }\n\n\tdef processPacket(Packet p) {\n\t\tif ((formFields.find { it.name != groups.name && Command.getFieldValue(p, it.name) == null}) == null) {\n\t\t\tString ownerJidStr = getFieldValue(p, ownerJid)\n\t\t\tString jidToManipulate = getFieldValue(p, jidToChange)\n\t\t\tString[] groups = (getFieldValue(p, groups) ?: \"\").split(\",\")\n\t\t\tString operationTypeStr = getFieldValue(p, operationType)\n\t\t\tString subscriptionTypeStr = getFieldValue(p, subscriptionType)\n\n\t\t\tPacket result = p.commandResult(Command.DataType.result)\n\n\t\t\tBareJID stanzaFromBare = p.getStanzaFrom().getBareJID();\n\t\t\tboolean isServiceAdmin = admins.contains( stanzaFromBare );\n\n\t\t\tJID jidRosterOwnerJid = JID.jidInstanceNS(ownerJidStr);\n\t\t\tJID jidRosterItemJid = JID.jidInstanceNS(jidToManipulate);\n\n\t\t\tVHostItem vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\n\n\t\t\tif (!isServiceAdmin && vhost != null && !(vhost.isOwner(stanzaFromBare.toString())) && !(vhost.isAdmin(stanzaFromBare.toString()))) {\n\n\t\t\t//if ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\t\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+ownerJidStr);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tvhost = vhost_man.getVHostItem(jidRosterItemJid.getDomain());\n\n\t\t\tif (!isServiceAdmin && vhost != null && !(vhost.isOwner(stanzaFromBare.toString())) && !(vhost.isAdmin(stanzaFromBare.toString()))) {\n\n\t\t\t//if ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\n\t\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+jidToManipulate);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tQueue<Packet> results;\n\t\t\tif (operationTypeStr == addOperation.name)\n\t\t\t\tresults = addJidToRoster(ownerJidStr, jidToManipulate, groups, subscriptionTypeStr)\n\t\t\telse\n\t\t\t\tresults = removeJidFromRoster(ownerJidStr, jidToManipulate)\n\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t\tresults.add(result)\n\t\t\treturn results\n\t\t}\n\t\telse {\n\t\t\tPacket result = p.commandResult(Command.DataType.form)\n\t\t\taddField(result, ownerJid)\n\t\t\taddField(result, jidToChange)\n\t\t\taddField(result, groups)\n\t\t\taddField(result, operationType, operationTypes)\n\t\t\taddField(result, subscriptionType, subscriptionTypes)\n\t\t\treturn result\n\t\t}\n\t}\n\n\tdef getActiveConnections(String ownerJid) {\n\t\tBareJID ownerBareJID = BareJID.bareJIDInstance(ownerJid)\n\t\tXMPPSession session = sessions.get(ownerBareJID)\n\t\treturn (session == null) ? [] : session.getActiveResources()\n\t}\n\n\tdef subscription(String str) { return RosterAbstract.SubscriptionType.valueOf(str) }\n\n\tQueue<Packet> updateLiveRoster(String jid, String jidToChange, boolean remove,\n\t\t\tString[] groups = null, String subStr = null) {\n\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\tQueue<Packet> packets = new LinkedList<Packet>()\n\t\tJID jidToChangeJID = JID.jidInstance(jidToChange)\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(jid)\n\t\tfor (XMPPResourceConnection conn : activeConnections) {\n\t\t\tif (remove == false) {\n\t\t\t\trosterUtil.addBuddy(conn, jidToChangeJID, jidToChange, groups, null)\n\t\t\t\trosterUtil.setBuddySubscription(conn, subscription(subStr), jidToChangeJID)\n\t\t\t\trosterUtil.updateBuddyChange(conn, packets,\n\t\t\t\t\t\trosterUtil.getBuddyItem(conn, jidToChangeJID))\n\t\t\t} else {\n\t\t\t\tElement it = new Element(\"item\")\n\t\t\t\tit.setAttribute(\"jid\", jidToChange)\n\t\t\t\tit.setAttribute(\"subscription\", \"remove\")\n\t\t\t\trosterUtil.updateBuddyChange(conn, packets, it)\n\t\t\t\trosterUtil.removeBuddy(conn, jidToChangeJID)\n\t\t\t}\n\t\t}\n\t\treturn packets\n\t}\n\n\tdef modifyDbRoster(String ownerJid, modifyFunc) {\n\t\tBareJID ownerBareJID = BareJID.bareJIDInstance(ownerJid)\n\t\tString rosterStr = repository.getData(ownerBareJID, null, RosterAbstract.ROSTER, null)\n\t\trosterStr = (rosterStr == null) ? \"\" : rosterStr\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\n\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\tmodifyFunc(roster)\n\t\tStringBuilder sb = new StringBuilder()\n\t\tfor (RosterElement relem: roster.values())\n\t\t\tsb.append(relem.getRosterElement().toString())\n\t\trepository.setData(ownerBareJID, null, RosterAbstract.ROSTER, sb.toString());\n\t}\n\n\tQueue<Packet> addJidToRoster(ownerJid, jidToAdd, groups, subscriptionType) {\n\t\tJID ownerBareJID = JID.jidInstance(ownerJid)\n\t\tJID jidToAddJID = JID.jidInstance(jidToAdd)\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(ownerJid)\n\t\tif (activeConnections.size() == 0) {\n\t\t\tprintln ([\"activeConnections.size() == 0\"])\n\n\t\t\tmodifyDbRoster(ownerJid, { roster ->\n\t\t\t\tRosterElement userToAdd = roster.get(jidToAdd)\n\t\t\t\tif (userToAdd == null) {\n\t\t\t\t\tuserToAdd = new RosterElement(\n\t\t\t\t\t\tjidToAddJID, jidToAdd, groups, null)\n\t\t\t\t}\n\t\t\t\tuserToAdd.setSubscription(subscription(subscriptionType))\n\t\t\t\tuserToAdd.setGroups(groups)\n\t\t\t\troster.put(jidToAdd, userToAdd)\n\t\t\t})\n\t\t\treturn new LinkedList<Packet>()\n\t\t}\n\t\telse\n\t\t\treturn updateLiveRoster(ownerJid, jidToAdd, false, groups, subscriptionType)\n\t}\n\n\tQueue<Packet> removeJidFromRoster(ownerJid, jidToRemove) {\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(ownerJid)\n\t\tif (activeConnections.size() == 0) {\n\t\t\tmodifyDbRoster(ownerJid, { roster ->\n\t\t\t\tRosterElement userToRemove = roster.get(jidToRemove)\n\t\t\t\tif (userToRemove == null) {\n\t\t\t\t\tthrow new Exception(\"User to be deleted is not on roster\")\n\t\t\t\t}\n\t\t\t\troster.remove(jidToRemove)\n\t\t\t})\n\t\t\treturn new LinkedList<Packet>()\n\t\t}\n\t\telse\n\t\t\treturn updateLiveRoster(ownerJid, jidToRemove, true)\n\t}\n}\n\nnew RosterChangesControler(repository: userRepository, admins: adminsSet, vhost_man: vhostMan,\n\t\tsessions: userSessions).processPacket((Packet)packet)"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/UserRosterManagementExt.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\n\nUpdate user roster entry, extended version.\nIf both given JIDs are local, rosters for both users are updated accordingly.\n\nAS:Description: Update user roster entry, extended version.\nAS:CommandId: user-roster-management-ext\nAS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.cluster.*;\nimport tigase.cluster.api.*;\nimport tigase.cluster.strategy.*;\n\n\ntry {\n\tprintln \"==========================\"\n\n\tdef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\tdef ROSTER_OWNER_PRESENCE = \"roster-owner-presence\"\n\tdef ROSTER_OWNER_NAME = \"roster-owner-name\"\n\tdef ROSTER_OWNER_GROUPS = \"roster-owner-groups\"\n\tdef ROSTER_ITEM_JID = \"roster-item-jid\"\n\tdef ROSTER_ITEM_NAME = \"roster-item-name\"\n\tdef ROSTER_ITEM_GROUPS = \"roster-item-groups\"\n\tdef ROSTER_ITEM_SUBSCR = \"roster-item-subscr\"\n\tdef ROSTER_ACTION = \"roster-action\"\n\tdef NOTIFY_CLUSTER = \"notify-cluster\"\n\n\tdef UPDATE = \"update\"\n\tdef REMOVE = \"remove\"\n\tdef UPDATE_EXT = \"update-ext\"\n\tdef REMOVE_EXT = \"remove-ext\"\n\tdef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\n\tdef actions = [UPDATE, REMOVE, UPDATE_EXT, REMOVE_EXT]\n\tdef actions_descr = [\"Add/Update item\", \"Remove item\", \"Add/Update both rosters\", \"Remove from both rosters\"]\n\n\tQueue results = new LinkedList()\n\tdef p = (Packet)packet\n\tdef repository = (UserRepository)userRepository\n\tdef sessions = (Map<BareJID, XMPPSession>)userSessions\n\tdef vhost_man = (VHostManagerIfc)vhostMan\n\tdef admins = (Set)adminsSet\n\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID();\n\tdef isServiceAdmin = admins.contains(stanzaFromBare);\n\n\tdef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\n\tdef rosterOwnerName = Command.getFieldValue(packet, ROSTER_OWNER_NAME)\n\tdef rosterOwnerGroups = Command.getFieldValue(packet, ROSTER_OWNER_GROUPS)\n\tdef rosterItemJid = Command.getFieldValue(packet, ROSTER_ITEM_JID)\n\tdef rosterItemName = Command.getFieldValue(packet, ROSTER_ITEM_NAME)\n\tdef rosterItemGroups = Command.getFieldValue(packet, ROSTER_ITEM_GROUPS)\n\tdef rosterItemSubscr = Command.getFieldValue(packet, ROSTER_ITEM_SUBSCR)\n\tdef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\n\tboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\n\tboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\n\tif (rosterOwnerJid == null || rosterItemJid == null ||\n\t\trosterItemSubscr == null || rosterAction == null) {\n\t\tdef res = p.commandResult(Command.DataType.form);\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\", \"jid-single\", \"Roster owner JID\")\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_NAME, rosterOwnerName ?: \"\",  \"text-single\", \"Roster owner name\")\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_GROUPS, rosterOwnerGroups ?: \"\", \"text-single\", \"Comma separated list of owner groups\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_JID, rosterItemJid ?: \"\", \"jid-single\", \"Roster item JID\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_NAME, rosterItemName ?: \"\",  \"text-single\", \"Roster item name\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_GROUPS, rosterItemGroups ?: \"\", \"text-single\", \"Comma separated list of item groups\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_SUBSCR, subscriptions[0], \"Roster item Subscription\", (String[])subscriptions, (String[])subscriptions)\n\t\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0], \"Action\", (String[])actions_descr, (String[])actions)\n\t\tif \t( clusterMode  ) {\n\t\t\tCommand.addHiddenField(res, NOTIFY_CLUSTER, true.toString())\n\t\t}\n\t\treturn res\n\t}\n\n\tif \t( clusterMode && notifyCluster ) {\n\t\tif ( null != clusterStrategy ) {\n\t\t\tdef cluster = (ClusteringStrategyIfc) clusterStrategy\n\t\t\tList<JID> cl_conns = cluster.getAllNodes()\n\t\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\t\tcl_conns.each { node ->\n\n\t\t\t\t\tdef forward = p.copyElementOnly();\n\t\t\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\t\t\tforward.setPacketTo( node );\n\t\t\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\t\t\tresults.offer(forward)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tdef remove_item = rosterAction == REMOVE || rosterAction == REMOVE_EXT\n\n\tdef updateRoster = { jid, i_jid, i_name, i_groups, i_subscr, i_original_node ->\n\n\t\tdef sess = sessions == null ? null : sessions.get(jid.getBareJID());\n\t\tdef conn = (sess != null && sess.getActiveResourcesSize() > 0) ? sess.getActiveResources().get(0) : null;\n\t\tif (conn) {\n\t\t\t// Update online\n\t\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t\tElement item = new Element(\"item\",\n\t\t\t\t(String[])[\"jid\", \"subscription\"], (String[])[i_jid, \"remove\"])\n\t\t\tif (remove_item) {\n\t\t\t\trosterUtil.removeBuddy(conn, i_jid)\n\t\t\t} else {\n\t\t\t\trosterUtil.addBuddy(conn, i_jid, i_name ?: i_jid.getLocalpart(), i_groups ? i_groups.split(\",\") : null, null)\n\t\t\t\trosterUtil.setBuddySubscription(conn, RosterAbstract.SubscriptionType.valueOf(i_subscr), i_jid)\n\t\t\t\titem = rosterUtil.getBuddyItem(conn, i_jid)\n\t\t\t}\n\t\t\trosterUtil.updateBuddyChange(conn, results, item)\n\t\t} else if (i_original_node) {\n\t\t\t// We need to synchronize on some object (ie. on UserRepository instance) to fix issue with\n\t\t\t// race condition when we modify roster of user which is offline\n\t\t\t// Is there a better object to use for synchronization?\n\t\t\tsynchronized (repository) {\n\t\t\t\t// Update offline and only on original node\n\t\t\t\tString rosterStr = repository.getData(jid.getBareJID(), null, RosterAbstract.ROSTER, null) ?: \"\"\n\t\t\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\t\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\t\t\tif (remove_item) {\n\t\t\t\t\troster.remove(i_jid.getBareJID())\n\t\t\t\t} else {\n\t\t\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, i_groups ? i_groups.split(\",\") : null, null)\n\t\t\t\t\trel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\t\t\trel.setPersistent(true);\n\t\t\t\t\troster.put(i_jid, rel)\n\t\t\t\t}\n\t\t\t\tStringBuilder sb = new StringBuilder(200)\n\t\t\t\tfor (RosterElement relem: roster.values())\n\t\t\t\tsb.append(relem.getRosterElement().toString())\n\t\t\t\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\t\t\t}\n\t\t}\n\t}\n\n\tdef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid);\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid);\n\n\tPacket result = p.commandResult(Command.DataType.result)\n\tdef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\n\tif (vhost == null || (!isServiceAdmin && !vhost.isOwner(stanzaFromBare.toString()) && !vhost.isAdmin(stanzaFromBare.toString()))) {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\t\tresults.add(result);\n\t\treturn results;\n\t}\n\n\tupdateRoster(jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemGroups, rosterItemSubscr, notifyCluster)\n\n\tElement pres;\n\tif (rosterAction == UPDATE_EXT || rosterAction == REMOVE_EXT) {\n\t\tdef subscr = rosterItemSubscr;\n\t\tswitch (rosterItemSubscr) {\n\t\tcase \"to\" : subscr = \"from\"; break;\n\t\tcase \"from\" : subscr = \"to\"; break;\n\t\t}\n\n\t\tvhost = vhost_man.getVHostItem(jidRosterItemJid.getDomain());\n\t\tif (vhost == null || (!isServiceAdmin && !vhost.isOwner(stanzaFromBare.toString()) && !vhost.isAdmin(stanzaFromBare.toString()))) {\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterItemJid);\n\t\t\tresults.add(result);\n\t\t\treturn results;\n\t\t}\n\n\t\tupdateRoster(jidRosterItemJid, jidRosterOwnerJid, rosterOwnerName, rosterOwnerGroups, subscr, notifyCluster)\n\t\t\n\t\tif (!remove_item) {\n\t\t\tpres = new Element(\"presence\", (String[])[\"from\", \"to\", \"type\"], (String[])[rosterOwnerJid, rosterItemJid, \"probe\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t}\n\t}\n\tif (!remove_item) {\n\t\tpres = new Element(\"presence\", (String[])[\"from\", \"to\", \"type\"], (String[])[rosterItemJid, rosterOwnerJid, \"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t}\n\n\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\tresults.add(result)\n\n\t//return results\n\treturn (Queue)results\n\n}  catch (Exception ex) { ex.printStackTrace(); }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/UserStatistics.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Obtaining User Statistics as described in in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-user-stats\n AS:Description: Get User Statistics\n AS:CommandId: http://jabber.org/protocol/admin#user-stats\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get User Statistics\")\n\tCommand.addInstructions(result, \"Fill out this form to gather user statistics.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for statistics\")\n\n\treturn result\n}\n\nbareJID = BareJID.bareJIDInstance(userJid)\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\ndef result = p.commandResult(Command.DataType.result)\n\nif (isServiceAdmin ||\n(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\tXMPPSession session = sessions.get(BareJID.bareJIDInstanceNS(userJid))\n\n\tif (session == null) {\n\t\treturn \"There is no user's ${userJid} active session on the server\"\n\t} else {\n\t\tList<XMPPResourceConnection> conns = session.getActiveResources()\n\t\tString conns_str = \"Connections: \"\n\t\tfor (XMPPResourceConnection con: conns)\n\t\t\tconns_str += con.toString() + \"###\\n\"\n\t\treturn \"There is ${conns?.size()} active user's ${userJid} sessions, packets: ${session.getPacketsCounter()}\\n\" +\n\t\t\"user connections:\\n\" + conns_str\n\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to obtain statistics for user in this domain.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/example_HelloWorld.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nExample Hello World admin script for the script development guide.\n\nAS:Description: [example] Hello World Script.\nAS:CommandId: hello\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\n\ndef p = (Packet)packet\n\ndef name = Command.getFieldValue(packet, \"name\")\n\nif (name == null) {\n\tdef res = p.commandResult(Command.DataType.form)\n\tCommand.addTitle(res, \"Hello World Script\")\n\tCommand.addInstructions(res, \"Please provide some details\")\n\tCommand.addFieldValue(res, \"name\", name ?: \"\", \"text-single\",\n\t  \"Your name\")\n\treturn res\n}\n\ndef res = p.commandResult(Command.DataType.result)\nCommand.addTitle(res, \"Hello World Script\")\nCommand.addInstructions(res, \"Hello ${name}, how are you?\")\n\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/admin/example_TigaseScriptingGuide.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2008 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nThis is an example script for Tigase scripting support.\n\nAS:Description: [example] Tigase scripting guide\nAS:CommandId: groovy-example\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.Command\nimport tigase.server.Packet\n\nPacket p = (Packet)packet\nnum1 = Command.getFieldValue(p, \"num1\")\nnum2 = Command.getFieldValue(p, \"num2\")\n\nif (num1 == null || num2 == null) {\n\tPacket res = Packet.commandResultForm(p)\n\tCommand.addTextField(res, \"Note\", \"This is Groovy script!\")\n\tCommand.addFieldValue(res, \"num1\", \"\")\n\tCommand.addFieldValue(res, \"num2\", \"\")\n\treturn res\n}\n\nreturn num1 + num2\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/config.sh",
    "content": "#!/bin/bash\n##\n##  Tigase Jabber/XMPP Server\n##  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n##\n##  This program is free software: you can redistribute it and/or modify\n##  it under the terms of the GNU Affero General Public License as published by\n##  the Free Software Foundation, either version 3 of the License.\n##\n##  This program is distributed in the hope that it will be useful,\n##  but WITHOUT ANY WARRANTY; without even the implied warranty of\n##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n##  GNU Affero General Public License for more details.\n##\n##  You should have received a copy of the GNU Affero General Public License\n##  along with this program. Look for COPYING file in the top folder.\n##  If not, see http://www.gnu.org/licenses/.\n##\n##  $Rev: $\n##  Last modified by $Author: $\n##  $Date: $\n##\n\nCP=\"jars/tigase-server.jar:/usr/share/jdbc-mysql/lib/jdbc-mysql.jar:libs/tigase-xmltools.jar:libs/tigase-utils.jar\"\n\njava -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -cp $CP tigase.conf.Configurator $*"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create-derby.cmd",
    "content": "@echo off\n\nif [%1]==[] (\n\techo. && echo Give me a path to the location where you want to have the database created && echo.\n  exit /b\n)\n\nset PWD=\"%cd%\"\n\n:: for tigase 5.0 and below\n::java -Dij.protocol=jdbc:derby: -Dij.database=\"%1;create=true\" ^\n::\t\t-Dderby.system.home=%PWD% ^\n::\t\t-classpath \"libs/*\" ^\n::\t\torg.apache.derby.tools.ij database/derby-schema-4.sql\n::java -Dij.protocol=jdbc:derby: -Dij.database=\"%1\" ^\n::\t\t-Dderby.system.home=%PWD% ^\n::\t\t-classpath \"libs/*\" ^\n::\t\torg.apache.derby.tools.ij database/derby-schema-4-sp.schema\n::java -Dij.protocol=jdbc:derby: -Dij.database=\"%1\" ^\n::\t\t-Dderby.system.home=%PWD% ^\n::\t\t-classpath \"libs/*\" ^\n::\t\torg.apache.derby.tools.ij database/derby-schema-4-props.sql\n\n:: for Tigase 5.1\n\njava -Dij.protocol=jdbc:derby: -Dij.database=\"%1;create=true\" ^\n\t\t-Dderby.system.home=%PWD% ^\n\t\t-classpath jars/* ^\n\t\torg.apache.derby.tools.ij database/derby-schema-5-1.sql > derby-db-create.txt 2>&1\n\njava -Dij.protocol=jdbc:derby: -Dij.database=\"%1;create=true\" ^\n\t\t-Dderby.system.home=%PWD% ^\n\t\t-classpath jars/* ^\n\t\torg.apache.derby.tools.ij database/derby-pubsub-schema-3.0.0.sql > derby-db-create-pubsub.txt 2>&1\n\n\nif %errorlevel% neq 0 (\n  echo. && echo Error: please check the derby-db-create.txt error file for more details && echo. && echo.\n  exit /b %errorlevel%\n) else (\n  echo. && echo Success: please look at the derby-db-create.txt file for more details && echo. && echo.\n  echo configuration: && echo. && echo. && echo --user-db=derby && echo. && echo --user-db-uri=jdbc:derby:%1 && echo. && echo.\n  exit /b\n)\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create-derby.sh",
    "content": "#!/bin/bash\n\n[[ \"$1\" = \"\" ]] && \\\n  echo \"Give me a path to the location where you want to have the database created\" && \\\n  exit 1\n\n# for tigase 5.0 and below\n#java -Dij.protocol=jdbc:derby: -Dij.database=\"$1;create=true\" \\\n#\t\t-Dderby.system.home=`pwd` \\\n#\t\t-cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar \\\n#\t\torg.apache.derby.tools.ij database/derby-schema-4.sql\n#java -Dij.protocol=jdbc:derby: -Dij.database=\"$1\" \\\n#\t\t-Dderby.system.home=`pwd` \\\n#\t\t-cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar \\\n#\t\torg.apache.derby.tools.ij database/derby-schema-4-sp.schema\n#java -Dij.protocol=jdbc:derby: -Dij.database=\"$1\" \\\n#\t\t-Dderby.system.home=`pwd` \\\n#\t\t-cp libs/derby.jar:libs/derbytools.jar:jars/tigase-server.jar \\\n#\t\torg.apache.derby.tools.ij database/derby-schema-4-props.sql\n\n# for Tigase 5.1\n\njava -Dij.protocol=jdbc:derby: -Dij.database=\"$1;create=true\" \\\n\t\t-Dderby.system.home=`pwd` \\\n\t\t-cp jars/derby.jar:jars/derbytools.jar:jars/tigase-server.jar \\\n\t\torg.apache.derby.tools.ij database/derby-schema-5-1.sql &> derby-db-create.txt\n\njava -Dij.protocol=jdbc:derby: -Dij.database=\"$1;create=true\" \\\n\t\t-Dderby.system.home=`pwd` \\\n\t\t-cp jars/derby.jar:jars/derbytools.jar:jars/tigase-server.jar \\\n\t\torg.apache.derby.tools.ij database/derby-pubsub-schema-3.0.0.sql &> derby-db-create-pubsub.txt\n\n\necho -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=derby\\n--user-db-uri=jdbc:derby:$1\\n\\n\"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create-mysql.sh",
    "content": "#!/bin/bash\n\necho -e \"\\n\\nusage: db-create-mysql.sh tigase_username tigase_password database_name root_username root_password database_host \\n\\n\"\n\nif [ \"${1}\" = \"-y\" ] ; then\n  NONINTERACTIVE=yes\n  shift\nfi\n\nif [ -z \"${1}\" ] ; then\n  echo \"No username given. Using: tigase_user\"\n  USR_NAME=tigase_user\nelse\n  USR_NAME=\"${1}\"\nfi\n\nif [ -z \"${2}\" ] ; then\n  echo \"No password given. Using: tigase_passwd\"\n  USR_PASS=tigase_passwd\nelse\n  USR_PASS=\"${2}\"\nfi\n\nif [ -z \"${3}\" ] ; then\n  echo \"No DB name given. Using: tigasedb\"\n  DB_NAME=tigasedb\nelse\n  DB_NAME=\"${3}\"\nfi\n\n\nif [ -z \"${4}\" ] ; then\n  echo \"No DB root username given. Using: root\"\n  DB_USER=root\nelse\n  DB_USER=\"${4}\"\nfi\n\nif [ -z \"${5}\" ] ; then\n  echo \"No DB root password given. Using: root\"\n  DB_PASS=root\nelse\n  DB_PASS=\"${5}\"\nfi\n\nif [ -z \"${6}\" ] ; then\n  echo \"No DB hostname given. Using: localhost\"\n  DB_HOST=localhost\nelse\n  DB_HOST=\"${6}\"\nfi\n\n\nif [ -z \"$NONINTERACTIVE\" ] ; then\n  echo \"\"\n  echo \"creating ${DB_NAME} database for user ${USR_NAME} identified by ${USR_PASS} password:\"\n  echo \"\"\n\n  read -p \"Press [Enter] key to start, otherwise abort...\"\nelse\n  echo \"User: $USR_NAME, Pass: $USR_PASS, Db: $DB_NAME, Db Admin: $DB_USER, Admin Pass: $DB_PASS, Host: $DB_HOST\"\nfi\n\necho \"DROP DATABASE IF EXISTS ${DB_NAME}\" | mysql -h $DB_HOST -u $DB_USER -p$DB_PASS\necho \"CREATE DATABASE ${DB_NAME}\" | mysql -h $DB_HOST -u $DB_USER -p$DB_PASS\n\necho \"GRANT ALL ON ${DB_NAME}.* TO ${USR_NAME}@'%' IDENTIFIED BY '${USR_PASS}';\" | \\\n        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\necho \"GRANT ALL ON ${DB_NAME}.* TO ${USR_NAME}@'localhost' IDENTIFIED BY '${USR_PASS}';\" | \\\n        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\necho \"GRANT ALL ON ${DB_NAME}.* TO ${USR_NAME} IDENTIFIED BY '${USR_PASS}';\" | \\\n        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\n\necho \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USR_NAME}@'localhost';\" | \\\n        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\necho \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USR_NAME}@'%';\" | mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\necho \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USR_NAME};\" | mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\n\necho \"FLUSH PRIVILEGES;\" | mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME\n\necho \"Loading schema\"\nmysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME < database/mysql-schema-5-1.sql\necho \"Loading PubSub3 schema\"\nmysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME < database/mysql-pubsub-schema-3.0.0.sql\n\n\necho -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=mysql\\n--user-db-uri=jdbc:mysql://$DB_HOST:3306/$DB_NAME?user=$DB_USER&password=$DB_PASS&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\\n\\n\"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create-postgresql.sh",
    "content": "#!/bin/bash\n\necho -e \"\\n\\nusage: db-create-mysql.sh tigase_username tigase_password database_name database_host \\n\\n\"\n \nif [ \"${1}\" = \"-y\" ] ; then\n  NONINTERACTIVE=yes\n  shift\nfi\n\nif [ -z \"${1}\" ] ; then\n  echo \"No username given. Using: tigase_user\"\n  USR_NAME=tigase_user\nelse\n  USR_NAME=\"${1}\"\nfi\n\nif [ -z \"${2}\" ] ; then\n  echo \"No password given. Using: tigase_passwd\"\n  USR_PASS=tigase_passwd\nelse\n  USR_PASS=\"${2}\"\nfi\n\nif [ -z \"${3}\" ] ; then\n  echo \"No DB name given. Using: tigasedb\"\n  DB_NAME=tigasedb\nelse\n  DB_NAME=\"${3}\"\nfi\n\n\nif [ -z \"${4}\" ] ; then\n  echo \"No DB hostname given. Using: localhost\"\n  DB_HOST=localhost\nelse\n  DB_HOST=\"${4}\"\nfi\n\n\nif [ -z \"$NONINTERACTIVE\" ] ; then\n  echo \"\"\n  echo \"creating ${DB_NAME} database for user ${USR_NAME} identified by ${USR_PASS} password:\"\n  echo \"\"\n \n  read -p \"Press [Enter] key to start, otherwise abort...\"\nelse\n  echo \"User: $USR_NAME, Pass: $USR_PASS, Db: $DB_NAME, Host: $DB_HOST\"\nfi\n\necho \"Creating user\"\ncreateuser -d -S -R -h $DB_HOST -U postgres ${USR_NAME}\necho \"Creating database\"\ncreatedb -h $DB_HOST -U ${USR_NAME} ${DB_NAME}\necho \"Loading DB schema\"\npsql -h $DB_HOST -q -U ${USR_NAME} -d $DB_NAME -f database/postgresql-schema-5-1.sql\necho \"Loading PubSub3 schema\"\npsql -h $DB_HOST -q -U ${USR_NAME} -d $DB_NAME -f database/postgresql-pubsub-schema-3.0.0.sql\n\n\necho -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=pgsql\\n--user-db-uri=jdbc:postgresql://$DB_HOST/$DB_NAME?user=$USR_NAME&password=$USR_PASS&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\\n\\n\"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create-sqlserver.cmd",
    "content": "IF [%1]==[] (\n\tset servername=localhost\n\tset database=tigasedb\n\tset user=tigase\n\tset password=tigase12\n\tset root_user=sa\n\tset root_pass=sa\n) ELSE (\n\tset servername=%1\n\tset database=%2\n\tset user=%3\n\tset password=%4\n\tset root_user=%5\n\tset root_pass=%6\n)\n\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -Q \"CREATE DATABASE [%database%]\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -Q \"CREATE LOGIN [%user%] WITH PASSWORD=N'%password%', DEFAULT_DATABASE=[%database%]\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -Q \"ALTER AUTHORIZATION ON DATABASE::%database% TO %user%;\"\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-5-1-schema.sql\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-5-1-sp.sql\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-schema-5-1-props.sql\n\nsqlcmd -S %servername% -U %root_user% -P %root_pass% -d %database% -i database\\sqlserver-pubsub-schema-3.0.0.sql\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/db-create.sh",
    "content": "#!/bin/bash\n\n\nif [ -z \"${1}\" ] ; then\n  echo -e \"Usage:\"\n  echo -e \"$ scripts/db-create.sh\"\n  echo -e \"\\t -t database_type {derby, mysql, postgresql} \"\n  echo -e \"\\t[-v schema_version {4, 5, 5.1} ]\"\n  echo -e \"\\t[-d database_name]\"\n  echo -e \"\\t[-h database hostname]\"\n  echo -e \"\\t[-u tigase_username]\"\n  echo -e \"\\t[-p tigase_userpass]\"\n  echo -e \"\\t[-r database root name]\"\n  echo -e \"\\t[-a database root pass]\"\n\n  exit 1\nfi\n\ncreate_derby() {\n  echo -e \"database type:\\t\\t ${DB_TYPE}\"\n  echo -e \"schema_version:\\t\\t ${VERSION}\"\n  echo -e \"schema_file:\\t\\t database/derby-schema-${FILE_VERSION}.sql\"\n  echo -e \"database_name:\\t\\t ${DB_NAME}\"\n  \n  read -p \"Press [Enter] key to start, otherwise abort...\"\n\n  java -Dij.protocol=jdbc:derby: -Dij.database=\"${DB_NAME};create=true\" \\\n\t\t  -Dderby.system.home=`pwd` \\\n\t\t  -cp jars/derby.jar:jars/derbytools.jar:jars/tigase-server.jar \\\n\t\t  org.apache.derby.tools.ij database/derby-schema-${FILE_VERSION}.sql\n\n  echo -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=derby\\n--user-db-uri=jdbc:derby:${DB_NAME}\\n\\n\"\n}\n\ncreate_mysql() {\n  echo -e \"database type:\\t\\t ${DB_TYPE}\"\n  echo -e \"schema_version:\\t\\t ${VERSION}\"\n  echo -e \"schema_file:\\t\\t database/mysql-schema-${FILE_VERSION}.sql\"\n  echo -e \"database_name:\\t\\t ${DB_NAME}\"\n  echo -e \"database_hostname:\\t ${DB_HOST}\"\n  echo -e \"tigase_username:\\t ${USER_NAME}\"\n  echo -e \"tigase_userpass:\\t ${USER_PASS}\"\n  echo -e \"database_root_name:\\t ${ROOT_NAME}\"\n  echo -e \"database_root_pass:\\t ${ROOT_PASS}\"\n\n  read -p \"Press [Enter] key to start, otherwise abort...\"\n\n  echo \"DROP DATABASE IF EXISTS ${DB_NAME}\" | mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS\n  echo \"CREATE DATABASE ${DB_NAME}\" | mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS\n\n  echo \"GRANT ALL ON ${DB_NAME}.* TO ${USER_NAME}@'%' IDENTIFIED BY '${USER_PASS}';\" | \\\n\t  mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n  echo \"GRANT ALL ON ${DB_NAME}.* TO ${USER_NAME}@'localhost' IDENTIFIED BY '${USER_PASS}';\" | \\\n\t  mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n  echo \"GRANT ALL ON ${DB_NAME}.* TO ${USER_NAME} IDENTIFIED BY '${USER_PASS}';\" | \\\n\t  mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n\n  echo \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USER_NAME}@'localhost';\" | \\\n\t  mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n  echo \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USER_NAME}@'%';\" | mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n  echo \"GRANT SELECT, INSERT, UPDATE ON mysql.proc TO ${USER_NAME};\" | mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n\n  echo \"FLUSH PRIVILEGES;\" | mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME\n\n  echo \"Loading schema\"\n\n  mysql -h $DB_HOST -u $ROOT_NAME -p$ROOT_PASS $DB_NAME < database/mysql-schema-${FILE_VERSION}.sql\n\n  echo -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=mysql\\n--user-db-uri=jdbc:mysql://$DB_HOST:3306/$DB_NAME?user=$USER_NAME&password=$USER_PASS&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\\n\\n\"\n\n}\n\ncreate_postgresql() {\n  echo -e \"database type:\\t\\t ${DB_TYPE}\"\n  echo -e \"schema_version:\\t\\t ${VERSION}\"\n  echo -e \"schema_file:\\t\\t database/postgresql-schema-${FILE_VERSION}.sql\"\n  echo -e \"database_name:\\t\\t ${DB_NAME}\"\n  echo -e \"database_hostname:\\t\\t ${DB_HOST}\"\n  echo -e \"tigase_username:\\t\\t ${USER_NAME}\"\n  echo -e \"tigase_userpass:\\t\\t ${USER_PASS}\"\n  echo -e \"database_root_name:\\t\\t ${ROOT_NAME}\"\n  echo -e \"database_root_pass:\\t\\t ${ROOT_PASS}\"\n\n  read -p \"Press [Enter] key to start, otherwise abort...\"\n\n  export PGPASSWORD=${ROOT_PASS}\n  echo \"CREATE ROLE ${USER_NAME} WITH PASSWORD '${USER_PASS}' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;\" | psql -h $DB_HOST -U ${ROOT_NAME}\n  echo \"CREATE DATABASE ${DB_NAME} OWNER ${USER_NAME} ENCODING 'UTF8' TEMPLATE template0;\" | psql -h $DB_HOST -U ${ROOT_NAME}\n\n  export PGPASSWORD=${USER_PASS}\n  psql -h $DB_HOST -q -U ${USER_NAME} -d $DB_NAME -f database/postgresql-schema-${FILE_VERSION}.sql\n\n  echo -e \"\\n\\n\\nconfiguration:\\n\\n--user-db=pgsql\\n--user-db-uri=jdbc:postgresql://$DB_HOST/$DB_NAME?user=$USER_NAME&password=$USER_PASS&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\\n\\n\"\n}\n\n\n\nwhile getopts \":t:v:u:p:r:a:d:h:\" optname\n  do\n    case \"$optname\" in\n      \"t\")\tDB_TYPE=\"${OPTARG}\";;\n      \"v\")\tVERSION=\"${OPTARG}\";;\n      \"d\")\tDB_NAME=\"${OPTARG}\";;\n      \"h\")\tDB_HOST=\"${OPTARG}\";;\n      \"u\")\tUSER_NAME=\"${OPTARG}\";;\n      \"p\")\tUSER_PASS=\"${OPTARG}\";;\n      \"r\")\tROOT_NAME=\"${OPTARG}\";;\n      \"a\")\tROOT_PASS=\"${OPTARG}\";;\n      \"?\")\techo \"Unknown option: $OPTARG\";;\n      \":\")\techo \"No argument value for option $OPTARG\";;\n      *)\techo \"Unknown error while processing options\";;\n    esac\n  done\n\n#echo -e \"\\n\"\n\nif [ -z \"${DB_TYPE}\" ] ; then\n  echo \"No Database type specified - must be [derby,mysql,postgresql]; exiting\"\n  exit 1\nfi\n\nif [ -z \"${DB_NAME}\" ] ; then\n  echo -e \"No database_name given. Using: \\t\\ttigasedb\"\n  DB_NAME=tigasedb\nfi\n\nif [ -z \"${DB_HOST}\" ] ; then\n  echo -e \"No database_hostname given. Using: \\tlocalhost\"\n  DB_HOST=localhost\nfi\n\nif [ -z \"${USER_NAME}\" ] ; then\n  echo -e \"No tigase_username given. Using: \\ttigase_user\"\n  USER_NAME=tigase_user\nfi\n\nif [ -z \"${USER_PASS}\" ] ; then\n  echo -e \"No tigase_userpass given. Using: \\ttigase_pass\"\n  USER_PASS=tigase_pass\nfi\n\nif [ -z \"${ROOT_NAME}\" ] ; then\n  echo -e \"No database_root_name given. Using: \\troot\"\n  ROOT_NAME=root\nfi\n\nif [ -z \"${ROOT_PASS}\" ] ; then\n  echo -e \"No database_root_pass given. Using: \\troot\"\n  ROOT_PASS=root\nfi\n\nif [ -z \"${VERSION}\" ] ; then\n  echo -e \"No schema_version given. Using latest: \\t5.1\"\n  FILE_VERSION=5-1\n  VERSION=5.1\nelse\n  case \"$VERSION\" in\n    \"5.1\")\t\tFILE_VERSION=\"5-1\";;\n    \"5\")\t\tFILE_VERSION=\"5\";;\n    \"4\")\t\tFILE_VERSION=\"4\";;\n    \"3\")\t\tFILE_VERSION=\"3\";;\n    *)\t\t\techo \"unknown schema version $VERSION - must be [5.1, 5, 4, 3]; exiting\" ; exit 1;;\n  esac\nfi\n\necho \"\"\n\n\ncase \"$DB_TYPE\" in\n  \"derby\")\t\tcreate_derby;;\n  \"mysql\")\t\tcreate_mysql;;\n  \"postgresql\")\t\tcreate_postgresql;;\n  *)\t\t\techo \"unknown database type $DB_TYPE - must be [derby,mysql,postgresql]; exiting\" ; exit 1;;\nesac\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/changelog",
    "content": "tigase (@version@) unstable; urgency=medium\n\n  * For full changelog, see\n  http://www.tigase.org/\n\n -- Sergey Nazarov <phearnot@renee.ru>  @builddate@\n2008-11-07 13:38  kobit\n\n\t* build.xml, package.html, src/main/izpack/install.xml,\n\t  src/main/izpack/java/TigaseConfigLoadPanel.java,\n\t  src/main/izpack/java/TigaseConfigSavePanel.java,\n\t  src/main/izpack/java/TigaseDBCheckPanel.java,\n\t  src/main/izpack/resources/pics/tigase-install-logo.png,\n\t  src/main/izpack/userInputSpec.xml: A few installer fixes, added\n\t  unix scripts\n\n2008-11-07 13:38  kobit\n\n\t* etc/tigase.conf, win-stuff/wrapper/wrapper.conf: Added jdbc\n\t  drivers for all 3 supported databases: derby, mysql, pgsql\n\n2008-11-06 11:37  kobit\n\n\t* License.html: GPLv3 license copy in HTML frmat\n\n2008-11-06 11:37  kobit\n\n\t* database/mysql-schema-4-props.sql, src/main/izpack,\n\t  src/main/izpack/install.xml, src/main/izpack/java,\n\t  src/main/izpack/java/DerbyPathPanel.java,\n\t  src/main/izpack/java/TigaseConfigConst.java,\n\t  src/main/izpack/java/TigaseConfigLoadPanel.java,\n\t  src/main/izpack/java/TigaseConfigSavePanel.java,\n\t  src/main/izpack/java/TigaseDBCheckPanel.java,\n\t  src/main/izpack/resources,\n\t  src/main/izpack/resources/packsLang.xml,\n\t  src/main/izpack/resources/pics,\n\t  src/main/izpack/resources/pics/tigase-install-logo.png,\n\t  src/main/izpack/resources/pics/tiger.png,\n\t  src/main/izpack/userInputSpec.xml: Installer files added\n\n2008-11-06 11:13  kobit\n\n\t* database/derby-create-db.sql, database/derby-schema-4-props.sql,\n\t  database/derby-schema-4-sp.schema, database/derby-schema-4.sql,\n\t  database/mysql-create-db.sql, database/mysql-schema-4-sp.schema,\n\t  database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql,\n\t  database/postgresql-create-db.sql,\n\t  database/postgresql-schema-4-props.sql,\n\t  database/postgresql-schema-4-sp.schema,\n\t  database/postgresql-schema-4.sql, etc/tigase.conf: Changes for\n\t  the installer\n\n2008-11-04 12:28  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added more detailed logging for session closing event\n\n2008-10-30 12:54  kobit\n\n\t* src/main/java/tigase/xmpp/impl/roster/RosterFlat.java: Fixed a\n\t  bug in RosterFlat that the code didn't remove the resource part\n\n2008-10-30 11:48  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added patch from Yate guys for the user status command containing\n\t  presence info\n\n2008-10-30 11:24  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/util/RepositoryUtils.java,\n\t  src/main/java/tigase/xmpp/impl/AnonymousRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/RosterAbstract.java,\n\t  src/main/java/tigase/xmpp/impl/RosterFactory.java,\n\t  src/main/java/tigase/xmpp/impl/RosterFlat.java,\n\t  src/main/java/tigase/xmpp/impl/roster,\n\t  src/main/java/tigase/xmpp/impl/roster/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/roster/RosterAbstract.java,\n\t  src/main/java/tigase/xmpp/impl/roster/RosterElement.java,\n\t  src/main/java/tigase/xmpp/impl/roster/RosterFactory.java,\n\t  src/main/java/tigase/xmpp/impl/roster/RosterFlat.java:\n\t  Implemented roster flat storage\n\n2008-10-28 22:42  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Disconnection monitoring\n\t  and debugging added\n\n2008-10-28 22:27  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Disconnection monitoring and debugging added\n\n2008-10-28 22:20  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Disconnection monitoring and debugging added\n\n2008-10-28 22:16  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Disconnection monitoring and debugging added\n\n2008-10-28 21:43  kobit\n\n\t* etc/init.properties, package.html,\n\t  src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/util/TimeUtils.java: Disconnection\n\t  monitoring and debugging added\n\n2008-10-22 19:35  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/TigaseAuth.java,\n\t  src/main/java/tigase/db/jdbc/TigaseCustomAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixed deadlock problem occuring in derby database, if a query\n\t  returns results it must be read and freed....\n\n2008-10-22 17:20  bmalkow\n\n\t* src/main/java/tigase/db/derby/StoredProcedures.java: add\n\t  connection closing\n\n2008-10-22 15:25  bmalkow\n\n\t* src/main/java/tigase/db/derby/StoredProcedures.java: fixed\n\t  problem with login user. I don't know why, but now it works\n\n2008-10-22 13:32  kobit\n\n\t* database/derby-schema-4.sql,\n\t  src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/db/derby/StoredProcedures.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/TigaseAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixes and changes for Derby database\n\n2008-10-21 20:15  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/db/jdbc/TigaseCustomAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  TigaseCustomAuth is finished, tested and added as a standard\n\t  authentication connector to the system\n\n2008-10-21 20:14  kobit\n\n\t* database/mysql-schema-4-sp.schema,\n\t  database/postgresql-schema-4-sp.schema: Fixed problem with the SP\n\t  incorrectly removing users from the database\n\n2008-10-21 17:33  kobit\n\n\t* src/main/java/tigase/db/jdbc/TigaseCustomAuth.java: Custom auth\n\t  implementation finished, not tested yet\n\n2008-10-21 17:16  kobit\n\n\t* database/mysql-schema-4-sp.schema,\n\t  database/postgresql-schema-4-sp.schema: Added new SP for password\n\t  update with procedure parameters in reverse order\n\n2008-10-21 16:32  kobit\n\n\t* src/main/java/tigase/db/jdbc/TigaseCustomAuth.java: JavaDoc\n\t  documentation updated\n\n2008-10-21 13:43  kobit\n\n\t* src/main/java/tigase/db/jdbc/TigaseCustomAuth.java: User\n\t  authentication connector allowing to use custom SQL queries\n\n2008-10-21 08:47  kobit\n\n\t* database/postgresql-schema-4-sp.schema: Added\n\t  MD5-USERNAME-PASSWORD password encoding support\n\n2008-10-20 23:40  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/ServerConnectionClustered.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/ConnectionStatus.java,\n\t  src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java: Reimplementation of\n\t  the clustering code in the SM and lots of improvements in other\n\t  areas, all related to the clustering and user session management\n\t  for multiple user connections\n\n2008-10-16 12:02  kobit\n\n\t* database/mysql-schema-4-sp.schema: Added a new password encoding\n\t  option: MD5_USERNAME_PASSWORD\n\n2008-10-09 20:35  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Offline presence is\n\t  not now broadcasted if the client didn't send initial presence\n\t  before\n\n2008-10-08 22:41  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Attempt to solve the first TLS problem\n\n2008-10-08 22:39  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Attempt to solve the first TLS problem\n\n2008-10-08 22:31  kobit\n\n\t* src/main/java/tigase/io/TLSIO.java: Attempt to solve the first\n\t  TLS problem\n\n2008-10-08 22:26  kobit\n\n\t* src/main/java/tigase/io/SocketIO.java,\n\t  src/main/java/tigase/net/IOService.java: Attempt to solve the\n\t  first TLS problem\n\n2008-10-08 22:21  kobit\n\n\t* src/main/java/tigase/io/SocketIO.java: Attempt to solve the first\n\t  TLS problem\n\n2008-10-08 22:18  kobit\n\n\t* src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/net/IOService.java: Attempt to solve the\n\t  first TLS problem\n\n2008-10-08 22:14  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Attempt to solve the\n\t  first TLS problem\n\n2008-10-08 22:10  kobit\n\n\t* src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Attempt to solve the first TLS problem\n\n2008-10-08 20:35  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Server vhosts session has now resource bond\n\n2008-10-08 17:11  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  a problem with not releasing hold on session in some cases\n\n2008-10-08 15:35  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  sendAllOnHold can now process packet locally if there is no\n\t  packet rdirection address\n\n2008-10-08 15:25  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java: The session is put on\n\t  hold just after successful authentication\n\n2008-10-08 11:13  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Presence broadcast\n\t  sends only unavailable presence to all entities to which user\n\t  sent direct presence\n\n2008-10-03 15:51  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Removed\n\t  inserting HTML tags around http links detected in the message,\n\t  this is client side stuff\n\n2008-10-03 11:25  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Presence\n\t  subscription flow changed to match last changes in the RFC\n\n2008-10-01 22:12  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added responses either the 'result' or 'error' to all USER_STATUS\n\t  commands\n\n2008-10-01 17:52  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Fixed problem with\n\t  the USER_STATUS command\n\n2008-10-01 15:47  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Now the server\n\t  requires user to bind the resource first before sending any other\n\t  packet\n\n2008-10-01 12:05  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java: Added more\n\t  logging infor\n\n2008-09-30 20:51  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  IsBrokenPacket detection fixed\n\n2008-09-30 16:05  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  CHECK_USER_SESSION result may arrive when the user session is\n\t  gone already, added a code to handle this\n\n2008-09-30 07:13  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Added read/write\n\t  locking mechanism, apparently in certain cases multiple threads\n\t  may try to read/write on a single socket\n\n2008-09-29 20:06  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Removed silly\n\t  logging messages\n\n2008-09-29 18:41  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: XML parser\n\t  exception printed to a log file\n\n2008-09-29 14:11  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/RosterAbstract.java: Fixed a bug\n\t  with presence subscription when contact replies with unsubscribed\n\t  to the subscription request\n\n2008-09-29 12:57  bmalkow\n\n\t* database/derby-schema-4.sql: fix\n\n2008-09-29 12:57  bmalkow\n\n\t* src/main/java/tigase/db/derby/StoredProcedures.java: fix\n\n2008-09-26 21:56  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Subscription\n\t  management has been simplified to meet requirements from\n\t  RFC-3921bis-5\n\n2008-09-26 14:10  kobit\n\n\t* src/main/java/tigase/db/UserAuthRepository.java: Comment fixed\n\t  for the digestAuth method\n\n2008-09-26 07:46  bmalkow\n\n\t* database/derby-schema-4.sql, src/main/java/tigase/db/derby,\n\t  src/main/java/tigase/db/derby/StoredProcedures.java: add: JavaDB\n\t  (Derby) DDL and Stored Procedures\n\n2008-09-24 13:03  kobit\n\n\t* src/main/java/tigase/xmpp/impl/OfflineMessages.java: Fixed\n\t  problem with sorting off-line presence packets, corrected offline\n\t  message removal and changes the time stamp from the xep-0091 to\n\t  xep-0203\n\n2008-09-20 17:57  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Fixes in the Bosh\n\t  protocol for clustering supoprt - the BoshConnectionManager\n\t  exyends now ClientConnectionManager\n\n2008-09-18 18:29  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: getUserUID now\n\t  expects result greater then 0\n\n2008-09-18 17:53  kobit\n\n\t* database/postgresql-schema-4-sp.schema: Removed returning from\n\t  the stored procedures for compatibility with postgresql 8.0\n\n2008-09-18 17:04  kobit\n\n\t* database/mysql-schema-4-sp.schema,\n\t  database/postgresql-schema-4-sp.schema,\n\t  src/main/java/tigase/db/jdbc/TigaseAuth.java: Removed OUT\n\t  parameters from stored procedures for compatibility with\n\t  postgresql 8.0. These parameters were not used in normal\n\t  operation anyway. Only in SQL database test script.\n\n2008-09-17 17:20  kobit\n\n\t* src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Privacy.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/RosterAbstract.java,\n\t  src/main/java/tigase/xmpp/impl/RosterFlat.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: The repository\n\t  access code no longer catches and hides database exceptions, they\n\t  are passed out to the calling code allowing for proper error\n\t  singaling\n\n2008-09-17 11:51  kobit\n\n\t* src/main/java/tigase/server/XMPPServer.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java: In some cases\n\t  strange characters cause database to throw error as en effect the\n\t  whole roster can not be loaded properly as well as it also\n\t  impacts presence, the fix should hangel it properly\n\n2008-09-17 08:59  kobit\n\n\t* pom.xml, src/main/java/tigase/conf/ConfigRepository.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/XMPPServer.java: Fixed a bug when the\n\t  server is run with incorrect (non-xml) configuration file, now\n\t  the server discovers it and terminates it's work with a proper\n\t  message\n\n2008-09-16 14:02  kobit\n\n\t* database/postgresql-schema-4-sp.schema: Fixed a bug in the stored\n\t  function\n\n2008-09-16 11:06  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Fixed a bug\n\t  where prepared statement was used instead of callable statement,\n\t  apparently MySQL can handle it, PostreSQL throws an error\n\n2008-09-16 11:06  kobit\n\n\t* database/postgresql-schema-4-sp.schema: Fixed a problem with\n\t  returing query results\n\n2008-09-16 09:58  kobit\n\n\t* database/postgresql-schema-4-sp.schema,\n\t  database/postgresql-schema-4.sql,\n\t  database/postgresql-schema-upgrade-to-4.sql: The first complete\n\t  (untested) version of the schema 4 and upgrade script for\n\t  postgresql\n\n2008-09-16 00:37  kobit\n\n\t* database/mysql-schema-4-sp.schema,\n\t  database/postgresql-schema-4-sp.schema,\n\t  database/postgresql-schema-4.sql: PostgreSQL schema ver 4.0\n\t  updated\n\n2008-09-15 20:48  kobit\n\n\t* database/postgresql-schema-4.sql: postgresql schema definition\n\t  updated to version 4.0\n\n2008-09-11 18:04  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  filter processing condition changed\n\n2008-09-11 16:38  kobit\n\n\t* database/mysql-schema-upgrade-to-4.sql: Fixed problem with\n\t  tig_nodes table upgrade\n\n2008-09-11 16:29  kobit\n\n\t* database/mysql-schema-upgrade-to-4.sql: Fixed tig_nodes\n\t  conversion\n\n2008-09-11 15:18  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Added code to\n\t  online fix the database and adding root node when missing\n\n2008-09-11 13:42  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Revertet back a\n\t  fix causing problems with database - the case with null submode\n\n2008-09-11 09:36  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Fixed problem\n\t  when the subnode is null\n\n2008-09-10 19:16  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Removed dumping\n\t  stack trace on the db schema version conflict\n\n2008-09-10 18:56  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  serverSession object initialization added\n\n2008-09-10 18:56  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added support for TigaseAuth connector\n\n2008-09-10 18:55  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Changed log level for statistics from finest to info\n\n2008-09-10 18:54  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPImplIfc.java: init(UserRepository\n\t  rep) method added to allow custom repository configuration by\n\t  plugins\n\n2008-09-10 18:53  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPProcessor.java: init(UserRepository\n\t  rep) method added to allow custom repository configuration by\n\t  plugins\n\n2008-09-10 18:52  kobit\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Added proper\n\t  response on user session missing - which means the user is not\n\t  connected and can not respond to the ping\n\n2008-09-10 18:51  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Added roster\n\t  abstract to allow different Roster storage implementations\n\n2008-09-10 18:51  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java: Added roster\n\t  abstract to allow different Roster storage implementations\n\n2008-09-10 18:50  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added roster\n\t  abstract to allow different Roster storage implementations\n\n2008-09-10 18:50  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/RosterAbstract.java,\n\t  src/main/java/tigase/xmpp/impl/RosterFactory.java,\n\t  src/main/java/tigase/xmpp/impl/RosterFlat.java: Added roster\n\t  abstract to allow different Roster storage implementations\n\n2008-09-10 18:49  kobit\n\n\t* src/main/java/tigase/db/jdbc/TigaseAuth.java: A new\n\t  authentication connector whish can base on the stored procedures\n\t  in the database\n\n2008-09-10 18:48  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Database schema\n\t  upgrade to version 4.0\n\n2008-09-10 18:47  kobit\n\n\t* database/mysql-schema-4-sp.schema, database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: A few fixes to stored\n\t  procedures and schema upgrade process\n\n2008-09-09 16:24  kobit\n\n\t* database/mysql-schema-4-sp.schema, database/mysql-schema-4.sql:\n\t  Added missing drop stored procedure expression and changed the\n\t  order of the table creation\n\n2008-09-08 13:51  kobit\n\n\t* database/mysql-schema-4-sp.schema, database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: Improved schema upgrade\n\t  script, it correctly copies tables to new one with\n\t  auto-incrementing IDs and it should work with any database now\n\n2008-09-06 16:33  kobit\n\n\t* database/mysql-schema-4-sp.schema,\n\t  database/mysql-schema-4-test.sql, database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: Proper schema upgrade\n\t  procedure which converts also UIDs and NIDs to autoincrementing\n\t  fields\n\n2008-09-05 16:38  kobit\n\n\t* database/mysql-schema-4-sp.schema: TigGetDBProperty funciton is\n\t  READS SQL DATA now\n\n2008-09-05 12:13  kobit\n\n\t* database/mysql-schema-4-sp.schema, database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: MySQL Schema for Tigase\n\t  4.0 and schema upgarde scripts are ready\n\n2008-09-03 22:26  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: More detailed\n\t  logging in case of exception\n\n2008-09-03 20:09  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/db/UserAuthRepository.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/TigaseAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added TigaseAuth - generic connector which can authenticate users\n\t  agains any SQL (JDBC) database if the database offers specific\n\t  stored procedures\n\n2008-09-03 13:02  kobit\n\n\t* pom.xml: utils dependency changed to 3.1.1\n\n2008-09-02 17:43  kobit\n\n\t* src/main/java/tigase/db/DummyRepository.java,\n\t  src/main/java/tigase/db/UserRepository.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/xml/XMLRepository.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Blocked automatic adding anonymous users to the database when\n\t  userAutoCreate property is set to true\n\n2008-09-02 13:19  kobit\n\n\t* etc/init-mysql.properties, etc/tigase-mysql.conf: Changed default\n\t  vhost name from tigase.org to devel.tigase.org and added line to\n\t  clear the default classpath to reduce number of classes loaded at\n\t  runtime and avoid conflicts\n\n2008-09-02 13:17  kobit\n\n\t* database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: Adjusted database schema\n\t  to handle JID of size according to XMPP spec - 2048\n\n2008-09-02 13:16  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed problem with redirect result arriving before cluster\n\t  session_transfer result\n\n2008-09-02 13:16  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  problem with redirect result arriving before cluster\n\t  session_transfer result\n\n2008-09-01 21:17  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added support for\n\t  nickname for anonymous user connection\n\n2008-09-01 16:02  kobit\n\n\t* etc/init.properties: Removed anonymouse roster line which is not\n\t  needed anymore\n\n2008-08-29 15:01  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java: The authentication\n\t  plugin allows now for 3 tries before the user gets disconnected\n\n2008-08-29 14:17  kobit\n\n\t* src/main/java/tigase/xmpp/RepositoryAccess.java: Intendation\n\t  corrected\n\n2008-08-27 17:00  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java: drupal users table\n\t  is automatically altered if online_status field is missing\n\n2008-08-27 09:08  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Incorrect\n\t  VHost initalization bug fixed\n\n2008-08-27 07:32  kobit\n\n\t* src/main/java/tigase/xmpp/impl/BindResource.java: Fixed a bug\n\t  with the resource part incorrectly send to the client\n\n2008-08-27 07:31  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Performance\n\t  improvements - the dynamic roster is queried first and if it\n\t  returns null then the static roster is queried\n\n2008-08-22 16:57  kobit\n\n\t* database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql: Upgrade to the Tigase db\n\t  schema version 4.0\n\n2008-08-22 16:44  kobit\n\n\t* database/mysql-schema-4.sql,\n\t  database/mysql-schema-upgrade-to-4.sql,\n\t  database/postgresql-schema-4.sql,\n\t  database/sqlserver-schema-4.sql: Upgrade to the Tigase db schema\n\t  version 4.0\n\n2008-08-19 12:28  kobit\n\n\t* pom.xml, src/main/java/tigase/cluster/MethodCall.java,\n\t  src/main/java/tigase/cluster/MethodCallCriteria.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/cluster/methodcalls,\n\t  src/main/java/tigase/cluster/methodcalls/SessionTransferMC.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/ConnectionStatus.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java: Initial\n\t  fix for the session transfer bug\n\n2008-08-07 06:13  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Temp code just\n\t  compilable but not finished yet\n\n2008-08-07 06:12  kobit\n\n\t* src/main/java/tigase/cluster/ServerConnectionClustered.java:\n\t  Replaced DEF_S2S_NAME with getName()\n\n2008-08-07 06:12  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  bug causing NPE for 'onHold()' connection mode\n\n2008-08-07 06:11  kobit\n\n\t* win-stuff/scripts/Run.bat: Changed loading initial.properties to\n\t  init.properties\n\n2008-08-07 05:22  bmalkow\n\n\t* src/main/java/tigase/server/DisableDisco.java,\n\t  src/main/java/tigase/server/MessageRouter.java: this ugly patch\n\t  allows to process Disco stanzas as normal stanzas, not by\n\t  getDisco*() methods\n\n2008-08-07 05:18  bmalkow\n\n\t* src/main/java/tigase/server/XMPPServer.java:\n\t  getImplementationVersion() should return '0.0.0-0' if manifest is\n\t  unavailable\n\n2008-08-07 05:17  bmalkow\n\n\t* src/main/java/tigase/server/Packet.java: add copying xmlns from\n\t  source stanza to error stanza\n\n2008-07-03 15:53  kobit\n\n\t* src/main/java/tigase/server/ssender/DrupalCommentsTask.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java: Added\n\t  drupal comments notifier task\n\n2008-07-03 10:35  kobit\n\n\t* src/main/bash/users-list-moitor.sh: Corrected wording in the\n\t  welcome email\n\n2008-07-03 10:35  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: is_moderated\n\t  better handling\n\n2008-07-03 00:27  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Fixes for the\n\t  Gateway to work with the new API\n\n2008-07-02 17:29  kobit\n\n\t* src/main/bash/users-list-moitor.sh: Added full path to adduser\n\t  program which is needed when run from the cron job and also mail\n\t  program is used to send the first greetings message to newly\n\t  created user account\n\n2008-07-02 09:08  kobit\n\n\t* src/main/php/drupal/modules/tigase_usrreg-5.x/tigase_usrreg.module:\n\t  Added missing semicolon\n\n2008-07-02 09:07  kobit\n\n\t* src/main/php/drupal/modules/short_news-5.x/short_news.module,\n\t  src/main/php/drupal/modules/tigase_usrreg-5.x,\n\t  src/main/php/drupal/modules/tigase_usrreg-5.x/tigase_usrreg.info,\n\t  src/main/php/drupal/modules/tigase_usrreg-5.x/tigase_usrreg.module:\n\t  Module used for adding user directories when the account is\n\t  created\n\n2008-07-01 23:10  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Ad-hoc\n\t  commands for task managemebt work again\n\n2008-07-01 23:04  kobit\n\n\t* src/main/bash, src/main/bash/cron-dnotify-check.sh,\n\t  src/main/bash/users-list-moitor.sh: User accounts from drupal to\n\t  system scripts\n\n2008-07-01 22:41  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Fixed a bug when\n\t  some packets were not routed correctly between different user\n\t  connections (resources), instead they were send back to the\n\t  sender\n\n2008-07-01 06:32  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java: Added more\n\t  control over packets received from the client, if body element\n\t  name is incorrect or xmlns is incorrect or to=hostname is\n\t  incorrect the bosh returns an error message to the client and\n\t  terminates connection\n\n2008-07-01 06:31  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java:\n\t  Accept news without subject and put 'No subject' string if the\n\t  subject is missing\n\n2008-07-01 06:30  kobit\n\n\t* src/main/java/tigase/server/Packet.java: Added getXMLNS\n\t  convenience method\n\n2008-06-23 22:13  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: A fix\n\t  for slow database update in cluster mode when the user session\n\t  trasfer arrives to the node before database has been updated with\n\t  the authorization token - 2 secs for now....\n\n2008-06-21 22:14  kobit\n\n\t* src/main/java/tigase/cluster/ClientConnectionClustered.java:\n\t  Added logging information\n\n2008-06-21 22:08  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java: Added c2s\n\t  clustered implementation\n\n2008-06-21 22:06  kobit\n\n\t* src/main/java/tigase/cluster/ClientConnectionClustered.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/ServiceChecker.java: Added support\n\t  for disconnecting all connections when cluster node with\n\t  corresponding SM has been disconnected\n\n2008-06-21 16:39  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: user\n\t  session transfer is run with 1/2 sec delay to allow all queued\n\t  packet to be processed\n\n2008-06-21 15:42  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Cluster notifications are sent now from default (the first) vhost\n\n2008-06-21 15:31  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java: Better calculation\n\t  session life time and added also packets forwarding for the\n\t  session being transfered\n\n2008-06-21 12:53  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Added XML parser\n\t  error better handling\n\n2008-06-21 12:51  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Added XML parser\n\t  error better handling\n\n2008-06-21 12:31  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added log message on sending connection verify result\n\n2008-06-21 06:59  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Session closed after the session tranfser doesn't send unavilable\n\t  packet\n\n2008-06-20 22:37  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  handleLogin is not now called on user session transfer\n\n2008-06-20 22:04  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  droping check_user_session packet when all nodes are checked\n\n2008-06-20 21:54  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java: Added more\n\t  logging messages and improved calculation of the next cluster\n\t  node\n\n2008-06-20 21:54  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java: Added more\n\t  logging messages and improved calculation of the next cluster\n\t  node\n\n2008-06-20 21:40  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Corrected stanza type settings\n\n2008-06-20 21:30  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Added\n\t  detailed logging information\n\n2008-06-20 16:01  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Changed cluster notifications from headline to normal to make\n\t  them archivizable by offline message plugin\n\n2008-06-20 15:53  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java: Try\n\t  without serverSession loaded\n\n2008-06-20 15:32  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Commented out packet-from usage, for now\n\n2008-06-20 15:12  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Changed code to not pack clustered packets\n\n2008-06-20 14:57  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Changed logging parameters\n\n2008-06-20 09:29  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  New s2s implementation supporting reuse of the incoming\n\t  connection\n\n2008-06-20 07:37  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Started support for reusing s2s connection by... google?\n\n2008-06-20 06:45  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  Added detection for adding incoming connection when this is\n\t  outgoing in fact\n\n2008-06-19 23:58  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/ServerConnectionClustered.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  problem with user session transfer\n\n2008-06-19 23:35  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added calculation s2s connections for debugging\n\n2008-06-19 23:35  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Handling properly case when the IOService for REDIRECT command\n\t  does not exist\n\n2008-06-19 18:57  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Fixed\n\t  retrieving disco items from components\n\n2008-06-19 14:04  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Service\n\t  disovery processing corrected to call for all components based on\n\t  component id\n\n2008-06-19 13:33  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  Fixed problem with statistics - number of open s2s connections\n\n2008-06-19 12:57  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  Added extra logging information\n\n2008-06-19 12:42  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Added support for\n\t  configurable components IDs\n\n2008-06-19 10:51  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Fixed service\n\t  discovery problem when asking non-local domain or entity\n\n2008-06-19 10:01  kobit\n\n\t* pom.xml: tigase-utils dependency set to version 3.0.12 - opendns\n\t  workaround\n\n2008-06-19 07:13  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  Added more loggin for s2s connections\n\n2008-06-18 06:24  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java: User\n\t  session inter-node transfer\n\n2008-06-18 05:43  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: User\n\t  session inter-node transfer\n\n2008-06-18 05:41  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/ClusterController.java,\n\t  src/main/java/tigase/cluster/ClusterMethods.java,\n\t  src/main/java/tigase/cluster/ServerConnectionClustered.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java: Added support for\n\t  cluster method calls and querying other cluster nodes for\n\t  dialback key\n\n2008-06-17 11:21  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/PubSub.java: Plugin has moved to\n\t  tigase-pubsub project\n\n2008-06-17 09:38  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/ClusterController.java,\n\t  src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/ClusterMethods.java,\n\t  src/main/java/tigase/cluster/ServerConnectionClustered.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added support for cluster method calls and querying other cluster\n\t  nodes for dialback key\n\n2008-06-16 10:56  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Infinite loop\n\t  detecting logic has changed a bit to block packets with 'error'\n\t  type only\n\n2008-06-16 09:56  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added pubsub plugin to the list of default plugins\n\n2008-06-16 09:53  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/PubSub.java: PEP: add notification\n\t  to account owner\n\n2008-06-16 09:51  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed problem with storing incoming connections with incorrect\n\t  session id\n\n2008-06-16 09:50  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  Added statistics for s2s component\n\n2008-06-16 09:50  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Connection is\n\t  now tested evert 29 minutes instead of 60\n\n2008-06-16 09:38  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/PubSub.java: first simple\n\t  implementation of PEP\n\n2008-06-14 00:47  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java:\n\t  Statistics added\n\n2008-06-13 19:59  kobit\n\n\t* src/main/java/tigase/cluster/ServerConnectionClustered.java,\n\t  src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/xmppserver/ConnectionHandlerIfc.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManagerOLD.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnections.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: New implementation\n\t  of s2s protocol, initial version suitable for clustering\n\n2008-06-10 17:24  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  a bug with adding new cluster node\n\n2008-06-10 17:14  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Fixed\n\t  a bug with adding new cluster node\n\n2008-06-10 16:02  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/conf/Configurable.java: Changed wording in\n\t  messages and parameters\n\n2008-06-10 15:38  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java:\n\t  ClusterController it loaded automatically in cluster mode\n\n2008-06-10 14:01  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added cluster components registrator and notifications mechanism\n\n2008-06-10 14:00  kobit\n\n\t* src/main/java/tigase/cluster/ClusterController.java,\n\t  src/main/java/tigase/cluster/ClusteredComponent.java: Added\n\t  cluster components registrator and notifications mechanism\n\n2008-06-09 14:09  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Connect all parameter name change to --cluster-connect-all\n\n2008-06-09 14:07  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Connect all parameter added\n\n2008-06-09 13:22  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java: Fixed\n\t  a bug with multiple cluser nodes connections\n\n2008-06-09 13:22  kobit\n\n\t* pom.xml: Updated tigase-utils version dependency\n\n2008-06-09 12:20  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java: Allows\n\t  for multiple cluster nodes connection on single connection\n\t  manager\n\n2008-06-09 12:19  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Allows for multiple cluster nodes connection on single connection\n\t  manager\n\n2008-06-06 09:11  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Removed direct\n\t  usage of errorResult method\n\n2008-06-06 09:06  bmalkow\n\n\t* src/main/java/tigase/server/Packet.java: add deprecated\n\t  annotation to errorResult\n\n2008-06-06 09:05  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: change error\n\t  stanza generation way\n\n2008-06-06 09:02  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: change error\n\t  stanza generation way\n\n2008-06-06 08:46  bmalkow\n\n\t* src/main/java/tigase/server/ErrorCondition.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/xmpp/Authorization.java: fix: remove\n\t  reduntant code\n\n2008-06-06 08:25  bmalkow\n\n\t* src/main/java/tigase/server/ErrorCondition.java,\n\t  src/main/java/tigase/server/Packet.java: add XEP-0086 (Error\n\t  Condition) implementation\n\n2008-06-05 19:52  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Cluster packets processing fixes\n\n2008-06-05 19:52  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added XMLNS for all\n\t  created presence stanzas\n\n2008-06-05 18:42  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java: Fixed\n\t  routings for cluster connection manager bug\n\n2008-06-05 18:25  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java: New\n\t  routings for cluster connection manager are set properly\n\n2008-06-05 16:42  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Setting correct remote host address for a node to connect to\n\n2008-06-05 16:39  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java,\n\t  src/main/java/tigase/server/ConnectionManager.java: Setting\n\t  correct remote host address for a node to connect to\n\n2008-06-05 13:54  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added more\n\t  detailed logging info\n\n2008-06-05 13:42  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added more\n\t  detailed logging info\n\n2008-06-05 13:35  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Cleaned up the removing routing for disconnected service\n\n2008-06-05 12:41  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Replaced\n\t  integer numbers with constatnts\n\n2008-06-05 12:41  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: Moved\n\t  default component names to this interface to make it easier to\n\t  access them from other code places\n\n2008-06-05 12:40  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Moved cluster-nodes parameter out to Configurable ifc for use in\n\t  other places\n\n2008-06-05 12:39  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Moved default component names to this interface to make it easier\n\t  to access them from other code places\n\n2008-06-05 12:39  kobit\n\n\t* src/main/java/tigase/server/Packet.java: Setting\n\t  isServiceDiscovery flag for packet to speed packet processing up\n\n2008-06-05 12:38  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Moved default\n\t  component names to this interface to make it easier to access\n\t  them from other code places\n\n2008-06-05 12:37  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Loading default cluster nodes list from properties file\n\n2008-06-05 12:37  kobit\n\n\t* src/main/java/tigase/cluster/ClusterConnectionManager.java:\n\t  Cluster nodes connectivity component\n\n2008-06-05 12:36  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Service\n\t  Discovery handling improvements\n\n2008-06-04 17:55  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Changed links\n\t  generation from _top to _blank\n\n2008-06-04 15:19  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Fixed\n\t  service discovert and ad-hoc command processing\n\n2008-06-04 12:22  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed incorreclty handled writeRawData method\n\n2008-06-04 12:22  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added proper\n\t  handling for writing raw data to the socket and fixed method:\n\t  writePacketsToSocket\n\n2008-06-04 12:21  kobit\n\n\t* src/main/java/tigase/server/ServerComponent.java: Added\n\t  getComponentId() method\n\n2008-06-04 12:20  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Major code\n\t  cleanup and improved routing selecting logic\n\n2008-06-04 12:20  kobit\n\n\t* src/main/java/tigase/server/AbstractComponentRegistrator.java:\n\t  Added component ID support\n\n2008-06-04 12:19  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: Added\n\t  cluster mode stuff\n\n2008-06-04 12:19  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java:\n\t  Added writeRawData(...) method to the handler\n\n2008-06-04 12:19  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSessionTaskHandler.java:\n\t  Added writeRawData(...) method to the handler\n\n2008-06-04 12:18  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Fixed\n\t  incorrectly called writeRawData(...)\n\n2008-06-04 12:17  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java: Code\n\t  changes to reflect API changes, processPacket(packet, results)\n\t  can not be overwritten anymore, all stuff must be done in\n\t  processPacket(packet) now\n\n2008-06-04 12:17  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Code\n\t  changes to reflect API changes, processPacket(packet, results)\n\t  can not be overwritten anymore, all stuff must be done in\n\t  processPacket(packet) now\n\n2008-06-04 12:15  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Removed tricky stuff done when activating TLS mode, they are not\n\t  needed anymore\n\n2008-06-04 12:14  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: selectNow() is\n\t  only called now if there was a key canceled for the selector,\n\t  fixes old bug with infinite loop\n\n2008-06-04 12:13  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Added support for\n\t  cluster mode parameters and triming configuration parameters\n\n2008-06-04 12:12  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Added\n\t  suport for component ID and processPacket(packet, results) is now\n\t  final\n\n2008-06-04 12:11  kobit\n\n\t* src/main/java/tigase/xmpp/impl/SimpleForwarder.java: Removed,\n\t  commented out, unused code\n\n2008-06-04 12:10  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java:\n\t  Loading cluster nodes configuration\n\n2008-06-04 12:09  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added constants for\n\t  cluster mode parameters\n\n2008-06-04 11:32  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  Fixed path to binary files from other than frontpage\n\n2008-05-16 08:11  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Cluster initial implementation ready, not tested yet, doesn't\n\t  support multiple connections for the same user yet\n\n2008-05-15 10:23  kobit\n\n\t* etc/init-mysql.properties: Added comments to the init properties\n\t  file\n\n2008-05-14 19:22  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Refactoring and routing improvements continued..., may stop\n\t  working now but it compiles\n\n2008-05-14 14:56  kobit\n\n\t* src/main/java/tigase/cluster/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java:\n\t  Class moved to different package\n\n2008-05-14 14:55  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java:\n\t  Cluster mode initial development\n\n2008-05-14 13:56  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerClustered.java:\n\t  Further improvements and code cleaning up to prepare sources for\n\t  cluster mode implementation\n\n2008-05-14 13:55  kobit\n\n\t* src/main/java/tigase/server/Packet.java: Further improvements and\n\t  code cleaning up to prepare sources for cluster mode\n\t  implementation\n\n2008-05-14 13:53  kobit\n\n\t* src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Further\n\t  improvements and code cleaning up to prepare sources for cluster\n\t  mode implementation\n\n2008-05-13 15:42  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/ServerComponent.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Message routing\n\t  code cleanup and performance improvements, breaks the current/old\n\t  config filessvn status\n\n2008-05-13 10:17  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: add: returning IQ\n\t  error when vcard not found\n\n2008-05-12 21:40  kobit\n\n\t* pom.xml: tigase-utils dependencies updated\n\n2008-05-12 10:50  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/BoshSessionCache.java:\n\t  Implementation of keeping chat history in the Bosh cache\n\n2008-05-12 10:50  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Replaces presence\n\t  string with constant\n\n2008-05-12 09:16  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java:\n\t  Cluster code cleanup\n\n2008-05-09 18:01  kobit\n\n\t* src/main/java/tigase/xmpp/impl/OfflineMessages.java: Fixed\n\t  compilation error\n\n2008-05-09 17:58  kobit\n\n\t* src/main/java/tigase/xmpp/impl/OfflineMessages.java: Fixed a bug\n\t  with saving messages with an empty body\n\n2008-05-07 19:39  kobit\n\n\t* etc/tigase-mysql.conf: Updated sample configuration for mysql\n\t  database\n\n2008-05-07 19:31  kobit\n\n\t* etc/init-mysql.properties, etc/tigase-mysql.conf: Updated sample\n\t  configuration for mysql database\n\n2008-05-07 19:30  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Corrected logging\n\t  messages slightly\n\n2008-05-02 13:43  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Recreating\n\t  selector on IO error\n\n2008-05-02 13:43  kobit\n\n\t* src/main/java/tigase/xmpp/impl/AnonymousRoster.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Proper handling\n\t  error type packets\n\n2008-05-02 13:42  kobit\n\n\t* src/main/java/tigase/cluster,\n\t  src/main/java/tigase/cluster/ClusterElement.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerClustered.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Initial full cluster mode implementation\n\n2008-05-01 16:49  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Recreating the\n\t  selector on empty selection loop\n\n2008-05-01 08:17  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: A fix for\n\t  concurrent modification exception\n\n2008-05-01 08:06  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: A fix for\n\t  concurrent modification exception\n\n2008-04-30 22:10  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Anonymous messages can not go outside the server installation\n\n2008-04-30 21:16  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Selector select 0\n\t  keys, workaround for JVM bugs:\n\t  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4850373 and\n\t  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933\n\n2008-04-30 08:12  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Better handling\n\t  for CanceledKeyException\n\n2008-04-29 16:45  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  Added running server version displaying to the monitor\n\n2008-04-29 16:45  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java:\n\t  CancelledKeyException proper handling\n\n2008-04-27 15:13  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Force stop on write data\n\t  exception\n\n2008-04-25 21:28  kobit\n\n\t* pom.xml: xmltools dependencies updated\n\n2008-04-25 16:45  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Fixed problem with\n\t  returning not real-online presence to anonymouse user\n\n2008-04-25 16:35  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Sending\n\t  initial presence to anonymouse user and added some more logging\n\t  info\n\n2008-04-25 16:08  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Infinite loop with empty\n\t  read calls fix - network problems?\n\n2008-04-25 14:41  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/AnonymousRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java: Anonymous roster and\n\t  presence changed, they are now based on the direct presence and\n\t  can be easily adjusted to use for different users\n\n2008-04-24 22:01  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Added handling\n\t  issue described here:\n\t  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4850373\n\n2008-04-23 23:20  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Added forceStop()\n\t  when socket read was called but the service is not connected\n\n2008-04-23 23:12  kobit\n\n\t* src/main/java/tigase/xmpp/impl/DynamicRosterIfc.java: Added\n\t  JavaDoc documentationf or the interfacce\n\n2008-04-23 23:11  kobit\n\n\t* src/main/java/tigase/util/RepositoryUtils.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java: Added roster\n\t  export/import functionality\n\n2008-04-23 07:34  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Replaced stop()\n\t  with forceStop() on exception catch\n\n2008-04-22 21:44  kobit\n\n\t* etc/init.properties: Added anonymous roster handler\n\n2008-04-22 21:32  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/AnonymousRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Implemented online\n\t  status sending between anonymous users and anonymous peers\n\n2008-04-22 20:15  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/RosterPresence.java: Anonymous\n\t  login - dynamic roster update and presence sending\n\n2008-04-22 20:14  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: more detailed\n\t  logging to see what is really going on in there\n\n2008-04-21 11:02  kobit\n\n\t* pom.xml: Dependency for xmltools updated\n\n2008-04-21 09:19  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Ignoring certain packet to avoid processing them -\n\t  stream:features with error type which came back from the\n\t  connection manager component after the connection has been lost\n\t  but before the features has been delivered\n\n2008-04-19 20:13  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed a bug when message sent to the domain address was not\n\t  forwarded automaticaly to the server admins\n\n2008-04-19 20:12  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  Removed double forward slash from the download link\n\n2008-04-19 20:12  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/util/UpdatesChecker.java: Updates checker\n\t  initial implementation\n\n2008-04-17 10:44  kobit\n\n\t* src/main/java/tigase/xmpp/RepositoryAccess.java: Fixed bug with\n\t  missing ANONYMOUS mech\n\n2008-04-17 10:31  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Added missing\n\t  import statement\n\n2008-04-17 10:30  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed the bug causing infinite stream of packets sent to the\n\t  client and Checking isLoggable before running expensive\n\t  packet.toString for a better performance\n\n2008-04-17 10:29  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Checking\n\t  isLoggable before running expensive packet.toString for a better\n\t  performance\n\n2008-04-17 10:29  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java:\n\t  Checking isLoggable before running expensive packet.toString for\n\t  a better performance\n\n2008-04-17 10:28  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Added one more log\n\t  message\n\n2008-04-17 10:28  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Checking isLoggable\n\t  before running expensive packet.toString for a better performance\n\n2008-04-17 10:25  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Checking isLoggable\n\t  before running expensive packet.toString for a better performance\n\n2008-04-16 20:39  kobit\n\n\t* build.properties, src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Anonymous login added\n\n2008-04-16 11:16  kobit\n\n\t* pom.xml: Dependency for tigase-utils updated\n\n2008-04-16 08:48  kobit\n\n\t* pom.xml: XMLTools depedency change\n\n2008-04-15 21:27  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2008-04-15 21:27  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-3.3.2\n\n2008-04-15 21:22  kobit\n\n\t* src/main/java/tigase/auth/SaslAnonymous.java,\n\t  src/main/java/tigase/auth/TigaseSaslProvider.java,\n\t  src/main/java/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/main/java/tigase/server/Permissions.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java: SASL anonymous\n\t  added and the whole support for anonymous users - still in\n\t  development\n\n2008-04-15 21:20  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/gateways/GatewayConnection.java,\n\t  src/main/java/tigase/server/gateways/GatewayListener.java: Added\n\t  javadoc\n\n2008-04-03 08:40  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java,\n\t  src/main/java/tigase/server/ssender/DrupalForumTask.java,\n\t  src/main/java/tigase/server/ssender/JDBCTask.java: changes select\n\t  localtime to select 1\n\n2008-04-02 13:28  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Changed attributes order in a stream open element in order to\n\t  make it compatible with nagios monitoring tool\n\n2008-03-31 20:11  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Properly handle the\n\t  case when buddy name is not set, is it possible at all???\n\n2008-03-27 07:07  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java: On SID not\n\t  found error, the bosh component now sends 404 error code\n\n2008-03-27 07:07  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Graceful stop\n\t  implemented - the actual stop is performed when all data have\n\t  been sent\n\n2008-03-27 06:37  kobit\n\n\t* scripts/repo.sh: Slightly modified initial parameters in the\n\t  script\n\n2008-03-27 06:36  kobit\n\n\t* ant-definitions.xml, win-stuff/Tigase.iss,\n\t  win-stuff/wrapper/wrapper.conf: Modified binary build scripts in\n\t  order to add all new files, libraries, certificates and scripts\n\n2008-03-27 06:35  kobit\n\n\t* src/main/java/tigase/util/RepositoryUtils.java: Trimming data\n\t  before loading to database\n\n2008-03-27 06:30  kobit\n\n\t* src/main/java/tigase/util/RepositoryUtils.java: Added import user\n\t  data (roster) function from comma separated flat file, format is:\n\t  user_jid, password, roser_jid, roster_nick, subscription, group\n\n2008-03-20 17:19  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessor.java: Changed code to\n\t  properly handle and use new xmltools with intern() strings\n\n2008-03-20 17:18  kobit\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: Fixed log message\n\t  content\n\n2008-03-19 11:15  kobit\n\n\t* pom.xml, src/main/java/tigase/db/jdbc/JDBCRepository.java:\n\t  Changes to work with SimpleCache when it is turned off\n\n2008-03-18 23:05  kobit\n\n\t* scripts/tigase.sh: Fixed a bug for the case when TIGASE_HOME is\n\t  set manually\n\n2008-03-18 14:40  kobit\n\n\t* src/main/java/tigase/io/SocketIO.java,\n\t  src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/net/SocketReadThread.java: Fixed an issue\n\t  with never ending loop when the server couldn't write the rest\n\t  portion of data to the network socket\n\n2008-03-18 14:39  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshIOService.java: Added\n\t  'Server' header to make it easier to identify that the data come\n\t  from tigase bosh component\n\n2008-03-17 12:59  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Added statistics\n\t  to display memory usage by the server\n\n2008-03-16 08:14  kobit\n\n\t* src/main/java/tigase/net/ConnectionOpenThread.java,\n\t  src/main/java/tigase/net/SocketReadThread.java: Main worker\n\t  threads are now protected from unexpected finishing work on\n\t  exception\n\n2008-03-15 15:33  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Catchinh all\n\t  exceptions happening at Selector.select() on 64bit arch\n\n2008-03-14 20:25  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Catching up\n\t  CancelledKeyException which should not happen according to JAVA\n\t  API but it happens on Apple JVM, a bug?\n\n2008-03-14 20:23  kobit\n\n\t* src/main/java/tigase/xmpp/impl/SaslAuth.java: Closing connection\n\t  after unsuccessful authentication\n\n2008-03-14 20:23  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqAuth.java: Closing\n\t  connection after unsuccessful authentication\n\n2008-03-13 21:44  kobit\n\n\t* database/mysql-message-archive-schema.sql,\n\t  src/main/java/tigase/xmpp/impl/xep0136/MessageArchiveDB.java:\n\t  Message archive under development\n\n2008-03-07 16:42  kobit\n\n\t* src/main/java/tigase/db/RepositoryFactory.java: XMLRepository\n\t  initialization bug, it was loaded twice, once by UserRepo and\n\t  another by UserAuthRepo, accessing the same file from different\n\t  threads\n\n2008-03-07 16:41  kobit\n\n\t* src/main/java/tigase/net/ConnectionOpenThread.java: Catching up\n\t  socket exception in case it is closed immediately after it had\n\t  been opened before we start configuring the socket\n\n2008-03-05 17:28  kobit\n\n\t* src/main/java/tigase/util/RepositoryUtils.java: Rosetr cleaning\n\t  up function added\n\n2008-03-05 17:28  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java: Added\n\t  xml:lang default stream value to the user session\n\n2008-03-05 17:26  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/BoshSessionCache.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Added resource\n\t  binding to the automatic Bosh caching\n\n2008-03-05 08:04  kobit\n\n\t* pom.xml: tigase-utils dependency update for version 3.0.5\n\n2008-03-05 07:59  kobit\n\n\t* pom.xml: tigase-utils dependency update for version 3.0.4\n\n2008-03-04 16:21  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Initial presence\n\t  processing bug fixed - the server didn't look in the dynamic\n\t  roster\n\n2008-03-04 11:36  kobit\n\n\t* database/mysql-message-archive-schema.sql,\n\t  src/main/java/tigase/xmpp/impl/xep0136/MessageArchiveDB.java:\n\t  MessageArchive in development\n\n2008-03-04 11:36  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: New, improved\n\t  SimpleCache in use, caching data for 1minute only\n\n2008-03-04 11:35  kobit\n\n\t* pom.xml: Dependecy for tigase-utils change\n\n2008-03-03 13:23  kobit\n\n\t* pom.xml: Dependency for tigase-utils updated to utils ver. 3.0.2\n\n2008-03-03 13:13  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Commented\n\t  out user logout after calling unregister, instead the plugin\n\t  sends 'stop' to c2s component and then the disconnection finishes\n\t  correctly informing the client about successul unregistration\n\t  frst\n\n2008-03-02 10:08  kobit\n\n\t* database/mysql-schema.sql, etc/init.properties,\n\t  etc/initial.properties: Fixed sample files\n\n2008-03-02 10:08  kobit\n\n\t* database/mysql-message-archive-schema.sql,\n\t  scripts/user_roster.sh, src/main/java/tigase/xmpp/impl/xep0136,\n\t  src/main/java/tigase/xmpp/impl/xep0136/MessageArchive.java,\n\t  src/main/java/tigase/xmpp/impl/xep0136/MessageArchiveDB.java:\n\t  Message Archiving initial code\n\n2008-03-02 10:07  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Fixed problem\n\t  with displaying roster entries which are not in any group\n\n2008-02-26 21:02  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/BoshSessionCache.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Added Bosh\n\t  Session cache implementation\n\n2008-02-21 12:27  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Fixed a bug related\n\t  to presence probe and dynamic roster - tigase used to send\n\t  forbidden\n\n2008-02-21 10:31  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Initial port\n\t  open delay increased to 10sec\n\n2008-02-21 09:50  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java: Fixed NPE\n\t  when it tried to retrieve contact groups and the contact wasn't\n\t  in any group\n\n2008-02-19 23:27  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Fixed problem\n\t  with responding to service disco for error type packets\n\n2008-02-15 08:58  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixed the problem with incorrect loading multiple parameters to\n\t  the Map for initRepository\n\n2008-02-14 17:55  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Subscription to\n\t  yourself problem fixed - ticket #84\n\n2008-02-14 10:22  kobit\n\n\t* src/main/java/tigase/db/DummyRepository.java,\n\t  src/main/java/tigase/db/RepositoryFactory.java,\n\t  src/main/java/tigase/db/UserAuthRepository.java,\n\t  src/main/java/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/main/java/tigase/db/UserRepository.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/db/xml/XMLRepository.java,\n\t  src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/util/RepositoryUtils.java: Added an extra\n\t  Map parameter to the UserRepository and AuthRepository interfaces\n\n2008-02-14 10:20  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: To speed up\n\t  processing the bosh session remembers now last received RID to\n\t  compare it with the next rid\n\n2008-02-10 16:29  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/RosterPresence.java: On page\n\t  reload in Bosh session disapears, actually it happens every time\n\t  there is anotherconnection made with the same resource while the\n\t  old connection hasn't been closed yet\n\n2008-02-08 13:21  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java: Proper RID\n\t  handling and ACK implementation added\n\n2008-02-08 13:21  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: A workaround\n\t  for the static roster, it is now ignoring all contacts which are\n\t  in 'Upline Support' group or is not in any group at all\n\n2008-02-08 13:20  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Performance\n\t  improvement - isSubscribed static method which now takes a single\n\t  parameter SubscriptionType and determines whether it is\n\t  subscribedfrom type\n\n2008-02-08 13:18  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: A fix for the case\n\t  when the same contact appears in the static and dynamic roster,\n\t  the dynamic roster should and now does it, overwrite settings in\n\t  the static roster\n\n2008-02-02 14:15  kobit\n\n\t* prj.el,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/IBB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/RosterPresence.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Added new plugin -\n\t  RosterPresence which replaces two old plugins: Presence and\n\t  JabberIqRoster to avoid concurrent execution of those 2 stanza\n\t  types. This solves the problem with adding new contacts on\n\t  multi-cpu or multi-core machines, Arrays.copyOf statement has\n\t  been removed from all plugins and it is not needed and affect\n\t  performance\n\n2008-01-29 18:13  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java: Disco name\n\t  is now configurable and you can turn off showing the server\n\t  version\n\n2008-01-29 17:12  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: The subscription\n\t  presence is now send with correct 'from' address without resource\n\t  part which caused adding the user with resource to the roster in\n\t  some client/server combination\n\n2008-01-26 18:43  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Fixed the problem\n\t  with missing unavailable presence from the server when the user\n\t  is unsubscribed and the default available presence sent when user\n\t  has been subscribed\n\n2008-01-26 15:26  kobit\n\n\t* build.properties, pom.xml: Version number change to 3.3.2\n\n2008-01-26 14:33  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java:\n\t  connections.size() is tested against 'hold_requests' variable\n\t  instead of 'concurrent_reuqests'\n\n2008-01-26 14:20  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java:\n\t  connections.size() is tested against 'concurrent_requests'\n\t  variable instead of '1'\n\n2008-01-26 14:02  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Closing the\n\t  session after received terminate from the client\n\n2008-01-26 13:34  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Corrected a\n\t  timeout bug - server was using incorrect inactivity timeout\n\n2008-01-26 11:48  kobit\n\n\t* src/main/java/tigase/server/bosh/Constants.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java: For broken data in\n\t  database there might be no buddy subscription info, in such case\n\t  the subscription is updated to none\n\n2008-01-26 10:27  kobit\n\n\t* pom.xml, src/main/java/tigase/server/bosh/Constants.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Updated\n\t  xmltools dependency for version 3.0.4\n\n2008-01-25 11:16  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added support for\n\t  pending_in subscriptions\n\n2008-01-25 11:16  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Added support for\n\t  pending_in subscriptions\n\n2008-01-21 12:04  kobit\n\n\t* src/main/java/tigase/xmpp/impl/OfflineMessages.java: Null pointer\n\t  catched\n\n2008-01-21 10:46  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java:\n\t  Stopping connection with invalid SID\n\n2008-01-21 10:30  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java: Closing\n\t  connection on logout implemented\n\n2008-01-21 10:24  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Closing connection on logout implemented\n\n2008-01-21 09:41  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPSession.java: Old resource\n\t  connection logout corrected\n\n2008-01-20 02:40  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Links target\n\t  set to _top\n\n2008-01-19 16:20  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Added links\n\t  conversion to clickable URLs\n\n2008-01-17 23:18  kobit\n\n\t* build.properties, pom.xml: Version number change to 3.3.1\n\n2008-01-15 22:15  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added one more logging message\n\n2008-01-15 22:15  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Fixed problem with system commands send to incorrect session\n\t  manager\n\n2008-01-15 22:14  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPResourceConnection.java: Added\n\t  stanza ID generator in resource session to use by all plugins and\n\t  processors\n\n2008-01-15 09:22  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Modified default configuration generator to not add default\n\t  routings if routing table already exist\n\n2008-01-15 00:44  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Fixed an old bug with routings resolution, the old code tried to\n\t  resolve routings based on packet address while it should look at\n\t  the domain settings for the connection\n\n2008-01-14 22:19  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Moved\n\t  synchronization on connection resource from SM to Presence\n\t  plugin, to not blog the whole processing because of Presence\n\t  plugin constraints\n\n2008-01-14 13:16  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed permission for result packets problem which prevented\n\t  admins to access the ad-hoc commands\n\n2008-01-13 23:40  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed a bug with synchronization on connection resource\n\n2008-01-13 23:32  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added proper synchronization on connection resource to avoid\n\t  conflict with accessing the object during logout by many threads\n\t  concurrently\n\n2008-01-13 23:31  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Added removal\n\t  of gateway connection on logout\n\n2008-01-13 23:31  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Corrected wrong log\n\t  message\n\n2008-01-13 22:41  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Added proper\n\t  handling multiple user connections to the transport\n\n2008-01-13 22:28  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Optimized\n\t  logout handler\n\n2008-01-13 22:07  kobit\n\n\t* build.properties, pom.xml,\n\t  src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/gateways/GatewayConnection.java,\n\t  src/main/java/tigase/server/gateways/GatewayListener.java:\n\t  Gateway API has been changed, version change to 3.3.0\n\n2008-01-13 21:03  kobit\n\n\t* pom.xml: Version number change to 3.2.1\n\n2008-01-13 21:02  kobit\n\n\t* build.properties,\n\t  src/main/java/tigase/server/gateways/Gateway.java: Indentation\n\t  corrected\n\n2008-01-13 21:02  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/server/ConnectionManager.java: Fixed problem\n\t  with sending packets in multithreading code\n\n2008-01-10 07:09  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Reverted back code,\n\t  now presences from not-subscribed IDs are NOT ignored\n\n2008-01-09 00:11  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java: Deadlock\n\t  problem solved, replaced all synchronized methods with\n\t  synchronized blocks\n\n2008-01-08 11:03  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java: Each\n\t  plugin - XMPPProcessorIfc is now executed in separate thread to\n\t  avoid slowdowns if one plugin runs slowlu due to resource\n\t  availability delays\n\n2008-01-08 11:02  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java: Changed code\n\t  to allow multithreading support\n\n2008-01-08 11:01  kobit\n\n\t* src/main/java/tigase/xmpp/RepositoryAccess.java: Removed final\n\t  keyword from methods definition, it is not needed anymore\n\n2007-12-22 23:43  kobit\n\n\t* build.properties, pom.xml: Version number change to 3.2.0\n\n2007-12-22 18:51  kobit\n\n\t* win-stuff/Tigase-minimal.iss: Configuration for minimal tigase\n\t  package\n\n2007-12-22 18:51  kobit\n\n\t* etc/tigase-mysql.conf: Initial properties moved to a property\n\t  file\n\n2007-12-22 18:48  kobit\n\n\t* prj.el: Code indetation corrected\n\n2007-12-22 18:47  kobit\n\n\t* src/main/java/tigase/io/CertFilesTrustManager.java,\n\t  src/main/java/tigase/io/SSLContextContainer.java,\n\t  src/main/java/tigase/io/SSLContextContainerIfc.java,\n\t  src/main/java/tigase/io/TLSUtil.java,\n\t  src/main/java/tigase/io/TelnetClient.java,\n\t  src/main/java/tigase/io/TelnetServer.java,\n\t  src/main/java/tigase/server/ConnectionManager.java: Added support\n\t  for pluggable SSLContextContainers for network layer\n\n2007-12-22 18:46  kobit\n\n\t* src/main/java/tigase/server/ssender/StanzaHandler.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java: Added\n\t  handler for a single stanza packet\n\n2007-12-22 18:45  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: Moved to\n\t  extras package\n\n2007-12-22 18:45  kobit\n\n\t* src/main/java/tigase/io/IOInterface.java,\n\t  src/main/java/tigase/io/SocketIO.java,\n\t  src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/net/SocketReadThread.java: Implement fully\n\t  asynchronous communication over Java NIO\n\n2007-12-22 18:44  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Added support for\n\t  multiple extra components in initial.properties file, added\n\t  support for parameters types in initial.properties file\n\n2007-12-22 18:42  kobit\n\n\t* src/main/java/tigase/xmpp/impl/OfflineMessages.java: Fixed a bug\n\t  with incorrect order for off-line messages: #74\n\n2007-12-14 10:23  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Support for plugins list in property file added\n\n2007-12-14 10:22  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: Due to\n\t  library version change p2pMessageReceived listener had to be\n\t  added\n\n2007-12-14 10:21  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added --sm-plugins\n\t  parameter, so you can list plugins in property file for\n\t  configuration initialization\n\n2007-12-14 10:20  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Changed xmlns\n\t  raw string to variable use\n\n2007-12-11 23:24  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Removed unused import\n\n2007-12-11 22:55  kobit\n\n\t* src/main/java/tigase/server/Command.java: Added new, predefined\n\t  commands: BROADCAST_TO_ONLINE and BROADCAST_TO_ALL\n\n2007-12-11 22:54  kobit\n\n\t* src/main/java/tigase/server/bosh/Constants.java: Added\n\t  MAX_PACKETS number to set the maximum number of queuet packets to\n\t  be send to the client\n\n2007-12-11 22:54  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: If there is\n\t  huge number of packets waiting, they are sent in MAX_PACKETS\n\t  number at a time\n\n2007-12-11 22:52  kobit\n\n\t* src/main/java/tigase/server/Permissions.java: Added trusted user\n\t  permission\n\n2007-12-11 22:51  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added message broadcating and trusted user permission support\n\n2007-12-11 22:50  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added trusted configuration settings for trusted permission which\n\t  allows user to do certain actions like broadcasting messages\n\n2007-12-11 22:50  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: Improved\n\t  logging and roster synchronization\n\n2007-12-11 22:49  kobit\n\n\t* src/main/java/tigase/server/gateways/UserStatus.java: Corrected\n\t  user status translation, show message now contain correct XMPP\n\t  values\n\n2007-12-11 22:48  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: Changed\n\t  registration message\n\n2007-12-11 22:47  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added trusted\n\t  configuration settings for trusted permission which allows user\n\t  to do certain actions like broadcasting messages\n\n2007-12-11 22:46  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Dynamic,\n\t  large rosters are now sent in packets, 20 roster items in a\n\t  signle packet\n\n2007-12-03 13:33  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPResourceConnection.java: Fixed\n\t  problem with temporary resource setting\n\n2007-12-01 22:04  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Added another\n\t  log entry to monitor restart command processing\n\n2007-12-01 21:45  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Removed an\n\t  instruction for service.stop() if there was a problem with\n\t  starting the servicce\n\n2007-12-01 21:31  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added more\n\t  logging information to investigate problem with: 'attempt to stop\n\t  incorrect service: null' message\n\n2007-12-01 21:30  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Added support\n\t  for stream restart functionality\n\n2007-12-01 21:30  kobit\n\n\t* src/main/java/tigase/xmpp/impl/SaslAuth.java: Stream features are\n\t  now returned correctly in all cases\n\n2007-12-01 21:30  kobit\n\n\t* src/main/java/tigase/xmpp/impl/BindResource.java: Stream features\n\t  are now returned correctly in all cases\n\n2007-12-01 21:29  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqAuth.java: Stream features\n\t  are now correctly returned in all cases\n\n2007-12-01 21:28  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPResourceConnection.java: userJid is\n\t  now properly set after authentication\n\n2007-12-01 20:31  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java: Is it\n\t  really possible that getJID() returns null? let's try to catch it\n\n2007-12-01 20:30  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added one log\n\t  message for a case when from attribute is null and commented out\n\t  initial presence delivery if the buddy is not subscribed....\n\n2007-11-30 12:30  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java: Fix for a\n\t  problem with a new connection established for the same resource\n\t  name, the old connection wasn't properly closed and that caused\n\t  confusion on the server\n\n2007-11-28 21:29  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Fixed problem\n\t  with roster requests with empty group element - group name is\n\t  empty\n\n2007-11-24 08:54  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Fixed the problem\n\t  with sending roster items with resource part\n\n2007-11-23 20:52  kobit\n\n\t* database/sqlserver-schema.sql: Index for tig_node table has been\n\t  changed to keep 3 fields\n\n2007-11-23 20:39  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: On\n\t  gateway disconnection all roster elements from the gateway are\n\t  automaticaly marked as off-line now\n\n2007-11-23 20:38  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java: If gateway is\n\t  not connected, message received is sent back with an error\n\n2007-11-23 20:37  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql:\n\t  Modified unique index for tig_node to keep 3 fields instead of 2\n\n2007-11-23 20:37  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Added one more\n\t  log instruction\n\n2007-11-23 11:09  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: Finally\n\t  fixed the problem with user status, bocking/unblocking\n\n2007-11-23 09:12  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java: Added\n\t  missing import and fixed compilation error\n\n2007-11-23 00:29  kobit\n\n\t* src/main/java/tigase/server/gateways/MsnConnection.java,\n\t  win-stuff/Tigase.iss: Suport for MsnList added\n\n2007-11-22 14:44  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/gateways/MsnConnection.java: Added\n\t  full support for adding, removing buddies in roster\n\n2007-11-22 14:43  kobit\n\n\t* src/main/java/tigase/server/gateways/GatewayListener.java:\n\t  formatJID, decodeLegacyName methods added\n\n2007-11-22 14:43  kobit\n\n\t* src/main/java/tigase/db/xml/XMLRepository.java: Added\n\t  synchronization and support for multithreaded use\n\n2007-11-22 14:42  kobit\n\n\t* src/main/java/tigase/server/gateways/GatewayConnection.java:\n\t  addBuddy, removeBuddy, getPromptMessage methods added\n\n2007-11-22 14:42  kobit\n\n\t* src/main/java/tigase/db/RepositoryFactory.java: Fixed a bug with\n\t  accessing XML repository by different components\n\n2007-11-22 14:32  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Commented out\n\t  System.out.printlns\n\n2007-11-22 14:28  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Fixed a bug with\n\t  Tigase sending available presence with unsubscribed presence\n\n2007-11-22 14:27  kobit\n\n\t* win-stuff/Tigase.iss: Character case changed\n\n2007-11-21 18:03  kobit\n\n\t* database/sqlserver-schema.sql: Database schema definition for\n\t  SQLServer\n\n2007-11-20 17:10  kobit\n\n\t* src/main/java/tigase/io/SSLContextContainerIfc.java: SSL\n\t  container interface to allow use of different container\n\t  implementation, for example implementation capable of loading\n\t  certificates from *.pem files\n\n2007-11-14 10:20  kobit\n\n\t* win-stuff/Tigase.iss: Now gateway stores roster buddy last status\n\t  in database\n\n2007-11-14 10:20  kobit\n\n\t* src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/gateways/GatewayListener.java,\n\t  src/main/java/tigase/server/gateways/MsnConnection.java: Now\n\t  gateway stores roster buddy last status in database\n\n2007-11-14 10:19  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Fix for missing\n\t  subscriptions in roster coming for transports\n\n2007-11-13 23:53  kobit\n\n\t* src/main/java/tigase/server/gateways,\n\t  src/main/java/tigase/server/gateways/Gateway.java,\n\t  src/main/java/tigase/server/gateways/GatewayConnection.java,\n\t  src/main/java/tigase/server/gateways/GatewayException.java,\n\t  src/main/java/tigase/server/gateways/GatewayListener.java,\n\t  src/main/java/tigase/server/gateways/LoginGatewayException.java,\n\t  src/main/java/tigase/server/gateways/MsnConnection.java,\n\t  src/main/java/tigase/server/gateways/RosterItem.java,\n\t  src/main/java/tigase/server/gateways/UserStatus.java: Transports\n\t  initial implementation with MSN gateway\n\n2007-11-13 23:36  kobit\n\n\t* prj.el: Added more jar files\n\n2007-11-13 23:36  kobit\n\n\t* src/main/java/tigase/io/SSLContextContainer.java: Removed\n\t  System.exit(1) instruction\n\n2007-11-13 23:35  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added more logging information\n\n2007-11-13 23:35  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Removed System.exit(1) instruction\n\n2007-11-13 23:34  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Removed System.exit(1) instruction\n\n2007-11-13 23:34  kobit\n\n\t* src/main/java/tigase/net/SocketReadThread.java: Removed\n\t  System.exit(1) instruction\n\n2007-11-13 23:33  kobit\n\n\t* src/main/java/tigase/net/ConnectionOpenThread.java: Removed\n\t  System.exit(1) instruction\n\n2007-11-13 23:33  kobit\n\n\t* src/main/java/tigase/db/xml/XMLRepository.java: Added support for\n\t  user autocreate mode\n\n2007-11-13 23:32  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Fix for\n\t  internal transport support\n\n2007-11-13 23:31  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: A few fixes for a\n\t  case when nick part does not exist and when current_subscription\n\t  is null\n\n2007-11-13 23:30  kobit\n\n\t* etc/tigase.conf: By default now it loads init.properties file\n\n2007-11-13 23:27  kobit\n\n\t* src/main/java/tigase/xmpp/ProcessorFactory.java: Full stack trace\n\t  output to the console as logs are not working at this stage\n\n2007-11-13 23:26  kobit\n\n\t* src/main/java/tigase/util/DBUtils.java: A few convenience methods\n\t  for repository initialization\n\n2007-11-07 22:43  kobit\n\n\t* win-stuff/Tigase.iss: Version change and etc/ content corrected\n\n2007-11-07 22:42  kobit\n\n\t* etc/initial.properties: Initial server properties, which can be\n\t  used for config generators\n\n2007-11-07 22:42  kobit\n\n\t* src/main/java/tigase/server/XMPPServer.java: Changed initial\n\t  logging configuration\n\n2007-11-07 22:41  kobit\n\n\t* win-stuff/scripts/Run.bat: Added parameter for initial properties\n\t  and changed classpath to use wildcards\n\n2007-11-07 16:35  kobit\n\n\t* src/main/java/tigase/server/XMPPServer.java: Initial\n\t  configuration generation is now outputed to the log file\n\t  correctly\n\n2007-11-07 16:34  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixed initial configuration generation when database connector is\n\t  given as class name\n\n2007-11-07 16:34  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Added support for\n\t  initial parameters read from property file which is useful\n\t  especially on windows\n\n2007-11-07 12:30  kobit\n\n\t* src/main/java/tigase/xmpp/impl/DynamicRoster.java: Dynamic roster\n\t  classes are now comma separated list instead of string array of\n\t  class names\n\n2007-11-06 21:35  kobit\n\n\t* build.properties, win-stuff/Tigase.iss: Version change to 3.1.1\n\n2007-11-06 21:33  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Improvemements for plugins settings, plugins can share now the\n\t  same settings and stop listeners are receiving plugins settings\n\t  as a method parameter\n\n2007-11-06 21:32  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPStopListenerIfc.java: Added plugin\n\t  settings to the method parameters list\n\n2007-11-06 21:27  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Moved dynamic\n\t  roster initialization to separate class - DynamicRoster\n\n2007-11-06 21:26  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added support for\n\t  dynamic rosters\n\n2007-11-06 21:26  kobit\n\n\t* src/main/java/tigase/xmpp/impl/DynamicRoster.java: Static class\n\t  with static helper methods for accessing dynamic rosters' data\n\n2007-11-03 16:49  kobit\n\n\t* win-stuff/Tigase.iss: Changed default content of etc directory\n\n2007-11-03 16:46  kobit\n\n\t* win-stuff/Licence.txt: License change to GPLv3\n\n2007-11-03 16:45  kobit\n\n\t* src/main/java/tigase/db/DummyRepository.java: Dummy user\n\t  repository\n\n2007-11-02 20:29  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java: JavaDoc comments\n\t  added\n\n2007-11-02 20:28  kobit\n\n\t* src/main/java/tigase/db/UserAuthRepository.java: JavaDoc comments\n\t  added\n\n2007-11-02 20:28  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Improved\n\t  handling dynamic rosters\n\n2007-10-31 17:35  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Corrected generating default regex routing, '.' character is now\n\t  backslashed to avoid special treatment by regex engibe\n\n2007-10-31 17:24  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRoster.java: Fixed null\n\t  pointer exception in case of missing plugin settings for roster\n\n2007-10-31 17:12  kobit\n\n\t* prj.el, src/main/java/tigase/auth/TigaseSaslProvider.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/DynamicRosterIfc.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: MNodifications for\n\t  dynamic rosters functionality\n\n2007-10-23 06:52  bmalkow\n\n\t* pom.xml, src/main/resources, src/main/resources/META-INF,\n\t  src/main/resources/META-INF/MANIFEST.MF: Add creating manifest by\n\t  maven (with version number)\n\n2007-10-18 09:03  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-10-18 09:03  kobit\n\n\t* pom.xml: Dependencies update\n\n2007-10-18 08:57  kobit\n\n\t* scripts/repo.sh, win-stuff/Tigase.iss: Version change\n\n2007-10-17 13:08  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Corrected logic mistake in the s2s\n\n2007-10-17 12:56  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshIOService.java: Changed\n\t  strings literals to constants, might improve performance/resource\n\t  consumption slightly\n\n2007-10-17 12:54  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Yet\n\t  another fix to packet counters for last second, minute, hour\n\n2007-10-17 12:54  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Changed code slightly to allow multiple s2s connections from\n\t  other servers, apparently this is correct\n\n2007-10-13 18:07  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Improved calculating number of last packets sent\n\n2007-10-13 18:06  kobit\n\n\t* src/main/java/tigase/net/ConnectionOpenThread.java: Changed\n\t  default TCP/IP packet size to 2k\n\n2007-10-13 18:06  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java: Improved\n\t  retrieving privacy lists\n\n2007-10-11 23:53  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Corrected calculation of the number of packets in last second\n\n2007-10-11 23:37  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Corrected calculation of the number of packets in last second\n\n2007-10-09 16:36  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.info,\n\t  src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  tigase monitor updated for drupal 5.x\n\n2007-10-09 13:01  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/Authorization.java,\n\t  src/main/java/tigase/xmpp/PacketErrorTypeException.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java,\n\t  src/main/php/drupal/modules/short_news-5.x/short_news.module,\n\t  win-stuff/Tigase.iss: Authorization throws now exception if you\n\t  try to assing error type to the packet which is already an error,\n\t  it used to cause infinite loops in the server in many places.\n\t  This change aims to kill infinite loops in the server for\n\t  ever....\n\n2007-10-08 09:41  kobit\n\n\t* src/main/php/drupal/modules/short_news-5.x/short_news.module:\n\t  Modifications for compatibility with drupal-5.x\n\n2007-10-06 16:34  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/php/drupal/modules/short_news-5.x,\n\t  src/main/php/drupal/modules/short_news-5.x/short_news.info,\n\t  src/main/php/drupal/modules/short_news-5.x/short_news.module,\n\t  src/main/php/drupal/modules/tigase_monitor-5.x,\n\t  src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module:\n\t  Drupal v5.x modules\n\n2007-10-02 13:26  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Corrected link\n\t  description to detailed statistics\n\n2007-10-02 13:26  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Added\n\t  statisics for packets processed in last second, minute and hour\n\n2007-10-02 13:25  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Increased\n\t  watchdog timeout from 1 min to 30 minutes, it cleans up\n\t  connections which are iddle for an hour, so there is no need for\n\t  running it every minute\n\n2007-10-02 13:24  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Catching possible authorization exception during resource set and\n\t  returning def for max queue size\n\n2007-10-02 13:23  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java:\n\t  Checking whether the session is authorized before processing,\n\t  eliminates generating authorization exceptions and improves\n\t  performance\n\n2007-10-02 13:22  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java: Checking\n\t  whether the session is authorized before processing, eliminates\n\t  generating authorization exceptions and improves performance\n\n2007-10-02 13:21  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPResourceConnection.java: userID and\n\t  userJID is cached now so it doesn't need to be generated on each\n\t  call, performance improvement\n\n2007-10-01 11:06  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Added details\n\t  and configuration page\n\n2007-09-29 22:55  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Rewriten\n\t  module to display number of registered account from the server\n\t  statistics rather than from drupal database and number of active\n\t  sessions\n\n2007-09-29 22:54  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed a bug when s2s received packet without 'to' attribute due\n\t  to missconfiguration\n\n2007-09-29 22:54  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added statustics for registered accounts number\n\n2007-09-29 22:53  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Fixed\n\t  a bug with task names in upper case\n\n2007-09-29 22:53  kobit\n\n\t* src/main/java/tigase/db/UserRepository.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/xml/XMLRepository.java: Added method\n\t  returning number of user accounts in database\n\n2007-09-24 18:43  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Fixed problem with packets addresses to the component which can\n\t  not be processed by the component\n\n2007-09-22 14:41  kobit\n\n\t* build.properties: Version change\n\n2007-09-22 13:24  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/xmpp/StanzaType.java: Added proper session\n\t  termination code for Bosh component\n\n2007-09-21 21:31  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Fixed problem\n\t  with calculating uptime in some cases\n\n2007-09-21 21:31  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshIOService.java: Fixed\n\t  problem with incorrectly calculated content length if data\n\t  contains multibyte UTF-8 characters\n\n2007-09-21 08:44  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Fixed problem\n\t  with missing version and xmlns attributes in body element\n\n2007-09-19 08:08  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Changed\n\t  from HashSet to CopyOnWriteArraySet for routings tables\n\n2007-09-18 08:56  kobit\n\n\t* src/main/java/tigase/server/sreceiver/TesterTask.java: Tester\n\t  task for testing server functionality\n\n2007-09-18 08:56  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Spelling corrected\n\n2007-09-17 09:46  kobit\n\n\t* src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed the problem when repository is not set or can't support\n\t  user autocreate mode\n\n2007-09-16 07:06  bmalkow\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-09-16 07:06  bmalkow\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-3.0.1-beta\n\n2007-09-16 01:33  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Added bosh\n\t  connections\n\n2007-09-15 16:02  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Fixed problem\n\t  with uptime when uptime is shorter than 1day\n\n2007-09-15 15:29  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Fixed problem\n\t  with uptime when uptime is shorter than 1day\n\n2007-09-15 14:06  kobit\n\n\t* win-stuff/Tigase.iss: Version change\n\n2007-09-15 14:06  kobit\n\n\t* build.properties, win-stuff/Tigase.iss: Version change\n\n2007-09-15 14:04  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Packet.toString() changed to display XMLNS\n\n2007-09-15 14:04  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java: Fixed minor\n\t  bug with default XMLNS settings for many children with different\n\t  XMLNSes\n\n2007-09-15 11:41  bmalkow\n\n\t* pom.xml: update dependecies\n\n2007-09-14 22:59  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Bosh is now\n\t  completed but untested...\n\n2007-09-14 22:03  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: presence\n\t  unavailable removes now jid from directpresence set\n\n2007-09-12 10:16  bmalkow\n\n\t* pom.xml: changes in maven group and version\n\n2007-09-12 10:04  bmalkow\n\n\t* pom.xml: changes in maven group and version\n\n2007-09-11 21:58  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: You can now\n\t  add components during configuration generation with parameters:\n\t  --comp-name and --comp-class\n\n2007-09-11 17:55  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Bosh - timeouts\n\t  implemented, untested\n\n2007-09-04 20:02  bmalkow\n\n\t* src/main/java/tigase/io/CertFilesTrustManager.java: Add\n\t  TrustManager based on PEM files, stored in (for example)\n\t  /etc/ssl/certs\n\n2007-08-09 09:03  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/BoshSessionTaskHandler.java:\n\t  Added max_pause support, untested\n\n2007-08-03 17:45  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Initial, working\n\t  version of Bosh implementation\n\n2007-08-03 17:45  kobit\n\n\t* prj.el: License text changed\n\n2007-08-03 17:44  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Packet id changed to be different from other commands\n\n2007-08-03 17:44  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqStats.java: Fixed problem\n\t  with ID retrieving in incorrect place of code\n\n2007-07-25 15:06  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Added real\n\t  statistics from tigase jabber server, these statistics are\n\t  updated every minute\n\n2007-07-21 16:36  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Link to all\n\t  downloads fixed\n\n2007-07-21 15:13  kobit\n\n\t* src/main/php/drupal/modules/short_news.module,\n\t  src/main/php/drupal/modules/tigase.module: Spelling corrections +\n\t  license update\n\n2007-07-21 15:12  kobit\n\n\t* src/main/php/drupal/modules/tigase_monitor.module: Real Tigase\n\t  monitor as a separate module with online_status and all other\n\t  stuff\n\n2007-07-21 15:12  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java: Added online_status\n\t  support\n\n2007-07-18 18:13  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-07-18 18:13  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-3.0.0\n\n2007-07-18 18:12  kobit\n\n\t* pom.xml: Dependencies change to libraries which also use GPLv3\n\n2007-07-18 18:10  kobit\n\n\t* build.properties: Version change to 3.0.1 - license change to\n\t  GPLv3\n\n2007-07-18 18:09  kobit\n\n\t* COPYING: Initial version of file with license GPLv3\n\n2007-07-18 17:38  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql,\n\t  scripts/config.sh, scripts/repo.sh, scripts/tigase.sh,\n\t  src/main/java/tigase/annotations/TODO.java,\n\t  src/main/java/tigase/auth/AuthorisationSystem.java,\n\t  src/main/java/tigase/auth/LoginHandler.java,\n\t  src/main/java/tigase/auth/ResourceConnectionCallback.java,\n\t  src/main/java/tigase/auth/SaslPLAIN.java,\n\t  src/main/java/tigase/auth/TigaseSaslProvider.java,\n\t  src/main/java/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/main/java/tigase/conf/ConfigComponent.java,\n\t  src/main/java/tigase/conf/ConfigRepository.java,\n\t  src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/db/AuthorizationException.java,\n\t  src/main/java/tigase/db/ConfigurationDB.java,\n\t  src/main/java/tigase/db/DBInitException.java,\n\t  src/main/java/tigase/db/DataOverwriteException.java,\n\t  src/main/java/tigase/db/MessageHistoryDB.java,\n\t  src/main/java/tigase/db/MessageOfflineDB.java,\n\t  src/main/java/tigase/db/NonAuthUserRepository.java,\n\t  src/main/java/tigase/db/RepositoryFactory.java,\n\t  src/main/java/tigase/db/TigaseDBException.java,\n\t  src/main/java/tigase/db/UserAuthRepository.java,\n\t  src/main/java/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/main/java/tigase/db/UserDB.java,\n\t  src/main/java/tigase/db/UserExistsException.java,\n\t  src/main/java/tigase/db/UserNotFoundException.java,\n\t  src/main/java/tigase/db/UserRepository.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/db/xml/XMLRepository.java,\n\t  src/main/java/tigase/disco/ServiceEntity.java,\n\t  src/main/java/tigase/disco/ServiceIdentity.java,\n\t  src/main/java/tigase/disco/XMPPService.java,\n\t  src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/http/HttpServer.java,\n\t  src/main/java/tigase/http/HttpService.java,\n\t  src/main/java/tigase/io/BufferUnderflowException.java,\n\t  src/main/java/tigase/io/IOInterface.java,\n\t  src/main/java/tigase/io/SSLContextContainer.java,\n\t  src/main/java/tigase/io/SampleSocketThread.java,\n\t  src/main/java/tigase/io/SocketIO.java,\n\t  src/main/java/tigase/io/TLSEventHandler.java,\n\t  src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/io/TLSStatus.java,\n\t  src/main/java/tigase/io/TLSUtil.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/io/TelnetClient.java,\n\t  src/main/java/tigase/io/TelnetServer.java,\n\t  src/main/java/tigase/net/Accept.java,\n\t  src/main/java/tigase/net/ConnectionOpenListener.java,\n\t  src/main/java/tigase/net/ConnectionOpenThread.java,\n\t  src/main/java/tigase/net/ConnectionType.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/net/IOServiceListener.java,\n\t  src/main/java/tigase/net/ServiceCommand.java,\n\t  src/main/java/tigase/net/SocketReadThread.java,\n\t  src/main/java/tigase/net/SocketType.java,\n\t  src/main/java/tigase/server/AbstractComponentRegistrator.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/ComponentRegistrator.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/Permissions.java,\n\t  src/main/java/tigase/server/ServerComponent.java,\n\t  src/main/java/tigase/server/ThreadExceptionHandler.java,\n\t  src/main/java/tigase/server/XMPPServer.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/DefaultValues.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyConstants.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/RosterItem.java,\n\t  src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommandIfc.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommons.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCreationPolicy.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java,\n\t  src/main/java/tigase/server/sreceiver/TaskType.java,\n\t  src/main/java/tigase/server/ssender/DrupalForumTask.java,\n\t  src/main/java/tigase/server/ssender/FileTask.java,\n\t  src/main/java/tigase/server/ssender/JDBCTask.java,\n\t  src/main/java/tigase/server/ssender/SenderTask.java,\n\t  src/main/java/tigase/server/ssender/StanzaHandler.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/stats/StatRecord.java,\n\t  src/main/java/tigase/stats/StatisticType.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/stats/StatisticsContainer.java,\n\t  src/main/java/tigase/stats/StatsComponent.java,\n\t  src/main/java/tigase/ui/UIComponent.java,\n\t  src/main/java/tigase/ui/WebUI.java,\n\t  src/main/java/tigase/ui/XMPPServiceComponent.java,\n\t  src/main/java/tigase/util/ElementUtils.java,\n\t  src/main/java/tigase/util/LogFormatter.java,\n\t  src/main/java/tigase/util/RepositoryUtils.java,\n\t  src/main/java/tigase/util/RoutingsContainer.java,\n\t  src/main/java/tigase/xmpp/Authorization.java,\n\t  src/main/java/tigase/xmpp/NotAuthorizedException.java,\n\t  src/main/java/tigase/xmpp/ProcessorFactory.java,\n\t  src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/StanzaType.java,\n\t  src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java,\n\t  src/main/java/tigase/xmpp/XMPPException.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java,\n\t  src/main/java/tigase/xmpp/XMPPIOServiceListener.java,\n\t  src/main/java/tigase/xmpp/XMPPImplIfc.java,\n\t  src/main/java/tigase/xmpp/XMPPPostprocessorIfc.java,\n\t  src/main/java/tigase/xmpp/XMPPPreprocessorIfc.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessor.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/XMPPStopListenerIfc.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/IBB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Privacy.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: License change to\n\t  GPLv3\n\n2007-07-13 12:48  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java: Bosh\n\t  implementation in progress\n\n2007-07-13 12:48  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Changed public constants to private constants\n\n2007-06-27 16:03  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Removed redundand\n\t  'from' attribute setting which is already done in PacketFilter\n\n2007-06-27 15:24  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Changed\n\t  access modifier from protected to private because this variable\n\t  is now accessible through public method for component\n\n2007-06-27 15:22  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java:\n\t  Removed 'forward' processing completely as it was conflicting\n\t  with all plugins processing stanzas on behalf of the user\n\n2007-06-27 15:21  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Replaced custom code with more generic code accessing default\n\t  hostname\n\n2007-06-27 15:21  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Replaced custom code with more generic code accessing default\n\t  hostname\n\n2007-06-27 15:20  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Fixed null pointer\n\t  exception in case of closing not authenticated session\n\n2007-06-18 16:21  kobit\n\n\t* etc/tigase-mysql.conf, src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java,\n\t  src/main/java/tigase/xmpp/XMPPIOServiceListener.java: Each\n\t  component can now provide own implementation/extension of\n\t  XMPPIOService. The specific component using this feature is Bosh\n\n2007-06-18 16:20  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/MessageRouter.java: Added NULL\n\t  routing which is dummy routing used for domain names hosted on\n\t  the server\n\n2007-06-18 16:19  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed bug when user could inject a stanza to the system before\n\t  the session has been authenticated\n\n2007-06-09 09:27  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Moved defHostname code to abstract class to make it automatically\n\t  available for all message receivers and set proper default\n\t  routing for all components\n\n2007-06-08 19:18  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Added default hostname for c2s component as using the first\n\t  hostname as default from the list doesn't work correctly,\n\t  elements often gets reordered\n\n2007-06-08 18:55  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java:\n\t  Fixed problem with error stanza received sometimes from s2s\n\t  component in case of problem with deivery\n\n2007-06-08 18:20  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Fixed\n\t  problem with default policies for task types and added\n\t  defHostname config parameter\n\n2007-06-08 18:20  kobit\n\n\t* build.properties: Version change to 2.9.6\n\n2007-06-08 17:05  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-06-08 17:05  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-2.9.5\n\n2007-06-08 11:43  kobit\n\n\t* build.properties, win-stuff/Tigase.iss: Version change to 2.9.5\n\n2007-06-08 11:41  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java: Fixed\n\t  bug with presence probe processing\n\n2007-06-08 11:00  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-06-08 11:00  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-2.9.4\n\n2007-06-08 11:00  kobit\n\n\t* pom.xml: changed xmltools version dependcy\n\n2007-06-08 10:59  kobit\n\n\t* ant-definitions.xml: Added Mandriva script to binary releases\n\n2007-06-08 07:49  kobit\n\n\t* win-stuff/Tigase.iss: Version number update to 2.9.4\n\n2007-06-07 23:57  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java: Corrected\n\t  packet forwarding addressed to domain\n\n2007-06-07 23:37  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java: Fixed\n\t  problem with packet forwarding\n\n2007-06-07 23:16  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Commented out some extra logging\n\n2007-06-07 23:15  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Improved\n\t  processing of lost packet to local component\n\n2007-06-07 23:14  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Improved packet filter - added default forwarder\n\n2007-06-07 23:13  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Increased default\n\t  log size to 10MB\n\n2007-06-07 23:12  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Improved\n\t  authorization checking\n\n2007-06-06 23:06  kobit\n\n\t* scripts/mandriva, scripts/mandriva/init.d,\n\t  scripts/mandriva/init.d/tigase: Startup script for Mandriva\n\n2007-06-06 23:06  kobit\n\n\t* src/main/java/tigase/disco/ServiceEntity.java,\n\t  src/main/java/tigase/net/ConnectionOpenThread.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommons.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/IBB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Code cleanup\n\n2007-06-06 20:29  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Stream\n\t  initialization - implementation in progress\n\n2007-06-06 20:28  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  c2s component now first sends stream initialization back to\n\t  client and then sends requests for GETFEATURES to avoid sending\n\t  features before stream initialization\n\n2007-06-06 20:27  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Removed all locks\n\t  as now IOService is synchronized\n\n2007-06-06 19:49  kobit\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Code cleanup\n\n2007-06-06 16:27  kobit\n\n\t* src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java: Code cleanup\n\n2007-06-06 16:23  kobit\n\n\t* src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/IBB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java: Code cleanup\n\n2007-06-06 15:48  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessor.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Code cleanup\n\n2007-06-06 12:21  kobit\n\n\t* src/main/java/tigase/auth/SaslPLAIN.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java: Code cleanup\n\n2007-06-06 12:06  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Performance optimizations\n\n2007-06-06 11:55  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/io/SSLContextContainer.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/io/TelnetClient.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java,\n\t  src/main/java/tigase/server/ssender/FileTask.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatRecord.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/util/RepositoryUtils.java,\n\t  src/main/java/tigase/util/RoutingsContainer.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java: Performance\n\t  optimizations\n\n2007-06-06 11:54  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Added\n\t  configuration settings\n\n2007-06-06 11:54  kobit\n\n\t* src/main/java/tigase/server/bosh/BoshSession.java: Added\n\t  configuration settings\n\n2007-06-06 11:52  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Protection\n\t  against infinite loop, server now doesn't send out any packet\n\t  which is addressed to local domain\n\n2007-06-05 22:03  kobit\n\n\t* etc/tigase-mysql.conf, src/main/java/tigase/server/bosh,\n\t  src/main/java/tigase/server/bosh/BoshConnectionManager.java,\n\t  src/main/java/tigase/server/bosh/BoshIOService.java,\n\t  src/main/java/tigase/server/bosh/BoshSession.java,\n\t  src/main/java/tigase/server/bosh/Constants.java: Initial version\n\t  of BOSH component - XEP-0124\n\n2007-06-05 22:03  kobit\n\n\t* src/main/java/tigase/util/RoutingsContainer.java: Replaced\n\t  HashMap with LinkedHashMap\n\n2007-06-05 21:48  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Replaced HashMap with LinkedHashMap\n\n2007-06-05 21:47  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Moved\n\t  XMPPIOService creation to separate method so it can be\n\t  overwritten and return more specialized classes implementation\n\t  like BoshIOService\n\n2007-06-05 21:46  kobit\n\n\t* src/main/java/tigase/server/ssender/StanzaSender.java: Replaced\n\t  HashMap with LinkedHashMap\n\n2007-06-05 21:46  kobit\n\n\t* src/main/java/tigase/server/AbstractComponentRegistrator.java:\n\t  Replaced HashMap with LinkedHashMap\n\n2007-06-05 21:46  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: Replaced\n\t  HashMap with LinkedHashMap and added Bosh component to a list of\n\t  standard components\n\n2007-06-05 21:45  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Removed extra, not used import\n\n2007-06-05 21:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Replaced HashMap with LinkedHashMap\n\n2007-06-05 21:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Replaced HashMap with LinkedHashMap\n\n2007-06-05 21:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/NewTaskCommand.java:\n\t  Replaced HashMap with LinkedHashMap\n\n2007-06-05 21:43  kobit\n\n\t* src/main/java/tigase/conf/ConfigRepository.java: Replaced HashMap\n\t  with LinkedHashMap\n\n2007-06-05 21:43  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: 1. Replaced HashMap\n\t  with LinkedHashMap, 2. changed default logging level to console\n\t  to FINER from ALL, 3. added stanza type checking for commands\n\t  requests\n\n2007-06-05 21:41  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added Bosh\n\t  implementation to a list of default components\n\n2007-06-05 21:41  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Unified i/o\n\t  interface, all methods now use writeRawData method which can be\n\t  overwritten in descendant classes like in BoshIOService to write\n\t  some HTTP headers before content\n\n2007-06-05 21:40  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Roster.java: Replaced HashMap with\n\t  LinkedHashMap\n\n2007-06-05 09:43  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Corrected service\n\t  discovery retrieving to work only for stanzas with 'get' type\n\n2007-06-01 17:18  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  s2s component now refuses to process packets (send out) which are\n\t  addressed to one of local domains\n\n2007-06-01 17:18  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added another default routings: .*.hostname\n\n2007-06-01 11:43  kobit\n\n\t* build.properties: Version number update to 2.9.4\n\n2007-06-01 11:43  kobit\n\n\t* pom.xml: Utils dependency update for version 2.4.2\n\n2007-06-01 11:43  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Corrected default routing table, to '.*@hostname' added also\n\t  'hostname'\n\n2007-06-01 10:22  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Default routing is now set to: .*@hostname instead of .*hostname\n\n2007-06-01 10:22  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: regex routings\n\t  are now checked agains whole node ID part not just hostame\n\n2007-06-01 09:01  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare for next development\n\t  iteration\n\n2007-06-01 09:01  kobit\n\n\t* pom.xml: [maven-release-plugin] prepare release\n\t  tigase-server-2.9.3\n\n2007-06-01 08:58  kobit\n\n\t* win-stuff/Tigase.iss: Version change to 2.9.3\n\n2007-05-31 21:32  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/ConnectionManager.java: Logging a bit\n\t  optimized\n\n2007-05-31 21:31  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added GEN_CONFIG_COMP parameter processing, special default\n\t  confiuration for single component like MUC and external\n\t  component, IOService id is now a constant which means this\n\t  component can server single connection only\n\n2007-05-31 21:30  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: Added\n\t  GEN_CONFIG_COMP parameter processing, special default\n\t  confiuration for single component like MUC and external component\n\n2007-05-31 21:29  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  ADMINS and HOSTNAMES property key moved to Configurable\n\n2007-05-31 21:29  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: ADMINS\n\t  property key moved to Configurable\n\n2007-05-31 21:28  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java:\n\t  super.processMessage call moved so commands are not distributed\n\t  to all subscribers\n\n2007-05-31 21:26  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Added GEN_COMP_NAME,\n\t  CLASS parameters processing\n\n2007-05-31 21:26  kobit\n\n\t* build.properties, pom.xml: Version change to 2.9.3\n\n2007-05-31 21:24  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added\n\t  --gen-config-comp parameter, added some more comments and moved\n\t  HOSTNAMES and ADMINS property key from SessionManager to this\n\t  class\n\n2007-05-30 11:30  bmalkow\n\n\t* pom.xml: make dependencies non-snapshot\n\n2007-05-29 22:29  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Corrected command processing - now commands not processed can be\n\t  sent out\n\n2007-05-29 21:36  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java,\n\t  win-stuff/Tigase.iss: Improved adding post confirmation - it now\n\t  should return warning in case if message is not correctly\n\t  formatted\n\n2007-05-29 21:06  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Added\n\t  non-blocking method for inserting 'out' packets\n\n2007-05-29 21:05  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Protection from\n\t  infinite loop and self-locking\n\n2007-05-29 21:05  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqStats.java: Removed\n\t  replacing from address, now it is left as it was originally\n\n2007-05-29 21:04  kobit\n\n\t* src/main/java/tigase/stats/StatisticsCollector.java: Changed\n\t  GETSTATS result generation to just normal result sent directly to\n\t  requesting entity\n\n2007-05-29 09:29  kobit\n\n\t* scripts/tigase.sh: Fixed a problem with the script when it was\n\t  run on systems where /bin/sh was not a bash shell, now it\n\t  specifically requests that it must be run under bash, first line\n\t  modified to: #!/bin/bash\n\n2007-05-29 07:05  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java:\n\t  Added response feedback for new short news submition\n\n2007-05-29 06:59  kobit\n\n\t* build.properties, pom.xml: Version change to 2.9.2\n\n2007-05-29 06:58  kobit\n\n\t* src/main/java/tigase/stats/StatisticsCollector.java: Fixed\n\t  problem with infinite loop in MessageRouter for this GETSTATS\n\t  packet\n\n2007-05-28 12:52  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java,\n\t  win-stuff/Tigase.iss: Fixed default configuration generation for\n\t  external compoentns\n\n2007-05-28 12:51  kobit\n\n\t* database/postgresql-schema.sql: Removed extra comma\n\n2007-05-28 12:51  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Corrected the\n\t  order in which records are removed from database - according to\n\t  requirements of foreign keys constraints\n\n2007-05-28 10:54  kobit\n\n\t* win-stuff/Tigase.iss: Version update to 2.9.1\n\n2007-05-28 10:52  kobit\n\n\t* database/mysql-schema.sql,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCreationPolicy.java,\n\t  src/main/java/tigase/server/sreceiver/TaskType.java: Added task\n\t  creation configurable permissions\n\n2007-05-27 19:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java:\n\t  Moved posting permission checking from processMessage to\n\t  processPacket\n\n2007-05-27 19:43  kobit\n\n\t* src/main/java/tigase/server/sreceiver/RepoRosterTask.java: Added\n\t  verification if RosterItem is null before trying to remove it\n\t  from repository\n\n2007-05-27 19:42  kobit\n\n\t* src/main/java/tigase/server/sreceiver/NewsDistributor.java:\n\t  Changed constants from public to private\n\n2007-05-27 19:42  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Corrected indendation\n\n2007-05-27 19:41  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java: Removed unnecesary\n\t  local variable rs and finally section\n\n2007-05-27 19:40  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java:\n\t  The first version of short news publishing module\n\n2007-05-27 19:39  kobit\n\n\t* src/main/php/drupal/modules/short_news.module: The first version\n\t  of short_news module\n\n2007-05-27 19:39  kobit\n\n\t* src/main/php/drupal/modules/tigase.module: Moved license\n\t  information to proper place\n\n2007-05-27 19:37  kobit\n\n\t* build.properties, pom.xml: Version number change to 2.9.1\n\n2007-05-27 19:37  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql:\n\t  publishing_date remabed to publishing_time and added news_type\n\t  field and key\n\n2007-05-26 10:31  kobit\n\n\t* src/main/java/tigase/server/Permissions.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java,\n\t  src/main/java/tigase/server/ssender/DrupalForumTask.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Fixed comments and\n\t  texts containing JIDUtils instead of JID after JID class\n\t  refactoring\n\n2007-05-26 10:30  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql: Added\n\t  short_news table, comments and licence note\n\n2007-05-25 20:18  bmalkow\n\n\t* tigase-server:\n\n2007-05-25 11:36  bmalkow\n\n\t* src/main/java/tigase/auth/SaslPLAIN.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/Permissions.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommons.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java,\n\t  src/main/java/tigase/server/ssender/DrupalForumTask.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/RepositoryAccess.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: refactoring:\n\t  renaming java.util.JID to tigase.util.JIDUtils\n\n2007-05-25 11:24  kobit\n\n\t* etc/tigase-mysql.conf: Added drupal forum tasks\n\n2007-05-25 11:24  kobit\n\n\t* win-stuff/Tigase.iss: Version number change\n\n2007-05-24 21:46  kobit\n\n\t* src/main/java/tigase/server/ssender/DrupalForumTask.java: Task\n\t  implementation finished and seems to work fine\n\n2007-05-24 21:45  kobit\n\n\t* src/main/java/tigase/server/ssender/StanzaSender.java: Added\n\t  generator for forum tasks\n\n2007-05-24 21:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/TaskCommons.java: Added\n\t  more options for creating presence stanza: status, nick name\n\n2007-05-24 21:44  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java:\n\t  Replaced sender address with more actions: REPLACE, LEAVE,\n\t  REMOVE, some tweaking to presence format (added status), added\n\t  error message sent back if not authorized user tries to post a\n\t  message\n\n2007-05-24 21:43  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Added\n\t  forum tasks for automatic config generation\n\n2007-05-24 21:42  kobit\n\n\t* src/main/java/tigase/server/sreceiver/PropertyConstants.java:\n\t  Replaced sender address with more actions: REPLACE, LEAVE, REMOVE\n\n2007-05-24 06:25  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Replaced all _ in component names with -\n\n2007-05-24 06:25  kobit\n\n\t* src/main/java/tigase/server/ssender/StanzaSender.java: Changed\n\t  task name from nickname to full JID\n\n2007-05-24 06:25  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java: Replaced\n\t  all _ in component names with -\n\n2007-05-24 06:24  kobit\n\n\t* src/main/java/tigase/server/Packet.java: Added static method:\n\t  getMessage(...)\n\n2007-05-24 06:24  kobit\n\n\t* src/main/java/tigase/server/ssender/StanzaHandler.java: Added new\n\t  handler method: void handleStanzas(Queue<Packet> results)\n\n2007-05-24 06:23  kobit\n\n\t* src/main/java/tigase/server/ssender/DrupalForumTask.java: New\n\t  task for sending notifications about new posts on drupal forum\n\n2007-05-24 06:22  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Corrected\n\t  javadoc\n\n2007-05-23 12:50  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Added some\n\t  javadoc comments.\n\n2007-05-23 12:49  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Added some\n\t  javadoc comments.\n\n2007-05-23 11:38  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: removed\n\t  system.out.println statements\n\n2007-05-23 11:38  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: removed\n\t  printStackTrace statement\n\n2007-05-23 11:37  kobit\n\n\t* src/main/java/tigase/xmpp/RepositoryAccess.java: Indentation\n\t  corrected\n\n2007-05-23 11:36  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Improved\n\t  max_uid, max_nid handling to make more suitable for distributed\n\t  environmane\n\n2007-05-23 11:01  kobit\n\n\t* database/mysql-schema.sql: Added missing commas\n\n2007-05-22 22:25  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/RosterItem.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommons.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Subscribers management commands have been implemented now...\n\n2007-05-22 21:25  kobit\n\n\t* src/main/java/tigase/server/sreceiver/TaskCommons.java: Fixed\n\t  class name and added 2 more methods for presence and message\n\t  packet creation\n\n2007-05-22 21:23  kobit\n\n\t* src/main/java/tigase/server/sreceiver/TaskCommandCommons.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommons.java: Renamed\n\t  as more stuff will be put there\n\n2007-05-22 12:39  kobit\n\n\t* src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Subscription moderation is working now\n\n2007-05-22 12:34  kobit\n\n\t* src/main/java/tigase/auth/SaslPLAIN.java: Added some more\n\t  commends\n\n2007-05-21 23:05  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyConstants.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Task configuration editing command is now completed and working\n\t  fine\n\n2007-05-21 21:36  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyConstants.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommandCommons.java:\n\t  Task adding, deleting works fine now...\n\n2007-05-21 21:36  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql: Added\n\t  foreig key constraints to the schema...\n\n2007-05-21 21:35  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Fixed a serious\n\t  bug with database access when there were many instances of this\n\t  class trying to save data to database. max_uid, max_nid were out\n\t  of sync, hopefuly making them static solves the problem\n\n2007-05-21 06:01  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Added task deleting functionality\n\n2007-05-21 05:59  kobit\n\n\t* src/main/java/tigase/server/sreceiver/NewTaskCommand.java: Added\n\t  setting owner property to a value of the command sender\n\n2007-05-21 05:58  kobit\n\n\t* src/main/java/tigase/disco/ServiceEntity.java: Added removing\n\t  ServiceEntity node from the tree\n\n2007-05-21 05:56  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java:\n\t  Replaced ArrayList with LinkedList for statistics list\n\n2007-05-21 05:51  kobit\n\n\t* src/main/java/tigase/disco/ServiceEntity.java: Added removing\n\t  ServiceEntity node from the tree\n\n2007-05-19 08:34  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/DefaultValues.java,\n\t  src/main/java/tigase/server/sreceiver/NewTaskCommand.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyConstants.java,\n\t  src/main/java/tigase/server/sreceiver/PropertyItem.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/sreceiver/TaskCommandIfc.java,\n\t  src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java:\n\t  Command for adding new tasks has been fully implemented, task\n\t  management command has been started, a lot of minor improvements\n\n2007-05-19 08:32  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: --debug options is\n\t  aware now of multiple, comma separated packages, add component\n\t  command removes MessageRouter from the list of available\n\t  components, method checking validy of nickname has been moved to\n\t  JID class\n\n2007-05-19 08:30  kobit\n\n\t* scripts/tigase.sh: Improved 'run' command to behave similarly as\n\t  'start'- uses in the same way environment variables in quotes\n\n2007-05-19 08:29  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Moved addOutPackets(...) method to abstract class for convenience\n\n2007-05-19 08:28  kobit\n\n\t* src/main/java/tigase/server/Command.java: Added label to command\n\t  field\n\n2007-05-19 08:27  kobit\n\n\t* src/main/java/tigase/stats/StatisticsCollector.java: Added label\n\t  to command field\n\n2007-05-17 21:27  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: A few fixes for\n\t  creating new component\n\n2007-05-15 22:35  kobit\n\n\t* ant-definitions.xml: Added gentoo startup files to build package\n\n2007-05-15 22:34  kobit\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Removed\n\t  whitespaces\n\n2007-05-15 22:34  kobit\n\n\t* src/main/java/tigase/server/XMPPServer.java: Renamed main\n\t  component from tigase-xmpp-server to message-router\n\n2007-05-15 22:33  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java:\n\t  Corrected javadoc\n\n2007-05-15 22:33  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Jingle.java: Corrected javadoc\n\n2007-05-15 22:33  kobit\n\n\t* scripts/gentoo/init.d/tigase: Removed redundant variables\n\t  settings\n\n2007-05-15 22:13  kobit\n\n\t* scripts/gentoo, scripts/gentoo/conf.d,\n\t  scripts/gentoo/conf.d/tigase, scripts/gentoo/init.d,\n\t  scripts/gentoo/init.d/tigase, scripts/tigase.sh: Added tigase\n\t  startup scripts for Gentoo system\n\n2007-05-14 22:36  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Adding components at runtime with ad-hoc commands is now\n\t  completed\n\n2007-05-14 10:06  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java: Defined\n\t  more constants for class names for components\n\n2007-05-14 10:05  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Added\n\t  identity for task item service discovery\n\n2007-05-13 12:53  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Fixed a bug with\n\t  --admins setting and now component parameters are sorted on the\n\t  ad-hoc command list\n\n2007-05-12 23:59  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RepoRosterTask.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Roster\n\t  and Tasks are now stored in database and all states are\n\t  persistent\n\n2007-05-12 23:59  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Changed 'component' naming to 'plugin' naming which is more\n\t  appropriate and follows general naming convention in Tigase\n\t  project\n\n2007-05-12 23:58  kobit\n\n\t* src/main/java/tigase/db/RepositoryFactory.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/util/RepositoryUtils.java: Repository\n\t  instance is now stored separately for each component using it to\n\t  avoid multithreaded access to JDBC repository\n\n2007-05-12 23:57  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Added command line\n\t  options loading for all starting with '--gen-'\n\n2007-05-12 23:55  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java: Added more contants\n\t  commonly used by different components\n\n2007-05-12 09:41  kobit\n\n\t* src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RosterItem.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Subscription fully works, permissions for subscription and\n\t  posting messages work, posting and distributing messages works\n\n2007-05-11 23:25  kobit\n\n\t* build.properties, pom.xml: Version change to 2.9.0, this is kind\n\t  of alpha version with new features under development\n\n2007-05-11 23:23  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/RosterItem.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Subscription via presence wors in both ways now\n\n2007-05-11 18:58  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Basic\n\t  stuff related to service discovery for exiting task instances\n\t  works now\n\n2007-05-11 18:57  kobit\n\n\t* src/main/java/tigase/disco/ServiceEntity.java: Added a few dummy\n\t  javadoc comments, they will be filled with useful stuff later on\n\n2007-05-11 18:57  kobit\n\n\t* src/main/java/tigase/disco/XMPPService.java: Defined separate\n\t  constants for service discovery XMLNSes\n\n2007-05-11 18:20  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Initial code for service discovery for tasks instances\n\n2007-05-11 08:58  kobit\n\n\t* src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java,\n\t  src/main/java/tigase/server/sreceiver/NewsDistributor.java,\n\t  src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Initial implementation of receiver tasks\n\n2007-05-10 22:36  kobit\n\n\t* src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Almost\n\t  API definition finished, some initial code for loading\n\t  configuration is done\n\n2007-05-10 19:05  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added support in config generator for multiple external\n\t  components --ext-comp_1, --ext-comp_2 and so on...\n\n2007-05-09 09:51  kobit\n\n\t* src/main/java/tigase/server/sreceiver/StanzaReceiver.java: Added\n\t  more configuration options - replace sender address and message\n\t  type\n\n2007-05-09 09:40  kobit\n\n\t* src/main/java/tigase/server/sreceiver,\n\t  src/main/java/tigase/server/sreceiver/StanzaReceiver.java:\n\t  Initial version - just javadoc\n\n2007-05-08 23:09  kobit\n\n\t* win-stuff, win-stuff/Licence.txt, win-stuff/Tigase.ico,\n\t  win-stuff/Tigase.iss, win-stuff/scripts,\n\t  win-stuff/scripts/InstallTigaseService.bat,\n\t  win-stuff/scripts/Run.bat, win-stuff/scripts/Tigase.bat,\n\t  win-stuff/scripts/Uninst.bat,\n\t  win-stuff/scripts/UninstallTigaseService.bat, win-stuff/wrapper,\n\t  win-stuff/wrapper/wrapper.conf, win-stuff/wrapper/wrapper.dll,\n\t  win-stuff/wrapper/wrapper.exe: Windows installation packaging\n\t  files\n\n2007-05-08 11:22  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.7\n\n2007-05-08 11:18  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Fixed a bug\n\t  when the pluging didn't add 'from' attribute for authenticated\n\t  sessions and when the registration request was sent to\n\t  third-party entity like transport\n\n2007-05-07 21:44  kobit\n\n\t* src/main/java/tigase/xmpp/impl/BindResource.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqPrivate.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/main/java/tigase/xmpp/impl/SaslAuth.java,\n\t  src/main/java/tigase/xmpp/impl/SessionBind.java,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Added missing\n\t  disco-features, ticket #65: http://server.tigase.org/ticket/65\n\n2007-05-07 14:21  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Further\n\t  corrections to the fix for the transport registration\n\n2007-05-07 13:16  kobit\n\n\t* build.properties, etc/tigase-mysql.conf, pom.xml,\n\t  src/main/java/tigase/conf/Configurator.java: Version change to\n\t  2.8.6\n\n2007-05-07 12:07  kobit\n\n\t* src/main/java/tigase/server/Command.java: Fix for a bug for a\n\t  case when the command contains no node attribute\n\n2007-05-07 12:07  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqRegister.java: Corrections\n\t  to make it possible to register user in external transport\n\n2007-05-07 12:06  kobit\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Added one extra\n\t  empty line to make it more readable\n\n2007-05-04 09:38  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Corrected broken, not-compilable code\n\n2007-05-04 09:18  kobit\n\n\t* build.xml: Added UTF-8 encoding for the build file which is\n\t  default anyway\n\n2007-05-04 09:18  kobit\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Corrected UTF-8\n\t  character\n\n2007-05-04 09:17  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added autoCreateUser=true for connection string if Drupal or\n\t  LibreSource auth is used\n\n2007-05-03 09:37  kobit\n\n\t* src/main/php/drupal/modules/tigase.module: Corrected function\n\t  name\n\n2007-05-03 08:56  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqAuth.java: Corrected\n\t  indendation for the code\n\n2007-05-03 08:54  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqAuth.java: Corrected\n\t  indendation for the code\n\n2007-05-02 17:50  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.5\n\n2007-05-02 17:49  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Changed default configuration generation - for Drupal and\n\t  LibreSource jabber:iq:register is not loaded\n\n2007-05-01 16:20  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed fix ;-), corrected condition statement which decided when\n\t  send remote-server-not-found error\n\n2007-05-01 16:12  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Unknown domain error handling improved for dialback packets\n\n2007-05-01 16:07  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed a bug in s2s implementation for a remote servers connecting\n\t  from domain which doesn't exist in DNS. It caused infinite loop\n\n2007-05-01 08:57  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Direct presence bug\n\t  fixed - #63\n\n2007-04-30 14:49  kobit\n\n\t* src/main/java/tigase/auth/SaslPLAIN.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java: Changed back\n\t  to use plain plain passwords in LS database\n\n2007-04-30 14:29  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco/XMPPService.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Solved\n\t  problem with missing features for top level service discovery\n\n2007-04-30 14:29  kobit\n\n\t* scripts/tigase.sh: Indentation corrections\n\n2007-04-29 22:43  kobit\n\n\t* build.properties, pom.xml: Version number change to 2.8.4\n\n2007-04-29 22:38  kobit\n\n\t* pom.xml, src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Fixed a bug with\n\t  ping to virtual domain and error response to unsupported packets\n\n2007-04-29 21:32  kobit\n\n\t* ant-definitions.xml: Added ChangeLog file for binary distribution\n\n2007-04-26 21:57  kobit\n\n\t* ant-definitions.xml: Added database schema scripts for\n\t  distribution packages\n\n2007-04-26 06:21  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.3\n\n2007-04-25 19:02  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added urn:xmpp:ping plugin for standard loaded plugins\n\n2007-04-25 18:32  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Fixed a bug when\n\t  server was dropping unsupported stanzas addressed to the server\n\t  itself instead of returning feature-not-supported error\n\n2007-04-25 17:12  kobit\n\n\t* prj.el, src/main/java/tigase/xmpp/impl/JabberIqPrivate.java:\n\t  Fixed error message when user tries to access other user private\n\t  data\n\n2007-04-25 17:12  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Removed some extra debug logs\n\n2007-04-23 06:53  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed problem with connecting to all other than google servers,\n\t  apparently google is the only one which processes XML names\n\t  spaces correctly, (and now Tigase server does it correctly too)\n\n2007-04-23 06:13  kobit\n\n\t* ant-definitions.xml,\n\t  src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Attempt to\n\t  remove warnings related to redundant casting and UTF-8 encoding\n\n2007-04-21 15:11  kobit\n\n\t* src/main/php, src/main/php/drupal, src/main/php/drupal/modules,\n\t  src/main/php/drupal/modules/tigase.module: Drupal module for\n\t  better integration with Tigase system - adding real online-status\n\t  for drupal users\n\n2007-04-21 15:10  kobit\n\n\t* src/main/java/tigase/server/ssender,\n\t  src/main/java/tigase/server/ssender/FileTask.java,\n\t  src/main/java/tigase/server/ssender/JDBCTask.java,\n\t  src/main/java/tigase/server/ssender/SenderTask.java,\n\t  src/main/java/tigase/server/ssender/StanzaHandler.java,\n\t  src/main/java/tigase/server/ssender/StanzaSender.java: Initial\n\t  version of stanza sender framework - sending stanzas taken from\n\t  directory or database\n\n2007-04-21 14:52  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql,\n\t  etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Added xmpp_stanza table for StanzaSender JDBC task\n\n2007-04-18 07:00  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Update\n\t  svn:keywords\n\n2007-04-18 06:58  bmalkow\n\n\t* src/main/java/tigase/xmpp/impl/UrnXmppPing.java: Add\n\t  implementation of XEP-0199 (XMPP Ping)\n\n2007-04-16 18:59  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivate.java: Improved\n\t  error handling and handling the case when user doesn't send any\n\t  child element in query\n\n2007-04-16 10:03  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.2\n\n2007-04-16 10:03  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/xmpp/impl/VCardTemp.java: Minor cleanup and\n\t  refactoring - renamed mehtod parseVCard to parseXML\n\n2007-04-16 10:02  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqPrivate.java: Initial\n\t  version of private storage implementation\n\n2007-04-16 06:05  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.1\n\n2007-04-16 06:04  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Minor changes related to different namespace and prefixes\n\t  processing in xmltools\n\n2007-04-15 22:13  kobit\n\n\t* build.properties, pom.xml: Version change to 2.8.0\n\n2007-04-15 22:13  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java: Added\n\t  better handling for extra namespaces and element prefixes,\n\t  prefixes should be dripped now and default namespace should be\n\t  updated for element to correct one\n\n2007-04-15 20:29  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Added problem\n\t  handling for the case when user sends subscribe to buddy before\n\t  adding him to his roster using Roster functionality\n\n2007-04-15 19:15  kobit\n\n\t* pom.xml: Dependency to 2.6.0 xmltools added\n\n2007-04-13 22:40  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java:\n\t  Changed log message slightly to avoid confusing for packet which\n\t  don't have matching plugin and they don't have 'to' attribute\n\t  set, in such case error message is generated, instead of droping\n\t  packet\n\n2007-04-13 21:47  kobit\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: Correct support\n\t  for old vCard protocol\n\n2007-04-13 21:35  kobit\n\n\t* build.properties, pom.xml: Version change\n\n2007-04-13 21:35  kobit\n\n\t* src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqIq.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/SimpleForwarder.java: Minor\n\t  modifications related to clone() method change in xmltools which\n\t  now returns Element to avoid type casting\n\n2007-04-13 21:28  kobit\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: Small change to\n\t  make it compatible with old vCard spec where element name was all\n\t  uppercase, clone() method in xmltools has been changed so the\n\t  class has been changed to reflect it\n\n2007-04-12 13:31  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added capabilities to presence information for USER_STATUS\n\t  command\n\n2007-04-10 16:22  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  fixed problem with initial presence for session activated by\n\t  external component\n\n2007-04-10 14:28  kobit\n\n\t* database/postgresql-schema.sql, scripts/repo.sh: Updated user\n\t  repository access files\n\n2007-04-10 14:27  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixed a bug where --test configuration was always generated\n\n2007-04-04 21:39  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Fixed problem with default configuration generation for component\n\t  names session_1/sess_man\n\n2007-04-04 21:27  kobit\n\n\t* build.properties, pom.xml: Version change\n\n2007-04-04 21:26  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Fixed bug in generating default configuration, sess_man instead\n\t  of session_1\n\n2007-04-04 20:05  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Changed default\n\t  logging level for console output\n\n2007-04-04 20:00  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Removed remote_host global class variable\n\n2007-04-04 07:53  kobit\n\n\t* pom.xml: Dependecies updated for new xmltools version 2.5.0\n\n2007-04-03 21:08  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Modified default config generation, routing part is generated\n\t  automatically\n\n2007-04-03 18:42  kobit\n\n\t* build.properties, pom.xml: Version number change to 2.7.1\n\n2007-04-03 18:42  kobit\n\n\t* src/main/java/tigase/server/AbstractMessageReceiver.java: Moved\n\t  time constants to parent class\n\n2007-04-03 18:42  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added config wizard option to automaticly pick-up external\n\t  component domain\n\n2007-04-03 18:41  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Moved time\n\t  constants to parent class\n\n2007-04-03 18:40  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Uptime statistics\n\t  added\n\n2007-04-03 18:39  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Changed default\n\t  logging levels for normal mode, test and debug\n\n2007-04-02 12:48  kobit\n\n\t* prj.el,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  added test mode to SM so it loads different set of plugins in\n\t  test mode, this is necessary to avoid interfrence with other\n\t  functionalities during tests\n\n2007-04-02 12:45  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Removed depreciated\n\t  and commented-out code\n\n2007-03-31 21:47  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Spelling\n\t  corrections and default config params slightly changed\n\n2007-03-30 22:50  kobit\n\n\t* pom.xml: Version dependencies update\n\n2007-03-30 22:48  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added Long/long data types for configuration storage and max\n\t  waiting time for packet parameter is back in configuration\n\n2007-03-30 22:21  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java: Deprecated\n\t  ServiceDiscovery class and removed loading disco from default\n\t  configuration, it is no longer used and needed\n\n2007-03-30 22:15  kobit\n\n\t* build.properties, pom.xml,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Temporarly disabled configuration option to set timeout for\n\t  waiting packets in s2s component\n\n2007-03-30 21:23  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Implemented timeout for packets sent through s2s, if Tigase can\n\t  not connect to remote server for some specified time it giveup\n\t  and returns all packages back to sender\n\n2007-03-30 21:21  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added 'XEP-0114' string to component name to avoid confusion\n\n2007-03-30 09:12  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco/ServiceEntity.java,\n\t  src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/MessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Final fixes\n\t  for service discovery and cluster management framework\n\n2007-03-28 06:18  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco/ServiceEntity.java,\n\t  src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/ServerComponent.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Changes in\n\t  service-disco layer to allow return correct info from instances\n\t  where SM is not available\n\n2007-03-20 23:05  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Corrected max reconnects value handling\n\n2007-03-20 22:53  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added remote hostname information to service discovery\n\n2007-03-20 22:52  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java: Fixed problem with\n\t  configuration file initialization\n\n2007-03-20 20:50  kobit\n\n\t* src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java: Changed JDBC\n\t  connection validation query to some more efficient\n\n2007-03-20 20:49  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Start of service-disco implementation for external component\n\n2007-03-20 00:04  kobit\n\n\t* src/main/java/tigase/db/jdbc/LibreSourceAuth.java: Added proper\n\t  code for add/remove user and update user password\n\n2007-03-19 23:24  kobit\n\n\t* src/main/java/tigase/db/UserAuthRepository.java,\n\t  src/main/java/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/main/java/tigase/db/jdbc/DrupalAuth.java,\n\t  src/main/java/tigase/db/jdbc/JDBCRepository.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/db/xml/XMLRepository.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added support for logout() event to database backend so Tigase\n\t  may now write presence status to database. It allows other\n\t  systems display online status. Currently it is implemented in\n\t  LibreSource connector only\n\n2007-03-19 17:21  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/net/ConnectionOpenThread.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixes for problems with reconfiguration at runtime, now it is\n\t  also even possible to switch on/off components, add new\n\t  components, add/remove TCP/IP port listeners and so on....\n\n2007-03-14 12:06  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added fix for proper handling malformed dialback requests sent by\n\t  very old jabber servers\n\n2007-03-13 10:56  kobit\n\n\t* src/main/java/tigase/auth/SaslPLAIN.java,\n\t  src/main/java/tigase/db/jdbc/LibreSourceAuth.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Implementation of authentication agains LibreSource database is\n\t  completed - this is simple implementation, just authentication\n\t  and nothing more\n\n2007-03-13 10:55  kobit\n\n\t* src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Started implementation for service-discovery support\n\n2007-03-13 10:54  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added fix for\n\t  a bug when service is stopped in accept method\n\n2007-03-12 16:03  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed a problem with connection stopped in accept method, no\n\t  retry was performed then\n\n2007-03-12 15:55  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Fixed problem\n\t  when stop is called afer unssuccesful accept call\n\n2007-03-12 15:48  kobit\n\n\t* src/main/java/tigase/net/IOService.java: Fixed problem when stop\n\t  is called afer unssuccesful accept call\n\n2007-03-12 15:41  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added fix for the case when connection is lost before handshaking\n\t  has started, like exception in accept phase\n\n2007-03-12 12:27  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java: Fixed\n\t  packet filter delivering packet to proper active resource - now\n\t  it behaves as described in RFC\n\n2007-03-12 11:56  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Commented out code for stop-other service and added proper\n\t  handling for case when packet write to socket was unsuccessful\n\n2007-03-10 22:50  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added proper handling for the situation when accept connection is\n\t  closed before handshaking has been completed\n\n2007-03-10 22:45  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Changed the order in which packets are sent, first all waiting\n\t  controll ackets, next db:result on connect\n\n2007-03-10 15:53  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added one more logging messgae to detect whether stopping old\n\t  connection is really an issue\n\n2007-03-10 15:50  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed problem with initializing new connection for remote server\n\t  when old connection still seems active\n\n2007-03-07 11:28  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Another fix for asynchronous dialback processing\n\n2007-03-07 11:14  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  BIG, BIG bug fixed finally\n\n2007-03-07 09:54  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Even more logging to track down opening extra s2s connections\n\n2007-03-06 22:35  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed bug in processing results from processDialback method,\n\t  after this method is finished service may be available in either\n\t  handsahking or established Map\n\n2007-03-06 22:12  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added more logging for dialback verification results\n\n2007-03-06 21:38  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Implementation for invalid dialback verification\n\n2007-03-06 15:33  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added diagnostic logs for stream opening - possible multiple\n\t  stream open calls\n\n2007-03-06 15:08  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added logging for all dialback handshaking\n\n2007-03-06 14:38  kobit\n\n\t* src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java,\n\t  src/main/java/tigase/xmpp/impl/Roster.java: Proper handling of\n\t  presence error in case of s2s can't send it to destination\n\t  address (or it should be just ignored)\n\n2007-03-06 13:46  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Added synchronization to service stopped handler\n\n2007-03-05 23:01  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed disconnection other dialback connection method and added\n\t  more logging info\n\n2007-03-05 21:37  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added logging\n\t  messages to watchdog\n\n2007-03-05 21:03  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Fixed log\n\t  message position, put in wrong place by mistake\n\n2007-03-05 20:51  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Added parameter about the maximum iddle time for connection\n\n2007-03-05 20:51  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPIOService.java: Added last transfer\n\t  timestamp information\n\n2007-03-05 20:49  kobit\n\n\t* src/main/java/tigase/server/MessageRouter.java: Removed DNS\n\t  resolving from message router\n\n2007-03-05 20:48  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Added\n\t  connection watchdog thread\n\n2007-03-05 20:48  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Full support for stream:error, detecting improper hosts in\n\t  sender/receiver stanza addreses\n\n2007-03-05 10:00  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: A few corrections\n\t  in IO/NET/SERVICES - check whether service ID is no duplicated\n\n2007-03-02 13:58  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  All handshaking connections are now also dumped to log file on\n\t  request\n\n2007-03-02 12:23  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Added extra logging\n\t  to detect s2s problems\n\n2007-03-01 11:10  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed a bug in s2s which caused automatic reconnecting s2s\n\t  connection even if it was not necessary\n\n2007-03-01 04:02  kobit\n\n\t* src/main/java/tigase/io/SocketIO.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Fixed a bug with\n\t  logging data buffer which is NULL\n\n2007-03-01 00:05  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Added extra log message\n\n2007-02-28 23:54  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Proper handling of stream:error in s2s\n\n2007-02-28 23:39  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Proper error response added if user account does not exist\n\n2007-02-28 23:25  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Proper error\n\t  response added if user account does not exist\n\n2007-02-28 21:59  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Fixed code for reconnecting s2s service if the first attempt was\n\t  unsuccessful\n\n2007-02-28 21:27  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Some fixes to s2s\n\t  implementation - retrying to connect if first try was\n\t  unsuccessfull and fixed a bug in IOService in stop() method -\n\t  handler is called in finally clausule\n\n2007-02-28 13:31  kobit\n\n\t* src/main/java/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  List of connected servers is now sorted to make it easier to find\n\t  particular connection\n\n2007-02-28 13:11  kobit\n\n\t* src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/ConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/stats/StatRecord.java,\n\t  src/main/java/tigase/stats/StatisticType.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: More\n\t  statistics about network connections and packet waiting in s2s\n\t  queues\n\n2007-02-27 23:04  kobit\n\n\t* src/main/java/tigase/xmpp/impl/JabberIqIq.java: Just for fun\n\n2007-02-22 23:04  kobit\n\n\t* etc/tigase-mysql.conf,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Solved initial\n\t  presence broadcating problem for many resources connected\n\n2007-02-22 00:07  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Jingle.java: Added session element\n\n2007-02-21 23:33  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/Jingle.java: Support for jingle in\n\t  Yate added\n\n2007-02-21 22:08  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  USER_STATUS - presence status fixed\n\n2007-02-21 22:00  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticType.java: USER_STATUS\n\t  processing command moved to different place\n\n2007-02-15 06:52  kobit\n\n\t* build.properties, pom.xml: Version change to 2.6.4\n\n2007-02-15 06:51  kobit\n\n\t* src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco/XMPPService.java,\n\t  src/main/java/tigase/server/AbstractMessageReceiver.java,\n\t  src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatRecord.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java: Improved\n\t  ad-hoc commands for configuration settings and statistics\n\t  retrieval\n\n2007-02-14 10:37  kobit\n\n\t* build.properties, pom.xml: Version number change\n\n2007-02-14 09:44  kobit\n\n\t* src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Fixed a bug with\n\t  UTF-8 encoder/decoder for network data\n\n2007-02-13 23:50  kobit\n\n\t* build.properties, pom.xml,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/server/AbstractComponentRegistrator.java,\n\t  src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Reconfiguration at\n\t  run-time ready - not well tested yet\n\n2007-02-12 14:25  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java:\n\t  Corrected handling stanzas: <iq type='result'/>\n\n2007-02-12 14:03  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Presence update to\n\t  other user accounts corrected - attributes from/to where set\n\t  incorrectly\n\n2007-02-12 12:04  kobit\n\n\t* src/main/java/tigase/xmpp/XMPPSession.java,\n\t  src/main/java/tigase/xmpp/impl/Presence.java: Resource priority\n\t  is now set correctly and message to account with multiple active\n\t  resources is handled properly\n\n2007-02-11 20:58  kobit\n\n\t* build.properties, pom.xml,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/disco,\n\t  src/main/java/tigase/disco/ServiceEntity.java,\n\t  src/main/java/tigase/disco/ServiceIdentity.java,\n\t  src/main/java/tigase/disco/XMPPService.java,\n\t  src/main/java/tigase/disco/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/MessageRouterConfig.java,\n\t  src/main/java/tigase/server/ServiceEntity.java,\n\t  src/main/java/tigase/server/ServiceIdentity.java,\n\t  src/main/java/tigase/server/XMPPService.java,\n\t  src/main/java/tigase/server/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/main/java/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java: Service\n\t  discovery API changed and small refactoring to move all disco\n\t  related classes to separate package\n\n2007-02-11 20:53  kobit\n\n\t* src/main/java/tigase/xmpp/impl/VCardTemp.java: Fixed a bug\n\t  related to strange stanza when user session is null....\n\n2007-02-11 14:06  kobit\n\n\t* src/main/java/tigase/conf/Configurable.java,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/server/AbstractComponentRegistrator.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/ServiceEntity.java,\n\t  src/main/java/tigase/server/ServiceIdentity.java,\n\t  src/main/java/tigase/server/XMPPServer.java,\n\t  src/main/java/tigase/server/XMPPService.java,\n\t  src/main/java/tigase/server/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/stats/StatisticsContainer.java: New service\n\t  discovert API\n\n2007-02-08 11:30  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Fixed problem with\n\t  initial presence after subscription, server used to send presnece\n\t  without resource part, Thank to Daniele for the fix\n\n2007-02-07 23:34  kobit\n\n\t* src/main/java/tigase/io/TLSEventHandler.java,\n\t  src/main/java/tigase/io/TLSIO.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/io/TelnetClient.java,\n\t  src/main/java/tigase/io/TelnetServer.java,\n\t  src/main/java/tigase/net/IOService.java,\n\t  src/main/java/tigase/xmpp/XMPPIOService.java: Fixed socket write\n\t  method for TLS connection, bug causing possible data loss for\n\t  large buffers, Gajim still inserts line-breaks in the middle of\n\t  large buffer, somewhere near 16k data block\n\n2007-02-04 22:43  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java: More components\n\t  depreciated due to PacketFilter use\n\n2007-02-04 18:19  bmalkow\n\n\t* pom.xml: add maven release plugin configuration\n\n2007-02-03 17:15  kobit\n\n\t* src/main/java/tigase/server/XMPPServer.java,\n\t  src/main/java/tigase/server/XMPPServiceCollector.java: Added\n\t  server version information to service discovery\n\n2007-02-03 09:25  kobit\n\n\t* build.properties, pom.xml: Version change\n\n2007-02-03 09:23  kobit\n\n\t* src/main/java/tigase/server/xmppsession/SessionManager.java: Fix\n\t  for the bug introduced by PacketFilter caused to ignore privacy\n\t  lists\n\n2007-02-02 16:20  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java: Fixed\n\t  a problem with NullPointerException when there is no 'from'\n\t  attribute in PacketFilter\n\n2007-02-02 16:10  kobit\n\n\t* build.xml,\n\t  src/main/java/tigase/server/xmppsession/PacketFilter.java: Fixed\n\t  a problem with NullPointerException when there is no 'to'\n\t  attribute in PacketFilter\n\n2007-02-02 15:47  kobit\n\n\t* src/main/java/tigase/server/xmppsession/PacketFilter.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/xmpp/impl/IBB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/main/java/tigase/xmpp/impl/Message.java: Introduced\n\t  PacketFilter in place of SimpleForwarder\n\n2007-02-02 11:33  kobit\n\n\t* .classpath, .project, .settings: Removed eclipse configuration\n\t  files to avoid overwriting other developers eclipse settings\n\n2007-02-02 11:09  kobit\n\n\t* src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed problem with incorrectly sent stream features\n\n2007-01-28 17:28  kobit\n\n\t* etc/tigase-mysql.conf, etc/tigase-pgsql.conf: sample\n\t  configuration file improved - added sample db connection uri\n\n2007-01-28 17:02  kobit\n\n\t* src/main/assembly/prodenv.xml: Removed some scripts not needed by\n\t  the user\n\n2007-01-28 16:02  bmalkow\n\n\t* pom.xml: fix error in dependency\n\n2007-01-28 15:54  kobit\n\n\t* etc, etc/tigase-mysql.conf, etc/tigase-pgsql.conf,\n\t  etc/tigase.conf, scripts/tigase.sh,\n\t  src/main/assembly/prodenv.xml: Configuration changed to better\n\t  integrate with maven\n\n2007-01-28 12:32  bmalkow\n\n\t* pom.xml: add version in package filename\n\n2007-01-28 12:17  bmalkow\n\n\t* pom.xml: add 'optional' attribute in dependency\n\n2007-01-28 12:04  bmalkow\n\n\t* pom.xml, src/main/assembly, src/main/assembly/prodenv.xml: add\n\t  simple assembly goal config\n\n2007-01-27 08:28  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Removed some\n\t  cache calls - calls for specific data items where cache was not\n\t  working correctly\n\n2007-01-26 22:22  kobit\n\n\t* database/mysql-schema.sql, database/postgresql-schema.sql,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Fixed problem with default auth-db-url if set only user-db-url\n\n2007-01-26 21:07  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Changed cache\n\t  size back to 10000\n\n2007-01-26 16:29  kobit\n\n\t* src/main/java/tigase/db/jdbc/JDBCRepository.java: Increased cache\n\t  size\n\n2007-01-26 11:57  kobit\n\n\t* src/main/java/tigase/server/ConnectionManager.java: Allow\n\t  component reconnection for about 1000h and then giveup\n\n2007-01-26 08:44  kobit\n\n\t* src/main/java/tigase/server/Permissions.java,\n\t  src/main/java/tigase/server/xmppsession/Permissions.java: Moved\n\t  to right location\n\n2007-01-25 23:18  kobit\n\n\t* build.properties, pom.xml, prj.el,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/server/Command.java,\n\t  src/main/java/tigase/server/MessageRouter.java,\n\t  src/main/java/tigase/server/Packet.java,\n\t  src/main/java/tigase/server/XMPPService.java,\n\t  src/main/java/tigase/server/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/main/java/tigase/server/xmppsession/Permissions.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/main/java/tigase/stats/StatisticsCollector.java,\n\t  src/main/java/tigase/xmpp/XMPPImplIfc.java,\n\t  src/main/java/tigase/xmpp/XMPPProcessor.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqCommand.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/main/java/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/main/java/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/main/java/tigase/xmpp/impl/StartTLS.java: ad-hoc commands,\n\t  service discovery, Yate integration first step\n\n2007-01-25 21:05  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: incoming direct\n\t  availability presence now allowed even if remote entity is not in\n\t  roster - required for MUC\n\n2007-01-25 14:56  kobit\n\n\t* src/main/java/tigase/xmpp/impl/Presence.java: Sending direct\n\t  presence bug fixed now\n\n2007-01-24 09:27  bmalkow\n\n\t* .classpath, pom.xml: fix errors in maven configuration\n\n2007-01-20 19:35  bmalkow\n\n\t* pom.xml: add deploy information to maven config\n\n2007-01-20 18:46  kobit\n\n\t* src/main/java/tigase/io/TLSWrapper.java: Indentation corrected\n\n2007-01-20 18:38  kobit\n\n\t* src/main/java/tigase/io/TLSWrapper.java: Indentation corrected\n\n2007-01-20 18:12  kobit\n\n\t* build.properties, build.xml,\n\t  src/main/java/tigase/conf/Configurator.java,\n\t  src/main/java/tigase/io/TLSWrapper.java,\n\t  src/main/java/tigase/server/XMPPService.java,\n\t  src/main/java/tigase/server/XMPPServiceCollector.java,\n\t  src/main/java/tigase/server/xmppsession/SessionManager.java,\n\t  src/main/java/tigase/xmpp/impl/ServiceDiscovery.java: service\n\t  discovery-items and ad-hoc command for configuration in progress\n\n2007-01-20 17:59  bmalkow\n\n\t* ., .classpath, .project, .settings,\n\t  .settings/org.eclipse.jdt.core.prefs,\n\t  .settings/org.eclipse.jdt.ui.prefs, pom.xml, src/main,\n\t  src/main/java, src/main/java/tigase, src/test, src/test/java,\n\t  src/tigase: convert to maven2 nature\n\n2007-01-19 17:37  kobit\n\n\t* src/tigase/server/Command.java, src/tigase/server/Packet.java:\n\t  Modified command so now command id is in node attribute instead\n\t  of action\n\n2007-01-19 10:28  kobit\n\n\t* scripts/tigase.sh, src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java: Number\n\t  of changes, but the most important related do confifuration\n\t  generation\n\n2007-01-17 00:55  kobit\n\n\t* src/tigase/server/Command.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/xmpp/StanzaType.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/StartTLS.java: Switched to ad-hoc command\n\t  for communication between components and implemented USER_STATUS\n\t  command. Update from xmltools is requiredsvn status\n\n2007-01-15 17:26  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatRecord.java: Added repository information to\n\t  statuses\n\n2007-01-15 17:10  kobit\n\n\t* src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/db/UserRepository.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java: Added methods to retrieve\n\t  repository URI\n\n2007-01-14 02:25  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java: Changed stats\n\t  implementation to conform XEP-39\n\n2007-01-13 22:12  kobit\n\n\t* prj.el, src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/tigase/xmpp/impl/IBB.java,\n\t  src/tigase/xmpp/impl/JabberIqOOB.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqSi.java,\n\t  src/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/SimpleForwarder.java: File transfer protocol\n\t  implemented\n\n2007-01-12 17:16  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java: Fixed bug with\n\t  processing incorrect Roster stanza\n\n2007-01-11 22:44  kobit\n\n\t* src/tigase/server/ConnectionManager.java: Added more detailed\n\t  loggin info\n\n2007-01-11 22:41  kobit\n\n\t* scripts/tigase.sh, src/tigase/server/ConnectionManager.java:\n\t  Added more detailed loggin info\n\n2007-01-09 06:16  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Removed packing stanza into routed packet - not needed anymore??\n\n2007-01-08 23:40  kobit\n\n\t* database/postgresql-schema.sql: Postgresql DB schema\n\n2007-01-07 23:08  kobit\n\n\t* ant-definitions.xml, build.xml, manifest.temp: Build scripts\n\t  slightly changed to not force user to have svn tools installed\n\t  separately\n\n2006-12-18 16:38  kobit\n\n\t* scripts/config.sh, scripts/repo.sh,\n\t  src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/xmpp/XMPPDomBuilderHandler.java: Corrected support for\n\t  IDN domain names\n\n2006-12-18 10:29  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java: Set autocommit to true\n\t  for JDBC connection\n\n2006-12-17 23:42  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Component protocol (JEP-114) implemented - untested\n\n2006-12-17 23:05  kobit\n\n\t* src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/impl/Privacy.java: Privacy lists management a few\n\t  bugs fixed\n\n2006-12-17 15:31  kobit\n\n\t* src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Fixed nullpointer exception bug in authorizatin module\n\n2006-12-17 15:21  kobit\n\n\t* src/tigase/server/xmppserver/ServerConnectionManager.java: Fixed\n\t  problem with command processing - temporarly, no command are\n\t  processed by this component for now\n\n2006-12-15 12:44  kobit\n\n\t* src/tigase/auth/LoginHandler.java,\n\t  src/tigase/auth/ResourceConnectionCallback.java,\n\t  src/tigase/auth/SaslPLAIN.java,\n\t  src/tigase/auth/TigaseSaslProvider.java,\n\t  src/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/tigase/db/AuthorizationException.java,\n\t  src/tigase/db/DBInitException.java,\n\t  src/tigase/db/NonAuthUserRepository.java,\n\t  src/tigase/db/RepositoryFactory.java,\n\t  src/tigase/db/TigaseDBException.java,\n\t  src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/io/BufferUnderflowException.java,\n\t  src/tigase/io/IOInterface.java,\n\t  src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/SampleSocketThread.java,\n\t  src/tigase/io/SocketIO.java, src/tigase/io/TLSIO.java,\n\t  src/tigase/io/TLSStatus.java, src/tigase/io/TLSUtil.java,\n\t  src/tigase/io/TLSWrapper.java, src/tigase/io/TelnetClient.java,\n\t  src/tigase/io/TelnetServer.java, src/tigase/net/Accept.java,\n\t  src/tigase/net/ConnectionOpenListener.java,\n\t  src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/net/ConnectionType.java,\n\t  src/tigase/net/IOServiceListener.java,\n\t  src/tigase/net/SocketReadThread.java,\n\t  src/tigase/net/SocketType.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/Command.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/tigase/stats/StatRecord.java,\n\t  src/tigase/stats/StatisticType.java,\n\t  src/tigase/util/ElementUtils.java,\n\t  src/tigase/util/LogFormatter.java,\n\t  src/tigase/util/RepositoryUtils.java,\n\t  src/tigase/util/RoutingsContainer.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/StanzaType.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPIOServiceListener.java,\n\t  src/tigase/xmpp/XMPPImplIfc.java,\n\t  src/tigase/xmpp/XMPPPostprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPPreprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/XMPPStopListenerIfc.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/Privacy.java,\n\t  src/tigase/xmpp/impl/Roster.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java,\n\t  src/tigase/xmpp/impl/VCardTemp.java: e-mail address corrected\n\n2006-12-15 12:38  kobit\n\n\t* prj.el:\n\n2006-12-15 12:18  kobit\n\n\t* prj.el, src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/io/SSLContextContainer.java: Now uses own Tigase\n\t  implementation of Base64\n\n2006-12-14 15:49  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Some fixes in implementation, work not finished yet but it\n\t  compiles\n\n2006-12-14 15:49  kobit\n\n\t* src/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java: Corrections related to\n\t  JDK-1.6 version change\n\n2006-12-14 15:32  kobit\n\n\t* build.properties: Version number change to 2.3.4\n\n2006-12-14 15:32  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  XEP-114 coponent protocol implementation in progress\n\n2006-12-14 15:31  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/Privacy.java: Active/default list is kept in\n\t  user session data to improve performance\n\n2006-12-14 15:30  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java: Increased cache size to\n\t  10k elements, cache.remove() has been improved so now\n\t  cache.clear() is replaced with cache.remove(user_id)\n\n2006-12-13 23:29  kobit\n\n\t* src/tigase/io/SSLContextContainer.java: Now adding all ICA\n\t  certificates for each domain keystore\n\n2006-12-13 12:52  kobit\n\n\t* certs/rsa-keystore: Dummy certificate\n\n2006-12-13 12:50  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/Privacy.java: Fixed a few minor bugs in\n\t  privacy lists management\n\n2006-12-13 12:50  kobit\n\n\t* src/tigase/io/SSLContextContainer.java: Fixed problem with loadin\n\t  certain types of certificates\n\n2006-12-10 19:22  kobit\n\n\t* src/tigase/server/xmppserver/ServerConnectionManager.java: vHosts\n\t  bug in s2s fixed now\n\n2006-12-10 15:49  kobit\n\n\t* build.properties,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java: vHosts\n\t  for s2s bug fixed\n\n2006-12-05 19:17  kobit\n\n\t* build.xml: Fixed build numbering problem\n\n2006-12-05 19:17  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: Fixed problem with sending\n\t  initial presence from all active resources\n\n2006-12-04 23:52  kobit\n\n\t* certs/rsa-keystore, src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/TLSUtil.java, src/tigase/io/TelnetClient.java,\n\t  src/tigase/io/TelnetServer.java,\n\t  src/tigase/server/ConnectionManager.java: Default certificate now\n\t  implemented, SSL uses default and TLS uses default if certificate\n\t  for selected domain does not exist\n\n2006-12-03 21:55  kobit\n\n\t* certs/rsa-keystore, src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/TLSUtil.java, src/tigase/io/TelnetClient.java,\n\t  src/tigase/io/TelnetServer.java, src/tigase/net/IOService.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Implemented support for vHosts certificates\n\n2006-11-29 23:31  kobit\n\n\t* build.properties: Version change to 2.3.2\n\n2006-11-29 23:31  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java: Removed all\n\t  synchronization code from the implementation as the class is\n\t  intended to use in single thread\n\n2006-11-29 15:45  kobit\n\n\t* build.properties: Version change\n\n2006-11-29 15:05  kobit\n\n\t* src/tigase/server/AbstractMessageReceiver.java: Fixed dead lock\n\t  problem on multi-cpu machines - replaced single thread/queue with\n\t  2 queues and a thread for each\n\n2006-11-29 15:04  kobit\n\n\t* src/tigase/server/ConnectionManager.java: Changed loging level\n\t  for case when service for packet can not be found\n\n2006-11-29 15:03  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java: Changed loging\n\t  level for case when session can not be found\n\n2006-11-29 15:03  kobit\n\n\t* src/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Removed commented import statement\n\n2006-11-29 15:02  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java: Added synchronization\n\t  code around checking connection code\n\n2006-11-29 15:02  kobit\n\n\t* src/tigase/conf/Configurator.java: Added some more test code to\n\t  change logging level after some timeout to diagnoze lockup\n\t  problem\n\n2006-11-29 15:01  kobit\n\n\t* src/tigase/xmpp/RepositoryAccess.java: Changed loggin level from\n\t  warning to finest for usernotfound exception\n\n2006-11-27 21:39  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java: Wrapped cache object in\n\t  synchronized Map\n\n2006-11-27 14:38  kobit\n\n\t* src/tigase/util/SimpleCache.java: Moved to tigase-util subproject\n\n2006-11-26 23:42  kobit\n\n\t* build.properties: Version change\n\n2006-11-26 23:02  kobit\n\n\t* ant-definitions.xml, build.xml: Modied build system to\n\t  automatically create MANIFEST file\n\n2006-11-26 22:43  kobit\n\n\t* MANIFEST.MF: Removed file which is automatically generated for\n\t  each JAR file\n\n2006-11-26 22:43  kobit\n\n\t* MANIFEST.MF: Version change\n\n2006-11-26 22:42  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml, build.xml, package.html,\n\t  scripts/tigase.sh, src/tigase/db/jdbc/DrupalAuth.java: Added\n\t  timestamp for login and last access in Drupal database\n\n2006-11-26 22:41  kobit\n\n\t* src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/util/SimpleCache.java: Added simple caching for JDBC\n\t  connector\n\n2006-11-25 08:50  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml: Modified building function to\n\t  include new startup script\n\n2006-11-20 00:16  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed a bug with improperly handling disconnection in case of\n\t  user unregistration\n\n2006-11-18 19:30  kobit\n\n\t* MANIFEST.MF, src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Implemented fix for long\n\t  lasting and idle jdbc connection disconnection from server side\n\n2006-11-18 16:57  kobit\n\n\t* src/tigase/xmpp/impl/SaslAuth.java: Ticket #35:\n\t  http://server.tigase.org/ticket/35, removed printing tacktrace\n\t  into standatd output\n\n2006-11-16 12:50  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/Configurator.java,\n\t  src/tigase/db/RepositoryFactory.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/util/RepositoryUtils.java: Fixed many small bugs found\n\t  during migration to Drupal\n\n2006-11-16 12:50  kobit\n\n\t* src/tigase/auth/SaslPLAIN.java: fixed the problem with the case\n\t  when client doesn't send authorization ID\n\n2006-11-14 22:32  kobit\n\n\t* MANIFEST.MF, scripts/tigase.sh: Statrup script added\n\n2006-11-13 23:02  kobit\n\n\t* MANIFEST.MF, src/tigase/util/RepositoryUtils.java: Added more\n\t  options and repository tests\n\n2006-11-13 23:02  kobit\n\n\t* src/tigase/db/xml/XMLRepository.java: JavaDoc fix\n\n2006-11-13 23:02  kobit\n\n\t* src/tigase/db/RepositoryFactory.java: Fixed problem with multiple\n\t  repository initialization for the same resource\n\n2006-11-13 21:01  kobit\n\n\t* src/tigase/db/xml/XMLRepository.java: Fixed the problem with\n\t  repository initialization on fresh installation where XML user\n\t  repo does not exist\n\n2006-11-12 19:25  kobit\n\n\t* MANIFEST.MF, src/tigase/util/RepositoryUtils.java: Added support\n\t  for UserAuthRepository\n\n2006-11-12 19:25  kobit\n\n\t* src/tigase/db/jdbc/DrupalAuth.java: addUser() implementation\n\t  added and checking for user status in drupal database\n\n2006-11-12 13:46  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/SaslPLAIN.java,\n\t  src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/UserAuthRepositoryImpl.java,\n\t  src/tigase/db/jdbc/DrupalAuth.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Authorization framework is\n\t  finished and polished, drupal authentication is implemented and\n\t  workssvn add src/tigase/db/UserAuthRepositoryImpl.java\n\t  src/tigase/db/jdbc/DrupalAuth.java\n\n2006-11-11 20:28  kobit\n\n\t* MANIFEST.MF, certs/rsa-keystore, scripts/repo.sh,\n\t  src/tigase/auth/SaslPLAIN.java,\n\t  src/tigase/auth/TigaseSaslProvider.java,\n\t  src/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/tigase/db/AuthorizationException.java,\n\t  src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Authorization framework\n\t  rewriten again, it works but not well tested\n\n2006-11-06 23:58  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/CommitHandler.java,\n\t  src/tigase/auth/DigestAuth.java,\n\t  src/tigase/auth/LoginHandler.java,\n\t  src/tigase/auth/PlainAuth.java,\n\t  src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/auth/SaslPLAIN.java,\n\t  src/tigase/auth/SessionCallback.java,\n\t  src/tigase/auth/TigaseConfiguration.java,\n\t  src/tigase/auth/TigaseSasl.java,\n\t  src/tigase/auth/TigaseSaslProvider.java,\n\t  src/tigase/auth/TigaseSaslServerFactory.java,\n\t  src/tigase/db/RepositoryFactory.java,\n\t  src/tigase/db/UserAuthRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/tigase/util/RepositoryUtils.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Authorization framework\n\t  rewritten and PLAIN SASL implemented\n\n2006-11-06 22:18  kobit\n\n\t* src/tigase/auth/TigaseSasl.java: Small experiments with auth\n\t  framework\n\n2006-11-02 19:54  kobit\n\n\t* MANIFEST.MF,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/xmpp/XMPPIOService.java: Fixed the problem with 'to'\n\t  attribute in stream open element, ticket:\n\t  http://server.tigase.org/ticket/4\n\n2006-10-30 22:38  kobit\n\n\t* MANIFEST.MF, src/tigase/util/RepositoryUtils.java: Modified to\n\t  allow print repository content only for one given user account\n\n2006-10-30 21:27  kobit\n\n\t* scripts, scripts/config.sh, scripts/repo.sh: Command line tools\n\t  for repository and configuration maniulation\n\n2006-10-30 21:21  kobit\n\n\t* MANIFEST.MF, database/mysql-schema.sql,\n\t  database/simple-sqldb.sql,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/Roster.java: Filename change to reflect\n\t  database\n\n2006-10-30 15:13  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/Configurator.java: Full off-line\n\t  configuration management implemented\n\n2006-10-29 10:57  kobit\n\n\t* src/tigase/db/NonAuthUserRepository.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/VCardTemp.java: Javadoc warning fixed -\n\t  javadoc is still not complete yet.\n\n2006-10-29 00:16  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/impl/Presence.java: Fixed a bug with\n\t  extra probe sent for each presence: ticket -\n\t  http://server.tigase.org/ticket/31\n\n2006-10-29 00:08  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/server/xmppsession/SessionManagerConfig.java,\n\t  src/tigase/util/RepositoryUtils.java: Simple configuration and\n\t  repository management\n\n2006-10-28 16:15  kobit\n\n\t* src/tigase/util/RepositoryUtils.java: JDBC module is ready and\n\t  tested\n\n2006-10-28 15:26  kobit\n\n\t* MANIFEST.MF, src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/util/RepositoryUtils.java: JDBC module is ready and\n\t  tested\n\n2006-10-28 09:32  kobit\n\n\t* MANIFEST.MF, src/tigase/db/jdbc/JDBCRepository.java: Jdbc\n\t  repository implementation is finished now but untested\n\n2006-10-27 16:10  kobit\n\n\t* MANIFEST.MF, database/simple-sqldb.sql,\n\t  src/tigase/auth/PlainAuth.java,\n\t  src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/db/DBInitException.java,\n\t  src/tigase/db/DataOverwriteException.java,\n\t  src/tigase/db/RepositoryFactory.java,\n\t  src/tigase/db/TigaseDBException.java,\n\t  src/tigase/db/UserExistsException.java,\n\t  src/tigase/db/UserNotFoundException.java,\n\t  src/tigase/db/UserRepository.java, src/tigase/db/jdbc,\n\t  src/tigase/db/jdbc/JDBCRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/RepositoryAccess.java: JDBC database backend\n\t  implementation\n\n2006-10-26 08:44  kobit\n\n\t* MANIFEST.MF, database/simple-sqldb.sql,\n\t  src/tigase/db/UserRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/xmpp/RepositoryAccess.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java: Added getUsers()\n\t  method - should be used only for conversion process from one\n\t  database to another....\n\n2006-10-26 08:05  kobit\n\n\t* database, database/simple-sqldb.sql: Database schema for SQL\n\t  databases\n\n2006-10-24 22:31  kobit\n\n\t* MANIFEST.MF, src/tigase/db/RepositoryFactory.java,\n\t  src/tigase/db/UserRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Separation\n\t  user repository from auth repository (ticket:\n\t  http://server.tigase.org/ticket/9 )and cleaned up repository\n\t  initialization api\n\n2006-10-24 22:30  kobit\n\n\t* src/tigase/server/xmppsession/SessionManagerConfig.java:\n\t  Separated config constants from main class to make code cleaner\n\n2006-10-24 14:48  kobit\n\n\t* src/tigase/xmpp/RepositoryAccess.java: Implementation of offline\n\t  and public data finished\n\n2006-10-24 14:35  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/impl/VCardTemp.java: Added support\n\t  for retrieving vCard info for off-line users.\n\n2006-10-24 14:27  kobit\n\n\t* MANIFEST.MF, src/tigase/db/DataOverwriteException.java,\n\t  src/tigase/db/NonAuthUserRepository.java,\n\t  src/tigase/db/UserRepository.java,\n\t  src/tigase/db/WriteOnlyUserRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/XMPPPostprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPPreprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPStopListenerIfc.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java,\n\t  src/tigase/xmpp/impl/VCardTemp.java: Implementation of offline\n\t  and public data finished\n\n2006-10-20 08:48  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java:\n\t  Serious bug fixed with infinite error message loop\n\n2006-10-20 01:13  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqVersion.java: Commented out double\n\t  attribute set\n\n2006-10-20 01:12  kobit\n\n\t* src/tigase/server/Packet.java: Added from and to attributes in\n\t  'result' packet\n\n2006-10-20 01:12  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java: Fixed nasty\n\t  bug with infinite loop sending error packets\n\n2006-10-20 01:11  kobit\n\n\t* src/tigase/xmpp/impl/VCardTemp.java: Added vCard implementation\n\n2006-10-19 22:11  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java: Fixed problem with\n\t  removing user from the last group.\n\n2006-10-19 22:10  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqVersion.java: Corrected version\n\t  retrieving between user clients.\n\n2006-10-18 21:14  kobit\n\n\t* MANIFEST.MF, src/tigase/server/Packet.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java: Privacy lists full\n\t  implementation finished\n\n2006-10-16 15:58  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/XMPPStopListenerIfc.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/Presence.java: Stop listener implementation\n\t  corrected\n\n2006-10-16 15:13  kobit\n\n\t* src/tigase/db/WriteOnlyUserRepository.java: This is a workaround\n\t  to allow plugins to write to repository even if there is no\n\t  authorized session. It is needed for off-line message storage\n\t  plugin\n\n2006-10-16 15:12  kobit\n\n\t* src/tigase/xmpp/OfflineMessageStorage.java: Reimplemented as\n\t  plugin not needed anymore\n\n2006-10-16 15:11  kobit\n\n\t* MANIFEST.MF, certs/rsa-keystore,\n\t  src/tigase/db/UserRepository.java, src/tigase/server/Packet.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/ProcessorFactory.java,\n\t  src/tigase/xmpp/XMPPImplIfc.java,\n\t  src/tigase/xmpp/XMPPPostprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPPreprocessorIfc.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPStopListenerIfc.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/OfflineMessages.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java: Major refactoring to add\n\t  preprocessing/postprocessing, stopped handlers, offline messages\n\t  are now implemented as a plugin\n\n2006-10-10 21:45  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/impl/JabberIqPrivacy.java,\n\t  src/tigase/xmpp/impl/Privacy.java: Initial Privacy lists\n\t  implementation. You can manage privacy lists now but server\n\t  doesn't use them yet\n\n2006-10-10 21:44  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/SessionBind.java: Because of overloading\n\t  okResult() method from Package class minor adjustemts in code\n\t  were necessary\n\n2006-10-10 21:43  kobit\n\n\t* src/tigase/xmpp/XMPPResourceConnection.java: Changed log levels\n\t  from SEVERE to WARNING and added new method: getDataKeys()\n\n2006-10-10 21:42  kobit\n\n\t* src/tigase/db/xml/XMLRepository.java: Added better support for\n\t  concurrent access to repository. Now each thread can initialize\n\t  and access repository indepedently even for the same resource\n\t  (data file)\n\n2006-10-10 21:41  kobit\n\n\t* src/tigase/db/UserRepository.java: Added but commented out\n\t  method: getInstance(resource) as there is still no consistent\n\t  idea how it should work\n\n2006-10-10 21:40  kobit\n\n\t* src/tigase/server/Packet.java: Added 2 more methods:\n\t  okResult(Element, int) and getElemChildren()\n\n2006-10-10 21:38  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java: Added privacy\n\t  component loading in default configuration and changed\n\t  initialization of XMLRepository to allow accessing repository\n\t  from different threads\n\n2006-10-10 21:37  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Changes related to reconnecting connections\n\n2006-10-10 21:36  kobit\n\n\t* src/tigase/server/ConnectionManager.java: All connections are\n\t  initialized with delay at startup time now to allow configuration\n\t  fully load first, especially initialization of SSL can take a bit\n\t  longer. Now all 'connect' type connections are not reconnecting\n\t  by default, you have to set counter for them to allow\n\t  reconnecting\n\n2006-10-10 21:34  kobit\n\n\t* src/tigase/io/TLSWrapper.java: Corrected logger package ID\n\n2006-10-09 16:02  kobit\n\n\t* package.html: Basic server documentation\n\n2006-10-09 16:02  kobit\n\n\t* MANIFEST.MF, src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouter.java: Changed\n\t  ClientConnectionManager component addressing\n\n2006-10-09 16:02  kobit\n\n\t* src/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Changed ClientConnectionManager component addressing\n\n2006-10-05 17:18  kobit\n\n\t* MANIFEST.MF, src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Component\n\t  addressing for ClientConnectionManager has been changed to make\n\t  it more consistent and make all hostnames setting mean the same\n\n2006-10-04 16:37  kobit\n\n\t* libs: Added directory required by build file\n\n2006-10-04 16:35  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml, build.xml: Corrected build file\n\n2006-10-04 16:35  kobit\n\n\t* src/tigase/xmpp/impl/ServiceDiscovery.java: Fixed null pointer\n\t  exception\n\n2006-10-03 11:20  kobit\n\n\t* MANIFEST.MF, src/tigase/server/Packet.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Fixed broken presence\n\n2006-10-02 21:43  kobit\n\n\t* src/tigase/xmpp/StanzaType.java: Added new - non-standard stanza\n\t  type used by kopete\n\n2006-10-02 21:42  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: Fixed problem with updating\n\t  presence for multiple user connections\n\n2006-09-30 16:48  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/impl/JabberIqVersion.java: Null\n\t  pointer exception fixed\n\n2006-09-30 16:37  kobit\n\n\t* MANIFEST.MF, src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/OfflineMessageStorage.java: Message to admin\n\t  implemented\n\n2006-09-28 22:45  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java: Fixed service\n\t  discovery and statistics reports\n\n2006-09-28 22:45  kobit\n\n\t* src/tigase/net/IOService.java: Commented out printing stack trace\n\t  on text console\n\n2006-09-28 22:44  kobit\n\n\t* src/tigase/xmpp/impl/SaslAuth.java: Corrected SASL implementation\n\t  for RFC compliance\n\n2006-09-28 22:44  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: Fixed null pointer exception\n\t  when probe was called for buddy not in roster\n\n2006-09-26 06:24  kobit\n\n\t* MANIFEST.MF, src/tigase/io/SocketIO.java: Fixed incorrect logger\n\t  id\n\n2006-09-26 06:23  kobit\n\n\t* src/tigase/xmpp/OfflineMessageStorage.java: Added time stamp and\n\t  off-line message delivery element\n\n2006-09-26 06:23  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: Fixed missing 'from'\n\t  attribute when user send message to himself and implemented\n\t  off-line message delivery on receiving presence packet\n\n2006-09-26 06:22  kobit\n\n\t* src/tigase/xmpp/impl/Message.java: Fixed missing 'from' attribute\n\t  when user send message to himself\n\n2006-09-25 18:54  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Off-line messages for XMPP\n\t  1.0 fixed. Now all off-line messages are delivered after\n\t  receiving initial presence message.\n\n2006-09-24 23:04  kobit\n\n\t* MANIFEST.MF, build.properties, build.xml,\n\t  src/tigase/io/BufferUnderflowException.java,\n\t  src/tigase/io/IOInterface.java, src/tigase/io/SocketIO.java,\n\t  src/tigase/io/TLSIO.java, src/tigase/io/TLSWrapper.java,\n\t  src/tigase/net/IOService.java: Fixed problem with disconnecting\n\t  SSL connection on receiving large packets of data. See ticket: #6\n\t  - http://server.tigase.org/ticket/6\n\n2006-09-24 23:02  kobit\n\n\t* src/tigase/xmpp/XMPPDomBuilderHandler.java: Added error message\n\t  for error() method, now it easier to find out what caused the\n\t  error.\n\n2006-09-19 14:00  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java:\n\t  Fixed problem with Processors not loaded for specified ID, it\n\t  used to trow NullPointerException\n\n2006-09-19 09:11  kobit\n\n\t* MANIFEST.MF,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Another correction for the code disconnecting second channel if\n\t  one of dialback connection has been closed\n\n2006-09-18 23:12  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml, build.xml: Corrected build\n\t  process for generating distribution files\n\n2006-09-18 23:12  kobit\n\n\t* src/tigase/conf/Configurator.java: Changed tigase log name from\n\t  java.log to tigase.log\n\n2006-09-18 23:10  kobit\n\n\t* src/tigase/server/xmppserver/ServerConnectionManager.java: Some\n\t  servers disconnect one connection from s2s pair and don't accept\n\t  any data on the other connection, as a result communication is\n\t  broken. This fix closes other connection if one of them has been\n\t  closed by remote server\n\n2006-09-18 13:09  kobit\n\n\t* src/tigase/server/ConnectionManager.java: Changed default\n\t  configuration to use rsa-keystore\n\n2006-09-18 13:00  kobit\n\n\t* certs/rsa-keystore: Keystore with RSA, default contain DSA wich\n\t  is not liked by gaim\n\n2006-09-18 12:33  kobit\n\n\t* build.properties: version numer change after bug fixes\n\n2006-09-18 12:10  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml,\n\t  src/tigase/server/xmppsession/SessionManager.java: Fixed problem\n\t  with gajim connection - now server sends back error for all\n\t  unsupported stanze received from the client, previously gajim\n\t  seemed to hang waiting for response on unsupported IQ stanzas\n\n2006-09-18 12:09  kobit\n\n\t* src/tigase/server/ComponentRegistrator.java: Fixed broken javadoc\n\t  comment\n\n2006-09-18 12:09  kobit\n\n\t* src/tigase/conf/Configurator.java: Changed default configuration,\n\t  handler for file logger is now setup correctly\n\n2006-09-18 12:08  kobit\n\n\t* src/tigase/auth/SaslCallbackHandler.java: Fixed broken javadoc\n\t  comment\n\n2006-09-17 18:48  kobit\n\n\t* MANIFEST.MF: This is version 2.2.0\n\n2006-09-17 18:48  kobit\n\n\t* build.properties: Version number change\n\n2006-09-17 18:47  kobit\n\n\t* src/tigase/server/xmppserver/ServerConnectionManager.java: Fixed\n\t  problem with remote server diconnect and impossible to establish\n\t  connection with that server later\n\n2006-09-17 18:47  kobit\n\n\t* src/tigase/xmpp/OfflineMessageStorage.java: Small correction to\n\t  preven storring for off-line delivery stanzas other than\n\t  <message/>\n\n2006-09-16 21:57  kobit\n\n\t* MANIFEST.MF, src/tigase/db/UserRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/net/IOService.java, src/tigase/server/Command.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/util/ElementUtils.java,\n\t  src/tigase/xmpp/OfflineMessageStorage.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java: Offline messages storage\n\t  added and fixed various bugs\n\n2006-09-14 12:17  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java: Fixed problem with\n\t  setting resources, later after authorization\n\n2006-09-14 07:21  kobit\n\n\t* MANIFEST.MF,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java: Fixed problem with\n\t  reconnecting resource - the old session for the same resource was\n\t  not removed correctly\n\n2006-09-14 04:54  kobit\n\n\t* MANIFEST.MF,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Session id and dialback key is kept under different entries in\n\t  shared session data\n\n2006-09-13 16:48  kobit\n\n\t* MANIFEST.MF, src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPSession.java: Corrected, simplified and\n\t  improved but not tested s2s - completely rewrited actually,\n\t  should handle google case easy\n\n2006-09-13 16:48  kobit\n\n\t* src/tigase/auth/DialbackAuth.java: Not used anymore....\n\n2006-09-13 16:47  kobit\n\n\t* src/tigase/xmpp/impl/Dialback.java: Not used anymore....\n\n2006-09-13 16:47  kobit\n\n\t* src/tigase/xmpp/impl/Dialback.java: Not used anymore....\n\n2006-09-11 19:35  kobit\n\n\t* MANIFEST.MF, src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Switched to\n\t  use SRV DNS record for xmpp servcice\n\n2006-09-11 19:35  kobit\n\n\t* src/tigase/net/IOService.java: Removed unused import statement\n\n2006-09-11 19:34  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: Fixed problem with sending\n\t  presence notification just after subscription has been approved\n\n2006-09-11 19:33  kobit\n\n\t* src/tigase/xmpp/impl/Roster.java: Added more logging code\n\n2006-09-11 15:11  kobit\n\n\t* src/tigase/net/DNSResolver.java: Moved to tigase.util project\n\n2006-09-11 15:11  kobit\n\n\t* src/tigase/net/DNSResolver.java: Changed function parameter to\n\t  'final'\n\n2006-09-11 15:04  kobit\n\n\t* src/tigase/net/AllAddresses.java,\n\t  src/tigase/net/DNSResolver.java: Renamed to more appropropriate\n\t  name\n\n2006-09-11 15:03  kobit\n\n\t* src/tigase/net/AllAddresses.java: Generic function implemented\n\t  for retrieving IP address for xmpp SRV DNS record\n\n2006-09-11 13:02  kobit\n\n\t* src/tigase/net/ConnectionOpenThread.java: Server used to die on\n\t  SocketException, that was wrong, fixed now....\n\n2006-09-11 13:01  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java: Corrected\n\t  default configuration generated during first startup\n\n2006-09-11 13:01  kobit\n\n\t* src/tigase/net/AllAddresses.java: Sample class showing how to\n\t  retrieve DNS records like SRV\n\n2006-09-10 22:33  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/DialbackAuth.java,\n\t  src/tigase/auth/SessionCallback.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/impl/Dialback.java, tests/data/tigase-config.xml:\n\t  s2s implementation finishedsvn status Finally.\n\n2006-09-10 22:31  kobit\n\n\t* src/tigase/server/ConnectionManager.java: Due to asynchronouse\n\t  nature I had to exchange 2 lines. Now serviceStarted(serv) is\n\t  called before readThread.addSocketService(serv)\n\n2006-09-10 22:30  kobit\n\n\t* src/tigase/server/MessageRouter.java: It may happen only due to a\n\t  bug in server code that packet.getTo() == null for packet\n\t  processing by this class. So just in case added checking at the\n\t  beginning of the processPacket method. Also replaced InetAddress\n\t  class call with new JID.getNodeHostIP method\n\n2006-09-10 22:28  kobit\n\n\t* src/tigase/server/Packet.java: Added getElemCData() method\n\n2006-09-10 22:27  kobit\n\n\t* src/tigase/xmpp/XMPPIOService.java: Added assert debug(data) code\n\n2006-09-10 22:27  kobit\n\n\t* src/tigase/xmpp/impl/Presence.java: According to RFC server\n\t  should not resend 'out_(un)subscribed' notice but it make it very\n\t  difficuly to synchronize presence subscrition in case of earlier\n\t  problems. So for now my implemention will resend such notice\n\n2006-09-10 22:24  kobit\n\n\t* src/tigase/xmpp/XMPPDomBuilderHandler.java: Support for\n\t  xmlns:elname added\n\n2006-09-08 19:33  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/DialbackAuth.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/impl/Dialback.java, tests/data/tigase-config.xml:\n\t  s2s implementation continued...., connecting to remote server\n\t  now....\n\n2006-09-08 19:32  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Changed code to make use of new method in IOService -\n\t  connectionType()\n\n2006-09-08 19:31  kobit\n\n\t* src/tigase/server/xmppsession/SessionManager.java: A few more\n\t  logging messages added\n\n2006-09-08 19:30  kobit\n\n\t* src/tigase/net/ConnectionOpenThread.java: A few more logging\n\t  messages added\n\n2006-09-08 19:30  kobit\n\n\t* src/tigase/xmpp/XMPPIOService.java: New method added -\n\t  xmppStreamOpen()\n\n2006-09-08 19:29  kobit\n\n\t* src/tigase/net/IOService.java: Fixed a bug in writeData method\n\t  for NULL data\n\n2006-09-04 19:37  kobit\n\n\t* src/tigase/server/xmppclient/ClientConnectionManager.java: Fixed\n\t  bug when constructing stream_opened command some data were added\n\t  as pure string rather than DOM XML structure.\n\n2006-08-31 06:04  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/DialbackAuth.java,\n\t  src/tigase/auth/DigestAuth.java, src/tigase/auth/semantic.cache,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/Dialback.java, tests/data/tigase-config.xml:\n\t  s2s implementation in progress\n\n2006-08-31 06:03  kobit\n\n\t* src/tigase/auth/TigaseConfiguration.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Changed\n\t  TigaseConfiguration to statis class\n\n2006-08-31 06:01  kobit\n\n\t* src/tigase/io/TelnetClient.java, src/tigase/io/TelnetServer.java:\n\t  Added support for sending files to test large portion of data\n\n2006-08-22 14:47  kobit\n\n\t* src/tigase/server/xmppserver/ServerConnectionManager.java:\n\t  Constant name change from SESSION_ID to SESSION_ID_KEY and\n\t  getUniqueId method corrected\n\n2006-08-22 14:46  kobit\n\n\t* src/tigase/server/ConnectionManager.java: TODO comments addded\n\t  for serviceStarted method\n\n2006-08-22 14:45  kobit\n\n\t* src/tigase/server/xmppcomponent/ComponentConnectionManager.java:\n\t  Constant name change from serv.SESSION_ID to serv.SESSION_ID_KEY\n\n2006-08-22 14:45  kobit\n\n\t* src/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  Constant name change from serv.SESSION_ID to serv.SESSION_ID_KEY\n\n2006-08-22 14:44  kobit\n\n\t* src/tigase/net/IOService.java: Added ConnectionType and\n\t  remote/local address retrieving for connection service\n\n2006-08-22 14:43  kobit\n\n\t* src/tigase/conf/Configurator.java: Changed depreciated code\n\t  accessing Logger.global\n\n2006-08-22 14:43  kobit\n\n\t* src/tigase/xmpp/XMPPResourceConnection.java: Added java doc for\n\t  connectionId variable\n\n2006-08-18 09:57  kobit\n\n\t* MANIFEST.MF, prj.el, src/tigase/server/Packet.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/xmpp/StanzaType.java,\n\t  src/tigase/xmpp/impl/Dialback.java: s2s implementation and\n\t  Dialback implementation\n\n2006-08-07 19:44  kobit\n\n\t* MANIFEST.MF, src/tigase/io/TelnetClient.java: It uses trust-all\n\t  mode si it doesn't get disconnected when server sends unknown\n\t  certificate\n\n2006-08-07 19:42  kobit\n\n\t* MANIFEST.MF, src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/TLSUtil.java, src/tigase/io/TLSWrapper.java: Added\n\t  support for trust-all SSLContext\n\n2006-08-07 19:02  kobit\n\n\t* MANIFEST.MF, src/tigase/io/TelnetClient.java,\n\t  src/tigase/io/TelnetServer.java: SSL connection is working now\n\t  and debug options turns debuging on\n\n2006-08-07 18:25  kobit\n\n\t* MANIFEST.MF, src/tigase/annotations/TODO.java,\n\t  src/tigase/auth/AuthorisationSystem.java,\n\t  src/tigase/auth/CommitHandler.java,\n\t  src/tigase/auth/DigestAuth.java, src/tigase/auth/PlainAuth.java,\n\t  src/tigase/auth/ResourceConnectionCallback.java,\n\t  src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/auth/TigaseConfiguration.java,\n\t  src/tigase/auth/TigaseSasl.java,\n\t  src/tigase/conf/ConfigComponent.java,\n\t  src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/db/ConfigurationDB.java,\n\t  src/tigase/db/MessageHistoryDB.java,\n\t  src/tigase/db/MessageOfflineDB.java, src/tigase/db/UserDB.java,\n\t  src/tigase/db/UserExistsException.java,\n\t  src/tigase/db/UserNotFoundException.java,\n\t  src/tigase/db/UserRepository.java,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/http/HttpServer.java,\n\t  src/tigase/http/HttpService.java, src/tigase/io/IOInterface.java,\n\t  src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/SocketIO.java, src/tigase/io/TLSIO.java,\n\t  src/tigase/io/TLSStatus.java, src/tigase/io/TLSUtil.java,\n\t  src/tigase/io/TLSWrapper.java, src/tigase/net/Accept.java,\n\t  src/tigase/net/ConnectionOpenListener.java,\n\t  src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/net/ConnectionType.java,\n\t  src/tigase/net/IOService.java,\n\t  src/tigase/net/IOServiceListener.java,\n\t  src/tigase/net/ServiceCommand.java,\n\t  src/tigase/net/SocketReadThread.java,\n\t  src/tigase/net/SocketType.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/Command.java,\n\t  src/tigase/server/ComponentRegistrator.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/ServerComponent.java,\n\t  src/tigase/server/ThreadExceptionHandler.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatRecord.java,\n\t  src/tigase/stats/StatisticType.java,\n\t  src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/stats/StatisticsContainer.java,\n\t  src/tigase/stats/StatsComponent.java,\n\t  src/tigase/ui/UIComponent.java, src/tigase/ui/WebUI.java,\n\t  src/tigase/ui/XMPPServiceComponent.java,\n\t  src/tigase/util/ElementUtils.java,\n\t  src/tigase/util/LogFormatter.java,\n\t  src/tigase/util/RoutingsContainer.java,\n\t  src/tigase/xmpp/Authorization.java,\n\t  src/tigase/xmpp/NotAuthorizedException.java,\n\t  src/tigase/xmpp/ProcessorFactory.java,\n\t  src/tigase/xmpp/StanzaType.java,\n\t  src/tigase/xmpp/XMPPDomBuilderHandler.java,\n\t  src/tigase/xmpp/XMPPException.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPIOServiceListener.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/Roster.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  src/tigase/xmpp/impl/StartTLS.java: e-mail address changed to\n\t  correct one in tigase.org domain\n\n2006-08-07 18:24  kobit\n\n\t* src/tigase/io/TelnetClient.java, src/tigase/io/TelnetServer.java:\n\t  Added SSL support, not working yet though\n\n2006-08-07 14:48  kobit\n\n\t* src/tigase/io/SampleSocketThread.java: Corrected error message,\n\t  when socket gets disconnected\n\n2006-08-07 14:40  kobit\n\n\t* MANIFEST.MF, src/tigase/io/SampleSocketThread.java,\n\t  src/tigase/io/TelnetClient.java, src/tigase/io/TelnetServer.java:\n\t  Sample classes for plain connection using tigase.io API\n\n2006-08-07 14:40  kobit\n\n\t* src/tigase/io/SocketIO.java: SocketIO now initializes\n\t  SocketChannel properly on its own, ie. set non-blocking mode and\n\t  so on\n\n2006-08-07 14:19  kobit\n\n\t* MANIFEST.MF, src/tigase/io/TelnetServer.java: TelnetServer works\n\t  now for plain socket connection, test it with telnet linux\n\t  program\n\n2006-08-07 10:35  kobit\n\n\t* MANIFEST.MF, src/tigase/io/SampleSocketThread.java,\n\t  src/tigase/io/SimpleReaderThread.java,\n\t  src/tigase/io/TelnetServer.java: Smaple classes implementation in\n\t  progress\n\n2006-08-06 22:59  kobit\n\n\t* src/tigase/io/SimpleReaderThread.java,\n\t  src/tigase/io/TelnetClient.java, src/tigase/io/TelnetServer.java:\n\t  Sample classes presenting tigase.io use\n\n2006-08-06 22:57  kobit\n\n\t* MANIFEST.MF, prj.el, src/tigase/io/TLSIO.java,\n\t  src/tigase/io/TLSWrapper.java, src/tigase/net/IOService.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java: Added\n\t  support for client connection\n\n2006-04-21 14:34  kobit\n\n\t* src/tigase/xmpp/impl/JabberIqAuth.java: Unblocked digest\n\t  authorization\n\n2006-04-21 13:54  kobit\n\n\t* MANIFEST.MF, src/tigase/xmpp/XMPPIOService.java: Fixes to\n\t  multithreaded tests\n\n2006-04-21 07:20  kobit\n\n\t* MANIFEST.MF, src/tigase/server/xmppsession/SessionManager.java,\n\t  tests/data/tigase-config.xml: Fixed a few minor configuration\n\t  bugs\n\n2006-04-21 07:15  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/AuthorisationSystem.java,\n\t  src/tigase/db/ConfigurationDB.java,\n\t  src/tigase/db/MessageHistoryDB.java,\n\t  src/tigase/db/MessageOfflineDB.java, src/tigase/db/UserDB.java,\n\t  src/tigase/http/HttpServer.java, src/tigase/server/Command.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/ui/UIComponent.java,\n\t  src/tigase/util/RoutingsContainer.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/StartTLS.java,\n\t  tests/data/tigase-config-1.xml, tests/data/tigase-config.xml:\n\t  Corrected thread synchronization issues\n\n2006-04-20 13:41  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/CommitHandler.java,\n\t  src/tigase/auth/PlainAuth.java,\n\t  src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/auth/semantic.cache,\n\t  src/tigase/net/SocketReadThread.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatRecord.java,\n\t  src/tigase/stats/StatisticType.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  tests/data/tigase-config-2.xml: Fixed a few concurency issues\n\n2006-04-10 20:23  kobit\n\n\t* MANIFEST.MF, src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/net/SocketReadThread.java,\n\t  tests/data/tigase-config-1.xml, tests/data/tigase-config-2.xml:\n\t  New XML-tools version support corrected, TestRoster now expects\n\t  XML data with \" instead of '\n\n2006-04-10 17:46  kobit\n\n\t* MANIFEST.MF: Compiler warnings fixed\n\n2006-04-10 16:47  kobit\n\n\t* src/tigase/util/ClassComparator.java: Separation util code from\n\t  the rest of components\n\n2006-04-10 16:46  kobit\n\n\t* src/tigase/util/ObjectComparator.java: Separation util code from\n\t  the rest of components\n\n2006-04-10 16:44  kobit\n\n\t* MANIFEST.MF, src/tigase/util/ClassUtil.java: Separation util code\n\t  from the rest of components\n\n2006-04-10 16:38  kobit\n\n\t* src/tigase/util/Algorithms.java, src/tigase/util/JID.java,\n\t  src/tigase/util/Telnet.java: Separation util code from the rest\n\t  of components\n\n2006-04-06 07:18  kobit\n\n\t* MANIFEST.MF, build.properties, src/tigase/io/TLSIO.java,\n\t  src/tigase/net/IOService.java,\n\t  src/tigase/net/SocketReadThread.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/Packet.java, src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/StartTLS.java,\n\t  tests/data/tigase-config-1.xml, tests/data/tigase-config-2.xml:\n\t  Fixes for bugs: TLS start, multithreaded I/0, uncautch exception\n\t  in main threads\n\n2006-03-29 06:32  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/Configurator.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/Command.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/ServerComponent.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatRecord.java,\n\t  src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/util/ElementUtils.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqStats.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/ServiceDiscovery.java,\n\t  src/tigase/xmpp/impl/StartTLS.java,\n\t  tests/data/tigase-config-2.xml: All basic implementations\n\t  comleted\n\n2006-03-21 07:18  kobit\n\n\t* MANIFEST.MF, src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/Command.java, src/tigase/server/Packet.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/IqType.java, src/tigase/xmpp/StanzaType.java,\n\t  src/tigase/xmpp/XMPPIOService.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/JabberIqRoster.java,\n\t  src/tigase/xmpp/impl/JabberIqVersion.java,\n\t  src/tigase/xmpp/impl/Message.java,\n\t  src/tigase/xmpp/impl/Presence.java,\n\t  src/tigase/xmpp/impl/Roster.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  tests/data/tigase-config-1.xml, tests/data/tigase-config-2.xml:\n\t  Implemented presence, roster, message, version\n\n2006-02-20 22:59  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/DigestAuth.java,\n\t  src/tigase/auth/PlainAuth.java, src/tigase/auth/semantic.cache,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/xmpp/Authorization.java, src/tigase/xmpp/IqType.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/BindResource.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/SessionBind.java,\n\t  tests/data/tigase-config-2.xml: Added session bind and bind\n\t  resource implementation\n\n2006-02-20 21:05  kobit\n\n\t* src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/XmppSasl.java: SASL authorization\n\t  implememted\n\n2006-02-20 21:03  kobit\n\n\t* src/tigase/xmpp/impl/XMPPSasl.java,\n\t  src/tigase/xmpp/impl/XmppSasl.java: SASL authorization\n\t  implememted\n\n2006-02-20 21:01  kobit\n\n\t* src/tigase/xmpp/impl/SaslAuth.java,\n\t  src/tigase/xmpp/impl/XMPPSasl.java: SASL authorization\n\t  implememted\n\n2006-02-20 21:01  kobit\n\n\t* MANIFEST.MF, src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/auth/semantic.cache,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/xmpp/IqType.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java,\n\t  tests/data/tigase-config-2.xml: SASL authorization implememted\n\n2006-02-20 16:42  kobit\n\n\t* tests/data/telnet-test.xml, tests/data/tigase-config-1.xml,\n\t  tests/data/tigase-config-2.xml, tests/data/tigase-config.xml:\n\t  Framework for authorization and some authorization implementation\n\t  is ready\n\n2006-02-20 16:41  kobit\n\n\t* src/tigase/xmpp/Authorization.java, src/tigase/xmpp/IqType.java,\n\t  src/tigase/xmpp/NotAuthorizedException.java,\n\t  src/tigase/xmpp/ProcessorFactory.java,\n\t  src/tigase/xmpp/XMPPException.java,\n\t  src/tigase/xmpp/XMPPIOServiceListener.java,\n\t  src/tigase/xmpp/XMPPProcessor.java,\n\t  src/tigase/xmpp/XMPPProcessorIfc.java,\n\t  src/tigase/xmpp/XMPPResourceConnection.java,\n\t  src/tigase/xmpp/XMPPSession.java: Framework for authorization and\n\t  some authorization implementation is ready\n\n2006-02-20 16:41  kobit\n\n\t* src/tigase/auth/CommitHandler.java,\n\t  src/tigase/auth/DigestAuth.java, src/tigase/auth/PlainAuth.java,\n\t  src/tigase/auth/ResourceConnectionCallback.java,\n\t  src/tigase/auth/SaslCallbackHandler.java,\n\t  src/tigase/auth/TigaseConfiguration.java,\n\t  src/tigase/auth/TigaseSasl.java, src/tigase/auth/semantic.cache,\n\t  src/tigase/db/UserExistsException.java,\n\t  src/tigase/db/UserNotFoundException.java,\n\t  src/tigase/db/UserRepository.java, src/tigase/db/xml,\n\t  src/tigase/db/xml/XMLRepository.java,\n\t  src/tigase/server/Command.java, src/tigase/util/Algorithms.java,\n\t  src/tigase/util/ClassComparator.java,\n\t  src/tigase/util/ClassUtil.java,\n\t  src/tigase/util/ObjectComparator.java,\n\t  src/tigase/util/RoutingsContainer.java, src/tigase/xmpp/impl,\n\t  src/tigase/xmpp/impl/JabberIqAuth.java,\n\t  src/tigase/xmpp/impl/JabberIqRegister.java,\n\t  src/tigase/xmpp/impl/SaslAuth.java: Framework for authorization\n\t  and some authorization implementation is ready\n\n2006-02-20 16:39  kobit\n\n\t* MANIFEST.MF, src/tigase/net/IOService.java,\n\t  src/tigase/net/Reply.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/XMPPIOService.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/util/Telnet.java, src/tigase/xmpp,\n\t  src/tigase/xmpp/XMPPDomBuilderHandler.java,\n\t  src/tigase/xmpp/XMPPIOService.java: Framework for authorization\n\t  and some authorization implementation is ready\n\n2006-02-07 07:45  kobit\n\n\t* MANIFEST.MF, src/tigase/net/IOService.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/XMPPIOService.java: Better separation network\n\t  layer from protocol layer\n\n2006-02-06 22:21  kobit\n\n\t* MANIFEST.MF, prj.el, src/tigase/io,\n\t  src/tigase/io/IOInterface.java,\n\t  src/tigase/io/SSLContextContainer.java,\n\t  src/tigase/io/SocketIO.java, src/tigase/io/TLSIO.java,\n\t  src/tigase/io/TLSStatus.java, src/tigase/io/TLSUtil.java,\n\t  src/tigase/io/TLSWrapper.java, src/tigase/net,\n\t  src/tigase/net/Accept.java,\n\t  src/tigase/net/ConnectionOpenListener.java,\n\t  src/tigase/net/ConnectionOpenThread.java,\n\t  src/tigase/net/ConnectionType.java,\n\t  src/tigase/net/IOService.java,\n\t  src/tigase/net/IOServiceListener.java, src/tigase/net/Reply.java,\n\t  src/tigase/net/ServiceCommand.java,\n\t  src/tigase/net/SocketReadThread.java,\n\t  src/tigase/net/SocketType.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/ThreadExceptionHandler.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/util/JID.java, src/tigase/util/Telnet.java: Routing\n\t  between instances implemented\n\n2006-01-23 00:04  kobit\n\n\t* MANIFEST.MF, src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ConnectionManager.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java:\n\t  abstract ConnectionManager introduced\n\n2006-01-15 23:48  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/MessageRouterConfig.java,\n\t  src/tigase/server/ServerComponent.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Server basic\n\t  startup\n\n2006-01-05 23:59  kobit\n\n\t* src/tigase/util, src/tigase/util/LogFormatter.java: Improved\n\t  configuration management\n\n2006-01-05 23:58  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/XMPPServer.java, tests/data/test_config.xml:\n\t  Improved configuration management\n\n2006-01-04 00:21  kobit\n\n\t* MANIFEST.MF, build.xml, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/XMPPServer.java: Configuration basics\n\t  implemented\n\n2006-01-02 22:52  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurator.java, tests/data/test_config.xml:\n\t  XMLDB and config repository fixes\n\n2005-12-29 07:42  kobit\n\n\t* MANIFEST.MF, build.xml, src/tigase/conf/ConfigRepository.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/stats/StatisticsCollector.java, tests/data,\n\t  tests/data/test_config.xml: Added types to XMLDB and support for\n\t  them in Configurator\n\n2005-11-28 23:30  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ComponentRegistrator.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: MessageRouter\n\t  implementation started\n\n2005-11-25 23:23  kobit\n\n\t* MANIFEST.MF, src/tigase/conf/Configurable.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java: Configurable\n\t  interface corrected\n\n2005-11-25 23:19  kobit\n\n\t* MANIFEST.MF, src/tigase/annotations,\n\t  src/tigase/annotations/TODO.java,\n\t  src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/XMPPServer.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatRecord.java,\n\t  src/tigase/stats/StatisticType.java,\n\t  src/tigase/stats/StatisticsContainer.java:\n\t  AbstractMessageReceiver initial implementation\n\n2005-11-22 23:19  kobit\n\n\t* MANIFEST.MF, ant-definitions.xml, build.xml, jar,\n\t  src/tigase/conf/ConfigComponent.java,\n\t  src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java,\n\t  src/tigase/http/HttpService.java,\n\t  src/tigase/http/HttpServiceIfc.java,\n\t  src/tigase/server/AbstractComponentRegistrator.java,\n\t  src/tigase/server/AbstractMessageReceiver.java,\n\t  src/tigase/server/ComponentRegistrator.java,\n\t  src/tigase/server/ComponentRegistratorIfc.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/ServerComponent.java,\n\t  src/tigase/server/ServerComponentIfc.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/stats/StatisticsContainer.java,\n\t  src/tigase/stats/StatisticsContainerIfc.java,\n\t  src/tigase/stats/StatsComponent.java, src/tigase/ui/WebUI.java,\n\t  src/tigase/ui/XMPPServiceComponent.java: Initial, compilable\n\t  sources\n\n2005-11-21 07:33  kobit\n\n\t* ., ant-definitions.xml, build.properties, build.xml, certs,\n\t  certs/client_truststore, certs/dummy.cer, certs/keystore,\n\t  certs/truststore, jar, package-list, package-list/package-list,\n\t  prj.el, src, src/tigase, src/tigase/auth,\n\t  src/tigase/auth/AuthorisationSystem.java, src/tigase/conf,\n\t  src/tigase/conf/ConfigComponent.java,\n\t  src/tigase/conf/Configurable.java,\n\t  src/tigase/conf/Configurator.java, src/tigase/db,\n\t  src/tigase/db/ConfigurationDB.java,\n\t  src/tigase/db/MessageHistoryDB.java,\n\t  src/tigase/db/MessageOfflineDB.java, src/tigase/db/UserDB.java,\n\t  src/tigase/http, src/tigase/http/HttpServer.java,\n\t  src/tigase/http/HttpServiceIfc.java, src/tigase/server,\n\t  src/tigase/server/ComponentRegistratorIfc.java,\n\t  src/tigase/server/MessageReceiver.java,\n\t  src/tigase/server/MessageRouter.java,\n\t  src/tigase/server/Packet.java,\n\t  src/tigase/server/ServerComponentIfc.java,\n\t  src/tigase/server/XMPPService.java,\n\t  src/tigase/server/XMPPServiceCollector.java,\n\t  src/tigase/server/xmppclient,\n\t  src/tigase/server/xmppclient/ClientConnectionManager.java,\n\t  src/tigase/server/xmppcomponent,\n\t  src/tigase/server/xmppcomponent/ComponentConnectionManager.java,\n\t  src/tigase/server/xmppserver,\n\t  src/tigase/server/xmppserver/ServerConnectionManager.java,\n\t  src/tigase/server/xmppsession,\n\t  src/tigase/server/xmppsession/SessionManager.java,\n\t  src/tigase/stats, src/tigase/stats/StatisticsCollector.java,\n\t  src/tigase/stats/StatisticsContainerIfc.java,\n\t  src/tigase/stats/StatsComponent.java, src/tigase/ui,\n\t  src/tigase/ui/UIComponent.java, src/tigase/ui/WebUI.java,\n\t  src/tigase/ui/XMPPServiceComponent.java, tests, tests/unittests,\n\t  tests/unittests/src: Initial version of Tigase project.\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/compat",
    "content": "5\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/control",
    "content": "Source: tigase\nSection: net\nPriority: optional\nMaintainer: Sergey Nazarov <phearnot@renee.ru>\nBuild-Depends: debhelper (>= 5), cdbs, patchutils, sun-java6-jdk, ant\nStandards-Version: 3.7.2\n\nPackage: tigase\nSection: net\nPriority: optional\nPre-Depends: sun-java6-jre\nArchitecture: all\nDescription: A high performance XMPP (Jabber) server.\n Tigase is an instant messaging server that implements the XMPP\n (Jabber) protocol. It features high performance, a robust\n administration console, and a full plugin system. The server\n is 100% Java.\n .\n See http://www.tigase.org/\nHomepage: http://www.tigase.org/\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/copyright",
    "content": "This package was debianized by Sergey Nazarov\n<phearnot@renee.ru> on January 9, 2009.\n The source was downloaded from http://www.tigase.org.\n\nUpstream author: Artur Hefczyc <artur.hefczyc@tigase.org>\n\nCopyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\nYou are free to distribute this software under the terms of\nthe GNU Affero General Public License. On Debian systems, the complete\ntext of the GNU Affero General Public License can be found in the file\n'/usr/share/common-licenses/GPL'.\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/init-debian.properties",
    "content": "config-type = --gen-config-def\n--admins = admin@$HOST_NAME\n--virt-hosts = $HOST_NAME\n--debug=server\n--user-db-uri = jdbc:derby:/var/lib/tigase/tigase-derbydb\nbasic-conf/logging/java.util.logging.FileHandler.pattern = /var/log/tigase/tigase.log\nvhost-man/vhost-repo-uri = jdbc:derby:/var/lib/tigase/tigase-derbydb\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/rules",
    "content": "#!/usr/bin/make -f\n\n#export DH_VERBOSE=1\n\ninclude /usr/share/cdbs/1/rules/simple-patchsys.mk\ninclude /usr/share/cdbs/1/rules/debhelper.mk\ninclude /usr/share/cdbs/1/class/ant.mk\n\nDEST := $(CURDIR)/debian/tigase\nTARGET := $(CURDIR)\nTIGJARS := $(CURDIR)/jars\nTIGASE := $(DEST)/usr/share/tigase\nETCDIR := $(DEST)/etc/tigase\nLOGDIR := $(DEST)/var/log/tigase\nVARDIR := $(DEST)/var/lib/tigase\n\nJAVA_HOME := /usr/lib/jvm/java-6-openjdk\nANT_HOME := /usr/share/ant\nDEB_ANT_BUILDFILE := build.xml\nDEB_ANT_CLEAN_TARGET := clean\nDEB_JARS := ant-nodeps\n\t\ninstall/tigase::\n\tcp $(TIGJARS)/*.jar $(TIGASE)/jars\n\tcp $(TARGET)/libs/*.jar $(TIGASE)/libs\n\tcp -r $(TARGET)/certs $(TIGASE)/certs\n\tcp $(TARGET)/etc/init-debian.properties $(ETCDIR)/init.properties\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase-debian.conf",
    "content": "ENC=\"-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8\"\nDRV=\"-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver:org.apache.derby.jdbc.EmbeddedDriver\"\n#GC=\"-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:ParallelCMSThreads=2\"\nJAVA_HOME=\"/usr/lib/jvm/java-6-sun\"\nCLASSPATH=\"\"\nJAVA_OPTIONS=\"${GC} ${ENC} ${DRV} -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m -XX:MaxDirectMemorySize=128m \"\nTIGASE_CONFIG=\"/etc/tigase/tigase-server.xml\"\nTIGASE_OPTIONS=\" --property-file /etc/tigase/init.properties \"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase-install.sh",
    "content": "#!/bin/bash\n\nCURDIR=`pwd`\nTARGET=/usr/share/tigase\nETCDIR=/etc/tigase\nLOGDIR=/var/log/tigase\nVARDIR=/var/lib/tigase\n\nif ! getent passwd tigase >/dev/null; then\n\tadduser --disabled-password  --quiet --system \\\n\t--home $VARDIR \\\n\t--gecos \"Tigase XMPP server\" --group tigase\nfi\nif ! getent group tigase >/dev/null; then\n\tadduser --system tigase\nfi\n\nmkdir -p $TARGET\nmkdir -p $ETCDIR\nmkdir -p $LOGDIR\nmkdir -p $VARDIR/tigase-derbydb\nmkdir -p $TARGET/jars/\nmkdir -p $TARGET/libs/\n\ncp -f $CURDIR/jars/*.jar $TARGET/jars/\ncp -f $CURDIR/libs/*.jar $TARGET/libs/\ncp -fr $CURDIR/certs/ $TARGET/\ncp -fr $CURDIR/database/ $TARGET/\ncp -fr $CURDIR/scripts/ $TARGET/\n\nchown -R tigase:tigase $TARGET\nchmod -R o-rwx $TARGET\n\ncp -f $CURDIR/scripts/debian/init-debian.properties $ETCDIR/init.properties\ncp -f $CURDIR/scripts/debian/tigase-debian.conf /etc/default/tigase\ncp -f $CURDIR/scripts/debian/tigase.init.d /etc/init.d/tigase\n\nchown -R tigase:tigase $ETCDIR\nchown -R tigase:tigase $LOGDIR\nchown -R tigase:tigase $VARDIR\n#chmod -R o-rwx $ETCDIR\n#chmod -R o-rwx $LOGDIR\n#chmod -R o-rwx $VARDIR\nchmod 755 /etc/init.d/tigase\n\nupdate-rc.d tigase defaults\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase.default",
    "content": "# Defaults for tigase initscript\n# sourced by /etc/init.d/tigase\n# installed at /etc/default/tigase by the maintainer scripts\n\n#\n# This is a POSIX shell fragment\n#\n\n# Additional options that are passed to the Daemon.\nTIGASE_OPTIONS=\"--property-file /etc/tigase/init.properties\"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase.dirs",
    "content": "/etc/tigase\n/usr/share/tigase/libs\n/usr/share/tigase/jars\n/var/log/tigase\n/var/lib/tigase/embedded-db\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase.init.d",
    "content": "#!/bin/bash\n### BEGIN INIT INFO\n# Provides:          tigase\n# Required-Start:    networking\n# Required-Stop:     networking\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: Start the Tigase XMPP server\n#\n### management instructions\n##\n## to install: update-rc.d tigase defaults\n##\n### END INIT INFO\n\n# Enable Tigase as OSGi bundle\n# OSGI=true\n\n# Settings paths and other variables\n# JAVA_HOME=\n\nUSERNAME=tigase\nUSERGROUP=tigase\nNAME=tigase\nDESC=\"Tigase XMPP server\"\n\nTIGASE_HOME=/usr/share/tigase\nTIGASE_CONFIG=/etc/tigase/tigase-server.xml\nTIGASE_OPTIONS=\nTIGASE_PARAMS=\n\nPIDFILE=\nTIGASE_CONSOLE_LOG=\n\nUSER=$USERNAME\neval HOME=\"~$USER\"\n\n# Attempt to locate JAVA_HOME, code borrowed from jabref package\nif [ -z $JAVA_HOME ]\nthen\n\tfor java_dir in /usr/lib/jvm/java-6-* ; do\n\t\ttest -d ${java_dir} && JAVA_HOME=${java_dir}\n\tdone\nfi\n\n# Include tigase defaults if available\nif [ -z \"${TIGASE_PARAMS}\" ] ; then\n\tif [ -r \"/etc/default/tigase\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/default/tigase\"\n\telif [ -r \"/etc/tigase/tigase.conf\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/tigase/tigase.conf\"\n\telif [ -r \"${TIGASE_HOME}/etc/tigase.conf\" ] ; then\n\t\tTIGASE_PARAMS=\"${TIGASE_HOME}/etc/tigase.conf\"\n\tfi\nfi\n\n[[ -f \"${TIGASE_PARAMS}\" ]] && . ${TIGASE_PARAMS}\n\nif [ -z \"${JAVA_HOME}\" ] ; then\n  echo \"JAVA_HOME is not set.\"\n  echo \"Please set it to correct value before starting the sever.\"\n  exit 1\nfi\n\nPATH=/sbin:/bin:/usr/sbin:/usr/bin:${JAVA_HOME}/bin\n\n# Find tigase-server jar\nif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\tLIB_DIR=jars\n\tJAR_FILE=${LIB_DIR}/org.apache.felix.main*.jar\nelse\n\tLIB_DIR=jars\n\tJAR_FILE=${LIB_DIR}/tigase-server*.jar\nfi\n\nfor j in ${TIGASE_HOME}/${JAR_FILE} ; do\n\tif [ -f ${j} ] ; then\n\t  TIGASE_JAR=${j}\n\t  break\n\tfi\ndone\n\nif [ -z \"${TIGASE_CONSOLE_LOG}\" ] ; then\n    if [ -w \"/var/log/${USERNAME}/\" ] ; then\n        TIGASE_CONSOLE_LOG=\"/var/log/${USERNAME}/tigase-console.log\"\n    elif [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n        TIGASE_CONSOLE_LOG=\"${TIGASE_HOME}/logs/tigase-console.log\"\n    else\n        TIGASE_CONSOLE_LOG=\"/dev/null\"\n    fi\nfi\n\nif [ -z \"${PIDFILE}\" ] ; then\n    if [ ! -d \"/var/run/$NAME/\" ] ; then\n        mkdir \"/var/run/$NAME/\"\n        chown -R \"$USERNAME\":\"$USERGROUP\" \"/var/run/$NAME/\"\n    fi\n\n    if [ -w \"/var/run/$NAME/\" ] ; then\n        PIDFILE=\"/var/run/$NAME/$NAME.pid\"\n    elif [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n        PIDFILE=\"${TIGASE_HOME}/logs/$NAME.pid\"\n    else\n        PIDFILE=\"/var/tmp/$NAME.pid\"\n    fi\nfi\n\n[[ -z \"${TIGASE_RUN}\" ]] && \\\n  TIGASE_RUN=\"tigase.server.XMPPServer -c ${TIGASE_CONFIG} ${TIGASE_OPTIONS}\"\n\n[[ -z \"${JAVA}\" ]] && JAVA=\"${JAVA_HOME}/bin/java\"\n\n[[ -z \"${CLASSPATH}\" ]] || CLASSPATH=\"${CLASSPATH}:\"\n\nCLASSPATH=\"${CLASSPATH}${TIGASE_JAR}\"\n\nfor lib in ${TIGASE_HOME}/${LIB_DIR}/*.jar ; do\n  CLASSPATH=\"${CLASSPATH}:$lib\"\ndone\n\nLOGBACK=\"-Dlogback.configurationFile=$TIGASE_HOME/etc/logback.xml\"\n\nif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\tTIGASE_CMD=\"${JAVA_OPTIONS} ${LOGBACK} -jar ${JAR_FILE}\"\nelse\n\tTIGASE_CMD=\"${JAVA_OPTIONS} ${LOGBACK} -cp ${CLASSPATH} ${TIGASE_RUN}\"\nfi\n\nif [ -d \"${TIGASE_HOME}\" ] ; then\n        cd ${TIGASE_HOME}\nelse\n  echo \"${TIGASE_HOME} is not set to correct value\"\n  echo \"Please set it to correct value before starting the sever.\"\n  exit 1\nfi\n\nset -e\n\n. /lib/lsb/init-functions\n\n#Helper functions\nstart() {\n\n\tif [ -f $PIDFILE ] && kill -0 `cat $PIDFILE` 2>/dev/null\n        then\n            echo \"Tigase is already running!\"\n            return 1\n        fi\n\n\tsu ${USERNAME} -c \"/sbin/start-stop-daemon --start --quiet --make-pidfile --chdir ${TIGASE_HOME} --pidfile $PIDFILE --chuid $USERNAME:$USERGROUP --exec $JAVA -- $TIGASE_CMD >>${TIGASE_CONSOLE_LOG} 2>&1 &\"\n\n\tsleep 3\n\tPID=`cat $PIDFILE`\n\n\tif [[ -z \"`ps -p ${PID} -o cmd=`\" ]]; then\n\t\trm -f \"$PIDFILE\"\n\t\treturn 1\n\telse\n\t\treturn 0\n\tfi\n}\n\nstop() {\n        su ${USERNAME} -c \"/sbin/start-stop-daemon --stop --quiet  --chdir ${TIGASE_HOME} --pidfile $PIDFILE --chuid $USERNAME:$USERGROUP  --exec $JAVA > /dev/null\"\n        \n\trm -f \"$PIDFILE\"\n}\n\ncase \"$1\" in\n  start)\n\tlog_daemon_msg \"Starting $DESC\"\n\tif start; then\n\t\tlog_end_msg 0\n\telse\n\t\tlog_end_msg 1\n\tfi\n\t;;\n  stop)\n\tlog_daemon_msg \"Stopping $DESC\"\n\tif stop; then\n\t\tlog_end_msg 0\n\telse\n\t\tlog_end_msg 1\n\tfi\n\t;;\n  restart|force-reload)\n\tlog_daemon_msg \"Restarting $DESC\"\n\tstop\n\tsleep 5\n\tif start; then\n\t\tlog_end_msg 0\n\telse\n\t\tlog_end_msg 1\n\tfi\n\t;;\n\n  clearrestart)\n    $0 stop $2\n    sleep 5\n    $0 clear $2\n    sleep 2\n    $0 start $2\n    ;;\n\n  clear)\n    LOGBACK=\"${TIGASE_HOME}/logs\"`date \"+%Y-%m-%d--%H:%M:%S\"`\n    log_daemon_msg \"Clearing logs $DESC, moving backup to \" ${LOGBACK}\n\tmkdir -p ${LOGBACK}\n\tmv \"${TIGASE_HOME}/logs\"/* ${LOGBACK}/\n\tlog_end_msg 0\n\tif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\t    log_daemon_msg \"Clearing osgi cache $DESC\"\n\t\trm -rf \"${TIGASE_HOME}/felix-cache\"/*;\n\t\tlog_end_msg 0\n\tfi\n\tlog_end_msg 0\n    ;;\n\n\n  check|status)\n\techo \"Checking arguments to Tigase: \"\n\techo\n\techo \"USERNAME            =  $USERNAME\"\n\techo \"USERGROUP           =  $USERGROUP\"\n\techo \"USER                =  $USER\"\n\techo \"HOME                =  $HOME\"\n\techo\n    echo \"OSGI                =  $OSGI\"\n\techo\n\techo \"TIGASE_HOME         =  $TIGASE_HOME\"\n\techo \"TIGASE_JAR          =  $TIGASE_JAR\"\n\techo \"TIGASE_CMD          =  $TIGASE_CMD\"\n\techo \"TIGASE_CONFIG       =  $TIGASE_CONFIG\"\n\techo \"TIGASE_PARAMS       =  $TIGASE_PARAMS\"\n\techo \"TIGASE_OPTIONS      =  $TIGASE_OPTIONS\"\n\techo \"TIGASE_CONSOLE_LOG  =  $TIGASE_CONSOLE_LOG\"\n\techo \"PIDFILE             =  $PIDFILE\"\n\techo \"JAVA_HOME           =  $JAVA_HOME\"\n\techo \"JAVA                =  $JAVA\"\n\techo \"JAVA_OPTIONS        =  $JAVA_OPTIONS\"\n\techo \"CLASSPATH           =  $CLASSPATH\"\n\n\tif [ -f $PIDFILE ] && kill -0 `cat $PIDFILE` 2>/dev/null\n\tthen\n\t\techo \"Tigase running pid=\"`cat $PIDFILE`\n\t\texit 0\n\tfi\n\texit 1\n\t;;\n\n  *)\n\tN=/etc/init.d/$NAME\n\techo \"Usage: $N {start|stop|restart|clearrestart|clear|force-reload|check|status}\" >&2\n\texit 1\n\t;;\nesac\n\nexit 0\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase.postinst",
    "content": "#! /bin/sh\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n#\n# quoting from the policy:\n#     Any necessary prompting should almost always be confined to the\n#     post-installation script, and should be protected with a conditional\n#     so that unnecessary prompting doesn't happen if a package's\n#     installation fails and the `postinst' is called with `abort-upgrade',\n#     `abort-remove' or `abort-deconfigure'.\n\ncase \"$1\" in\n\tconfigure)\n\t\tif ! getent passwd tigase >/dev/null; then\n\t\t\tadduser --disabled-password  --quiet --system \\\n\t\t\t--home /var/lib/tigase \\\n\t\t\t--gecos \"Tigase XMPP server\" --group tigase\n\t\tfi\n\t\tif ! getent group tigase >/dev/null; then\n\t\t\tadduser --system tigase\n\t\tfi\n \n\t\tmkdir -p /var/log/tigase\n\t\tmkdir -p /var/lib/tigase/tigase-derbydb\n\t\tchown -R tigase:tigase /usr/share/tigase\n\t\tchown -R tigase:tigase /var/lib/tigase\n\t\tchown -R tigase:tigase /var/log/tigase\n\t\tchown -R tigase:tigase /etc/tigase\n\t\tchmod -R o-rwx /usr/share/tigase\n\t\tchmod -R o-rwx /var/lib/tigase\n\t\tchmod -R o-rwx /var/log/tigase\n\t\tchmod -R o-rwx /etc/tigase\n\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/debian/tigase.postrm",
    "content": "#!/bin/sh\n# postrm script for tigase\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <r>overwrit>r> <new-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n     purge)\n\trm -Rf /etc/tigase\n\trm -Rf /var/log/tigase\n\trm -Rf /var/lib/tigase\n\trm -Rf /usr/share/tigase\n        ;; \n \n     remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n\n\n        ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/gentoo/conf.d/tigase",
    "content": "TIGASE_HOME=\"/home/tigase/tigase-server\"\nTIGASE_USER=tigase\nTIGASE_CONF=\"etc/tigase.conf\"\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/gentoo/init.d/tigase",
    "content": "#!/sbin/runscript\n\ndepend() {\n\tneed net\n\tuse dns logger postgresql mysql\n}\n\nstart()\t{\n\tebegin \"Starting Tigase\"\n\tsu - ${TIGASE_USER} -c \"${TIGASE_ENV} ${TIGASE_HOME}/bin/tigase.sh start ${TIGASE_HOME}/${TIGASE_CONF}\"\n\teend $?\n}\n\nstop ()\t{\n\tebegin \"Stopping Tigase\"\n\tsu - ${TIGASE_USER} -c \"${TIGASE_ENV} ${TIGASE_HOME}/bin/tigase.sh stop ${TIGASE_HOME}/${TIGASE_CONF}\"\n\tsleep 2\n\teend $?\n}\n\nsvc_restart () {\n\tebegin \"Restarting Tigase\"\n\tsu - ${TIGASE_USER} -c \"${TIGASE_ENV} ${TIGASE_HOME}/bin/tigase.sh stop ${TIGASE_HOME}/${TIGASE_CONF}\"\n\tsleep 10\n\tsu - ${TIGASE_USER} -c \"${TIGASE_ENV} ${TIGASE_HOME}/bin/tigase.sh start ${TIGASE_HOME}/${TIGASE_CONF}\"\n\teend $?\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/installer-generate.sh",
    "content": "#!/bin/bash\n\n## RUN from main tigase-server directory\n\nIZPACK_DIR=\"installer/izpack.patched\"\n#IZPACK_DIR=\"/Applications/IzPack\"\nMAKE_EXE=true\n\n# create packages directory\nif [ ! -e pack ] ; then\n\tmkdir pack || exit -1\nfi\n\n# create logs directory\nif [ ! -e logs ] ; then\n\tmkdir logs || exit -1\nfi\n\n# get dependencies\nmvn -f modules/distribution/pom.xml dependency:copy-dependencies -DoutputDirectory=jars -Dmdep.stripVersion=true\n\n# copy socks5 schema\nif [ -d ../socks5 ] ; then\n\tcp ../socks5/database/* database\nfi\n\n# insert appropriate version information\nexport TIGVER=`grep -m 1 \"Tigase-Version:\" target/classes/META-INF/MANIFEST.MF | sed -e \"s/Tigase-Version: \\(.*\\)/\\\\1/\" | sed 's/[[:space:]]//'`\necho -e $TIGVER\nsed -e \"s/<appversion>\\([^<]*\\)<\\/appversion>/<appversion>$TIGVER<\\/appversion>/\" \\\n    src/main/izpack/install.xml > src/main/izpack/install_copy.xml\n\n# compile installer\n$IZPACK_DIR/bin/compile \\\n     src/main/izpack/install_copy.xml \\\n     -h $IZPACK_DIR/ \\\n     -b . -o ./pack/tigase-server-$TIGVER.jar\n\n# create exe file, on Mac copy proper 7za binary to izpack directory\n\nif [[ \"$(uname -s)\" == \"Darwin\" && -f /usr/local/bin/7za ]] ; then\n\tcp /usr/local/bin/7za installer/izpack.patched/utils/wrappers/izpack2exe/\nelse\n\tMAKE_EXE=false\nfi\n\nif [ ${MAKE_EXE} ] ; then\npython $IZPACK_DIR/utils/wrappers/izpack2exe/izpack2exe.py \\\n     --file=./pack/tigase-server-$TIGVER.jar --no-upx \\\n     --output=./pack/tigase-server-$TIGVER.exe\nfi\n\n#rm -f src/main/izpack/install_copy.xml\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/installer-prepare.sh",
    "content": "#!/bin/bash\n\n## RUN from main tigase-server directory\n\nINSTALLER_DIR=\"installer\"\nORIGINAL_IZPACK_DIR=\"izpack.original\"\nPATCHED_IZPACK_DIR=\"izpack.patched\"\n\nGIT_URL=\"https://github.com/izpack/izpack.git\"\n\n# create installer directory\nif [ !  -e $INSTALLER_DIR ] ; then\n\tmkdir $INSTALLER_DIR || exit -1\nfi\n\n# create original izpack dir\nif [ -e $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR ] ; then\n\trm -rf $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR || exit -1\nfi\n\n# clone IzPack git repository\ngit clone $GIT_URL $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR || exit -1\ncd $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR/\n\tgit checkout -b original fde79de81836dbf4c594d6a6f184e27d756ae009 || exit -1\ncd ../../\n\n# create patched directory\nif [ -e $INSTALLER_DIR/$PATCHED_IZPACK_DIR ] ; then\n\trm -rf $INSTALLER_DIR/$PATCHED_IZPACK_DIR || exit -1\nfi\ncp -r $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR $INSTALLER_DIR/$PATCHED_IZPACK_DIR || exit -1\n\n#checkout correct revision of the sources from local repository\ncd $INSTALLER_DIR/$PATCHED_IZPACK_DIR/\ngit checkout -b v4 v4.3.0\ncd ../../\n\n# apply patch\npatch -d $INSTALLER_DIR/$PATCHED_IZPACK_DIR -p 1 < src/main/izpack/changes.patch || exit -1\n\n# add custom TigasePanels\ncp src/main/izpack/java/*.java $INSTALLER_DIR/$PATCHED_IZPACK_DIR/src/lib/com/izforge/izpack/panels\n\n#copy utilities from newer sources\nif [ ! -e $INSTALLER_DIR/$PATCHED_IZPACK_DIR/utils/wrappers/ ] ; then\n\tmkdir -p $INSTALLER_DIR/$PATCHED_IZPACK_DIR/utils/wrappers || exit -1\n\tcp -r $INSTALLER_DIR/$ORIGINAL_IZPACK_DIR/izpack-utils/src/main/resources/utils/wrappers $INSTALLER_DIR/$PATCHED_IZPACK_DIR/utils || exit -1\nfi\n\n# get dependencies\nmvn -f modules/distribution/pom.xml dependency:copy-dependencies -DoverWriteReleases=true -DoverWriteSnapshots=true -DoutputDirectory=${PWD}/jars -Dmdep.stripVersion=true\n\n# add tigase classes to installer build path\nmkdir $INSTALLER_DIR/$PATCHED_IZPACK_DIR/tigaseLib\nfor tigase_lib in jars/tigase-server.jar jars/tigase-utils.jar jars/tigase-xmltools.jar\ndo\n\tcp $tigase_lib $INSTALLER_DIR/$PATCHED_IZPACK_DIR/tigaseLib/`basename $tigase_lib`\ndone\n\n\n# make the new installer compiler\ncd $INSTALLER_DIR/$PATCHED_IZPACK_DIR/src\nant dist || exit -1\n\ncd ..\ncp src/dist-files/compile bin\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/machine-check.sh",
    "content": "#!/bin/bash\n\nfunction usage() {\n  echo \"The script has to be run with following parameters:\"\n  echo \"$0 hostname username [vhost]\"\n  echo \"--------------------\"\n  echo \"  hostname - is the machine hostname which might be also used as the cluster node name\"\n  echo \"  username - is a user account from which the Tigase server will be run\"\n  echo \"  vhost    - is a virtual hostname used for the service if different than the hostname\"\n}\n\nfunction check_dns() {\n  if host $1 | grep \"not found\" > /dev/null ; then\n    echo \"WARNING - the $1 does NOT resolve to a valid IP address\"\n  else\n    if host $1 | grep \"127.0.0.1\" > /dev/null ; then\n      echo \"WARNING - DNS points to the localhost for the domain: $1\"\n    else\n      echo \"OK, DNS settings for $1\"\n    fi\n  fi\n  if host -t SRV _xmpp-server._tcp.$1 | grep SRV > /dev/null ; then\n    echo \"OK, SRV record found _xmpp-server._tcp.$1\"\n  else\n    echo \"WARNING - no SRV record _xmpp-server._tcp.$1\"\n  fi\n  if host -t SRV _xmpp-client._tcp.$1 | grep SRV > /dev/null ; then\n    echo \"OK, SRV record found _xmpp-client._tcp.$1\"\n  else\n    echo \"WARNING - no SRV record _xmpp-client._tcp.$1\"\n  fi\n}\n\nfunction check_net() {\n  if ping -q -c 2 -W 100 $1 &> /dev/null ; then\n    echo \"OK, The $1 host accessible through the network\"\n  else\n    echo \"WARNING - the $1 host seems to be unaccessible through the network!\"\n  fi\n}\n\nif [ \"$1\" = \"\" ] || [ \"$2\" = \"\" ] ; then\n  echo \"Missing hostname or username as a parameter, please run the script with correct parameters\"\n  usage\n  exit\nfi\n\nHST=$1\nUSR=$2\nVHST=$3\n\nif [ \"$VHST\" = \"\" ] ; then\n  VHST=$HST\nfi\n\n# Checking network configuration\n\ncheck_dns $HST\ncheck_dns $VHST\n\ncheck_net $HST\ncheck_net $VHST\n\n# Checking system configuration\n\nif echo $OSTYPE | grep -i linux > /dev/null ; then\n\n  if [ \"$USR\" = \"root\" ] ; then\n    echo \"WARNING - you should not run the Tigase server from the root account.\"\n  fi\n\n  if [ \"$UID\" == \"0\" ] ; then\n    # Checking ulimits\n    RES=`su -c - $USR \"ulimit -n\"`\n    if echo $RES | grep -i \"user $USR does not exist\" > /dev/null ; then\n      echo \"WARNING - the $USR user given does not exist, run 'adduser -m $USR' to create the account\"\n    else\n      if [ $RES -lt 300000 ] ; then\n        echo \"WARNING - maximum open files for the $USR user is too low: $RES\"\n        echo \"          To fix this, add following lines to file: /etc/security/limits.conf\"\n        echo \"$USR               soft    nofile         500000\"\n        echo \"$USR               hard    nofile         500000\"\n        echo \"-------\"\n        echo \"Add these lines? (yes/no)\"\n        read ans\n        if [ \"$ans\" = \"yes\" ] ; then\n          echo \"$USR               soft    nofile         500000\" >> /etc/security/limits.conf\n          echo \"$USR               hard    nofile         500000\" >> /etc/security/limits.conf\n        fi\n      else\n        echo \"OK, Max open files set to: $RES\"\n      fi\n    fi\n  else\n    echo \"I am running not within root account, can't check limits for the $USR\"\n  fi\n\n  # Checking kernel settings\n  RES=`/sbin/sysctl fs.file-max | sed -e \"s/fs.file-max *= *\\([0-9]\\+\\)/\\\\1/\"`\n  if [ $RES -lt 600000 ] ; then\n    echo \"WARNING - system wide fs.file-max is too low: $RES\"\n    echo \"          To fix this, add following line to file: /etc/sysctl.conf\"\n    echo \"fs.file-max=1000000\"\n    echo \"-------\"\n    echo \"Add the line and adjust sysctl for running system? (yes/no)\"\n    read ans\n    if [ \"$ans\" = \"yes\" ] ; then\n      echo \"fs.file-max=1000000\" >> /etc/sysctl.conf\n      /sbin/sysctl -p > /dev/null\n    fi\n  else\n    echo \"OK, system wide fs.file-max set to: $RES\"\n  fi\n\n  LO_RES=`/sbin/sysctl net.ipv4.ip_local_port_range | sed -e \"s/[^=]*= *\\([0-9]\\+\\)[^0-9]*\\([0-9]\\+\\)/\\\\1/\"`\n  HI_RES=`/sbin/sysctl net.ipv4.ip_local_port_range | sed -e \"s/[^=]*= *\\([0-9]\\+\\)[^0-9]*\\([0-9]\\+\\)/\\\\2/\"`\n  if [ $LO_RES -gt 5000 ] || [ $HI_RES -lt 64000 ] ; then\n    echo \"WARNING - IP port range is not optimal: $LO_RES   $HI_RES\"\n    echo \"          Recommended: 1024   65530\"\n    echo \"          To fix this, add following line to file: /etc/sysctl.conf\"\n    echo \"net.ipv4.ip_local_port_range=1024 65530\"\n    echo \"-------\"\n    echo \"Add the line and adjust sysctl for running system? (yes/no)\"\n    read ans     \n    if [ \"$ans\" = \"yes\" ] ; then\n      echo \"net.ipv4.ip_local_port_range=1024 65530\" >> /etc/sysctl.conf\n      /sbin/sysctl -p > /dev/null\n    fi\n  else\n    echo \"OK, IP port range set to: $LO_RES   $HI_RES\"\n  fi\n\nelse\n  echo \"The $OSTYPE is not supported for further checks yet\"\nfi\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/mandriva/init.d/tigase",
    "content": "#!/bin/bash\n#\n# Startup script for SER\n#\n# chkconfig: 345 85 15\n# description: Ser is a fast SIP Proxy.\n#\n# processname: ser\n# pidfile: /var/run/ser.pid\n# config: /etc/ser/ser.cfg\n\n# Source function library.\n. /etc/rc.d/init.d/functions\n\nexport JAVA_HOME=/usr/java/jdk1.6.0\nexport TIGASE_DIR=/opt/tigase/server/\ntigase=$TIGASE_DIR/scripts/tigase.sh\nprog=tigase\nconfig=$TIGASE_DIR/etc/tigase.conf\nRETVAL=0\n\nstart() {\n        gprintf \"Starting %s: \" \"$prog\"\n        daemon $tigase start $config\n        RETVAL=$?\n        echo\n        [ $RETVAL = 0 ] \n        return $RETVAL\n}\n\nstop() {\n\tgprintf \"Stopping %s: \" \"$prog\"\n        daemon $tigase stop $config\n\tRETVAL=$?\n\techo\n\t[ $RETVAL = 0 ] \n}\n\n\n# See how we were called.\ncase \"$1\" in\n  start)\n\tstart\n\t;;\n  stop)\n\tstop\n\t;;\n  status)\n        status $tigase\n\tRETVAL=$?\n\t;;\n  restart)\n\tstop\n\tsleep 10\n\tstart\n\t;;\n  condrestart)\n\tif [ -f /var/run/ser.pid ] ; then\n\t\tstop\n\t\tstart\n\tfi\n\t;;\n  *)\n\tgprintf \"Usage: %s {start|stop|restart|status|help}\\n\" \"$prog\"\n\texit 1\nesac\n\nexit $RETVAL\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/pubsub/repository_migrator.groovy",
    "content": "#!/usr/bin/env groovy\n/*\n * Tigase Jabber/XMPP Publish Subscribe Component\n * Copyright (C) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\ndef tigase_config = \"/home/smoku/workspace/tigase-server/etc/tigase-mysql.xml\"\ndef component_name = \"pubsub\"\n\n\nimport tigase.db.*\nimport tigase.conf.*\nimport tigase.pubsub.NodeType\nimport tigase.pubsub.PubSubComponent\nimport tigase.pubsub.PubSubConfig\nimport tigase.pubsub.repository.PubSubDAO\nimport tigase.pubsub.repository.PubSubDAOJDBC\nimport tigase.pubsub.repository.RepositoryException\n\n\ndef conf_repo = new ConfigRepository(false, tigase_config)\ndef user_repo = RepositoryFactory.getUserRepository(\"util\",\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.USER_REPO_CLASS_PROP_KEY, null),\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.USER_REPO_URL_PROP_KEY, null),\n\t\t\tnull)\n\ndef cls_name = conf_repo.get(component_name, null, PubSubComponent.PUBSUB_REPO_CLASS_PROP_KEY, null)\ndef res_uri  = conf_repo.get(component_name, null, PubSubComponent.PUBSUB_REPO_URL_PROP_KEY, null)\n\nif (cls_name != \"tigase.pubsub.repository.PubSubDAOJDBC\") {\n\tprintln \"You need to use 'tigase.pubsub.repository.PubSubDAOJDBC' as PubSub data repository\"\n\n} else {\n\tdef config = new PubSubConfig()\n\tconfig.setServiceName(\"tigase-pubsub\")\n\tdef sourceDAO = new PubSubDAO(user_repo, config)\n\tdef destDAO = new PubSubDAOJDBC(user_repo, config, res_uri)\n\t\n\tprintln \"... BEGIN ...\"\n\tsourceDAO.getNodesList().each { nodeName ->\n\t\tprintln \"Node: $nodeName\"\n\t\ttry {\n\t\t\tNodeType type = NodeType.valueOf(sourceDAO.readNodeConfigForm(nodeName).getAsString(\"pubsub#node_type\"))\n\t\t\tdestDAO.createNode(nodeName, \"\", sourceDAO.getNodeConfig(nodeName), type, null)\n\t\t} catch (RepositoryException e) {\n\t\t\tprintln e\n\t\t}\n\t\t\n\t\tsourceDAO.getItemsIds(nodeName).each { id ->\n\t\t\tprintln \"  ItemID: $id\"\n\t\t\tdestDAO.writeItem(nodeName, sourceDAO.getItemCreationDate(nodeName, id).getTime(), id,\n\t\t\t\t\tsourceDAO.getItemPublisher(nodeName, id), sourceDAO.getItem(nodeName, id))\n\t\t}\n\t\n\t\tint index = 0;\n\t\twhile (true) {\n\t\t\tfinal String key = \"subscriptions\" + (index == 0 ? \"\" : (\".\" + index));\n\t\t\tString cnfData = user_repo.getData(config.getServiceName(), PubSubDAO.NODES_KEY + nodeName, key);\n\t\t\tif (cnfData == null || cnfData.length() == 0)\n\t\t\t\tbreak;\n\t\t\tdestDAO.updateSubscriptions(nodeName, index, cnfData)\n\t\t\tprintln \"  Sub[$index]: $cnfData\"\n\t\t\t++index;\n\t\t}\n\t}\n\t\n\tprintln \"... DONE ...\"\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/redhat/init.d/tigase",
    "content": "#!/bin/bash\n### BEGIN INIT INFO\n#\n# tigase        This starts and stops the Tigase XMPP server.\n#\n# chkconfig: 345 85 15\n# description: Tigase is a XMPP server.\n#\n# processname: tigase\n# pidfile: /var/run/tigase/tigase.pid\n# config: /home/tigase/tigase-server/etc/tigase.conf\n#\n### management instructions\n##\n## to install: /sbin/chkconfig --add tigase\n## to check:   /sbin/chkconfig --list tigase\n## to start:   /sbin/chkconfig tigase <on|off|reset>\n##\n### END INIT INFO\n\n# Settings paths and other variables\n\nJAVA_HOME=/usr/lib/jvm/java/\n\nUSERNAME=tigase\nUSERGROUP=tigase\nNAME=tigase\nDESC=\"Tigase XMPP server\"\n\nTIGASE_HOME=/home/tigase/tigase-server\nTIGASE_LIB=${TIGASE_HOME}/jars\nTIGASE_CONFIG=/etc/tigase/tigase-server.xml\nTIGASE_OPTIONS=\nTIGASE_PARAMS=\n\nPIDFILE=\nTIGASE_CONSOLE_LOG=\n\nUSER=$USERNAME\neval HOME=\"~$USER\"\n\n# Attempt to locate JAVA_HOME, code borrowed from jabref package\nif [ -z $JAVA_HOME ]\nthen\n\tfor java_dir in /usr/lib/jvm/java-6-* ; do\n\t\ttest -d ${java_dir} && JAVA_HOME=${java_dir}\n\tdone\nfi\n\n# Include tigase defaults if available\nif [ -z \"${TIGASE_PARAMS}\" ] ; then\n\tif [ -r \"/etc/default/tigase\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/default/tigase\"\n\telif [ -r \"/etc/tigase/tigase.conf\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/tigase/tigase.conf\"\n\telif [ -r \"${TIGASE_HOME}/etc/tigase.conf\" ] ; then\n\t\tTIGASE_PARAMS=\"${TIGASE_HOME}/etc/tigase.conf\"\n\tfi\nfi\n\n[[ -f \"${TIGASE_PARAMS}\" ]] && . ${TIGASE_PARAMS}\n\nif [ -z \"${JAVA_HOME}\" ] ; then\n\techo \"JAVA_HOME is not set.\"\n\techo \"Please set it to correct value before starting the sever.\"\n\texit 1\nfi\n\nPATH=/sbin:/bin:/usr/sbin:/usr/bin:${JAVA_HOME}/bin\n\n# Find tigase-server jar\nfor j in ${TIGASE_HOME}/jars/tigase-server*.jar ; do\n\tif [ -f ${j} ] ; then\n\t\tTIGASE_JAR=${j}\n\t\tbreak\n\tfi\ndone\n\nif [ -z \"${TIGASE_CONSOLE_LOG}\" ] ; then\n    if [ -w \"/var/log/${NAME}/\" ] ; then\n        TIGASE_CONSOLE_LOG=\"/var/log/${NAME}/tigase-console.log\"\n    elif [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n        TIGASE_CONSOLE_LOG=\"${TIGASE_HOME}/logs/tigase-console.log\"\n    else\n        TIGASE_CONSOLE_LOG=\"/dev/null\"\n    fi\nfi\n\nif [ -z \"${PIDFILE}\" ] ; then\n    if [ -w \"/var/run/\" ] ; then\n    \tif [ ! -d \"/var/run/$NAME/\" ]; then\n    \t\tmkdir \"/var/run/$NAME/\";\n    \t\tchown $USERNAME:$USERGROUP \"/var/run/$NAME/\";\n    \tfi\n        PIDFILE=\"/var/run/$NAME/$NAME.pid\"\n    elif [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n        PIDFILE=\"${TIGASE_HOME}/logs/$NAME.pid\"\n    else\n        PIDFILE=\"/var/tmp/$NAME.pid\"\n    fi\nfi\n\n[[ -z \"${TIGASE_RUN}\" ]] && \\\n\tTIGASE_RUN=\"tigase.server.XMPPServer -c ${TIGASE_CONFIG} ${TIGASE_OPTIONS}\"\n\n[[ -z \"${JAVA}\" ]] && JAVA=\"${JAVA_HOME}/bin/java\"\n\n[[ -z \"${CLASSPATH}\" ]] || CLASSPATH=\"${CLASSPATH}:\"\n\nCLASSPATH=\"${CLASSPATH}${TIGASE_JAR}\"\n\nfor lib in ${TIGASE_LIB}/*.jar ; do\n\tCLASSPATH=\"${CLASSPATH}:$lib\"\ndone\n\nTIGASE_CMD=\"${JAVA_OPTIONS} -cp ${CLASSPATH} ${TIGASE_RUN}\"\n\nif [ -d \"${TIGASE_HOME}\" ] ; then\n\tcd ${TIGASE_HOME}\nelse\n\techo \"${TIGASE_HOME} is not set to correct value\"\n\techo \"Please set it to correct value before starting the sever.\"\n\texit 1\nfi\n\n\n# Source function library.\n. /etc/rc.d/init.d/functions\n\n\n#Helper functions\nfunction checkRunning {\n\tlocal pid=\"$1\"\n\tif [ -z \"$pid\" -o \"$pid\" == \" \" ]; then\n\t\treturn 1;\n\tfi\n\t\n\tif [ ! -e /proc/$pid ]; then\n\t\trm -f $PIDFILE; return 1;\n\tfi\nreturn 0;\n}\n\nfunction getPid {\n\tif [ ! -f $PIDFILE ]; then\n\t\treturn 1;\n\tfi\n\tPID=\"$(<$PIDFILE)\"\n\tcheckRunning $PID || return 1\nreturn 0;\n}\n\nstart() {\n\tgetPid\n\tif [ $? -eq 0 ]; then\n\t\techo -ne \"Tigase is already running!\"\n\treturn 1\n\tfi\n\t\n\trm -f $PIDFILE\n\tlocal cmd=\"cd ${TIGASE_HOME}; setsid $JAVA $TIGASE_CMD >>${TIGASE_CONSOLE_LOG} 2>&1 & echo \\$! >$PIDFILE\"\n\tsu - ${USERNAME} -c \"$cmd\" || return 1\n\t\n\tsleep 1\n\tPID=\"$(<$PIDFILE)\"\n\tif checkRunning $PID; then :; else\n\t\techo -ne \"Tigase start failed, see logfile.\"\n\t\treturn 1\n\tfi\n\t\n\techo -ne \"Tigase started\"\n\treturn 0\n}\n\nstop() {\n    getPid\n\tif [ $? -ne 0 ]; then\n        echo -ne \"Tigase is not running!\"\n        return 1\n    fi\n\n    kill $PID || return 1\n    for ((i=0; i<15*10; i++)); do\n        checkRunning $PID\n            if [ $? -ne 0 ]; then\n                rm -f $PIDFILE\n                return 0\n            fi\n        sleep 1\n        done\n\n    echo -ne \"Tigase did not terminate within 15 seconds, sending SIGKILL...\"\n\n    kill -s KILL $PID || return 1\n    for ((i=0; i<15*10; i++)); do\n        checkRunning $PID\n        if [ $? -ne 0 ]; then\n            rm -f $PIDFILE\n            return 0\n        fi\n    sleep 0.1\n    done\n    echo -ne \"Error: Tigase could not be stopped\"\n    return 1\n}\n\ncase \"$1\" in\n\tstart)\n\techo \"Starting $DESC\"\n\tif start; then\n\t\tsuccess\n\telse\n\t\tfailure\n\tfi\n\techo\n\texit 1\n\t;;\n\n\tstop)\n\techo \"Stopping $DESC\"\n\tif stop; then\n\t\tsuccess\n\telse\n\t\tfailure\n\tfi\n\techo\n\texit 1\n\t;;\n\n\trestart|force-reload)\n\techo \"Restarting $DESC\"\n\tstop\n\tsleep 10\n\tif start; then\n\t\tsuccess\n\telse\n\t\tfailure\n\tfi\n\techo\n\texit 1\n\t;;\n\n  clearrestart)\n    $0 stop $2\n    sleep 5\n    $0 clear $2\n    sleep 2\n    $0 start $2\n    ;;\n\n  clear)\n    LOGBACK=\"${TIGASE_HOME}/logs\"`date \"+%Y-%m-%d--%H:%M:%S\"`\n\techo \"Clearing logs, moving backup to \" ${LOGBACK}\n\tmkdir -p ${LOGBACK}\n\tmv \"${TIGASE_HOME}/logs\"/* ${LOGBACK}/\n\tif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\t\techo \"Clearing osgi cache\"\n\t\trm -rf \"${TIGASE_HOME}/felix-cache\"/*;\n\tfi\n    ;;\n\n\tcheck)\n\tgetPid\n\techo \"Checking arguments to Tigase: \"\n\techo\n\techo \"USERNAME            =  $USERNAME\"\n\techo \"USERGROUP           =  $USERGROUP\"\n\techo \"USER                =  $USER\"\n\techo \"HOME                =  $HOME\"\n\techo \"NAME                =  $NAME\"\n\techo\n\techo \"TIGASE_HOME         =  $TIGASE_HOME\"\n\techo \"TIGASE_JAR          =  $TIGASE_JAR\"\n\techo \"TIGASE_CMD          =  $TIGASE_CMD\"\n\techo \"TIGASE_CONFIG       =  $TIGASE_CONFIG\"\n\techo \"TIGASE_PARAMS       =  $TIGASE_PARAMS\"\n\techo \"TIGASE_OPTIONS      =  $TIGASE_OPTIONS\"\n\techo \"TIGASE_CONSOLE_LOG  =  $TIGASE_CONSOLE_LOG\"\n\techo \"PIDFILE             =  $PIDFILE\"\n\techo \"JAVA_HOME           =  $JAVA_HOME\"\n\techo \"JAVA                =  $JAVA\"\n\techo \"JAVA_OPTIONS        =  $JAVA_OPTIONS\"\n\techo \"CLASSPATH           =  $CLASSPATH\"\n\n\tif [ -f $PIDFILE ] && kill -0 `cat $PIDFILE` 2>/dev/null\n\tthen\n\t\techo \"Tigase running pid=\"`cat $PIDFILE`\n\t\texit 0\n\tfi\n\texit 1\n\t;;\n\n\t*)\n\tN=/etc/init.d/$NAME\n\techo \"Usage: $N {start|stop|restart|clearrestart|clear|force-reload|check|status}\" >&2\n\texit 1\n\t;;\nesac\n\nexit 0\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/repo.sh",
    "content": "#!/bin/bash\n##\n##  Tigase Jabber/XMPP Server\n##  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n##\n##  This program is free software: you can redistribute it and/or modify\n##  it under the terms of the GNU Affero General Public License as published by\n##  the Free Software Foundation, either version 3 of the License.\n##\n##  This program is distributed in the hope that it will be useful,\n##  but WITHOUT ANY WARRANTY; without even the implied warranty of\n##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n##  GNU Affero General Public License for more details.\n##\n##  You should have received a copy of the GNU Affero General Public License\n##  along with this program. Look for COPYING file in the top folder.\n##  If not, see http://www.gnu.org/licenses/.\n##\n##  $Rev: $\n##  Last modified by $Author: $\n##  $Date: $\n##\n\nCP=\"jars/tigase-server.jar:libs/jdbc-mysql.jar:libs/jdbc-postgresql.jar:libs/tigase-xmltools.jar:libs/tigase-utils.jar\"\n\nD=\"-server -Xms100M -Xmx1500M -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver\"\n\nMYSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:mysql://localhost/nk_200k?user=root&password=mypass\"\nPGSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:postgresql://localhost/tigase?user=tigase\"\n\njava $D -cp $CP tigase.util.RepositoryUtils $MYSQL_REP $*\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/adhoc/AdHoc.groovy",
    "content": "package tigase.rest.adhoc\n\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.server.Command\nimport tigase.server.Iq\nimport tigase.server.Packet\nimport tigase.util.Base64\nimport tigase.xml.Element\nimport tigase.xmpp.BareJID\nimport tigase.xmpp.JID\nimport tigase.xmpp.StanzaType\n\nimport java.util.logging.Logger\nimport java.util.logging.Level\n\n/**\n * Class implements generic support for ad-hoc commands\n */\nclass AdHocHandler extends tigase.http.rest.Handler {\n\n\tprivate static final Logger log = Logger.getLogger(AdHocHandler.class.getCanonicalName());\n\t\n    def TIMEOUT = 30 * 1000;\n\n    def COMMAND_XMLNS = \"http://jabber.org/protocol/commands\";\n    def DATA_XMLNS = \"jabber:x:data\";\n    def DISCO_ITEMS_XMLNS = \"http://jabber.org/protocol/disco#items\";\n\n    public AdHocHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{component_jid}\",\n\t\t\tGET : [ info:'List available adhoc commands', \n\t\t\t\tdescription: \"\"\"Retrieves list of available adhoc commands to execute on component which is running as {component_jid}, where {component_jid} may be Tigase XMPP Server internal component jid.\n\nExample result:\n\\${util.formatData([items:[[jid:'sess-man@domain.com',node:'http://jabber.org/protocol/admin#get-active-users',name:'Get list of active users'],[jid:'sess-man@domain.com',node:'del-script',name:'Remove command script'],[jid:'sess-man@domain.com',node:'add-script',name:'New command script']]])}\n\"\"\"],\n\t\t\tPOST : [ info:'Execute adhoc command',\n\t\t\t\tdescription: \"\"\"To execute adhoc command you need to provide proper {component_jid} and also pass additional data in form of XML or JSON as ie. to execute Get list of active users command you need to pass following XML:\n\\${util.formatData([command:[node:'http://jabber.org/protocol/admin#get-active-users',fields:[[var:'domainjid',value:'domain.com'],[var:'max_items',value:'25']]]])}\n\nIn result of this operation you will receive ie. following XML:\n\\${util.formatData([command:[jid:'sess-man@domain.com',node:'http://jabber.org/protocol/admin#get-active-users',fields:[[var:'Users: 2',label:'text-multi',value:['user1@domain.com','user2@domain.com']]]]])}\n\"\"\"]\n\t\t];\n\t\tregex = /\\/(?:([^@\\/]+)@){0,1}([^@\\/]+)/\n        requiredRole = \"admin\"\n        isAsync = true\n\n        /**\n         * Handles GET request and returns list of available ad-hoc commands\n         */\n        execGet = { Service service, callback, user, localPart, domain ->\n\n            Element iq = new Element(\"iq\");\n            iq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n            iq.setAttribute(\"from\", user.toString());\n            iq.setAttribute(\"type\", \"get\");\n            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\n            Element query = new Element(\"query\");\n            query.setXMLNS(DISCO_ITEMS_XMLNS);\n            query.setAttribute(\"node\", COMMAND_XMLNS);\n            iq.addChild(query);\n\n            service.sendPacket(new Iq(iq), TIMEOUT, { Packet result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\n                def items = result.getElement().getChild(\"query\", DISCO_ITEMS_XMLNS).getChildren().findAll({ it.getName() == \"item\" })\n                items = items.collect { [jid: it.getAttribute(\"jid\"), node: it.getAttribute(\"node\"), name: it.getAttribute(\"name\")] }\n\n                def results = [items:items];\n                callback(results)\n            });\n        }\n\n        /**\n         * Handles POST request, executes ad-hoc command using data sent in POST content\n         * and returns result of execution\n         */\n        execPost = { Service service, callback, user, content, localPart, domain ->\n            def compJid = BareJID.bareJIDInstance(localPart, domain);\n\n            content = content.command;\n            def node = content.node;\n            if (!node) {\n                callback(null);\n                return;\n            }\n\n            def fields = content.fields;\n\n            Element iq = new Element(\"iq\");\n            iq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n            iq.setAttribute(\"from\", user.toString());\n            iq.setAttribute(\"type\", \"set\");\n            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\n            Element command = new Element(\"command\");\n            command.setXMLNS(COMMAND_XMLNS);\n            command.setAttribute(\"node\", node);\n            iq.addChild(command);\n\n            if (fields) {\n                Element x = new Element(\"x\");\n                x.setXMLNS(DATA_XMLNS);\n                x.setAttribute(\"type\", \"submit\");\n                command.addChild(x);\n\n                if (log.isLoggable(Level.FINEST)) {\n                  log.finest(\"adhoc fields: \" + fields);\n                }\n\n               \n\n                fields.each { field ->\n                    Element fieldEl = new Element(\"field\");\n                    fieldEl.setAttribute(\"var\", field.var);\n                    x.addChild(fieldEl);\n\n                    if (field.value) {\n                        if (field.value instanceof Collection) {\n                            field.value.each { val ->\n                                Element valueEl = new Element(\"value\", val);\n                                fieldEl.addChild(valueEl);\n                            }\n                        }\n                        else {\n                            Element valueEl = new Element(\"value\", field.value);\n                            fieldEl.addChild(valueEl);\n                        }\n                    }\n                }\n            }\n\n            service.sendPacket(new Iq(iq), TIMEOUT, { Packet result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\n                command = result.getElement().getChild(\"command\", COMMAND_XMLNS);\n                def data = command.getChild(\"x\", DATA_XMLNS);\n                def fieldElems = data.getChildren().findAll({ it.getName() == \"field\"});\n\n                fields = [];\n                def results = [jid: (localPart != null ? \"$localPart@$domain\" : domain), node: node, fields:fields];\n\n                def titleEl = data.getChild(\"title\");\n                if (titleEl) results.title = titleEl.getCData();\n\n                def instructionsEl = data.getChild(\"instructions\");\n                if (instructionsEl) results.instructions = instructionsEl.getCData();\n\n                def noteEl = command.getChild(\"note\");\n                if (noteEl) {\n                    results.note = [value:noteEl.getCData()];\n                    if (noteEl.getAttribute(\"type\")) {\n                        results.note.type = noteEl.getAttribute(\"type\");\n                    }\n                }\n\n                fieldElems.each { fieldEl ->\n                    def field = [var:fieldEl.getAttribute(\"var\")];\n\n                    if (fieldEl.getAttribute(\"label\")) {\n                        field.label = fieldEl.getAttribute(\"label\");\n                    }\n\n                    if (fieldEl.getAttribute(\"type\")) {\n                        field.type = fieldEl.getAttribute(\"type\");\n                    }\n                    fields.add(field);\n\n                    def valueElems = fieldEl.getChildren().findAll({ it.getName() == \"value\" });\n\n//  edit by cai     \n//                    if (valueElems.size() > 0) {\n//                        field.value = [];\n//                        valueElems.each { valueEl ->\n//                            field.value.add(valueEl.getCData());\n//                        }\n//                    }\n\n\n                  if (valueElems.size() == 1) {\n                      field.value = valueElems.get(0).getCData();\n                  }\n                    else if (valueElems.size() > 1) {\n                        field.value = [];\n                        valueElems.each { valueEl ->\n                            field.value.add(valueEl.getCData());\n                        }\n                    }\n\n                    def optionElems = fieldEl.getChildren().findAll({ it.getName() == \"option\" });\n                    if (!optionElems.isEmpty()) {\n                        field.options = [];\n                        optionElems.each { optionEl ->\n                            def item = [value:optionEl.getChild(\"value\").getCData()];\n                            if (optionEl.getAttribute(\"label\")) item.label = optionEl.getAttribute(\"label\");\n                            field.options.add(item);\n                        }\n                    }\n                }\t\t\t\t\n\t\t\t\t// add by cai\n\t\t\t\t// parse groups info\n\t\t\t\tdef fieldsElem = data.getChild(\"fields\");\n\t\t\t\tif (fieldsElem != null) {\n\t\t\t\t\tfieldsElem.getChildren().each { childElem ->\n\t\t\t\t\t\t\n\t\t\t\t\t\tdef field = new LinkedHashMap<String, String>();\n\t\t\t\t\t\tchildElem.getChildren().each { elem ->\n\t\t\t\t\t\t\tfield.(elem.getName()) = elem.getCData();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfields.add(field)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tdef tables = [];\n\t\t\t\tdef table = null;\n\t\t\t\tdata.getChildren().each { child ->\n\t\t\t\t\tif (!(child.getName() == \"reported\" || child.getName() == \"item\"))\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (child.getName() == \"reported\") {\n\t\t\t\t\t\ttable = [label:child.getAttribute(\"label\"), items:[]];\n\t\t\t\t\t\ttables.add(table);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (table == null)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tdef item = []\n\t\t\t\t\tchild.getChildren().each { fieldEl ->\n\t\t\t\t\t\tdef value = fieldEl.getChildren().findAll({ it.getName() == \"value\" });\n\t\t\t\t\t\tif (value.size() > 0) {\n\t\t\t\t\t\t\tvalue = value.get(0).getCData();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvalue = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\titem.add([var:fieldEl.getAttribute(\"var\"), value:value])\n\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\ttable.items.add([fields:item]);\n\t\t\t\t}\n\t\t\t\tif (!tables.isEmpty()) {\n\t\t\t\t\tresults.reported = tables;\n\t\t\t\t}\n\n                callback([command:results])\n            });\n        }\n    }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/avatar/AvatarGet.groovy",
    "content": "package tigase.rest.avatar\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.server.Iq\nimport tigase.util.Base64\nimport tigase.xml.Element\nimport tigase.xmpp.StanzaType\nimport java.util.regex.Matcher;\n\n/**\n * Class implements retrieving user avatar from VCard\n * HTTP GET request for /rest/avatar/user@domain will return avatar for jid user@domain retrived from VCard\n */\nclass AvatarHandler extends tigase.http.rest.Handler {\n\n\tdef DATA_PATTERN = /data:(.+);base64,(.+)/\n\t\n    public AvatarHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{user_jid}/{source}\",\n\t\t\tGET : [ info:'Retrieve user avatar', \n\t\t\t\tdescription: \"\"\"Retrieves avatar of user passed as {user_jid} parameter of url. Avatar is returned in binary form, so this might be used to present user avatar on web pages, etc.\nAdditional parameter {source} may be passed to specify source of avatar.  It may be:\n-avatar\n-vcard4\n-vcard-temp\nIf {source} is not specified server will return first avatar found while searching this list.\n\"\"\"]\n\t\t]\n        regex = /\\/(?:([^@\\/]+)@){0,1}([^@\\/]+)\\/?(avatar|vcard4|vcard-temp)?/\n        isAsync = true\n\t\texecGet = { Service service, callback, String localPart, String domain, String source ->\n\t\t\tif (source == null) {\n\t\t\t\tretrieveFromAvatar(service, { avatarPep ->\n\t\t\t\t\tif (avatarPep == null)\n\t\t\t\t\t\tretrieveFromVCard4(service, { avatarVCard4 ->\n\t\t\t\t\t\t\t\tif (avatarVCard4 == null)\n\t\t\t\t\t\t\t\t\tretrieveFromVCardTemp(service, callback, localPart, domain);\n\t\t\t\t\t\t\t\telse \n\t\t\t\t\t\t\t\tcallback(avatarVCard4);\n\t\t\t\t\t\t}, localPart, domain);\n\t\t\t\t\telse\n\t\t\t\t\t\tcallback(avatarPep);\n\t\t\t\t}, localPart, domain);\n\t\t\t} else {\n\t\t\t\tswitch (source) {\n\t\t\t\t\tcase \"avatar\":\n\t\t\t\t\t\tretrieveFromAvatar(service, callback, localPart, domain);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"vcard4\":\n\t\t\t\t\t\tretrieveFromVCard4(service, callback, localPart, domain);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"vcard-temp\":\n\t\t\t\t\t\tretrieveFromVCardTemp(service, callback, localPart, domain);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t}\n    }\n\t\n\tprivate void retrieveFromAvatar(Service service, def callback, String localPart, String domain) {\n\t\tElement iq = new Element(\"iq\");\n\t\tiq.setAttribute(\"from\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\tiq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\tiq.setAttribute(\"type\", \"get\");\n\t\t\n\t\tElement pubsub = new Element(\"pubsub\");\n\t\tpubsub.setXMLNS(\"http://jabber.org/protocol/pubsub\");\n\t\tiq.addChild(pubsub);\n\t\t\n\t\tElement items = new Element(\"items\");\n\t\titems.setAttribute(\"node\", \"urn:xmpp:avatar:metadata\")\n\t\titems.setAttribute(\"max_items\", \"1\");\n\t\tpubsub.addChild(items);\t\n\t\t\n\t\tservice.sendPacket(new Iq(iq), 30, { result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n                def infos = result.getElement().getChildren().find { it.getName() == \"pubsub\" && it.getXMLNS() == \"http://jabber.org/protocol/pubsub\" }?.getChildren()?.find { it.getName() == \"items\" }?.getChildren()?.find { it.getName() == \"item\" }?.getChildren()?.find { it.getName() == \"metadata\" }?.getChildren()?.findAll { it.getName() == \"info\" };\n                if (infos == null || infos.isEmpty()) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n\t\t\t\tdef info = infos.get(0);\n\t\t\t\tdef id = info.getAttribute(\"id\");\n\t\t\t\tdef type = info.getAttribute(\"type\");\n\t\t\t\t\n\t\t\t\tiq = new Element(\"iq\");\n\t\t\t\tiq.setAttribute(\"from\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\t\t\tiq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\t\t\tiq.setAttribute(\"type\", \"get\");\n\t\t\n\t\t\t\tpubsub = new Element(\"pubsub\");\n\t\t\t\tpubsub.setXMLNS(\"http://jabber.org/protocol/pubsub\");\n\t\t\t\tiq.addChild(pubsub);\n\t\t\n\t\t\t\titems = new Element(\"items\");\n\t\t\t\titems.setAttribute(\"node\", \"urn:xmpp:avatar:data\")\n\t\t\t\tpubsub.addChild(items);\n\t\t\t\t\n\t\t\t\tElement item = new Element(\"item\");\n\t\t\t\titem.setAttribute(\"id\", id);\n\t\t\t\titems.addChild(item);\n\t\t\t\t\n\t\t\t\tservice.sendPacket(new Iq(iq), 30, { resultData ->\n\t\t\t\t\tif (resultData == null || resultData.getType() == StanzaType.error) {\n\t\t\t\t\t\tcallback(null);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\tdef data = resultData.getElement().getChildren().find { it.getName() == \"pubsub\" && it.getXMLNS() == \"http://jabber.org/protocol/pubsub\" }?.getChildren()?.find { it.getName() == \"items\" }?.getChildren()?.find { it.getName() == \"item\" }?.getChildren()?.find { it.getName() == \"data\" }?.getCData();\n\t\t\t\t\t\t\n\t\t\t\t\tif  (!data) {\n\t\t\t\t\t\tcallback(null);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\tdef outResult = new tigase.http.rest.Handler.Result();\n\t\t\t\t\toutResult.contentType = type\n\t\t\t\t\tString contentBase64 = data;\n\t\t\t\t\t// TODO: added workaround for bad result of Base64.decode when encoded data is wrapped\n\t\t\t\t\t// It should be removed when issue https://projects.tigase.org/issues/1265 is fixed\n\t\t\t\t\t// outResult.data = Base64.decode(contentBase64);\n\t\t\t\t\toutResult.data = Base64.decode(contentBase64.replace('\\n', '').replace('\\r',''));\n\t\t\t\t\t\t\n\t\t\t\t\tcallback(outResult);\n\t\t\t\t});\n            });\t\t\t\t\n\t}\n\n\tprivate void retrieveFromVCard4(Service service, def callback, String localPart, String domain) {\n\t\tElement iq = new Element(\"iq\");\n\t\tiq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\tiq.setAttribute(\"type\", \"get\");\n\t\t\n\t\tElement vcard = new Element(\"vcard\");\n\t\tvcard.setXMLNS(\"urn:ietf:params:xml:ns:vcard-4.0\");\n\t\tiq.addChild(vcard);\n\t\t\n\t\tservice.sendPacket(new Iq(iq), 30, { result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n                def photoUri = result.getElement().getChildren().find { it.getName() == \"vcard\" && it.getXMLNS() == \"urn:ietf:params:xml:ns:vcard-4.0\" }?.getChildren()?.find { it.getName() == \"photo\" }?.getChildren()?.find { it.getName() == \"uri\" }?.getCData();\n                if (photoUri == null) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n\t\t\t\tMatcher matcher = (photoUri.replace('\\n', '').replace('\\r','')) =~ DATA_PATTERN\n\t\t\t\tif (!matcher.matches()) {\n\t\t\t\t\tcallback({ req, resp ->\n\t\t\t\t\t\tresp.sendRedirect(photoUri);\n\t\t\t\t\t});\n                    return;\n\t\t\t\t}\n\t\t\t\t\n                def outResult = new tigase.http.rest.Handler.Result();\n                outResult.contentType = matcher.group(1);\n                String contentBase64 = matcher.group(2);\n                // TODO: added workaround for bad result of Base64.decode when encoded data is wrapped\n                // It should be removed when issue https://projects.tigase.org/issues/1265 is fixed\n                // outResult.data = Base64.decode(contentBase64);\n                outResult.data = Base64.decode(contentBase64.replace('\\n', '').replace('\\r',''));\n\t\t\t\t\n                callback(outResult);\n            });\t\t\n\t}\n\t\n\tprivate void retrieveFromVCardTemp(Service service, def callback, String localPart, String domain) {\n\t\tElement iq = new Element(\"iq\");\n\t\tiq.setAttribute(\"to\", localPart != null ? \"$localPart@$domain\" : domain);\n\t\tiq.setAttribute(\"type\", \"get\");\n\t\t\n\t\tElement vcard = new Element(\"vCard\");\n\t\tvcard.setXMLNS(\"vcard-temp\");\n\t\tiq.addChild(vcard);\n\t\t\n\t\tservice.sendPacket(new Iq(iq), 30, { result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n                def photo = result.getElement().getChildren().find { it.getName() == \"vCard\" && it.getXMLNS() == \"vcard-temp\" }?.getChildren().find { it.getName() == \"PHOTO\" };\n                if (photo == null) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n\t\t\t\tdef extval = photo.getChildren().find { it.getName() == \"EXTVAL\" }?.getCData()\n\t\t\t\tif (extval) {\n\t\t\t\t\tcallback({ req, resp ->\n\t\t\t\t\t\tresp.sendRedirect(extval);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tdef outResult = new tigase.http.rest.Handler.Result();\n\t\t\t\t\toutResult.contentType = photo.getChildren().find { it.getName() == \"TYPE\" }?.getCData()\n\t\t\t\t\tString contentBase64 = photo.getChildren().find { it.getName() == \"BINVAL\" }?.getCData();\n\t\t\t\t\t// TODO: added workaround for bad result of Base64.decode when encoded data is wrapped\n\t\t\t\t\t// It should be removed when issue https://projects.tigase.org/issues/1265 is fixed\n\t\t\t\t\t// outResult.data = Base64.decode(contentBase64);\n\t\t\t\t\toutResult.data = Base64.decode(contentBase64.replace('\\n', '').replace('\\r',''));\n\t\t\t\t\t\n\t\t\t\t\tcallback(outResult);\n\t\t\t\t}\n            });\t\t\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/avatar/AvatarPutNoAuth.groovy",
    "content": "package tigase.rest.avatar\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.xmpp.BareJID\nimport tigase.util.Base64;\nimport tigase.xml.DomBuilderHandler\nimport tigase.xml.SimpleParser\nimport tigase.xml.Element\nimport tigase.xml.SingletonFactory\n\n/**\n * Class implements ability to manage users for service administrator\n * Handles requests for /rest/user/user@domain where user@domain is jid\n *\n * Example format of content of request or response:\n * <user><jid>user@domain</jid><password>Paa$$w0rd</password></jid></user>\n */\nclass AvatarPutNoAuthHandler extends tigase.http.rest.Handler {\n\n    public AvatarPutNoAuthHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{user_jid}\",\n\t\t\tPUT : [ info:'Change user avatar', \n\t\t\t\tdescription: \"\"\"Changes avatar of user passed as {user_jid} parameter of url. As content of request binary form of image should be passed as it will be used as new avatar of a user.\n\"\"\"]\n\t\t]\n        regex = /\\/(?:([^@\\/]+)@){0,1}([^@\\/]+)/\n        isAsync = false\n\t\tdecodeContent = false\n        execPut = { Service service, callback, request, localPart, domain ->\n            def jid = BareJID.bareJIDInstance(localPart, domain);\n\t\t\t\n\t\t\tInputStream is = request.getInputStream();\n\t\t\tbyte[] data = new byte[3*1024*1024];\n\t\t\tint size = 0;\n\t\t\tint read = 0;\n\t\t\twhile ((read = is.read(data, size, data.length - size)) != -1) {\n\t\t\t\tsize += read;\n\t\t\t}\n\t\t\t\n\t\t\tdata = Arrays.copyOf(data, size);\n\t\t\t\n\t\t\tString mimeType = request.getContentType();\n\t\t\tString encodedPhoto = Base64.encode(data);\n\t\t\t\n\t\t\tdef userRepo = service.getUserRepository();\n\t\t\t\n\t\t\tString vCardStr = userRepo.getData(jid, \"public/vcard-temp\", \"vCard\", null);\n\t\t\tdef vCardEl = null;\n\t\t\tdef parsed = null;\n\t\t\t\n\t\t\tif (vCardStr != null && !vCardStr.isEmpty()) {\n\t\t\t\tSimpleParser parser   = SingletonFactory.getParserInstance();\n\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\tdef vCardData = vCardStr.toCharArray()\n\t\t\t\tparser.parse(domHandler, vCardData, 0, vCardData.length);\t\t\t\n\t\t\t\tparsed = domHandler.getParsedElements();\n\t\t\t}\n\t\t\t\t\n\t\t\tif (parsed != null && !parsed.isEmpty()) {\n\t\t\t\tvCardEl = parsed.poll();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvCardEl = new Element(\"vCard\");\n\t\t\t\tvCardEl.setXMLNS(\"vcard-temp\");\n\t\t\t}\n\t\t\t\n\t\t\tElement photoEl = vCardEl.getChild(\"PHOTO\");\n\t\t\tif (photoEl == null) {\n\t\t\t\tphotoEl = new Element(\"PHOTO\");\n\t\t\t\tvCardEl.addChild(photoEl);\n\t\t\t}\n\t\t\t\n\t\t\tElement typeEl = photoEl.getChild(\"TYPE\");\n\t\t\tif (typeEl != null) {\n\t\t\t\tphotoEl.removeChild(typeEl);\n\t\t\t}\n\t\t\ttypeEl = new Element(\"TYPE\");\n\t\t\tphotoEl.addChild(typeEl);\n\t\t\ttypeEl.setCData(mimeType);\n\t\t\t\n\t\t\tElement binvalEl = photoEl.getChild(\"BINVAL\");\n\t\t\tif (binvalEl != null) {\n\t\t\t\tphotoEl.removeChild(binvalEl);\n\t\t\t}\n\t\t\tbinvalEl = new Element(\"BINVAL\");\n\t\t\tphotoEl.addChild(binvalEl);\n\t\t\tbinvalEl.setCData(encodedPhoto);\n\t\t\t\n\t\t\tuserRepo.setData(jid, \"public/vcard-temp\", \"vCard\", vCardEl.toString());\n\t\t\t\n            callback([user:[jid:(localPart != null ? \"$localPart@$domain\" : domain)]]);\n        }\n    }\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/footer.html",
    "content": "</div>\n<div class=\"footer\">Powered by Tigase XMPP Server ${tigase.server.XMPPServer.getImplementationVersion()}</div>\n</body>\n</html>"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/header.html",
    "content": "<html>\n<head>\n<title>Tigase XMPP Server: ${title}</title>\n<style>\nbody {\n    margin: 0px;\n}\n.root {\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n}\n.header {\n    height: 100px;\n    background-color: #306799;\n    color: white;\n    box-shadow: 0px 3px 3px 0px lightgray;\n}\n.header > span {\npadding-left: 30px;\ndisplay: block;\nwidth: 300px;\npadding-top: 30px;\nfloat: left;\nfont-size: 1.6em;\n}\n.content {\n    min-height: 600px;\n}\n.footer {\n    font-size: 0.9em;\n    text-align: center;\n}\n</style>\n<% imports.each { \n      if (it.type == 'css' && it.src) { %>\n<link rel='stylesheet' type='text/css' href='${src}'></link>\n<%    } else if (it.type == 'css' && it.content) { %>\n<style>.test {} ${it.content}</style>\n<%    } else if (it.type == 'script') { %>\n<script src=\"${it.src}\"></script>\n<%    } %>\n<%  } %>\n</head>\n<body>\n<div class=\"root\">\n<div class=\"header\">\n<img style=\"width: 64px;\nheight: 64px;\npadding: 15 15;\nfloat: left;\nbackground: radial-gradient(white 5%, rgba(255,255,255,0) 72%);\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAtCAYAAAAeA21aAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAASrAAAEqwEnCx5kAAAX6ElEQVRo3s2aeZRcV3Xuf3euea7u6nmSWqMl2ZZlbBnHAxh7AZ4w2OAHhscQeHmQNxHg5QUMyWJcZIUXQhheICTBjMGBZbAx2MY2kmVLsuW2ZHWrWz1XdVd3zXPVHc77o0styZKNnaxAdq27Vvequvec79vf3meffa7E79j2fuibAJ22I/YKxCW6ptywtT+2UVUVt6EqUtO0EQgUWUaWJVGtm0JT5FYyW16YSxdOeAxtTJalE4rMbKZYfyyZKTvFn370Xz0f6XcFfPcHvk7DtHSPS78x4NbfNdAZvGrrQNyTqzRQZBnbdjAMDY9LQ1FkipUmrZaJEAJdU3EcgWXb9MUDZIo15leKybl06adLufLfvGpzz/MtyxH/8NGb/+MRsP09f4sqy163rl0Y8Onv7I353zyYCAcMl47mMuiM+XEkGdNykKS1KUkSCAFCCABURcZQFSrVOqVqg3Kljl9XqFQbTCxkp1LZ8lddmvoNR4jS/Z+58/dPwOUf/CaqIkulWjMSC3hut4Vz6Whv9A198UDEMDQ0r5toNIihqyBJLzkJCRCwToojBBJQqzepl2vYjSYnUzlzfD7zo5Zpf39sJv2Ix1Drl23psR0hnB98/PbfHQHb3vMVhEDzubQBkN7UFw/c2dcR2NgXD7hMB3xBLx6fB5/XhbTm7hf1OoBl20zNpClWGvR3RwgHPbhdOiAhhMC2HUqlKrlMAcl2xPRSPl+utxZzpVqj2jAfLNaaP+7vCJ6UFbX000+++d+PAO/rP0P1Zx9jz3/9f5t9Lv1OQ5Vv3zbYMRINeuREPECxaePyuAgHfcjy2uSFgEq1TqFcp9FoUSjX6YgGGOiJIrVVUSjX+KefHCBfquF16/QlInR1BEnEgwx0R1FVBUmCfLFKq1rHpcis5MpkizVcmuIs5crlVK7yQKnafNyy7Qee/PJ7T3L7+yGVgMfv/rcTsPGuv0aRZcXn0gaDPtddnWHvbd3RwKZY0C07kozhceFIMn6fi2qlwVK2RKtlsZItU6k3EY6DaTs4jkM44OHKS0ZJxEPrz7cdh2eOzXP42ByWZYMQeA0Nl6ERDHjYONRJf08MXVMRQlCuNGi0TDyagtlskc2VCXl1ZlJ5cy5dnGi0rGcmFrNfT4R9E8PdkcxqoSr+VQRseueX+cib9vCth44OybL81q6I711DidCQ160rusuF7nExvbBKrdFCUxVyhSq1pgkCfG4NQ9ewHAchoDceYKAjiNA0OjtDnIoAIQSStKYW07QRgGyZbIj7qFQaHJ1dIVdu4A74GBroOCukhADLdpCBSqVGo9ZEcWxSmZJTrbfqCyvFZ1dLtS95Df2Xr4iAXR/4Gv6oi9xyLeJ363f2xwPvGOmOXCzLkjSzlEd16Vxz+VY8Lp3HD51gYibNpRcMsqk7TH/Ux1KuQqNl4jI0kCTiATcD8QAL6QKH5vMMDnSuJzloJ78zxi8Wqyyn8yiyhK4qjPTFKDUtXG5jnYDzmeM4FMt1VOFQLFZp1pvky/Xi+HzmO8rLBb/jvV/FshyvIZTr/R7jr0Z7Iu+6cudAv5Bl6ZEjs6RyFa6+dBNd8RCSBF63weRMmucmU8iqwnBXmN0jCXYNd7C5N8rmnjAbusIA/GT/CXSvm6Dfc9aYL4SkaSqBgIdA0Is/6EXICrquvSR4IQSyLONx62iGjsvjRkgShiy5hHAuVH8b8Js/8UNURZZnlnPDca/nYz0x/02jvdGox21gqjpN2ca0bDb2xelNhHHaGo6GfPzBnk38+qkJ9h2ZYWG5wCWbe9i5IUEi6MGxbVYKVY4v5GjICgPxYDs5inVAjuOcIW0JRZFRFPkF3hXIcnsplc4Ezvp9lu0ghKDZsphLZYmHfQRDPopTS+pLKmDHe7/K7HJedRzxvuGu0Jd3b+q+JugxvLm6xcBQF+Gwj+NTKU4uZNi1uY+hvvg6AZIkEQl5GeqNIUmwmC5wdGaZJ44uMJ7KMZup4A76cfs89CTCqIqy5i1JotmymF1YoVFv4fe7kSQJxxHUGy0URUaSJGzbYTGVpVlvIssSpWqTaqNFrX1Zpg3CwWpZlAplCvky0/OrpNN5CoUqsaAbx3F4UQXc+onvIwTKTLrwxyPdoT/fOhB3H5lKs1Ksctv1uwkFPGTzFcanl/F7DIbb4E957JQnw0Ev11y2hR2bekmmC5SrDQrlGvlKA5dLR9POmIKA1Gqep4/No8gyr969EVmWME2bI8fn0TWV7aM92LbNU2OzBFWJ112xiYblUKi12jXEWunk1lV8hoYQDtENcVy6SipTor8jSLVhcuD4IiWf6/wE7HjPV7nviSn1mosG/tslm7rv3tgTcT/8zAyLqyUu2zlMRzQAYq0ayxaqxMI+QsEXxO8ZcSlJEh3RAJ3xILSlKASobQFKElSqDfYdnuLEbJrB3hhX7hnF53FRa7R4/OAJZpMZ3nDVDizL5rGDJ1hZKfDJu65i22DHeR1oWjaKIiO31eMIQbw9R0NTifg9PPT0zLkE/NW9h2lKDX7wi2N/GPG7794x3Okdm10hna/iMjQGeqLomoLtCHKFKgII+91I8ksvKAJwbIEkcZbXhRAspHLsf2aalWyJLSNd7L1oBK/HRbZQ4TeHpxifXuLyXcMEfW6eeHqKp4/Nc8dV29g+GH/R8WpNC69LAxlKtSYuXUWRJSRJQlNlJAmy5frZBIy8/f8ibJOf75+8dUt/7O7doz3ehiRTM9cKlv6uCP3dEWxnLVnlSjUAQn43svTbV9QX/sS0bMbGFxmbWMDj0rn5NTvp6gyjqQor2RIP7nuek/MrbNvQzaahTh4+cJyxEyk29ES49dVbXjL7B70GANlijVK9xUBHkEKlQdDrot60qNRbdEV9pwnY+b6vEvG7+c7Dz23pjfk/tm0wHpPdBrGgj8KhKUDgcml43AaOEAjAshxAsPbfKzfLsgn63bzuim10RANoqgISrObKPPD4UWYWswz3xrhkxxD7j8zw7ESSLX0xPnz75QwmQi9rjLDfjdetU2+ZBL2utZxi20wlc9QaZnGdgKFEiGK1GY74XZ/aNZLY7Qv4iMRD1BsmuVK9LR2lvTOTEI7AaVdz2UKtvRy9fPBCCNwunQ0DZ8SwBPlijV/tP87MYoaBnhjXXbGNybkVxiYW2b2xi/9x22Vsewnpv9BkWUKRJYSQkNthupyrUG2YLOeqX5EBtr77K/zLD/ZLkiT998HO0K2xsA+X34NL1xBiDagiy4S8rrPkrGprhJRqzVfs/fPJt9m02Hd4ksnZNN3xIDe8ehsAR44vEA96eN8bLv6t4IUQlGpNMqUatuMAoKkKbkMDYKVQZXwxi8tQnVqjdVS95k++jSwkOl5/0YVdEd/btg93ykLXCfo9OEKgKjJ+j0GjadKy7LNBnKo8hEA+FQhnLYXnxv1L2bHJJM+dSNLTEeL6K7fj9Rjc/9hRGs0WH7rlUi7e2PWi91q2w4HjixycSBH2uTg2lyHoMRjpDhP0Ggig1jTRVYWJhSwHx5O/aFnOb1QJiXKzpYc9rj8e6Q6PNGxBXyy4DkJTFaIhH8vZEqVq4xxUEiArMqJNhyRJmKYFp0LmDEJeymr1JoePzRMJennD1TuIRfw8tP84k7NpbrtyCzddNoqqvHiMPXJklk/f8zi2EHz2Pddy5GSaX4/NMpXK4XPr9HUEcBwhlrKV6WS2/EAyU/6MpshJVZdlvLp2XU8scGO1YVI0qwwOy+sTlxUZt0sDJEqVOsVyjWDAuya1ah2A3s4Qkny6szO/lGN2McNF2/oJBbzr0nwxIiRgfHoJy7a5/optJOJBjk2mODK+yO7Rbt553a51CZ/PsqUa9+4bJxr00BPzMzadpjPiFbYTd8I+l12sNosHJ1L3larNZ31u7Tc3v/8th+/64kH41Q9R77/3oHT9rXtu6Yn5Q/uOLuDzuXnVhSPrRYoqywTbsS+1P7BWg69kyvg9Bjs396Eo8nr9bZo2lWKViCzI5Ur4Aj407fxqkCRIZ0qMjS+y98JhhvvjZApVHjs8yXAiyEfv2Esi4ntR8C3T5nuPHEOWJTb3x8RMKp99cGW6KkmS23HEpx8dm3tUArMv7p9362r53k/ewb2fvGP9fnXv9Tv3BD3GFYamUqg2qLYsZhZWGR1OrPfgGi0LCYiEvAQDbgSQK1YRQvCqXcN0xgKc0cmiOx7kN4dOYKgye/tjHJrNINxudF09a58vSRKtlsVTYzMEfG5Gh7twBBydSNJqmLzzlj0MJkJMJrMMdIQo1hoUK01GusPrRO5/foHn51bpDHut/c8v3nfF9v6vPfrsrGFo6g0DnaFvBb2u0rc/chNjL0KgbNtix3BXeGOhYdLdEaJaa3Lw6CyVagNJWksu5VoTTVMY6o2txboEpXKdS3cOcdG2AZT2RuaUabpKvWXz4KGTJMJeXru9F7nZwGyZZ4G3bIenj87RaplcuWcUt6GztFLg2FSSmy7fxNW7hlgpVHnyeJKWZfPLw9M8O51eB3/g+CLffeQoiYiPI9PpB2fThQ/98vD0A5qiPuQx9M+Ypl09yzPnMdXQlTcFvIYU74pieNwsZ0rMJrOk0gVGhxPrcu/tCLFxqLMdzzDQG0ORJWRZPkfaqqrQ3xXmwPEkj43NcfPezVx7QS8PH0thyfJ6Ly+br2A7DtddsQ2/z02jZXLo6Cz9MT9vvWYbiizxswOTRINuKvUWBydS3HntBQCk81W++cARWpZNplibWy3U7u6LBxdMy+H+z76tAlR+a+YF5OFEeG+1YeJyG4wOddLbGcJxBKnV4tphhGUjHIc9O4dwGfp6QtNUBbld+bwwrjVVoS8RodGyeHRsDtO2iQe9bOzwU6vU1+vGSNDDJTuH8fvcIGB8epnZxQz/6TU76Ir4OTCe5NCJFLtGEozNpFFkmU29UQAWVos8ezJNLOCh1jQNn1u7a3a5sMu27Y7d/+XrHTd87Duxt3zqh5vf+Kf3bLrz8/8Cu/7X+RUQ8BleXVexbIHXYzDYE2UmmcW214oI2xEM9MYYHUysg3/JDgygSBLxqB+vW2cymeNkMs/m/hhb+qIsF6oU6w3KTQtNU3EZGs2WxcJSjkcOjLNntIs9m7qpN01+sm+c3Zu66Qh5uefho1x74RB+z1qN7zE0PIbK83OrvP7SjQmXpr5/Q3fkDkWWzFrTQpHlVjpfIVdpHEpmK1+gJR0433yV17353XfHIj50jwuXrmFaNkcnU2wc7KA3EUHXVDoiftSXuaafOsgwdJV0psj8Up5NfVG2DsTRVIXBjiB+TcYlQyZbZmYhw7MTixw+NofP0PjgLXsYSoR5ajyFZTvccfX2tapTldk92oVLX6ve/R6D/o4g2XKDZ6aW8Lg0WVVkz2qx5lMV2edz60G3oQY39ca2FCqNgXh3+Puvv/0P7cMP3nO2AoA1b7d7CafO5/oSkXYPH/T2oC+noDmlArdLY/NwFyfnMzw2Ns9rLhom5HOhtfuDg4kQu4biVBsmlXqL2XSReNDD9qEOHCHoivjY3B/D59YRQnDZlt6zCiGXrvLai4e5bFsf2WKNw5NLPDezQrVhYjsO2VKNWMBDwGsw0h25cHG1dN1irnjfOSGQL9eFQJKC8QiItXV/+4YuomHfWQnUcdb28i8kQZynCySxlihHBzuZ3bDKwYkkvzh0ktuu3ILSzhuyJOFzG/jcBp1hGOmOnPXc4e4wtE+KhGD9QOWFjRa/W8fv1hlMhLj1is0IAbVmi3K9hRDwswOTVBut2InF7AWW7ZxDgNJ36U23dUV9HbFoAEVVkCWIhXwEAp51b0rA1Ewan9e1XiCdOQnbdjBN65zvNE3B73VzYnaFJ48vslqs4XPpqIqMI0S7MXEakGnZFCoN8uU6y7kKc6tF5ldKHJ9fZTFTolhpUqo1abbW9iS6qpxDiCRJ6JqK323g9xioqkyp2uT4fObZazcP/9K/43VMPP6j0wqYSxf/Ycdw5+eXVwr093fgdunt87c1N651WyVOzK+g6QqDvfFzPFGq1JlPZdm1tb+tlNOboc5YgL0XjfDoUyf43iNHefDQSUa6w0QDHjb1RdnQHUbXVJKZEghommvgnp9fXQs/TaFp2kKWJHRFxrQdaTgRojvmx+fRGekK0xHyvmh4DneFeezZOQY6g7f/6vj0twxNOXrm/JUtV71ZEnBVT9QXVjQNw9Da+x0JAaQzRQxNYTGVo1iuM9gbO2ewydk02XyFjYMdCAG5QmV9mTzVD+xNhPF7XQT9bhotm6lUniePJ3lyPIksQaZUY3whWzs2t7KQLzVW51aKqXrTPGlazs8R4ht+t/69RsvOza0UW8v5SnV8IdO0beFfylWkcq1FZ9h73s2SKkuUak2y5bp/tVDLjU1mfn3/wSlmnrh37ftffeHt+278s+9+qVSuf86RZJeqKRjtPgDASqZEq2mytT9KrlhlKZ2ntyuK3e7ZCyHI5SvYlk2t3sLQNZ6fSq21z3piCCFQFJmBnii9icjaplkIbEeQyZY4MZXCtB3zsefmH/Z79H/2Gtq933zgmUataTHQGXB2jiTMXKVuPvT5d/DBv37gh/uPLWpzKwUu3ti1YWG1/KGt/bFbFldLkWjAzeb+2DkEKIpMbzyAZdmSz61fXW419IZlrjcw1N1/9A1W8tW/dwQ3XLG9//psOk+sM7JetzeaJs8tZdnWH8dnaCSXssSiAfR2Y9MRAsu06Iv5KNea2I4A22ZmMUN/z+kJnUpkp04vFGWtSTrYGeDI1PJTjhD/ud40U//88becVlb7ApC+cBeA2b5oDHxtLF9pvP/IdDp54Uji/xSqDdm07LW22hlWqjaZTOZQFdmuNcy//+z7rmz+/InZ0wSFLrie4e5IM1OsTZi28+rBmD+eLVZxeww0VaVUqtHhNdAUae1sr2Hidrvw+9xr3SIB6ZU8m7rDVG2Badl0+deKlVDIf85Jzqn4K1XqiHqd5Uy5MZXM/4XX0B6/7y/exsu19OH72H7NW5xipb7k8+g3WpYTalk2lu2gKBKFSoOZ5TwHnl9kdrnAkZPpw8ls6bPH53LFh7/4jtMEZJ75OdP7fkzi4jemVou1Zwq15o5EwN1dr7ckZJl8uUbIrTK7XMiPz2d+4DW0rU3TUmLtJqZAsLJaJOozkDWdbLFG1FDQdZWaJfC1u7Nngrdtm9WVHNVKXUwkc//o82hf0FXFfO6hH7xsAgC2Xn0b/R3+4sxysSpJ0kW5ct3ftCyml/LMLheZSuaYWMyaE8ns4ZmlwgdkSRo/8OV3n50jTv0hyxKyI/afTOXeZZr2hy8Y6rhFESKgC4dyzSZTrO2rN62PJrNl/B79roXFVYaHEsiShKyp+D0GlfbOsa5LRIMe5sstTteGrB9xLafzOM0Wh04s/Spbqt8thKg9+pd3cc//fkX4+emfv403/ul3LLemfOvozMqBYrX54RPJbNdStoKuKkQCHrtlWvcFvMYPn/qb9yyd7xkvWDtC8Lqv0S9Pylt2Dr43Efb9z9HeaO/CavEXcyvFjyA4UW2Ye/o7At8d7okOd3ZFiceCjI0vEFJh22AHP3nqJHtHE6iKzPHVKju39GHbpxNmoVChkisyMb+69Oz0ylv9Hv3RX37u7a8M+Qvtgg9D0AOTSxKrJ8FxAbU2vEq7nHvqvLeed/G87iP/iFtX1FS2OlhrWj5JEotAZrgrguk4yPCmvnjgGwNd4bDu9aLqKmPPzXDDJSOU602qDZN8uUEVhT07BtcSI5BczmFXa8wt5auTqdwf3X/fQ9++7U038KNPnP/9nd+FveI3RF77kX8CcCmy9L6dw52figW9wZYk8cTYLK+5cIhyrbl6MpWXOkKemOL1cMmOIUzLplisUsmXWM2Vzalk7m//5PbLP76ULRdvvHzz7w08wMt+QeKUTe/7MaN/cJtVrDWfTq2WpqqN1sUxn8u3pT+qrBZqlQPPL/6l21Dtjb3RzaWWTTTkI7NaxGnUmVvK5TPF6t+l85VP//zJyezn3vva3yt4+De8JJV48xdZns9Kl106siHkcb096HNtqLfMg784dPIrt+zd/PVdI53vkDUNv0enXK4zlcxNTi/n/+xDN13yozdctsmGl7+7/A9JwJnWrhoNwPno3z1kjs2sXNsd9n1fU+WorinOwkrpnpVC9UvFcuvQ0W++//eN+Sz7/ymfZnBjMeG6AAAAInpUWHRTb2Z0d2FyZQAAeNorLy/Xy8zLLk5OLEjVyy9KBwA22AZYEFPKXAAAAABJRU5ErkJggg==\"/>\n<span style=\"padding-left: 20px;\">${title}</style>\n</div>\n<div class=\"content\">"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/index.html",
    "content": "${ util.include('header', [title: 'Index',\n    imports: [\n\t\t[\n\t\t\ttype:'css', \n\t\t\tcontent: '* {font-family: \\'Droid Sans\\', sans-serif; } \\ndiv.content { font-size: 0.8em; }\\ndiv.code { background-color:whitesmoke; padding: 3px; margin:3px 5px; }'\n\t\t]\n    ]]) }\n<script>\nvar toggleVisibility = function(id, group) {\n\tvar els = document.getElementsByClassName(group);\n\tfor (var i=0; i<els.length; i++) {\n\t\tels[i].style.display = 'none';\n\t}\n\tvar el = document.getElementById(id);\n\tel.style.display = 'inline-block';\n}\n</script>\n<div style=\"width: 80%; clear: both; margin: 0.5em 10%;\">\nThis is a list of currently available and installed features of REST API.<br/>\nTo see details of each request, click on this item and it will expand showing description of usage.<br/>\n<br/>\nIn this examples we present example request content and response content in form of XML as this is default format used for content by Tigase XMPP Server and it's REST API.\nHowever by different format may be used. Currently Tigase XMPP Server supports JSON or XML:<br/>\nTo use JSON format you need to pass <em>application/json</em> as <em>type</em> url paramter of HTTP request or by passing same value as value of <em>Content-Type</em> HTTP request header.<br/>\nTo ensure use of XML format you need to pass <em>application/xml</em> as <em>type</em> url paramter of HTTP request or by passing same value as value of <em>Content-Type</em> HTTP request header.<br/>\n<br/><u><strong>Note:</strong></u> If no <em>type</em> attribute is passed and <em>Content-Type</em> is set to <em>text/html</em> then response may not be sent in form of JSON or XML but in user readable form of HTML web page.<br/>\n</div>\n<div>\n<% \ndef colors = [ \n\t'GET' : '#0f6ab4',\n\t'POST' : '#547f00',\n\t'PUT' : '#c5862b',\n\t'DELETE' : '#a41e22'\n];\ndef servlets = [];\nservlets.addAll(result.service.module.restServlets);\nservlets = servlets.findAll { it.handlers.values().find { !it.isEmpty() } }\nservlets.sort { it.getServletContext()?.getContextPath() } \nservlets.each { \n\tdef prefix = request.getContextPath() + it.getInitParameter(\"mapping\").replace(\"/*\",\"\");\n\tdef handlers = [];\n\tit.handlers.values().each { v ->\n\t\thandlers.addAll(v);\n\t}\n\thandlers = handlers.unique();\n\thandlers.sort { it.regexDescription ?: it.regex }\n\thandlers.each { handler ->\n\t\t[\"GET\",\"PUT\",\"POST\",\"DELETE\"].each { method ->\n\t\t\tif (!handler.\"exec${method.toLowerCase().capitalize()}\") \n\t\t\t\treturn;\n\t\t\tdef color = colors[method];\n\t\t\tdef id = java.util.UUID.randomUUID().toString();\n%>\n<div style=\"width: 80%; clear: both; margin: 0.5em 10%; border: 1px solid ${color}; display: inline-block; background-color: ${color}\">\n\t<div style=\"background-color: rgba(255,255,255,0.8);display: inline-block; width:100%;\" onclick=\"toggleVisibility('${id}','description')\">\n\t<div class=\"method\" style=\"float:left;width:50px;border-radius: 2px;padding: 6px;background-color:${color};color: white;font-size: 0.9em;text-align: center;\">${method}</div>\n\t<div class=\"url\" style=\"float:left;padding: 5px;font-size:1.1em;\">${prefix}${(handler.description?.regex) ?: handler.regex}</div>\n\t<div class=\"info\" style=\"float:right;padding: 5px;color:${color}\">${handler.description?.\"$method\"?.info}</div>\n\t</div>\n\t<div class=\"description\" style=\"clear:both;background-color: rgba(255,255,255,0.8);width:100%; border-top:1px solid ${color};display:none;\" id=\"${id}\">\n\t\t<div style=\"padding:5px;\">\n${result.fillTemplate(handler.description?.\"$method\"?.description)}\n\t\t</div>\n\t</div>\n</div>\n\t\t<% } %>\n\t<% } %>\n<% } %>\n</div>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/static/chart_legend_templates.js",
    "content": "var templateLegends = {\n    bar : \"<ul class=\\\"chart-<%=name.toLowerCase()%>-legend\\\"><% for (var i=0; i<datasets.length; i++){%><li style=\\\"background-color:<%=datasets[i].strokeColor%>\\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>\",\n    other : \"\"  \n};\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/stats/ComponentStats.groovy",
    "content": "package tigase.rest.adhoc\n\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.server.Command\nimport tigase.server.Iq\nimport tigase.server.Packet\nimport tigase.util.Base64\nimport tigase.util.DNSResolverFactory\nimport tigase.xml.Element\nimport tigase.xmpp.BareJID\nimport tigase.xmpp.JID\nimport tigase.xmpp.StanzaType\n\n/**\n * Class implements support for retrieving component statistics\n */\nclass ComponentStatsHandler extends tigase.http.rest.Handler {\n\n    def TIMEOUT = 30 * 1000;\n\n    def COMMAND_XMLNS = \"http://jabber.org/protocol/commands\";\n    def DATA_XMLNS = \"jabber:x:data\";\n    def DISCO_ITEMS_XMLNS = \"http://jabber.org/protocol/disco#items\";\n\n    public ComponentStatsHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{component_jid}\",\n\t\t\tGET : [ info:'Retrieve statistics of component', \n\t\t\t\tdescription: \"\"\"Retrieves statistics of a component which jid is passed in url as {component_jid} and returns them in form of XML or JSON depending on passed Accept HTTP request header.\n\nExample partial response for sess-man component:\n\\${util.formatData([stats:[component:'sess-man',node:'stats/sess-man',data:[[var:'sess-man/Registered accounts',value:292],[var:'sess-man/Open user connections',value:10]]]])}\n\"\"\"]\n\t\t]\n\t\tregex = /\\/([^@\\/]+)/\n        requiredRole = \"admin\"\n        isAsync = true\n\n        /**\n         * Handles GET request and returns list of available ad-hoc commands\n         */\n        execGet = { Service service, callback, user, compName ->\n\n\t\t\tString domain = DNSResolverFactory.getInstance().getDefaultHost();\n\t\t\tString node = \"stats/\" + compName;\n\t\t\t\n            Element iq = new Element(\"iq\");\n            iq.setAttribute(\"to\", \"stats@$domain\");\n            iq.setAttribute(\"from\", user.toString());\n            iq.setAttribute(\"type\", \"get\");\n            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\n            Element command = new Element(\"command\");\n            command.setXMLNS(COMMAND_XMLNS);\n            command.setAttribute(\"node\", node);\n\t\t\tiq.addChild(command);\n\n            Element x = new Element(\"x\");\n            x.setXMLNS(DATA_XMLNS);\n            x.setAttribute(\"type\", \"submit\");\n            command.addChild(x);\n            Element qfieldEl = new Element(\"field\");\n            qfieldEl.setAttribute(\"var\", 'Stats level');\n            x.addChild(qfieldEl);\n\t\t\tqfieldEl.addChild(new Element(\"value\", 'FINEST'));\n\t\t\t\n            service.sendPacket(new Iq(iq), TIMEOUT, { Packet result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\n                command = result.getElement().getChild(\"command\", COMMAND_XMLNS);\n                def data = command.getChild(\"x\", DATA_XMLNS);\n                def fieldElems = data.getChildren().findAll({ it.getName() == \"field\"});\n\n                def fields = [];\n                def results = [component: compName , node: node, data:fields];\n\n                def titleEl = data.getChild(\"title\");\n                if (titleEl) results.title = titleEl.getCData();\n\n                def instructionsEl = data.getChild(\"instructions\");\n                if (instructionsEl) results.instructions = instructionsEl.getCData();\n\n                def noteEl = command.getChild(\"note\");\n                if (noteEl) {\n                    results.note = [value:noteEl.getCData()];\n                    if (noteEl.getAttribute(\"type\")) {\n                        results.note.type = noteEl.getAttribute(\"type\");\n                    }\n                }\n\n                fieldElems.each { fieldEl ->\n                    def field = [var:fieldEl.getAttribute(\"var\")];\n\n                    if (fieldEl.getAttribute(\"label\")) {\n                        field.label = fieldEl.getAttribute(\"label\");\n                    }\n\n                    if (fieldEl.getAttribute(\"type\")) {\n                        field.label = fieldEl.getAttribute(\"type\");\n                    }\n                    fields.add(field);\n\n                    def valueElems = fieldEl.getChildren().findAll({ it.getName() == \"value\" });\n                    if (valueElems.size() == 1) {\n                         field.value = valueElems.get(0).getCData();\n                    }\n                    else if (valueElems.size() > 1) {\n                        field.value = [];\n                        valueElems.each { valueEl ->\n                            field.value.add(valueEl.getCData());\n                        }\n                    }\n\n                    def optionElems = fieldEl.getChildren().findAll({ it.getName() == \"option\" });\n                    if (!optionElems.isEmpty()) {\n                        field.options = [];\n                        optionElems.each { optionEl ->\n                            def item = [value:optionEl.getChild(\"value\").getCData()];\n                            if (optionEl.getAttribute(\"label\")) item.label = optionEl.getAttribute(\"label\");\n                            field.options.add(item);\n                        }\n                    }\n                }\n\n                callback([stats:results])\t\t\t\t\t\n            });\n        }\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/stats/ComponentStatsGet.html",
    "content": "${ util.include('header', [title: result?.stats?.component + ' statistics', \n    imports: [\n\t[ type: 'css', content:'.chart-bar-legend { display: block; } .chart-bar-legend > li { width: 100; display: block; padding: 2px; }' ]\n    ]]) }\n<script src=\"${request.getContextPath()}/static/Chart.min.js\" ></script>\n<script src=\"${request.getContextPath()}/static/chart_legend_templates.js\" ></script>\n\n<% def userConnections = null;\n   def tmp = result.stats.data.findAll { it.var.contains(' user connections') };\n   if (tmp && !tmp.isEmpty()) { \n\t\tuserConnections = [\n\t\t\tlabels : [],\n\t\t\tdatasets: [[\n\t\t\t\tlabel: 'User connections',\n\t\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\t\tdata: []\n\t\t\t]]\n\t\t];\n\t\t['Open','Closed','Total','Maximum'].each { name ->\n\t\t\tuserConnections.labels.add(name);\n\t\t\tuserConnections.datasets[0].data.add( Integer.parseInt((tmp.find { it.var.contains(name) }).value) );\n\t\t}\n   } \n   def userSessions = null;\n   tmp = result.stats.data.findAll { it.var.contains(' user sessions') };\n   if (tmp && !tmp.isEmpty()) { \n\t\tuserSessions = [\n\t\t\tlabels : [],\n\t\t\tdatasets: [[\n\t\t\t\tlabel: 'User sessions',\n\t\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\t\tdata: []\t\t\t\t\n\t\t\t]]\n\t\t];\n\t\t['Open','Total','Maximum'].each { name ->\n\t\t\tuserSessions.labels.add(name);\n\t\t\tuserSessions.datasets[0].data.add( Integer.parseInt((tmp.find { it.var.contains(name) }).value) );\n\t\t}\n   } \n   def processors = null;\n   tmp = result.stats.data.findAll { it.var.contains('/Processor: ') };\n   if (tmp && !tmp.isEmpty()) {\n\t\tprocessors = [\n\t\t\tlabels : [],\n\t\t\tdatasets : [[\n\t\t\t\tlabel: 'Processors average processing time',\n\t\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\t\tdata: []\t\t\t\n\t\t\t]]\n\t\t];\n\t\ttmp.each {\n\t\t\tprocessors.labels.add(it.var.replace(result.stats.component+'/Processor: ', ''));\n\t\t\tprocessors.datasets[0].data.add(Integer.parseInt(it.value.split(',')[2].split(':')[1].trim()));\n\t\t}\n   }\n %>\n<table>\n\t<tr><td>\n\t\t<canvas id=\"packetsRecvSent\" width=\"180\" height=\"400\"></canvas>\n\t\t<div id='packetsRecvSent-legend'></div>\n\t</td>\t\n<% if (userConnections) { %>\n\t<td><canvas id=\"userConnections\" width=\"180\" height=\"400\"></canvas><div id='userConnections-legend'></div></td>\n\t<td><canvas id=\"userSessions\" width=\"180\" height=\"400\"></canvas><div id='userSessions-legend'></div></td>\n\t<td colspan='3'><canvas id=\"processors\" width=\"800\" height=\"400\"></canvas><div id='processors-legend'></div></td>\n<% } %>\n\t</tr>\n\t<tr><td colspan=\"6\">\n\t\t<canvas id=\"packetsPerInThread\" width=\"1400\" height=\"300\"></canvas>\t\n\t</td></tr>\n\t<tr><td colspan=\"6\">\n\t\t<canvas id=\"packetsPerOutThread\" width=\"1400\" height=\"300\"></canvas>\t\n\t</td></tr>\t\n</table>\n\n<% \n\tdef packetsRecvSent = [\n\t\tlabels: ['Packets (total)'],\n\t\tdatasets: [[\n\t\t\tlabel: 'Received',\n\t\t\tfillColor: \"rgba(220,220,220,0.5)\",\n            strokeColor: \"rgba(220,220,220,0.8)\",\n            highlightFill: \"rgba(220,220,220,0.75)\",\n            highlightStroke: \"rgba(220,220,220,1)\",\n            data: [ Integer.parseInt((result.stats.data.find { it.var == (result.stats.component+'/Packets received') }).value) ]\n\t\t],[\n\t\t\tlabel: 'Sent',\n\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n            strokeColor: \"rgba(151,187,205,0.8)\",\n            highlightFill: \"rgba(151,187,205,0.75)\",\n            highlightStroke: \"rgba(151,187,205,1)\",\n            data: [ Integer.parseInt((result.stats.data.find { it.var == (result.stats.component+'/Packets sent') }).value) ]\t\t\n\t\t]]\n\t];\n\t\n\tdef packetsPerInThread = [ labels: [], datasets: [[\n\t\tlabel:'Packets per \"in\" thread',\n\t\tfillColor: \"rgba(151,187,205,0.5)\",\n        strokeColor: \"rgba(151,187,205,0.8)\",\n        highlightFill: \"rgba(151,187,205,0.75)\",\n        highlightStroke: \"rgba(151,187,205,1)\",\n\t\tdata : []\n\t]] ];\n\tdef inData = result.stats.data.findAll { it.var.contains('Processed packets thread: in_') }\n\tinData.each {\n\t\tpacketsPerInThread.labels.add(it.var.replace(result.stats.component+\"/Processed packets thread: \", \"\"));\n\t\tpacketsPerInThread.datasets[0].data.add(Integer.parseInt(it.value));\t\t\t\n\t}\n\n\tdef packetsPerOutThread = [ labels: [], datasets: [[\n\t\tlabel:'Packets per \"out\" thread',\n\t\tfillColor: \"rgba(151,187,205,0.5)\",\n        strokeColor: \"rgba(151,187,205,0.8)\",\n        highlightFill: \"rgba(151,187,205,0.75)\",\n        highlightStroke: \"rgba(151,187,205,1)\",\n\t\tdata : []\n\t]] ];\n\tinData = result.stats.data.findAll { it.var.contains('Processed packets thread: out_') }\n\tinData.each {\n\t\tpacketsPerOutThread.labels.add(it.var.replace(result.stats.component+\"/Processed packets thread: \", \"\"));\n\t\tpacketsPerOutThread.datasets[0].data.add(Integer.parseInt(it.value));\t\t\t\n\t}\n\n%>\n\n<script>\n<% if (userConnections) { %>\n\tvar userConnectionsData =  ${groovy.json.JsonOutput.toJson(userConnections)};\t\n\tvar userConnectionsCtx = document.getElementById(\"userConnections\").getContext(\"2d\");\n\tvar userConnectionsChart = new Chart(userConnectionsCtx).Bar(userConnectionsData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('userConnections-legend').innerHTML = userConnectionsChart.generateLegend();\n\n\tvar userSessionsData =  ${groovy.json.JsonOutput.toJson(userSessions)};\t\n\tvar userSessionsCtx = document.getElementById(\"userSessions\").getContext(\"2d\");\n\tvar userSessionsChart = new Chart(userSessionsCtx).Bar(userSessionsData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('userSessions-legend').innerHTML = userSessionsChart.generateLegend();\n\t\t\n\tvar processorsData =  ${groovy.json.JsonOutput.toJson(processors)};\t\n\tvar processorsCtx = document.getElementById(\"processors\").getContext(\"2d\");\n\tvar processorsChart = new Chart(processorsCtx).Bar(processorsData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('processors-legend').innerHTML = processorsChart.generateLegend();\t\t\n<% } %>\n\t\n\tvar packetsRecvSentData =  ${groovy.json.JsonOutput.toJson(packetsRecvSent)};\n\t\n\tvar packetsRecvSentCtx = document.getElementById(\"packetsRecvSent\").getContext(\"2d\");\n\tvar packetsRecvSentChart = new Chart(packetsRecvSentCtx).Bar(packetsRecvSentData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('packetsRecvSent-legend').innerHTML = packetsRecvSentChart.generateLegend();\n\t\n\tvar packetsPerInThreadData = ${groovy.json.JsonOutput.toJson(packetsPerInThread)};\n\tvar packetsPerInThreadCtx = document.getElementById(\"packetsPerInThread\").getContext(\"2d\");\n\tvar packetsPerInThreadChart = new Chart(packetsPerInThreadCtx).Bar(packetsPerInThreadData, { legendTemplate : templateLegends.bar });\n\n\tvar packetsPerOutThreadData = ${groovy.json.JsonOutput.toJson(packetsPerOutThread)};\n\tvar packetsPerOutThreadCtx = document.getElementById(\"packetsPerOutThread\").getContext(\"2d\");\n\tvar packetsPerOutThreadChart = new Chart(packetsPerOutThreadCtx).Bar(packetsPerOutThreadData, { legendTemplate : templateLegends.bar });\n\n</script>\n\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/stats/ServerStats.groovy",
    "content": "package tigase.rest.adhoc\n\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.server.Command\nimport tigase.server.Iq\nimport tigase.server.Packet\nimport tigase.util.Base64\nimport tigase.util.DNSResolverFactory\nimport tigase.xml.Element\nimport tigase.xmpp.BareJID\nimport tigase.xmpp.JID\nimport tigase.xmpp.StanzaType\n\n/**\n * Class implements support for retrieving server statistics\n */\nclass ServerStatsHandler extends tigase.http.rest.Handler {\n\n    def TIMEOUT = 30 * 1000;\n\n    def COMMAND_XMLNS = \"http://jabber.org/protocol/commands\";\n    def DATA_XMLNS = \"jabber:x:data\";\n    def DISCO_ITEMS_XMLNS = \"http://jabber.org/protocol/disco#items\";\n\n    public ServerStatsHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/\",\n\t\t\tGET : [ info:'Retrieve statistics of server', \n\t\t\t\tdescription: \"\"\"Retrieves statistics of a server and returns them in form of XML or JSON depending on passed Accept HTTP request header.\n\nExample partial response:\n\\${util.formatData([stats:['vhost-man':[component:'vhost-man',node:'stats/vhost-man',data:[[var:'vhost-man/Number of VHosts',value:15]]],'sess-man':[component:'sess-man',node:'stats/sess-man',data:[[var:'sess-man/Registered accounts',value:292],[var:'sess-man/Open user connections',value:10]]],'message-router':[component:'message-router',node:'stats/message-router',data:[[var:'message-router/CPU usage',value:'0,1%'],[var:'message-router/Used Heap',value:'101 454 KB']]]]])}\n\"\"\"]\n\t\t]\n\t\tregex = /\\//\n        requiredRole = \"admin\"\n        isAsync = true\n\n        /**\n         * Handles GET request and returns list of available ad-hoc commands\n         */\n        execGet = { Service service, callback, user ->\n\t\t\tdef domain = DNSResolverFactory.getInstance().getDefaultHost();\n\t\t\t\n\t\t\tElement iq = new Element(\"iq\");\n            iq.setAttribute(\"to\", \"stats@$domain\");\n            iq.setAttribute(\"from\", user.toString());\n            iq.setAttribute(\"type\", \"get\");\n            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\t\t\tElement query = new Element(\"query\");\n\t\t\tquery.setXMLNS(\"http://jabber.org/protocol/disco#items\");\n\t\t\tiq.addChild(query);\n\t\t\t\n\t\t\tservice.sendPacket(new Iq(iq), TIMEOUT, { Packet result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n\t\t\t\tdef items = result.getElement().getChild(\"query\", \"http://jabber.org/protocol/disco#items\").getChildren();\n\t\t\t\tdef results = [:];\n\t\t\t\t\t\n\t\t\t\tretrieveStats(service, user, items, results, callback);\n\t\t\t\t\t\n\t\t\t})\n\t\t\t\n\t\t}\n\t}\n\t\tdef retrieveStats = { service, user, items, allResults, callback ->\n\t\t\titems.each { ditem ->\n\t\t\t\tdef domain = DNSResolverFactory.getInstance().getDefaultHost();\n\t\t\t\tdef compName = ditem.getAttribute(\"node\");\n\t\t\t\tdef node = \"stats/\" + compName;\n\t\t\t\n\t\t        Element iq = new Element(\"iq\");\n\t\t\t\tiq.setAttribute(\"to\", \"stats@$domain\");\n\t\t\t    iq.setAttribute(\"from\", user.toString());\n\t\t        iq.setAttribute(\"type\", \"get\");\n\t            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\n\t\t\t\tElement commandReq = new Element(\"command\");\n\t\t\t    commandReq.setXMLNS(COMMAND_XMLNS);\n\t\t        commandReq.setAttribute(\"node\", node);\n\t\t\t\tiq.addChild(commandReq);\n\t\t\t\t\n\t\t\t\tIq iqPacket = new Iq(iq);\n\t\t\t\n\t\t\t\tCommand.addFieldValue(iqPacket, \"Stats level\", \"FINEST\")\n\t\t\t\t\n\t\t\t\tservice.sendPacket(iqPacket, TIMEOUT, { Packet result ->\n\t\t\t\t\tif (result == null || result.getType() == StanzaType.error) {\n\t\t\t\t\t\tsynchronized (results) {\n\t\t\t\t\t\t\tallResults[compName] = [component:compName];\n\t\t\t\t\t\t\tif (allResults.size() == items.size())\n\t\t\t\t\t\t\t\tcallback([stats:allResults]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n                def command = result.getElement().getChild(\"command\", COMMAND_XMLNS);\n                def data = command.getChild(\"x\", DATA_XMLNS);\n                def fieldElems = data.getChildren().findAll({ it.getName() == \"field\"});\n\n                def fields = [];\n                def results = [component: compName , node: node, data:fields];\n\n                def titleEl = data.getChild(\"title\");\n                if (titleEl) results.title = titleEl.getCData();\n\n                def instructionsEl = data.getChild(\"instructions\");\n                if (instructionsEl) results.instructions = instructionsEl.getCData();\n\n                def noteEl = command.getChild(\"note\");\n                if (noteEl) {\n                    results.note = [value:noteEl.getCData()];\n                    if (noteEl.getAttribute(\"type\")) {\n                        results.note.type = noteEl.getAttribute(\"type\");\n                    }\n                }\n\n                fieldElems.each { fieldEl ->\n                    def field = [var:fieldEl.getAttribute(\"var\")];\n\n                    if (fieldEl.getAttribute(\"label\")) {\n                        field.label = fieldEl.getAttribute(\"label\");\n                    }\n\n                    if (fieldEl.getAttribute(\"type\")) {\n                        field.label = fieldEl.getAttribute(\"type\");\n                    }\n                    fields.add(field);\n\n                    def valueElems = fieldEl.getChildren().findAll({ it.getName() == \"value\" });\n                    if (valueElems.size() == 1) {\n                         field.value = valueElems.get(0).getCData();\n                    }\n                    else if (valueElems.size() > 1) {\n                        field.value = [];\n                        valueElems.each { valueEl ->\n                            field.value.add(valueEl.getCData());\n                        }\n                    }\n\n                    def optionElems = fieldEl.getChildren().findAll({ it.getName() == \"option\" });\n                    if (!optionElems.isEmpty()) {\n                        field.options = [];\n                        optionElems.each { optionEl ->\n                            def item = [value:optionEl.getChild(\"value\").getCData()];\n                            if (optionEl.getAttribute(\"label\")) item.label = optionEl.getAttribute(\"label\");\n                            field.options.add(item);\n                        }\n                    }\n                }\n\n\t\t\t\tsynchronized (allResults) {\n\t\t\t\t\tallResults[compName] = results;\n\t\t\t\t\tif (allResults.size() == items.size())\n\t\t\t\t\t\tcallback([stats:allResults]);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t});\n\t\t\t}\t\t\t\n\t\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/stats/ServerStatsGet.html",
    "content": "${ util.include('header', [title: tigase.util.DNSResolverFactory.getInstance().getDefaultHost() + ' statistics', \n    imports: [\n\t[ type: 'css', content:'.chart-bar-legend { display: block; } .chart-bar-legend > li { width: 100; display: block; padding: 2px; }' ]\n    ]]) }\n<script src=\"${request.getContextPath()}/static/Chart.min.js\" ></script>\n<script src=\"${request.getContextPath()}/static/chart_legend_templates.js\" ></script>\n\n<% \n\tdef compNames = [];\n\tcompNames.addAll(result.stats.keySet());\n\tcompNames.sort();\n\tdef packetsLastSecond = [\n\t\tlabels : [],\n\t\tdatasets: [[\n\t\t\tlabel: 'Last second packets',\n\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\tdata: []\n\t\t]]\n\t];\n\tcompNames.each { compName ->\n\t\tdef value = result.stats[compName].data.find { it.var.contains('Last second packets') };\n\t\tif (!value) return;\n\t\tpacketsLastSecond.labels.add(compName);\n\t\tpacketsLastSecond.datasets[0].data.add(Integer.parseInt(value.value));\n\t}\n\n\tdef packetsLastMinute = [\n\t\tlabels : [],\n\t\tdatasets: [[\n\t\t\tlabel: 'Last minute packets',\n\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\tdata: []\n\t\t]]\n\t];\n\tcompNames.each { compName ->\n\t\tdef value = result.stats[compName].data.find { it.var.contains('Last minute packets') };\n\t\tif (!value) return;\n\t\tpacketsLastMinute.labels.add(compName);\n\t\tpacketsLastMinute.datasets[0].data.add(Integer.parseInt(value.value));\n\t}\t\n\t\n\tdef packetsLastHour = [\n\t\tlabels : [],\n\t\tdatasets: [[\n\t\t\tlabel: 'Last hour packets',\n\t\t\tfillColor: \"rgba(151,187,205,0.5)\",\n\t\t\tstrokeColor: \"rgba(151,187,205,0.8)\",\n\t\t\thighlightFill: \"rgba(151,187,205,0.75)\",\n\t\t\thighlightStroke: \"rgba(151,187,205,1)\",\n\t\t\tdata: []\n\t\t]]\n\t];\n\tcompNames.each { compName ->\n\t\tdef value = result.stats[compName].data.find { it.var.contains('Last hour packets') };\n\t\tif (!value) return;\n\t\tpacketsLastHour.labels.add(compName);\n\t\tpacketsLastHour.datasets[0].data.add(Integer.parseInt(value.value));\n\t}\t\t\n\tdef tmp = null;\n%>\n\n<table style='border-spacing: 0px;'>\n\t<tr>\n\t\t<td style=\"margin:0px;vertical-align:top; background-color: lightgray; padding: 8px;\">\n\t\t\t<h3>Components:</h3>\n\t\t\t<ul style='padding: 0px;width: 150px;'><% compNames.each { %>\n\t\t\t\t<li style='padding:0px; margin: 0px; display:block;'><a style=\"display:block;\" href='${it}'>${it}</a></li>\n\t\t\t<% } %></ul>\n\t\t</td>\n\t\t<td>\n\n<table>\n\t<tr>\n\t\t<td><% def mr = result.stats['message-router'].data; \n\t\t\t   tmp  = Float.parseFloat(mr.find { it.var.endsWith('Load average') }?.value?.replace(',','.'));\n\t\t\t   def loadAverage = [[\n\t\t\t\t\tvalue : tmp,\n\t\t\t\t\tcolor:\"#F7464A\",\n\t\t\t\t\thighlight: \"#FF5A5E\",\n\t\t\t\t\tlabel : 'Load'\n\t\t\t   ],[\n\t\t\t\t\tvalue : (Float.parseFloat(mr.find { it.var.endsWith('CPUs no') }?.value)-tmp),\n\t\t\t\t\tcolor: \"#46BFBD\",\n\t\t\t\t\thighlight: \"#5AD3D1\",\n\t\t\t\t\tlabel : 'Free'\n\t\t\t   ]];\n\t\t\t   tmp = Float.parseFloat(mr.find { it.var.endsWith('CPU usage [%]') }?.value.replace(',','.'));\n\t\t\t   def cpuUsage = [[\n\t\t\t\t\tvalue : tmp,\n\t\t\t\t\tcolor:\"#F7464A\",\n\t\t\t\t\thighlight: \"#FF5A5E\",\n\t\t\t\t\tlabel : 'Used'\n\t\t\t   ],[\n\t\t\t\t\tvalue : (((Float) 100) - (tmp)),\n\t\t\t\t\tcolor: \"#46BFBD\",\n\t\t\t\t\thighlight: \"#5AD3D1\",\n\t\t\t\t\tlabel : 'Free'\t\t\t   \n\t\t\t   ]];\n\t\t\t   tmp = Float.parseFloat(mr.find { it.var.endsWith('HEAP usage [%]') }?.value.replace(',','.'));\n\t\t\t   def memHeapUsage = [[\n\t\t\t\t\tvalue : tmp,\n\t\t\t\t\tcolor:\"#F7464A\",\n\t\t\t\t\thighlight: \"#FF5A5E\",\n\t\t\t\t\tlabel : 'Used'\n\t\t\t   ],[\n\t\t\t\t\tvalue : (((Float) 100) - (tmp)),\n\t\t\t\t\tcolor: \"#46BFBD\",\n\t\t\t\t\thighlight: \"#5AD3D1\",\n\t\t\t\t\tlabel : 'Free'\t\t\t\t   \n\t\t\t   ]];\n\t\t\t%>\n\t\t\t<table>\n\t\t\t\t<tr><td colspan='3'>Uptime: ${mr.find { it.var.endsWith('Uptime') }?.value }<br/>CPUs no: ${mr.find { it.var.endsWith('CPUs no') }?.value}<br/>Threads count: ${mr.find { it.var.endsWith('Threads count') }?.value}</td></tr> \n\t\t\t\t<tr>\n\t\t\t\t\t<td><canvas id='loadAverage' width='300' height='200'></canvas></td>\n\t\t\t\t\t<td><canvas id='cpuUsage' width='300' height='200'></canvas></td>\n\t\t\t\t\t<td><canvas id='memHeapUsage' width='300' height='200'></canvas></td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style='text-align: center'>Load average: ${mr.find { it.var.endsWith('Load average') }?.value }</td>\n\t\t\t\t\t<td style='text-align: center'>CPU usage [%]: ${mr.find { it.var.endsWith('CPU usage [%]') }?.value.replace(',','.')}</td>\n\t\t\t\t\t<td style='text-align: center'>HEAP usage [%]: ${mr.find { it.var.endsWith('HEAP usage [%]') }?.value.replace(',','.')}</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<canvas id=\"packetsLastSecond\" width=\"800\" height=\"400\"></canvas>\n\t\t\t<div id='packetsLastSecond-legend'></div>\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<canvas id=\"packetsLastMinute\" width=\"800\" height=\"400\"></canvas>\n\t\t\t<div id='packetsLastMinute-legend'></div>\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<canvas id=\"packetsLastHour\" width=\"800\" height=\"400\"></canvas>\n\t\t\t<div id='packetsLastHour-legend'></div>\n\t\t</td>\n\t</tr>\n</table>\n\n<script>\n\tvar loadAverageData = ${groovy.json.JsonOutput.toJson(loadAverage)};\n\tvar loadAverageCtx = document.getElementById(\"loadAverage\").getContext(\"2d\");\n\tvar loadAverageChart = new Chart(loadAverageCtx).Doughnut(loadAverageData);\n\n\tvar cpuUsageData = ${groovy.json.JsonOutput.toJson(cpuUsage)};\n\tvar cpuUsageCtx = document.getElementById(\"cpuUsage\").getContext(\"2d\");\n\tvar cpuUsageChart = new Chart(cpuUsageCtx).Doughnut(cpuUsageData);\n\n\tvar memHeapUsageData = ${groovy.json.JsonOutput.toJson(memHeapUsage)};\n\tvar memHeapUsageCtx = document.getElementById(\"memHeapUsage\").getContext(\"2d\");\n\tvar memHeapUsageChart = new Chart(memHeapUsageCtx).Doughnut(memHeapUsageData);\t\n\t\n\tvar packetsLastSecondData =  ${groovy.json.JsonOutput.toJson(packetsLastSecond)};\t\n\tvar packetsLastSecondCtx = document.getElementById(\"packetsLastSecond\").getContext(\"2d\");\n\tvar packetsLastSecondChart = new Chart(packetsLastSecondCtx).Bar(packetsLastSecondData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('packetsLastSecond-legend').innerHTML = packetsLastSecondChart.generateLegend();\n\n\tvar packetsLastMinuteData =  ${groovy.json.JsonOutput.toJson(packetsLastMinute)};\t\n\tvar packetsLastMinuteCtx = document.getElementById(\"packetsLastMinute\").getContext(\"2d\");\n\tvar packetsLastMinuteChart = new Chart(packetsLastMinuteCtx).Bar(packetsLastMinuteData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('packetsLastMinute-legend').innerHTML = packetsLastMinuteChart.generateLegend();\n\n\tvar packetsLastHourData =  ${groovy.json.JsonOutput.toJson(packetsLastHour)};\t\n\tvar packetsLastHourCtx = document.getElementById(\"packetsLastHour\").getContext(\"2d\");\n\tvar packetsLastHourChart = new Chart(packetsLastHourCtx).Bar(packetsLastHourData, { legendTemplate : templateLegends.bar });\n\tdocument.getElementById('packetsLastHour-legend').innerHTML = packetsLastHourChart.generateLegend();\n</script>\n\t\t</td>\n\t</tr>\n</table>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/stream/Stream.groovy",
    "content": "/*\n * Tigase HTTP API\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage rest.stream\n\nimport tigase.http.rest.Service\nimport tigase.server.Packet\nimport tigase.xml.DomBuilderHandler\nimport tigase.xml.Element\nimport tigase.xml.SimpleParser\nimport tigase.xml.SingletonFactory\n\nimport javax.servlet.http.HttpServletRequest\nimport javax.servlet.http.HttpServletResponse\n/**\n * Class implements ability to send packets to any JID using REST API\n *\n * @author andrzej\n */\nclass Stream extends tigase.http.rest.Handler {\n\t\n\tpublic Stream() {\n\t\tdescription = [\n\t\t\tregex : \"/{to_jid}\",\n\t\t\tPOST : [ info:'Send XMPP stanza', \n\t\t\t\tdescription: \"\"\"Sends passed HTTP content as XMPP stanza.\nIf {to_jid} parameter is part of url then value of this parameter is used as destination address of XMPP stanza.\\n\\\n\nExample of content for sending a message:\n*code*<message to=\"user1@example.com\" from=\"user2@example.com\">\n<body>Example message</body>\n</message>*/code*\n\"\"\"]\n\t\t]\n\t\tregex = /\\/(.*)/\n\t\tisAsync = true\n\t\tdecodeContent = false\n\t\trequiredRole = \"admin\"\n\t\t\n\t\texecPost = { Service service, callback, user, HttpServletRequest request, to ->\n\t\t\tchar[] data = request.getReader().getText()?.toCharArray();\n\t\t\tif (data == null || data.length == 0) {\n\t\t\t\tcallback({ req, HttpServletResponse resp ->\n\t\t\t\t\t\tresp.sendError(HttpServletResponse.SC_BAD_REQUEST, \"No data received\");\n\t\t\t\t})\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tSimpleParser parser   = SingletonFactory.getParserInstance();\n\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\tparser.parse(domHandler, data, 0, data.length);\n\t\t\tElement packetEl = domHandler.getParsedElements().poll();\n\t\t\tif (packetEl == null) {\n\t\t\t\tcallback({ req, HttpServletResponse resp ->\n\t\t\t\t\t\tresp.sendError(HttpServletResponse.SC_BAD_REQUEST, \"Missing XML element in content\");\n\t\t\t\t})\n\t\t\t\treturn;\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif (to != null) {\n\t\t\t\tto = to.trim();\n\t\t\t\tif (!to.isEmpty()) {\n\t\t\t\t\tpacketEl.setAttribute(\"to\", to);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\t\tdef responseHandler = (packet.getElemName() == \"iq\" && packet.getAttribute(\"from\") == null) ? { Packet result ->\n\t\t\t\tcallback({ req, HttpServletResponse resp -> \n\t\t\t\t\tdef outBytes = result.getElement().toString().getBytes();\n\t\t\t\t\tresp.setContentType(\"application/xml\");\n\t\t\t\t\tresp.setContentLength(outBytes.length);\n\t\t\t\t\tresp.getOutputStream().write(outBytes);\n\t\t\t\t});\n\t\t\t} : null;\n\t\t\t\n\t\t\tservice.sendPacket(packet, null, responseHandler);\n\t\t\t\n\t\t\tif (responseHandler == null) {\n\t\t\t\tcallback(\"\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/user/UserAdmin.groovy",
    "content": "package tigase.rest.user\n\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.server.Iq\nimport tigase.server.Packet\nimport tigase.xml.Element\nimport tigase.xmpp.BareJID\nimport tigase.xmpp.StanzaType\n\n/**\n * Class implements ability to manage users for service administrator\n * Handles requests for /rest/user/user@domain where user@domain is jid\n *\n * Example format of content of request or response:\n * <user><jid>user@domain</jid><password>Paa$$w0rd</password></jid></user>\n */\nclass UserAdminHandler extends tigase.http.rest.Handler {\n\n\t def TIMEOUT = 30 * 1000;\n\t def COMMAND_XMLNS = \"http://jabber.org/protocol/commands\";\n\t\n    public UserAdminHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{user_jid}\",\n\t\t\tGET : [ info:'Retrieve user account details', \n\t\t\t\tdescription: \"\"\"Only required parameter is part of url {user_jid} which is jid of user which account informations you want to retrieve.\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\\n\\\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\" ],\n\t\t\tPUT : [ info:'Create new user account',\n\t\t\t\tdescription: \"\"\"Part of url {user_jid} is parameter which is jid of user which account you want to create, ie. user@example.com.\nTo create account additional data needs to be passed as content of HTTP request:\n\\${util.formatData([user:[password:'some_password',email:'user@example.com']])}\n\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\" ],\n\t\t\tPOST : [ info:'Update user account',\n\t\t\t\tdescription: \"\"\"Part of url {user_jid} is parameter which is jid of user which account you want to update, ie. user@example.com.\\n\\\nAdditional data needs to be passed as content of HTTP request to change password for this account:\n\\${util.formatData([user:[password:'some_password']])}\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\"],\n\t\t\tDELETE : [ info:'Delete user account',\n\t\t\t\tdescription: \"\"\"Part of url {user_jid} is parameter which is jid of user which account you want to remove, ie. user@example.com.\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\"],\n\t\t];\n        regex = /\\/([^@\\/]+)@([^@\\/]+)/\n\t\tauthRequired = { api_key -> return api_key == null && requiredRole != null }\n        requiredRole = \"admin\"\n        isAsync = true\n        execGet = { Service service, callback, user, localPart, domain ->\n            def jid = BareJID.bareJIDInstance(localPart, domain);\n            def uid = service.getUserRepository().getUserUID(jid);\n            if (uid <= 0) {\n                callback(null);\n            }\n            else {\n                callback([user:[jid:\"$localPart@$domain\", domain:domain, uid:uid]]);\n            }\n        }\n        execPut = { Service service, callback, user, content, localPart, domain ->\n            def jid = BareJID.bareJIDInstance(localPart, domain);\n            def password = content.user.password;\n\t\t\tdef email = content.user.email;\n\t\t\ttry {\n\t\t        service.getAuthRepository().addUser(jid, password);\n\t\t\t\tdef uid = service.getUserRepository().getUserUID(jid);\n\t\t\t\tif (uid && email) {\n\t\t\t\t\tservice.getUserRepository().setData(jid, \"email\", email);\n\t\t\t\t}\n\t\t\t\tcallback([user:[jid:\"$localPart@$domain\", domain:domain, uid: uid]]);\n\t\t\t} catch (tigase.db.UserExistsException ex) {\n\t\t\t\tcallback({ req, resp -> \n\t\t\t\t\t\tresp.sendError(409, \"User exists\");\n\t\t\t\t\t});\n\t\t\t}\n        }\n        execDelete = { Service service, callback, user, localPart, domain ->\n            def jid = BareJID.bareJIDInstance(localPart, domain);\n            def uid = service.getUserRepository().getUserUID(jid);\n            \n\t\t\tElement iq = new Element(\"iq\");\n            iq.setAttribute(\"to\", \"sess-man@\" + domain);\n\t\t\tif (user != null && user != \"null\") {\n\t\t\t\tiq.setAttribute(\"from\", user.toString());\n\t\t\t}\n            iq.setAttribute(\"type\", \"set\");\n            iq.setAttribute(\"id\", UUID.randomUUID().toString())\n\n            Element command = new Element(\"command\");\n            command.setXMLNS(COMMAND_XMLNS);\n            command.setAttribute(\"node\", \"http://jabber.org/protocol/admin#delete-user\");\n            iq.addChild(command);\n\n\t\t\tElement x = new Element(\"x\");\n\t\t\tx.setXMLNS(\"jabber:x:data\");\n\t\t\tx.setAttribute(\"type\", \"submit\");\n\t\t\tcommand.addChild(x);\n\t\t\t\n\t\t\tElement fieldEl = new Element(\"field\");\n\t\t\tfieldEl.setAttribute(\"var\", \"notify-cluster\");\n\t\t\tfieldEl.addChild(new Element(\"value\", \"true\"));\n\t\t\tx.addChild(fieldEl);\n\t\t\tfieldEl = new Element(\"field\");\n\t\t\tfieldEl.setAttribute(\"var\", \"accountjids\");\n\t\t\tfieldEl.addChild(new Element(\"value\", jid.toString()));\n\t\t\tx.addChild(fieldEl);\n\t\t\t\n\t\t\tservice.sendPacket(new Iq(iq), TIMEOUT, { Packet result ->\n                if (result == null || result.getType() == StanzaType.error) {\n                    callback(null);\n                    return;\n                }\n\t\t\t\t\n\t\t\t\tcommand = result.getElement().getChild(\"command\", COMMAND_XMLNS);\n\t\t\t\tdef noteEl = command.getChildren().find{ it.getName() == \"x\" }.getChildren().find{ it.getAttribute(\"var\") == \"Notes\" };\n\t\t\t\tif (noteEl == null) {\n\t\t\t\t\tcallback(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcallback([user:[jid:\"$localPart@$domain\", domain:domain, uid:uid]]);\n\t\t\t});\n        }\n        execPost = { Service service, callback, user, content, localPart, domain ->\n            def jid = BareJID.bareJIDInstance(localPart, domain);\n            def password = content.user.password;\n            service.getAuthRepository().updatePassword(jid, password)\n            def uid = service.getUserRepository().getUserUID(jid);\n            callback([user:[jid:\"$localPart@$domain\", domain:domain, uid: uid]]);\n        }\n    }\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/user/UserAdminGet.html",
    "content": "${ util.include('header', [title:'User details']) }\n<table style=\"margin: auto;\">\n<tr>\n<td>\n<img style=\"max-height: 100px; max-width: 100px;\" src=\"${util.link(\"/avatar/\" + result?.user?.jid)}\" />\n</td>\n<td>\n<b>User:   </b>${result?.user?.jid}<br/>\n<b>Domain: </b>${result?.user?.domain}<br/>\n<b>UID:    <b/>${result?.user?.uid}<br/>\n</td>\n</tr>\n</table>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/user/UserUser.groovy",
    "content": "package tigase.rest.user\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.xmpp.BareJID\n\n/**\n * Class implements ability to change user password or remove account by user\n * Handles requests for /rest/user/ and executes request for currently authenticated user\n *\n * Example format of content of request or response:\n * <user><jid>user@domain</jid><password>Paa$$w0rd</password></jid></user>\n */\nclass UserUserHandler extends tigase.http.rest.Handler {\n\n    public UserUserHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/\",\n\t\t\tGET : [ info:'Retrieve details of active user account', \n\t\t\t\tdescription: \"\"\"Only required parameter is part of url {user_jid} which is jid of user which account informations you want to retrieve.\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\\n\\\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\" ],\n\t\t\tPOST : [ info:'Change password of active user account',\n\t\t\t\tdescription: \"\"\"Part of url {user_jid} is parameter which is jid of user which account you want to update, ie. user@example.com.\\n\\\nAdditional data needs to be passed as content of HTTP request to change password for this account:\n\\${util.formatData([user:[password:'some_password']])}\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\"],\n\t\t\tDELETE : [ info:'Delete active user account',\n\t\t\t\tdescription: \"\"\"Part of url {user_jid} is parameter which is jid of user which account you want to remove, ie. user@example.com.\nData will be returned in form of JSON or XML depending on selected format by Accept HTTP header\n\nExample response:\n\\${util.formatData([user:[jid:'user@example.com', domain:'example.com', uid:10 ]])}\t\t\t\t\n\"\"\"],\n\t\t];\n        regex = /\\//\n        requiredRole = \"user\"\n        isAsync = false\n        execGet = { Service service, callback, jid ->\n            def uid = service.getUserRepository().getUserUID(jid);\n            if (uid <= 0) {\n                callback(null);\n            }\n            else {\n                callback([user:[jid:\"${jid.toString()}\", domain:jid.getDomain(), uid:uid]]);\n            }\n        }\n        execDelete = { Service service, callback, jid ->\n\t\t\tdef uid = service.getUserRepository().getUserUID(jid);\n\t\t\t\tservice.getAuthRepository().removeUser(jid)\n\t\t\t\ttry {\n\t\t\t\t\tservice.getUserRepository().removeUser(bareJID)\n\t\t\t\t} catch (tigase.db.UserNotFoundException ex) {\n\t\t\t\t\n\t\t\t\t}\n            callback([user:[jid:\"${jid.toString()}\", domain:jid.getDomain(), uid:uid]]);\n        }\n        execPost = { Service service, callback, content, jid ->\n            def password = content.user.password;\n            service.getAuthRepository().updatePassword(jid, password)\n            def uid = service.getUserRepository().getUserUID(jid);\n            callback([user:[jid:\"${jid.toString()}\", domain:jid.getDomain(), uid:uid]]);\n        }\n    }\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/user/UserUserGet.html",
    "content": "${ util.include('header', [title:'User details']) }\n<table style=\"margin: auto;\">\n<tr>\n<td>\n<img style=\"max-height: 100px; max-width: 100px;\" src=\"${util.link(\"/avatar/\" + result?.user?.jid)}\" />\n</td>\n<td>\n<b>User:   </b>${result?.user?.jid}<br/>\n<b>Domain: </b>${result?.user?.domain}<br/>\n<b>UID:    <b/>${result?.user?.uid}<br/>\n</td>\n</tr>\n</table>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/users/UsersDomainList.groovy",
    "content": "package tigase.rest.users\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.xmpp.BareJID\n\n/**\n * Class implements ability to retrieve by service administrator list of registered accounts for domain\n * Handles requests for /rest/users/domain where domain is name of domain for which we want to retrieve list of users\n *\n * Example format of content of response:\n * <users><items><item>user1@domain</item><item>user2@domain</item></items><count>2</count></users>\n */\nclass UsersDomainHandler extends tigase.http.rest.Handler {\n\n    public UsersDomainHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/{domain}\",\n\t\t\tGET : [ info:'Retrieve list of registered user jids for domain', \n\t\t\t\tdescription: \"\"\"Request requires name of domain as parameter {domain} and returns list of all registered user accounts for this domain.\n\nExample response will look like this:\n\\${util.formatData([users:[items:['user1@example.com','user2@example.com','user3@example.com'],count:3]])}\n\"\"\"]\n\t\t];\t\t\n        regex = /\\/([^@\\/]+)/\n        requiredRole = \"admin\"\n        isAsync = false\n        execGet = { Service service, callback, jid, domain ->\n            def repo = service.getUserRepository().getRepo(domain);\n            if (!repo) callback(null);\n            def users = repo.getUsers().findAll { it.getDomain() == domain };\n            callback([users:[items:users, count:users.size()]]);\n        }\n    }\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/users/UsersDomainListGet.html",
    "content": "${ util.include('header', [title:'All users for domain ' + result.users.domain]) }\n<table style=\"margin: auto;\">\n<tr>\n<th>Avatar</th>\n<th>User JID</th>\n</tr>\n<% result.users.items.each { user -> %>\n<tr>\n<td>\n<img style=\"max-height: 50px; max-width: 50px;\" src=\"${util.link(\"/avatar/\" + user)}\" />\n</td>\n<td>\n<a href=\"${util.link(\"/user/\"+user)}\">${user}</a>\n</td>\n</tr>\n<% } %>\n</table>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/users/UsersList.groovy",
    "content": "package tigase.rest.users\n/*\n * Tigase HTTP API\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\nimport tigase.http.rest.Service\nimport tigase.xmpp.BareJID\n\n/**\n * Class implements ability to retrieve by service administrator list of registered accounts\n * Handles requests for /rest/users/\n *\n * Example format of content of response:\n * <users><items><item>user1@domain</item><item>user2@domain</item></items><count>2</count></users>\n */\nclass UsersHandler extends tigase.http.rest.Handler {\n\n    public UsersHandler() {\n\t\tdescription = [\n\t\t\tregex : \"/\",\n\t\t\tGET : [ info:'Retrieve list of registered user jids', \n\t\t\t\tdescription: \"\"\"Request do not require any parameters and returns list of all registered user accounts on this server (for all vhosts).\n\nExample response will look like this:\n\\${util.formatData([users:[items:['user1@example.com','user2@example.com','user1@example2.com'],count:3]])}\n\"\"\"]\n\t\t];\n        regex = /\\//\n        requiredRole = \"admin\"\n        isAsync = false\n        execGet = { Service service, callback, jid ->\n            def users = service.getUserRepository().getUsers()\n            callback([users:[items:users, count:users.size()]]);\n        }\n    }\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/scripts/rest/users/UsersListGet.html",
    "content": "${ util.include('header', [title:'All users']) }\n<table style=\"margin: auto;\">\n<tr>\n<th>Avatar</th>\n<th>User JID</th>\n</tr>\n<% result.users.items.each { user -> %>\n<tr>\n<td>\n<img style=\"max-height: 50px; max-width: 50px;\" src=\"${util.link(\"/avatar/\" + user)}\" />\n</td>\n<td>\n<a href=\"${util.link(\"/user/\"+user)}\">${user}</a>\n</td>\n</tr>\n<% } %>\n</table>\n${ util.include('footer') }"
  },
  {
    "path": "tigase-server 7.1.0/scripts/restart-all-servers.sh",
    "content": "#!/bin/bash\n\n\nif [ \"$1\" == \"\" ] ; then\n  SERVS=`cat all-production-servers.txt`\nelse\n  SERVS=`cat $1`\nfi\n\n[[ -f script.conf ]] && . script.conf\n\nSERVERS=\"\"\n\nfor s in \"${SERVS}\" ; do\n  if [[ ${s} != \"#\"* ]] ; then\n    SERVERS=\"${SERVERS} ${s}\"\n  fi\ndone\n\nTIGASE_USER=\"tigase\"\nDIR=\"/home/${TIGASE_USER}/tigase-server\"\nPROP_FILE=\"cluster.properties\"\nCONF_FILE=\"cluster.tigase.conf\"\nJARS=\"target/tigase-server.jar\"\nLOG_TIMESTAMP=`date +\"%Y-%m-%d_%H-%M-%S\"`\nIPS=()\nCOLORS=('green' 'yellow' 'orange' 'blue' 'white' 'lightblue' 'gray' 'pink' 'lightgreen' 'red')\n\necho -e \"=== SERVERS:\\n${SERVERS}\"\necho -e \"=== DIR:\\n${DIR}\"\n\nread -p \"Press [Enter] key to start restart...\"\n\nfunction restart_server() {\n\n  s=$1\n  s_ip=$2\n  echo \"Restarting: ${s} ${s_ip}\"\n\n  if [ -f ${PROP_FILE} ] ; then\n    echo -e \"\\n\\n Copying ${PROP_FILE} file to ${s}\"\n    scp ${PROP_FILE} root@${s}:${DIR}/etc/init.properties\n  fi\n  if [ -f ${CONF_FILE} ] ; then\n    echo -e \"\\n\\n Copying ${CONF_FILE} file to ${s}\"\n    echo \"The cluster node ${s} IP is: ${s_ip}\"\n    sed -e \"s/\\(Djava.rmi.server.hostname=.*\\\"\\)/Djava.rmi.server.hostname=${s_ip}\\\"/\" ${CONF_FILE} > ${CONF_FILE}_${s}\n    scp ${CONF_FILE}_${s} root@${s}:${DIR}/etc/tigase.conf\n  fi\n  echo \"Copying jar files\"\n  for f in ${JARS} ; do\n    echo -e \"\\n\\n Copying ${f} file to ${s}\"\n    [[ -f ${f} ]]  && scp ${f} root@${s}:${DIR}/jars/\n  done\n  echo -e \"\\n\\n===\\trestarting ${s} ===\"\n  ssh root@${s} \"chown -R ${TIGASE_USER}:${TIGASE_USER} /home/${TIGASE_USER} ; service tigase stop ; sleep 10 ; cp -r $\\\n{DIR}/logs ${DIR}/logs_${LOG_TIMESTAMP} ; rm -f ${DIR}/logs/* ; service tigase start\"\n  echo -e \"===\\trestart of ${s} FINISHED ===\"\n}\n\nfunction restart_tmp() {\n\n  s=$1\n  s_ip=$2\n\techo \"Restarting: ${s} ${s_ip}\"\n  sleep 5\n\techo \"${s} restarted\"\n\n}\n\necho \"Resolving IPs...\"\n\ncnt=0\nfor s in ${SERVERS} ; do\n\n  IPS[$cnt]=`host ${s} | sed -e \"s/.*has address \\(.*\\)/\\1/\"`\n  echo \"${COLORS[$cnt]}:${s}:${IPS[$cnt]}\"\n  ((cnt++))\n\ndone\n\necho -ne \"nodes=\"\nCOLORS=('green' 'yellow' 'orange' 'blue' 'white' 'lightblue' 'gray' 'pink' 'lightgreen' 'red')\nfor i in \"${!IPS[@]}\"; do\n  echo -ne \"${COLORS[$i]}:${IPS[$i]},\"\ndone\necho \"\"\n\ncnt=0\nfor s in ${SERVERS} ; do\n\n  s_ip=${IPS[$cnt]}\n  ((cnt++))\n\n  restart_server $s $s_ip&\n\ndone\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/stop-all-servers.sh",
    "content": "#!/bin/bash\n\n\nif [ \"$1\" == \"\" ] ; then\n  SERVERS=`cat all-production-servers.txt`\nelse\n  SERVERS=`cat $1`\nfi\n\nDIR=\"/home/tigase/tigase-server\"\n\necho -e \"=== SERVERS:\\n${SERVERS}\"\necho -e \"=== DIR:\\n${DIR}\"\n\nread -p \"Press [Enter] key to start restart...\"\n\nfor s in ${SERVERS} ; do\n\n  if [[ ${s} != \"#\"* ]] ; then\n\n\techo -e \"\\n\\n===\\trestarting ${s} ===\"\n\n\tssh root@${s} \"service tigase stop\"\n\n\techo -e \"===\\trestart of ${s} FINISHED ===\"\n\n  fi\n\ndone\n\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/tigase.sh",
    "content": "#!/bin/bash\n##\n##  Tigase Jabber/XMPP Server\n##  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n##\n##  This program is free software: you can redistribute it and/or modify\n##  it under the terms of the GNU Affero General Public License as published by\n##  the Free Software Foundation, either version 3 of the License.\n##\n##  This program is distributed in the hope that it will be useful,\n##  but WITHOUT ANY WARRANTY; without even the implied warranty of\n##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n##  GNU Affero General Public License for more details.\n##\n##  You should have received a copy of the GNU Affero General Public License\n##  along with this program. Look for COPYING file in the top folder.\n##  If not, see http://www.gnu.org/licenses/.\n##\n##  $Rev: $\n##  Last modified by $Author: $\n##  $Date: $\n##\n#\n# This is Tigase (http://www.tigase.org) server startup file.\n#\n# First parameter is a command (start, stop and so on...),\n# second parameters is parameters file - the file where from\n# environment variables are read like:\n# JAVA_HOME\n# JAVA_OPTIONS\n# CLASSPATH\n# TIGASE_HOME\n# TIGASE_CONSOLE_LOG\n# TIGASE_PID\n# OSGI=true\n#\n# If not given the script will try to search for the file and if\n# not found default parameters will be used.\n\nfunction usage()\n{\n  echo \"Usage: $0 {start|stop|run|clear|clearrestart|restart|check|status} [params-file.conf]\"\n  exit 1\n}\n\nif [ -z \"${2}\" ] ; then\n  DEF_PARAMS=\"tigase.conf\"\n  # Gentoo style config location\n  if [ -f \"/etc/conf.d/${DEF_PARAMS}\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/conf.d/${DEF_PARAMS}\"\n  elif [ -f \"/etc/${DEF_PARAMS}\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/${DEF_PARAMS}\"\n  elif [ -f \"/etc/tigase/${DEF_PARAMS}\" ] ; then\n\t\tTIGASE_PARAMS=\"/etc/tigase/${DEF_PARAMS}\"\n  else\n\t\tTIGASE_PARAMS=\"${TIGASE_HOME}/etc/tigase.conf\"\n  fi\n # echo \"No params-file.conf given. Using: '$TIGASE_PARAMS'\"\nelse\n  TIGASE_PARAMS=${2}\nfi\n\n[[ -f \"${TIGASE_PARAMS}\" ]] && . ${TIGASE_PARAMS}\n\nif [ -z \"${JAVA_HOME}\" ] ; then\n  echo \"JAVA_HOME is not set.\"\n  echo \"Please set it to correct value before starting the sever.\"\n  exit 1\nfi\n\nif [ -z \"${TIGASE_HOME}\" ] ; then\n  if [ ${0:0:1} = '/' ] ; then\n    TIGASE_HOME=${0}\n  else\n    TIGASE_HOME=${PWD}/${0}\n  fi\n  TIGASE_HOME=`dirname ${TIGASE_HOME}`\n  TIGASE_HOME=`dirname ${TIGASE_HOME}`\n\n  TIGASE_JAR=\"\"\nfi\n\nif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\tLIB_DIR=jars\n\tJAR_FILE=${LIB_DIR}/org.apache.felix.main*.jar\nelse\n\tLIB_DIR=jars\n\tJAR_FILE=${LIB_DIR}/tigase-server*.jar\nfi\n\nfor j in ${TIGASE_HOME}/${JAR_FILE} ; do\n\tif [ -f ${j} ] ; then\n\t  TIGASE_JAR=${j}\n\t  break\n\tfi\ndone\n\nif [ -z ${TIGASE_JAR} ] ; then\n\techo \"TIGASE_HOME is not set.\"\n\techo \"Please set it to correct value before starting the sever.\"\n\texit 1\nfi\n\nif [ -z \"${TIGASE_CONSOLE_LOG}\" ] ; then\n  if [ ! -d \"logs\" ] ; then\n    mkdir logs\n  fi\n  if [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n\t\tTIGASE_CONSOLE_LOG=\"${TIGASE_HOME}/logs/tigase-console.log\"\n  else\n\t\tTIGASE_CONSOLE_LOG=\"/dev/null\"\n  fi\nfi\n\nif [ -z \"${TIGASE_PID}\" ] ; then\n  if [ -w \"${TIGASE_HOME}/logs/\" ] ; then\n\t\tTIGASE_PID=\"${TIGASE_HOME}/logs/tigase.pid\"\n  else\n\t\tif [ -w \"/var/run/\" ] ; then\n\t    TIGASE_PID=\"/var/run/tigase.pid\"\n\t\telse\n\t    TIGASE_PID=\"/var/tmp/tigase.pid\"\n\t\tfi\n  fi\nfi\n\n[[ -z \"${TIGASE_RUN}\" ]] && \\\n  TIGASE_RUN=\"tigase.server.XMPPServer ${TIGASE_OPTIONS}\"\n\n[[ -z \"${JAVA}\" ]] && JAVA=\"${JAVA_HOME}/bin/java\"\n\n[[ -z \"${CLASSPATH}\" ]] || CLASSPATH=\"${CLASSPATH}:\"\n\nCLASSPATH=\"${CLASSPATH}${TIGASE_JAR}\"\n\nCLASSPATH=\"`ls -d ${TIGASE_HOME}/${LIB_DIR}/*.jar 2>/dev/null | grep -v wrapper | tr '\\n' :`${CLASSPATH}\"\n\nLOGBACK=\"-Dlogback.configurationFile=$TIGASE_HOME/etc/logback.xml\"\n\nif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\tTIGASE_CMD=\"${JAVA} ${JAVA_OPTIONS} ${LOGBACK} -jar ${JAR_FILE}\"\nelse\n\tTIGASE_CMD=\"${JAVA} ${JAVA_OPTIONS} ${LOGBACK} -cp ${CLASSPATH} ${TIGASE_RUN}\"\nfi\n\ncd \"${TIGASE_HOME}\"\n\ncase \"${1}\" in\n  start)\n    echo \"Starting Tigase: \"\n\n    if [ -f ${TIGASE_PID} ] && kill -0 $(<${TIGASE_PID}) 2>/dev/null\n    then\n      echo \"Already Running!!\"\n      exit 1\n    fi\n\n    echo \"STARTED Tigase `date`\" >> ${TIGASE_CONSOLE_LOG}\n\n    nohup sh -c \"exec $TIGASE_CMD >>${TIGASE_CONSOLE_LOG} 2>&1\" >/dev/null &\n    echo $! > $TIGASE_PID\n    echo \"Tigase running pid=\"`cat $TIGASE_PID`\n    ;;\n\n  stop)\n    PID=`cat $TIGASE_PID 2>/dev/null`\n    if [ -z \"$PID\" ] ; then\n      echo \"Tigase is not running.\"\n      exit 0\n    fi\n    echo \"Shutting down Tigase: $PID\"\n\n\tkill $PID 2>/dev/null\n\tfor ((i=1; i <= 10; i++)) ; do\n\t  if ps -p $PID > /dev/null ; then\n\t\techo \"$i. Waiting for the server to terminate...\"\n\t\tsleep 1\n\t  else\n\t\techo \"$i. Tigase terminated.\"\n\t\tbreak\n\t  fi\n\tdone\n\t\n\tif ps -p $PID > /dev/null ; then\n      echo \"Forcing the server to terminate.\"\n      kill -9 $PID 2>/dev/null\n    fi\n    rm -f $TIGASE_PID\n    echo \"STOPPED `date`\" >>${TIGASE_CONSOLE_LOG}\n    ;;\n\n  restart)\n    $0 stop $2\n    sleep 5\n    $0 start $2\n    ;;\n\n  clearrestart)\n    $0 stop $2\n    sleep 5\n    $0 clear $2\n    sleep 2\n    $0 start $2\n    ;;\n\n  clear)\n    LOGBACK=\"${TIGASE_HOME}/logs\"`date \"+%Y-%m-%d--%H:%M:%S\"`\n\techo \"Clearing logs, moving backup to \" ${LOGBACK}\n\tmkdir -p ${LOGBACK}\n\tmv \"${TIGASE_HOME}/logs\"/* ${LOGBACK}/\n\tif [ -n \"${OSGI}\" ] && ${OSGI} ; then\n\t\techo \"Clearing osgi cache\"\n\t\trm -rf \"${TIGASE_HOME}/felix-cache\"/*;\n\tfi\n    ;;\n\n  run)\n    echo \"Running Tigase: \"\n\n    if [ -f $TIGASE_PID ]\n    then\n      echo \"Already Running!!\"\n      exit 1\n    fi\n\n    sh -c \"exec $TIGASE_CMD\"\n    ;;\n\n  check|status)\n    echo \"Checking arguments to Tigase: \"\n    echo \"OSGI            =  $OSGI\"\n    echo \"TIGASE_HOME     =  $TIGASE_HOME\"\n    echo \"TIGASE_JAR      =  $TIGASE_JAR\"\n    echo \"TIGASE_PARAMS   =  $TIGASE_PARAMS\"\n    echo \"TIGASE_RUN      =  $TIGASE_RUN\"\n    echo \"TIGASE_PID      =  $TIGASE_PID\"\n    echo \"TIGASE_OPTIONS  =  $TIGASE_OPTIONS\"\n    echo \"JAVA_OPTIONS    =  $JAVA_OPTIONS\"\n    echo \"JAVA            =  $JAVA\"\n    echo \"JAVA_CMD        =  $JAVA_CMD\"\n    echo \"CLASSPATH       =  $CLASSPATH\"\n    echo \"TIGASE_CMD      =  $TIGASE_CMD\"\n    echo \"TIGASE_CONSOLE_LOG  =  $TIGASE_CONSOLE_LOG\"\n    echo\n\n    if [ -f ${TIGASE_PID} ] && kill -0 $(<${TIGASE_PID}) 2>/dev/null\n    then\n      echo \"Tigase running pid=\"`cat ${TIGASE_PID}`\n      exit 0\n    fi\n    exit 1\n    ;;\n  zap)\n\t\trm -f $TIGASE_PID\n\t\t;;\n\n\t*)\n    usage\n\t\t;;\nesac\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/update-all-servers.sh",
    "content": "#!/bin/bash\n\nif [ \"$1\" == \"\" ] ; then\n\tLOCATIONS=`cat all-production-servers.txt`\nelse\n\tLOCATIONS=`cat $1`\nfi\nDIR=\"/home/tigase/tigase-server\"\n\necho -e \"=== LOCATIONS:\\n${LOCATIONS}\"\necho -e \"=== DIR:\\n${DIR}\"\n\nread -p \"Press [Enter] key to start update...\"\n\n\nfor s in ${LOCATIONS} ; do\n\n\techo -e \"\\n\\n===\\tuploading to ${s} ===\"\n\n\tscp jars/tigase-server.jar tigase@${s}:${DIR}/jars/\n\tscp libs/tigase-* tigase@${s}:${DIR}/libs/\n\tscp src/main/groovy/tigase/admin/*.groovy tigase@${s}:${DIR}/scripts/admin/\n\n\techo -e \"===\\tupload to ${s} DONE ===\"\n\ndone\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/update-code-functions.sh",
    "content": "#!/bin/bash\n\nexport TMP_DIR=\"/tmp\"\n\nfunction build_xmltools() {\n   mvn -q clean package install &> ${TMP_DIR}/xmltools-build.txt\n   ant clean jar-dist &> ${TMP_DIR}/xmltools-build.txt\n   echo jars/tigase-xmltools.jar\n }\n\n function build_utils() {\n   mvn -q clean package install &> ${TMP_DIR}/utils-build.txt\n   cp -f ../xmltools/jars/tigase-xmltools.jar jars/\n   ant clean jar-dist &> ${TMP_DIR}/utils-build.txt\n   echo jars/tigase-utils.jar\n }\n\n function build_server() {\n   mvn -q clean package install &> ${TMP_DIR}/server-build.txt\n   ant clean jar-dist &> ${TMP_DIR}/server-build.txt\n   echo \"\"\n }\n\n function build_maven() {\n   mvn clean package &> ${TMP_DIR}/$1-build.txt\n   echo `find target -name \"tigase-*.jar\"`\n }\n\n function build_extras() {\n   build_maven extras\n }\n\n function build_muc() {\n   build_maven muc\n }\n\n function build_pubsub() {\n   build_maven pubsub\n }\n\nfunction build_archiving() {\n\tbuild_maven archiving\n}\n\nfunction build_socks5() {\n\tbuild_maven socks5\n}\n\nfunction build_stun() {\n\tbuild_maven stun\n}\n\nfunction build_tigase_http_api() {\n  build_maven \"tigase-http-api\"\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/update-code.sh",
    "content": "#!/bin/bash\n\nMY_DIR=`dirname ${0}`\n\n# Load external script with some utility functions\n. ${MY_DIR}/update-code-functions.sh\n\n# Load configuration\n# PROJECTS_DIR - directory with source codes for all projects:\n# xmltools, utils, extras, server, muc, pubsub, socks5, stun, archiving\n# TARGET_DIR - a directory where the installed serve binaries are located\n\nCONFIG=\"${MY_DIR}/update-code-config.sh\"\nif [ \"$1\" != \"\" ] ; then\n  CONFIG=\"$1\"\nfi\n. ${CONFIG}\n\nSRV_PACKAGES=\"xmltools utils extras server muc pubsub archiving socks5 stun tigase_http_api\"\n\nCUR_DIR=`pwd`\n\ncd ${PROJECTS_DIR}\n\n#set -x\n\necho \"Updating and building packages...\"\n\n# Build all server packages\nfor p in $SRV_PACKAGES ; do\n  echo \"Building package: $p\"\n  cd $p\n  mkdir -p jars\n  git pull\n  JAR=`build_$p`\n  echo \"jar file: $JAR\"\n  if [ ! -z \"${JAR}\" ] ; then\n    cp -f $JAR ../server/jars/tigase-$p.jar\n  fi\n  cd ..\ndone\n\n\ncd ${CUR_DIR}\n\nif [ \"${TARGET_DIR}\" != \"\" ] ; then\n  cp -fv ${PROJECTS_DIR}/server/jars/* ${TARGET_DIR}/bundle/\n\tcp -fv ${PROJECTS_DIR}/server/jars/* ${TARGET_DIR}/jars/\nfi\n"
  },
  {
    "path": "tigase-server 7.1.0/scripts/user_roster.sh",
    "content": "#!/bin/bash\n##\n##  Tigase Jabber/XMPP Server\n##  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n##\n##  This program is free software: you can redistribute it and/or modify\n##  it under the terms of the GNU Affero General Public License as published by\n##  the Free Software Foundation, either version 3 of the License.\n##\n##  This program is distributed in the hope that it will be useful,\n##  but WITHOUT ANY WARRANTY; without even the implied warranty of\n##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n##  GNU Affero General Public License for more details.\n##\n##  You should have received a copy of the GNU Affero General Public License\n##  along with this program. Look for COPYING file in the top folder.\n##  If not, see http://www.gnu.org/licenses/.\n##\n##  $Rev: $\n##  Last modified by $Author: $\n##  $Date: $\n##\n\nCP=\"jars/tigase-server.jar:libs/jdbc-mysql.jar:libs/tigase-xmltools.jar:libs/tigase-utils.jar\"\n\nD=\"-server -Xms100M -Xmx1500M -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver\"\n\nXML_REP=\"-sc tigase.db.xml.XMLRepository -su ../testsuite/user-repository.xml_200k_backup\"\nD_MYSQL_REP=\"-dc tigase.db.jdbc.JDBCRepository -du jdbc:mysql://localhost/tigasetest200k?user=root&password=mypass\"\nS_MYSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:mysql://localhost/tigasetest?user=root&password=mypass\"\nS_PGSQL_REP=\"-sc tigase.db.jdbc.JDBCRepository -su jdbc:postgresql://localhost/tigase?user=tigase\"\n\njava $D -cp $CP tigase.util.RepositoryUtils $S_MYSQL_REP -u \"$1\" -pr\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/bash/cron-dnotify-check.sh",
    "content": "#!/bin/bash\n\nmonitored_dir=\"/home/webapp/drupal-sites/users-list\"\nmydir=`dirname $0`\n\ncron_check=`ps axw | grep -c \"[d]notify -C\"`\n\nif [ $cron_check -eq 0 ] ; then \n#  echo \"dnotify monitor is not running, starting a new one....\"\n  /usr/bin/dnotify -C -b $monitored_dir -e $mydir/users-list-moitor.sh '{}'\nfi\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/bash/users-list-moitor.sh",
    "content": "#!/bin/bash\n\nmydir=$1\n\nif [ \"$mydir\" == \"\" ] ; then\n  echo \"Directory name is missing...\"\n  exit 1\nfi\n\nfor i in $mydir/* ; do\n  newuser=`basename $i`\n  echo \"Adding new user: \"$newuser\n  /usr/sbin/useradd $newuser -m\n  rm -f $i\n  /usr/bin/mail -s \"Welcome to Tigase LiveCD\" -t ${newuser}@livecd.tigase.org <<EOFMAIL\nHi,\n\nThis is an automated message sent to every new user registered on the LiveCD.\n\nPlease enjoy the system and send me your comments.\n\nArtur Hefczyc\n.\nEOFMAIL\ndone\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/AddUser.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User add script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#add-user\n\n AS:Description: Add user\n AS:CommandId: http://jabber.org/protocol/admin#add-user\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\ndef PASSWORD = \"password\"\ndef PASSWORD_VERIFY = \"password-verify\"\ndef EMAIL = \"email\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef userPass = Command.getFieldValue(packet, PASSWORD)\ndef userPassVer = Command.getFieldValue(packet, PASSWORD_VERIFY)\ndef userEmail = Command.getFieldValue(packet, EMAIL)\n\nif (userJid == null || userPass == null || userPassVer == null || userEmail == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Adding a User\")\n\tCommand.addInstructions(result, \"Fill out this form to add a user.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the account to be added\")\n\tCommand.addFieldValue(result, PASSWORD, userPass ?: \"\", \"text-private\",\n\t\t\t\"The password for this account\")\n\tCommand.addFieldValue(result, PASSWORD_VERIFY, userPassVer ?: \"\", \"text-private\",\n\t\t\t\"Retype password\")\n\tCommand.addFieldValue(result, EMAIL, userEmail ?: \"\", \"text-single\",\n\t\t\t\"Email address\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tauth_repo.addUser(bareJID, userPass)\n\t\tuser_repo.setData(bareJID, \"email\", userEmail);\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to create account for this domain.\");\n\t}\n} catch (UserExistsException ex) {\n\tex.printStackTrace();\n\tCommand.addTextField(result, \"Note\", \"User already exists, can't be added.\");\n} catch (TigaseDBException ex) {\n\tex.printStackTrace();\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, user not added.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/AddUserTracker.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Activate on the server user tracking mechanisms to aid in problem resolution.\n AS:Description: Activate log tracker for a user\n AS:CommandId: http://jabber.org/protocol/admin#add-user-tracker\n AS:Component: sess-man\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\nimport java.util.logging.*\n\ndef JID = \"accountjid\"\ndef FILE_NAME = \"file-name\"\ndef FILE_LIMIT = 25000000\ndef FILE_COUNT = 5\n\ndef p = (Packet)packet\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef fileName = Command.getFieldValue(packet, FILE_NAME)\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Adding a User Log Tracker\")\n\tCommand.addInstructions(result, \"Fill out this form to add a user log tracker.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the account to be tracked\")\n\tCommand.addFieldValue(result, FILE_NAME, fileName ?: \"\", \"text-single\",\n\t\t\t\"File name to write user's log entries\")\n\n\treturn result\n}\n\n// Remove the old tracker if there is any active for that user\ndef hand = null\n\nHandler[] handlers = Logger.getLogger(\"\").getHandlers()\nhandlers.each {\n\tFilter filt = it.getFilter()\n\tif (filt != null && filt.class == LogUserFilter && ((LogUserFilter)filt).getId() == userJid) {\n\t\thand = it\n\t}\n}\nif (hand != null) {\n\tLogger.getLogger(\"\").removeHandler(hand)\n\thand.close()\n\tCommand.addTextField(result, \"Note\", \"Operation successful, tracker removed for \" + userJid);\n}\n\n// Ok now we can setup a new tracker\ndef result = p.commandResult(Command.DataType.result)\n\ndef users_sessions = (Map)userSessions\nbareJID = BareJID.bareJIDInstance(userJid)\n\nXMPPSession session = users_sessions.get(bareJID)\n\nif (fileName == null || fileName == \"\") {\n\tfileName = \"logs/\" + userJid\n}\nLogUserFilter filter = new LogUserFilter(bareJID, users_sessions)\n\nFileHandler handler = new FileHandler(fileName, FILE_LIMIT, FILE_COUNT)\nhandler.setLevel(Level.ALL)\nhandler.setFilter(filter)\nLogger.getLogger(\"\").addHandler(handler)\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addTextField(result, \"Note\", \"Tracking user \" + userJid)\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/BoshPreBindSession.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\n/*\nAS:Description: Pre-Bind BOSH user session\nAS:CommandId: pre-bind-bosh-session\nAS:Component: bosh\n */\n\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.bosh.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ntry {\n\n\tdef USER_JID = \"from\";\n\tdef RID = \"rid\"\n\tdef HOLD = \"hold\"\n\tdef WAIT = \"wait\"\n\tdef SID = \"sid\"\n\tdef HOSTNAME = \"hostname\"\n\n\tdef p = (Iq)packet\n\n\tdef vhost_man = (VHostManagerIfc)vhostMan\n\tdef admins = (Set)adminsSet\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID()\n\tdef isServiceAdmin = admins.contains(stanzaFromBare)\n\n\tdef userJid = Command.getFieldValue(p, USER_JID)\n\tdef rid = 0\n\tdef hold = Command.getFieldValue(p,HOLD)\n\tdef wait = Command.getFieldValue(p,WAIT)\n\n\tif (userJid == null || userJid.isEmpty() ) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form);\n\t\tCommand.addTitle(res, \"Pre-bind BOSH user session\")\n\t\tCommand.addInstructions(res, \"Fill out this form to create and pre-bind BOSH user session.\")\n\n\t\tCommand.addFieldValue(res, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\n\t\tCommand.addFieldValue(res, USER_JID, \"\", \"jid-single\", \"JID of the user for which session should be created - either BareJID or FullJID, the former will result in randomly generated resource\")\n\t\tCommand.addFieldValue(res, HOLD, hold ?: \"1\",\"text-single\", \"HOLD value (optional)\")\n\t\tCommand.addFieldValue(res, WAIT, wait ?: \"60\",\"text-single\", \"WAIT value (optional)\")\n\n\t\treturn res\n\t}\n\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\n\tdef result = (Iq)p.commandResult(Command.DataType.result)\n\n\tif (vhost == null ) {\n\t\tCommand.addTextField(result, \"Error\", \"Domain of the JID doesn't exists\");\n\t} else if (isServiceAdmin ||\n\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n\t\tMap args = new HashMap();\n\t\tif (userJid != null && !userJid.isEmpty()) {\n\t\t\targs.put(USER_JID,userJid)\n\t\t}\n\t\tif (hold != null && !hold.isEmpty()) args.put(HOLD,hold)\n\t\tif (wait != null && !wait.isEmpty()) args.put(WAIT,wait)\n\n\t\targs = boshCM.preBindSession(args)\n\n\t\trid = args.get(RID);\n\t\tdef sid = args.get(SID);\n\t\tdef hostname = args.get(HOSTNAME)\n\t\tuserJid = args.get(USER_JID)\n\n\t\tif (hostname != null ) {\n\t\tCommand.addFieldValue(result, USER_JID, userJid,\"jid-single\",  \"JID\")\n\t\tCommand.addFieldValue(result, HOSTNAME, hostname,\"jid-single\",  \"hostname\")\n\t\tCommand.addFieldValue(result, RID, rid, \"text-single\", \"RID\")\n\t\tCommand.addFieldValue(result, SID, sid, \"text-single\", \"SID\")\n\t\tCommand.addFieldValue(result, HOLD, hold, \"text-single\", \"HOLD\")\n\t\tCommand.addFieldValue(result, WAIT, wait, \"text-single\", \"WAIT\")\n\t\t} else {\n\t\t\tCommand.addTextField(result, \"Error\", \"Error processing request, provided data is invalid\");\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions\");\n\t}\n\treturn result\n\n}  catch (Exception ex) { ex.printStackTrace(); }"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/BroadcastToOnline.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\n4.23 Send Announcement to Online Users as described in XEP-0133:\nhttp://xmpp.org/extensions/xep-0133.html#announce\n\nAS:Description: Send Announcement to Online Users\nAS:CommandId: http://jabber.org/protocol/admin#announce\nAS:Component: sess-man\nAS:Group: Notifications\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.cluster.*;\nimport tigase.cluster.api.*;\nimport tigase.cluster.strategy.*;\n\n\ndef FROM_JID = \"from-jid\"\ndef SUBJECT = \"subject\"\ndef MSG_TYPE = \"msg-type\"\ndef MSG_BODY = \"announcement\"\n\ndef p = (Iq)packet\n\ndef fromJid = Command.getFieldValue(p, FROM_JID)\ndef subject = Command.getFieldValue(p, SUBJECT)\ndef msg_type = Command.getFieldValue(p, MSG_TYPE)\ndef body = Command.getFieldValues(p, MSG_BODY)\n\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\nif (fromJid == null || subject == null || msg_type == null || body == null) {\n\tdef res = (Iq)p.commandResult(Command.DataType.form);\n  Command.addTitle(res, \"Message to online users\")\n  Command.addInstructions(res, \"Fill out this form to make an announcement to all active users of this service.\")\n\n  Command.addFieldValue(res, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\n  Command.addFieldValue(res, FROM_JID, fromJid ?: p.getStanzaFrom().getDomain().toString(), \"jid-single\", \"From address\")\n\n  Command.addFieldValue(res, SUBJECT, subject ?: \"Message from administrators\", \"text-single\", \"Subject\")\n\n  def msg_types = [\"normal\", \"headline\", \"chat\" ]\n  Command.addFieldValue(res, MSG_TYPE, msg_type ?: msg_types[0], \"Type\", (String[])msg_types, (String[])msg_types)\n\n  if (body == null) {\n     body = [\"\"]\n  }\n\n\tCommand.addFieldMultiValue(res, MSG_BODY, body as List)\n\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(res, NOTIFY_CLUSTER, true.toString())\n\t}\n\n\n\treturn res\n}\n\nQueue results = new LinkedList()\nif \t( clusterMode && notifyCluster ) {\n\tif ( null != clusterStrategy ) {\n\t\tdef cluster = (ClusteringStrategyIfc) clusterStrategy\n\t\tList<JID> cl_conns = cluster.getNodesConnected()\n\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\tcl_conns.each { node ->\n\n\t\t\t\tdef forward = p.copyElementOnly();\n\t\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\t\tforward.setPacketTo( node );\n\t\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\t\tresults.offer(forward)\n\t\t\t}\n\t\t}\n\t}\n}\n\n\ndef jidFrom = JID.jidInstanceNS(fromJid)\ndef type = StanzaType.valueOf(msg_type)\ndef msg_body = body.join('\\n')\n\ndef msg = Message.getMessage(null, null, type, msg_body, subject, null, \"admin\")\ndef result = p.commandResult(Command.DataType.result)\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nresults += result\ndef conns = (Map)userConnections\nconns.each { key, value ->\n  if (value.isAuthorized()) {\n\t\tdef res = msg.copyElementOnly()\n\t\tres.initVars(jidFrom, value.getJID())\n\t\tres.setPacketTo(key)\n\t\tresults += res\n\t}\n\n}\n\nreturn (Queue)results\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ChangeUserPassword.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User change password script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#\n AS:Description: Change user password\n AS:CommandId: http://jabber.org/protocol/admin#change-user-password\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\ndef PASSWORD = \"password\"\n//def PASSWORD_VERIFY = \"password-verify\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef userPass = Command.getFieldValue(packet, PASSWORD)\n//def userPassVer = Command.getFieldValue(packet, PASSWORD_VERIFY)\n\nif (userJid == null || userPass == null /*|| userPassVer == null*/) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Changing a User Password\")\n\tCommand.addInstructions(result, \"Fill out this form to change a user's password.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for this account\")\n\tCommand.addFieldValue(result, PASSWORD, userPass ?: \"\", \"text-private\",\n\t\t\t\"The new password for this account\")\n//\tCommand.addFieldValue(result, PASSWORD_VERIFY, userPassVer ?: \"\", \"text-private\",\n//\t\t\t\"Retype password\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tif (user_repo.userExists(bareJID)) {\n\t\t\tauth_repo.updatePassword(bareJID, userPass)\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t}\n\t\telse {\n\t\t\tCommand.addTextField(result, \"Note\", \"User not exists, can't change password.\");\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to change account password for this domain.\");\n\t}\n} catch (UserNotFoundException ex) {\n\tCommand.addTextField(result, \"Note\", \"User not exists, can't change password.\");\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, password not changed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/CompManager.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nManage active server components\n\nAS:Description: Manage active server components\nAS:CommandId: comp-manager\nAS:Component: basic-conf\nAS:Group: Configuration\n */\n\npackage tigase.admin\n\nimport tigase.conf.ConfigRepositoryIfc\nimport tigase.conf.Configurable;\nimport tigase.conf.Configurator;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.*\n\nclass DelayedReloadTask extends Thread {\n\tvoid run() {\n\t\tThread.sleep(5000);\n\t    ((Configurator) XMPPServer.getConfigurator()).updateMessageRouter();\n\t}\n}\n\ntry {\n\n\tdef ACTION = \"action\";\n\tdef ACTION_ADD = \"Add\";\n\tdef ACTION_EDIT = \"Edit\";\n\tdef ACTION_REMOVE = \"Remove\";\n\tdef ACTION_LIST = \"List\";\n\n\tdef COMP_NAME = \"comp-name\";\n\tdef COMP_CLASS = \"comp-class\";\n\n\tdef SUBMIT = \"confirm\";\n\n\tdef getComponentProperties = { comp_name, comp_class ->\n\t\tdef conf = XMPPServer.getConfigurator();\n\t\tdef prop = conf.getProperties(comp_name);\n\t\ttry {\n\t\t\tdef comp = ModulesManagerImpl.getInstance().getServerComponent(comp_class);\n\t\t\tif (!comp) {\n\t\t\t\tdef INTERNAL_COMPONENTS = [];\n\t\t\t\tINTERNAL_COMPONENTS.addAll(MessageRouterConfig.COMPONENT_CLASSES.values());\n\t\t\t\tINTERNAL_COMPONENTS.addAll(MessageRouterConfig.COMP_CLUS_MAP.values());\n\t\t\t\t\n\t\t\t\tif (!XMPPServer.isOSGi() || INTERNAL_COMPONENTS.contains(comp_class)) {\n\t\t\t\t\tcomp = XMPPServer.class.getClassLoader().loadClass(comp_class).newInstance()\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (comp) {\n\t\t\t\tcomp.setName(comp_name)\n\t\t\t\tdef defProp = comp.getDefaults(conf.getDefConfigParams() ?: [:])  ?: [:];\n\t\t\t\tdefProp.putAll(prop);\n\t\t\t\treturn defProp;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn [:];\n\t\t\t}\n\t\t}\n\t\tcatch(Exception ex) {\n\t\t\tex.printStackTrace();\n\t\t\treturn [:];\n\t\t}\n\t};\n\n\tdef prepareComponentConfigForAdHoc = { res, comp_name, comp_class ->\n\t\tdef prop = getComponentProperties(comp_name, comp_class);\n\t\tdef keys = [];\n\t\tkeys.addAll(prop.keySet());\n\t\tkeys.sort { it }.each { key ->\n\t\t\tdef val = prop[key];\n\t\t\tif (val.getClass().isArray()) {\n\t\t\t\tdef tmp = [];\n\t\t\t\tfor (def x : val) {\n\t\t\t\t\ttmp.add(String.valueOf(x));\n\t\t\t\t}\n\t\t\t\tval = tmp.join(',');\n\t\t\t}\n\t\t\tif (!(val instanceof String)) {\n\t\t\t\tval = val.toString();\n\t\t\t}\n\t\t\tCommand.addFieldValue(res, key, val);\n\t\t}\n\t};\n\n\tdef getConfigFromAdHoc = { p, comp_name, comp_class ->\n\t\tdef defProp = getComponentProperties(comp_name, comp_class);\n        \n\t\tdef props = [:];\n\t\tdefProp.each { key, defVal ->\n\t\t\tdef val = Command.getFieldValue(p, key);\n                \n\t\t\tdef tmpVal = defVal;\n\t\t\tif (tmpVal.getClass().isArray()) {\n\t\t\t\tdef tmp = [];\n\t\t\t\tfor (def x : tmpVal) {\n\t\t\t\t\ttmp.add(String.valueOf(x));\n\t\t\t\t}\n\t\t\t\ttmpVal = tmp.join(',');\n\t\t\t}\n\n\t\t\tif (val && !val.equals(tmpVal)) {\n\t\t\t\tdef cls = defVal.getClass();\n\t\t\t\tif (val == \"null\") val = null;\n\t\t\t\tif (cls == Long[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(Long.parseLong(it))};\n\t\t\t\t\tval = (out as Long[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == Integer[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(Integer.parseInt(it))};\n\t\t\t\t\tval = (out as Integer[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == String[].class) {\n\t\t\t\t\tdef out = [];\n\t\t\t\t\tval.split(',').each { out.add(it)};\n\t\t\t\t\tval = (out as String[]);\n\t\t\t\t}\n\t\t\t\telse if (cls == Long.class) {\n\t\t\t\t\tval = Long.parseLong(val);\n\t\t\t\t}\n\t\t\t\telse if (cls == Integer.class) {\n\t\t\t\t\tval = Integer.parseInt(val);\n\t\t\t\t}\n\t\t\t\telse if (cls == Boolean.class) {\n\t\t\t\t\tval = Boolean.parseBoolean(val);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tprintln \"unknown convertion for key = \" + key + \" , \" + cls.getName()\n\t\t\t\t}\n                                                \n\t\t\t\tprops.put(key, val);\n\t\t\t}\n\t\t}\n        \n\t\treturn props;\n\t};\n\n\n\tdef conf_repo = (ConfigRepositoryIfc)comp_repo\n\tdef p = (Iq)packet\n\n\t// check permission\n\tdef admins = (Set)adminsSet\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID()\n\tdef isServiceAdmin = admins.contains(stanzaFromBare)\n\n\tif (!isServiceAdmin) {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n\t\treturn result\n\t}\n\n\n\tdef comp_name = Command.getFieldValue(p, COMP_NAME)\n\tdef action = Command.getFieldValue(p, ACTION);\n\tdef submit = Command.getFieldValue(p, SUBMIT);\n\n\tif (action == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef actions = [ACTION_LIST, ACTION_ADD, ACTION_EDIT, ACTION_REMOVE];\n\t\tCommand.addFieldValue(res, ACTION, actions[0], \"Action\",\n\t\t\t(String[]) actions, (String[]) actions)\n\t\treturn res;\n\t}\n\n\tif (action == ACTION_ADD && comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(res, COMP_NAME, \"\", \"text-single\", \"Component name\");\n\t\tCommand.addFieldValue(res, COMP_CLASS, \"\", \"text-single\", \"Component class\");\n\t\tCommand.addHiddenField(res, ACTION, ACTION_ADD);\n\t\treturn res;\n\t}\n\telse if ( action == ACTION_LIST && comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef compNames = []\n\t\tdef conf = XMPPServer.getConfigurator();\n\n\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\tcompNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n\t\tcompNames += mrProps.get(MessageRouterConfig.REGISTRATOR_NAMES_PROP_KEY).toList();\n\n\t\tcompNames.each {\n\t\t\tdef mr = conf.getComponent( it );\n\t\t\tif (mr) {\n\t\t\t\tCommand.addFieldMultiValue(res, it, Arrays.asList( mr.getComponentInfo().toString() ))\n\t\t\t}\n\t\t}\n\t\tCommand.addHiddenField(res, ACTION, action);\n\t\treturn res\n\t}\n\telse if (comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef compNames = []\n\t\tdef conf = XMPPServer.getConfigurator();\n\t\tconf_repo.getCompNames().findAll{ conf.getComponent(it) != null }.each { compNames += it }\n\t\tcompNames.sort();\n\t\tCommand.addFieldValue(res, COMP_NAME, comp_name ?: compNames[0], \"Components\",\n\t\t\t(String[])compNames, (String[])compNames)\n\t\tCommand.addHiddenField(res, ACTION, action ?: \"\");\n\t\treturn res\n\t}\n\telse {\n\t\tif (action == ACTION_REMOVE) {\n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.result)\n\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\tdef suffix = null;\n\t\t\tinitProps.each {\n\t\t\t\tsuffix = it.key.substring(Configurable.GEN_COMP_NAME.length());\n\t\t\t}\n\t\t\tconf.getDefConfigParams().remove(Configurable.GEN_COMP_NAME + suffix);\n\t\t\tconf.getDefConfigParams().remove(Configurable.GEN_COMP_CLASS + suffix);\n\n\t\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\t\tdef compNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n                        \n\t\t\tif (compNames.contains(comp_name)) {\n\t\t\t\tcompNames.remove(comp_name);\n\t\t\t}\n                        \n\t\t\tmrProps = [:];\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY, (compNames as String[]));\n\t\t\tconf.putProperties(\"message-router\", mrProps);\n                        \n\t\t\tnew DelayedReloadTask().start();\n\t\t\tCommand.addTextField(res, \"Note\", \"Operation successful.\")\n\n\t\t\treturn res;\n\t\t}\n\t\telse if (!submit) {\n\t\t\tdef comp_class = Command.getFieldValue(p, COMP_CLASS);\n                \n\t\t\tif (comp_class == null) {\n\t\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\t\tdef suffix = null;\n\t\t\t\tinitProps.each {\n\t\t\t\t\tsuffix = it.key.substring(Configurable.GEN_COMP_NAME.length());\n\t\t\t\t}\n\t\t\t\tcomp_class = conf.getDefConfigParams().get(Configurable.GEN_COMP_CLASS + suffix);\n\n\t\t\t\tif (!comp_class) comp_class = MessageRouterConfig.COMPONENT_CLASSES.get(comp_name);\n\t\t\t\tif (!comp_class) comp_class = MessageRouterConfig.COMP_CLUS_MAP.get(comp_name);\n\t\t\t\tif (!comp_class && comp_name == \"basic-conf\") comp_class = XMPPServer.getConfigurator().getClass().getCanonicalName();\n\t\t\t\tif (!comp_class) throw new Exception(\"Could not find component class for component: \" + comp_name);\n\t\t\t}\n                        \n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\t\tCommand.addFieldValue(res, COMP_NAME, comp_name, \"fixed\", \"Component name\");\n\t\t\tCommand.addHiddenField(res, COMP_CLASS, comp_class);\n\t\t\tCommand.addHiddenField(res, ACTION, action);\n\t\t\tCommand.addHiddenField(res, SUBMIT, SUBMIT);\n        \n\t\t\tprepareComponentConfigForAdHoc(res, comp_name, comp_class);\n         \n\t\t\treturn res;\n\t\t}\n\t\telse if (submit) {\n\t\t\tdef comp_class = Command.getFieldValue(p, COMP_CLASS);\n\n\t\t\t// here we should apply results of new or edit\n\t\t\tdef res = (Iq)p.commandResult(Command.DataType.result)\n\t\t\tdef props = getConfigFromAdHoc(p, comp_name, comp_class);\n                \n\t\t\tdef conf = XMPPServer.getConfigurator();\n\t\t\tconf.putProperties(comp_name, props);\n                \n\t\t\tdef initProps = conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.value.equals(comp_name); };\n\t\t\tif (initProps.isEmpty()) {\n\t\t\t\tdef suffix = 1;\n\t\t\t\twhile (!(conf.getDefConfigParams().findAll { return it.key.startsWith(Configurable.GEN_COMP_NAME) && it.key.endsWith(\"-\"+suffix); }.isEmpty())) {\n\t\t\t\t\tsuffix += 1;\n\t\t\t\t}\n\t\t\t\tconf.getDefConfigParams().put(Configurable.GEN_COMP_NAME+\"-\"+suffix, comp_name);\n\t\t\t\tconf.getDefConfigParams().put(Configurable.GEN_COMP_CLASS+\"-\"+suffix, comp_class);\n\t\t\t}\n\n\t\t\tdef mrProps = conf.getProperties(\"message-router\");\n\t\t\tdef compNames = mrProps.get(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY).toList();\n                        \n\t\t\tif (!compNames.contains(comp_name)) {\n\t\t\t\tcompNames.add(comp_name);\n\t\t\t}\n                        \n\t\t\tmrProps = [:];\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_NAMES_PROP_KEY, (compNames as String[]));\n\t\t\tmrProps.put(MessageRouterConfig.MSG_RECEIVERS_PROP_KEY + comp_name + \".class\", comp_class)\n\t\t\tconf.putProperties(\"message-router\", mrProps);\n                        \n\t\t\tnew DelayedReloadTask().start();\n\t\t\tCommand.addTextField(res, \"Note\", \"Operation successful.\");\n\t\t\treturn res;\n\t\t}\n\t}\n\n\n                \n                \n}\ncatch(Exception ex) {\n\tex.printStackTrace();\n\tthrow ex;\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/CompRepoItemAdd.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nAdd an item in a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Add new item\nAS:CommandId: comp-repo-item-add\nAS:Component: vhost-man,ext\nAS:ComponentClass: tigase.server.ext.ComponentProtocol\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef MARKER = \"command-marker\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Iq)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef item = repo.getItemInstance()\ndef marker = Command.getFieldValue(p, MARKER)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\n\nif (marker == null) {\n  def result = p.commandResult(Command.DataType.form)\n  item.addCommandFields(result)\n\tCommand.addHiddenField(result, MARKER, MARKER)\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t}\n\treturn result\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\nitem.initFromCommand(p)\ndef oldItem = item.getKey() != null ? repo.getItem(item.getKey()) : null;\ndef result = p.commandResult(Command.DataType.result)\nif (oldItem == null) {\n\tdef validateResult = repo.validateItem(item)\n\tif (validateResult == null && (isServiceAdmin && !item.getKey().isEmpty())) {\n\t\trepo.addItem(item)\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful.\")\n\t\tif (validateResult != null) {\n\t\t\tCommand.addTextField(result, \"Note\", \"   \")\n\t\t\tCommand.addTextField(result, \"Warning\", validateResult)\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"The item did not pass validation checking.\")\n\t\tCommand.addTextField(result, \"Note\", \"   \")\n\t\tCommand.addTextField(result, \"Warning\", validateResult)\n\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"The item is already added, you can't add it twice.\")\n}\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/CompRepoItemRemove.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nRemove an item from a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Remove an item\nAS:CommandId: comp-repo-item-remove\nAS:Component: vhost-man,ext\nAS:ComponentClass: tigase.server.ext.ComponentProtocol\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef ITEMS = \"item-list\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, ITEMS)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, ITEMS, itemsStr[0], \"List of items\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\tif \t( clusterMode  ) {\n\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t}\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Note\", \"There are no items on the list\");\n\t\treturn result\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\ndef item = repo.getItem(itemKey)\nif (item == null) {\n\tCommand.addTextField(result, \"Error\", \"No such item, deletion impossible.\");\n} else {\n  if (isServiceAdmin || item.isOwner(stanzaFromBare.toString())) {\n\t\trepo.removeItem(itemKey)\n\t\tCommand.addTextField(result, \"Note\", \"Operation successful\")\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You are not the Item owner or you have no \"\n\t\t\t+ \"enough permission to remove the item.\")\n\t}\n}\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/CompRepoItemUpdate.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n/*\n\nUpdate an item in a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Update item configuration\nAS:CommandId: comp-repo-item-update\nAS:Component: vhost-man,ext,basic-conf\nAS:ComponentClass: tigase.server.ext.ComponentProtocol\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\n\ndef MARKER = \"command-marker\"\ndef ITEMS = \"item-list\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, ITEMS)\ndef marker = Command.getFieldValue(packet, MARKER)\n\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\nQueue results = new LinkedList()\n\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, ITEMS, itemsStr[0], \"List of items\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Error\", \"There are no items on the list\");\n\t\treturn result\n\t}\n}\n\nif (marker == null) {\n\tdef item = repo.getItem(itemKey)\n\tif (item == null) {\n\t\tCommand.addTextField(result, \"Error\", \"No such item, update impossible.\");\n\t} else {\n\t\tif (isServiceAdmin || item.isOwner(stanzaFromBare.toString()) || item.isAdmin(stanzaFromBare.toString())) {\n\t\t\tdef result = p.commandResult(Command.DataType.form)\n\t\t\titem.addCommandFields(result)\n\t\t\tCommand.addHiddenField(result, MARKER, MARKER)\n\t\t\tCommand.addHiddenField(result, ITEMS, itemKey)\n\t\t\tif \t( clusterMode  ) {\n\t\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t\t}\n\t\t\treturn result\n\t\t} else {\n\t\t\tdef result = p.commandResult(Command.DataType.result)\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this item.\")\n\t\t\treturn result\n\t\t}\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\n\ndef item = repo.getItemInstance()\nitem.initFromCommand(packet)\ndef oldItem = repo.getItem(item.getKey())\n\nif (oldItem == null) {\n\tCommand.addTextField(result, \"Error\", \"The item you try to update does not exist.\");\n} else {\n\tdef validateResult = repo.validateItem(item)\n\tif (validateResult == null) {\n\t\tif (isServiceAdmin || oldItem.isOwner(stanzaFromBare.toString())\n\t\t\t// we allow changes by admins, except for changing the owner of the domain.\n\t\t\t|| oldItem.isAdmin(stanzaFromBare.toString()) && oldItem.getOwner().equals(item.getOwner())\n\t\t) {\n\t\t\trepo.addItem(item)\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t} else {\n\t\t\tCommand.addTextField(result, \"Error\", \"You are not the Item owner or you have no \"\n\t\t\t\t+ \"enough permission to change the item.\")\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"The item did not pass validation checking.\")\n\t\tCommand.addTextField(result, \"Note\", \"   \")\n\t\tCommand.addTextField(result, \"Warning\", validateResult)\n\t}\n}\n\n\nresults.add(result);\nreturn results;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/CompRepoReload.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nReload a component repository:\ntigase.db.ComponentRepository\nWorks only for some components which actually use the repository that way.\n\nAS:Description: Reload component repository\nAS:CommandId: comp-repo-reload\nAS:Component: vhost-man,ext\n*/\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\n\ndef repo = (ComponentRepository)comp_repo\nrepo.reload()\n\ndef result = \"Reloaded items - \" + repo.size() + \":\\n\"\ndef items = repo.allItems()\nif (items.size() > 0) {\n\titems.each { result += \"\\n\" + it.getKey() }\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ConfigList.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nList server/component configuration\n\nAS:Description: List server/component configuration\nAS:CommandId: config-list\nAS:Component: basic-conf\nAS:Group: Configuration\n*/\n\npackage tigase.admin\n\nimport tigase.conf.*\nimport tigase.server.*\n\ndef COMP_NAME = \"comp-name\"\ndef PARAMS_SET = \"params-set\"\n\ndef conf_repo = (ConfigRepositoryIfc)comp_repo\ndef p = (Iq)packet\ndef comp_name = Command.getFieldValue(p, COMP_NAME)\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ntry {\n\n\tif (!isServiceAdmin) {\n\t\t\tdef result = p.commandResult(Command.DataType.result)\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n\t\t\treturn result\n\t}\n\n\tif (comp_name == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.form)\n\t\tdef compNames = []\n\t\tconf_repo.getCompNames().each { compNames += it }\n\t\tCommand.addFieldValue(res, COMP_NAME, comp_name ?: compNames[0], \"Components\",\n\t\t\t(String[])compNames, (String[])compNames)\n\t\treturn res\n\t}\n\n\tdef params_set = Command.getFieldValue(p, PARAMS_SET)\n\n\tif (params_set == null) {\n\t\tdef res = (Iq)p.commandResult(Command.DataType.result)\n\t\tdef compNames = []\n\t\tconf_repo.getCompNames().each { compNames += it }\n\t\tCommand.addTextField(res, COMP_NAME, comp_name ?: compNames[0])\n\t\tCommand.addHiddenField(res, PARAMS_SET, PARAMS_SET)\n\t\tconf_repo.getItemsForComponent(comp_name).each {\n\t\t\tCommand.addFieldValue(res, it.getKey(), it.getConfigValToString())\n\t\t}\n\t\treturn res\n\t}\n\n} catch (Exception e) {\n\te.printStackTrace();\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ConnectionTime.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Calculates maximum and average connection time for all connected users\n AS:Description: Connections time\n AS:CommandId: connection-time\n AS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport tigase.conf.*\nimport tigase.server.*\nimport tigase.xmpp.*\n\ndef user_connections = (Map)userConnections\ndef p = (Iq)packet\n\ndef total_time = 0\ndef max_time = 0\ndef start_time = System.currentTimeMillis()\nuser_connections.entrySet().each {\n\tif (!it.getKey().toString().startsWith(\"sess-man\")) {\n\t\tdef session = (XMPPResourceConnection) it.getValue()\n\t\tdef creation_time = start_time - session.getCreationTime()\n\t\ttotal_time += creation_time\n\t\tif (creation_time  > max_time) {\n\t\t\tmax_time = creation_time\n\t\t}\n\t}\n}\ndef average_time = total_time / user_connections.size()\n\n\ndef res = (Iq)p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(res, \"Connections time: \",\n\t\t[\n\t\t\t\"Longest connection: \" + (max_time / 1000),\n\t\t\t\"Average connection time:\" + (average_time / 1000)\n\t\t])\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/DNSQuery.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User add script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#add-user\n AS:Description: DNS Query\n AS:CommandId: query-dns\n AS:Component: vhost-man\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\n\n\ndef DOMAIN = \"domain-name\"\n\ndef p = (Packet)packet\n\ndef domain = Command.getFieldValue(packet, DOMAIN)\n\nif (domain == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Provide domain name\")\n\tCommand.addInstructions(result, \"Fill out this form to query DNS for domain.\")\n\n\tCommand.addFieldValue(result, DOMAIN, domain ?: \"\", \"text-single\",\n\t\t\t\"Domain name to query DNS\")\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ndef response_data = []\ntry {\n\tresponse_data += \"IP: \" + DNSResolverFactory.getInstance().getHostIP(domain)\n} catch (Exception ex) {\n\tresponse_data += \"IP: \" + ex.toString()\n}\ntry {\n\tDNSEntry[] entries = DNSResolverFactory.getInstance().getHostSRV_Entries(domain)\n\tint cnt = 1\n\tentries.each {\n\t\tresponse_data += \"SRV \" + (cnt++) + \": \" + it.toString()\n\t}\n\tresponse_data += \"Selected SRV: \" + DNSResolverFactory.getInstance().getHostSRV_Entry(domain).toString()\n\tresponse_data += \"Selected SRV IP: \" + DNSResolverFactory.getInstance().getHostSRV_IP(domain)\n\n\n\tCommand.addFieldMultiValue(result, \"DNS Response \", response_data);\n} catch (Exception ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem querying DNS for domain: \" + domain);\n\t// There is a new API to pass exception, for now we have to do it manually\n\t//Command.addFieldMultiValue(result, \"Exception: \", ex)\n\tdef stes = []\n\tstes += ex.toString()\n\tex.getStackTrace().each {\n\t\tstes += it.toString()\n\t}\n\tCommand.addFieldMultiValue(result, \"Exception: \", stes);\n\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/DeleteUser.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User delete script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#delete-user\n AS:Description: Delete user\n AS:CommandId: http://jabber.org/protocol/admin#delete-user\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JIDS = \"accountjids\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\ndef notifyClusterStr = Command.getFieldValue(packet, NOTIFY_CLUSTER);\nboolean notifyCluster = (notifyClusterStr != null) ? Boolean.valueOf( notifyClusterStr ) : true;\n\ndef user_sessions = (Map)userSessions;\n\ndef userJids = Command.getFieldValues(packet, JIDS)\n\nif (userJids == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Deleting a User\")\n\tCommand.addInstructions(result, \"Fill out this form to delete a user.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JIDS, userJids ?: \"\", \"jid-multi\",\n\t\t\t\"The Jabber ID(s) to delete\")\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t}\n\n\treturn result\n}\n\ndef results = new LinkedList<Packet>();\n\ndef closeUserSessions = { userJid ->\n\ttry {\n\t\tdef bareJID = BareJID.bareJIDInstance(userJid)\n\t\tdef sess = user_sessions.get(bareJID);\n\t\tif (sess != null) {\n\t\t\tdef conns = sess.getConnectionIds();\n\t\t\tfor (conn in conns) {\n\t\t\t\tdef res = sess.getResourceForConnectionId(conn);\n\t\t\t\tif (res != null) {\n\t\t\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), conn,\n\t\t\t\t\t\t\tStanzaType.set, res.nextStanzaId());\n\t\t\t\t\tresults.offer(commandClose);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (Exception ex) {\n\t\tex.printStackTrace();\n\t}\n};\n\nif (clusterMode) {\n\tif (!notifyCluster) {\n\t\tfor (userJid in userJids) {\n\t\t\tcloseUserSessions(userJid);\n\t\t}\n\t\treturn results;\n\t}\n}\n\n\ndef result = p.commandResult(Command.DataType.result)\nresults.offer(result);\ndef msgs = [];\ndef errors = [];\nfor (userJid in userJids) {\n\ttry {\n\t\tdef bareJID = BareJID.bareJIDInstance(userJid)\n\t\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\t\tif (isServiceAdmin ||\n\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\t\tif (user_repo.userExists(bareJID)) {\n\t\t\t\tauth_repo.removeUser(bareJID)\n\t\t\t\ttry {\n\t\t\t\t\tuser_repo.removeUser(bareJID)\n\t\t\t\t} catch (UserNotFoundException ex) {\n\t\t\t\t\t// We ignore this error here. If auth_repo and user_repo are in fact the same\n\t\t\t\t\t// database, then user has been already removed with the auth_repo.removeUser(...)\n\t\t\t\t\t// then the second call to user_repo may throw the exception which is fine.\n\t\t\t\t}\n\t\t\t\tif (clusterMode && notifyCluster) {\n\t\t\t\t\tdef nodes = (List)clusterStrategy.getNodesConnected();\n\t\t\t\t\tif (nodes && nodes.size() > 0 ) {\n\t\t\t\t\t\tnodes.each { node ->\n\t\t\t\t\t\t\tdef forward = p.copyElementOnly();\n\t\t\t\t\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\t\t\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\t\t\t\t\tforward.setPacketTo( node );\n\t\t\t\t\t\t\tforward.setPermissions( Permissions.ADMIN );\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tresults.offer(forward)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\n\t\t\t\t} \n\t\t\t\tcloseUserSessions(userJid);\n\n\t\t\t\tmsgs.add(\"Operation successful for user \"+userJid);\n\t\t\t}\n\t\t\telse {\n\t\t\t\terrors.add(\"User \"+userJid+\" not found, can't be deleted.\");\n\t\t\t}\n\t\t} else {\n\t\t\terrors.add(\"You do not have enough permissions to delete accounts for domain \"+bareJID.getDomain()+\".\");\n\t\t}\n\t} catch (UserNotFoundException ex) {\n\t\terrors.add(\"User \"+userJid+\" not exists, can't be deleted.\");\n\t} catch (TigaseDBException ex) {\n\t\terrors.add(\"Problem accessing database, user \"+userJid+\" not deleted.\");\n\t}\n}\n\nif (!msgs.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Notes\", msgs);\n\nif (!errors.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Errors\", errors);\nreturn results\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/EditUser.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n User modify script\n\n AS:Description: Modify user\n AS:CommandId: modify-user\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\ndef EMAIL = \"email\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef userEmail = Command.getFieldValue(packet, EMAIL)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\t//Command.addFieldValue(result, \"FORM_TYPE\", \"\", \"hidden\")\n\tCommand.addTitle(result, \"Modifying a User\")\n\tCommand.addInstructions(result, \"Fill out this form to modify a user.\")\n\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the account to be modified\")\n\n\treturn result\n}\n\ndef result = null;\ntry {\n\tbareJID = BareJID.bareJIDInstance(userJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n\t\tif (Command.getFieldValue(packet, \"FORM_TYPE\") == null || Command.getFieldValue(packet, \"FORM_TYPE\").isEmpty()) {\n\t\t//if (Command.getFieldValue(packet, EMAIL) == null)\n\t\t\tresult = p.commandResult(Command.DataType.form);\n\n\t\t\tCommand.addTitle(result, \"Modifying a User\")\n\t\t\tCommand.addInstructions(result, \"Fill out this form to modify a user \" + (userJid ?: \"\"))\n\n\t\t\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\t\t\"hidden\")\n\t\t\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"hidden\")\t\n\t\t\tCommand.addFieldValue(result, EMAIL, user_repo.getData(bareJID, \"email\") ?: \"\", \"text-single\",\n\t\t\t\t\t\"Email address\")\n\t\t\t\n\t\t\tCommand.addCheckBoxField(result, \"Account enabled\", !authRepository.isUserDisabled(bareJID));\n//\t\t\t-- add disabled/enabled? vcard? roster?\n\t\t} else {\n\t\t\tresult = p.commandResult(Command.DataType.result);\n\t\t\tuser_repo.setData(bareJID, \"email\", userEmail);\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t\ttry {\n\t\t\t\tauthRepository.setUserDisabled(bareJID, !Command.getCheckBoxFieldValue(p, \"Account enabled\"));\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tCommand.addTextField(result, \"Warning\", \"Account state was not changed as it is not supported by used auth repository: \" + ex.getMessage());\n\t\t\t}\n\t\t}\n\t} else {\n\t\tresult = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to create account for this domain.\");\t\n\t}\n} catch (TigaseDBException ex) {\n\tresult = p.commandResult(Command.DataType.result)\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, user not added.\");\n}\n\nreturn result"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/EndUserSession.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n/*\n User delete script as described in XEP-0133:\n http://jabber.org/protocol/admin#end-user-session\n AS:Description: End User Session\n AS:CommandId: http://jabber.org/protocol/admin#end-user-session\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JIDS = \"accountjids\"\n\ndef p = (Packet)packet\n//def auth_repo =/**/ (AuthRepository)authRepository\n//def user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\ndef notifyClusterStr = Command.getFieldValue(packet, NOTIFY_CLUSTER);\nboolean notifyCluster = (notifyClusterStr != null) ? Boolean.valueOf( notifyClusterStr ) : true;\n\ndef user_sessions = (Map)userSessions;\n\ndef userJids = Command.getFieldValues(packet, JIDS)\n\nif (userJids == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Ending session for the users\")\n\tCommand.addInstructions(result, \"Fill out this form to end user(s) session(s). BareJID - will end all user sessions, FullJID - only particular session.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JIDS, userJids ?: \"\", \"jid-multi\",\n\t\t\t\"The Jabber ID(s) for which end session\")\n\tif \t( clusterMode  ) {\n\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t}\n\n\treturn result\n}\n\ndef results = new LinkedList<Packet>();\n\n\nif (clusterMode && notifyCluster) {\n\tdef nodes = (List)clusterStrategy.getNodesConnected();\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tprintln \"forwarding: \" + forward\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\nresults.offer(result);\ndef msgs = [];\ndef errors = [];\nfor (userJid in userJids) {\n\ttry {\n\n\t\tJID userFullJID = JID.jidInstance(userJid)\n\t\tdef sess = user_sessions.get(userFullJID.getBareJID());\n\t\tVHostItem vhost = vhost_man.getVHostItem(userFullJID.getDomain())\n\t\tif (isServiceAdmin ||\n\t\t\t\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n\t\t\tif (sess != null) {\n\t\t\t\tdef conns = sess.getConnectionIds();\n\t\t\t\tfor (conn in conns) {\n\t\t\t\t\tXMPPResourceConnection res = sess.getResourceForConnectionId(conn);\n\t\t\t\t\tif (res != null && userFullJID.getResource() == null || (userFullJID.getResource() == res.getResource())) {\n\t\t\t\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), conn,\n\t\t\t\t\t\t\t\tStanzaType.set, res.nextStanzaId());\n\t\t\t\t\t\tresults.offer(commandClose);\n\t\t\t\t\t\tmsgs.add(\"Operation successful for user \"+res.getjid());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\terrors.add(\"You do not have enough permissions to end sessions for accounts for domain \"+bareJID.getDomain()+\".\");\n\t\t}\n\n\t} catch (Exception ex) {\n\t\tex.printStackTrace();\n\t}\n}\n\nif (!msgs.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Notes\", msgs);\n\nif (!errors.isEmpty())\n\tCommand.addFieldMultiValue(result, \"Errors\", errors);\nreturn results\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ForceStopServiceForKey.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nForce stop IOService for a given key.\n\nAS:Description: Force stop service\nAS:CommandId: force-stop-service\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.net.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef KEY = \"key\"\n\ndef key = Command.getFieldValue(packet, KEY)\n\nif (key == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n  Command.addTitle(result, \"Force-stopping IOService for a given key\")\n\tCommand.addInstructions(result, \"Provide a key for IOService you wish to stop.\")\n\tCommand.addFieldValue(result, KEY, key ?: \"\", \"text-single\",  \"Key\")\n\n\treturn result\n}\n\nMap services = (Map)servicesMap\n\nIOService serv = services.get(key)\n\nif (serv == null) {\n\treturn \"IOService for key: ${key} not found!\"\n} else {\n  serv.forceStop()\n\treturn \"Stopped IOService for key: ${key}.\"\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetAnyFile.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet any file\n\nAS:Description: Get any file\nAS:CommandId: get-any-file\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport java.io.File;\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.conf.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef FILE_PATH = \"file\";\n\ndef filepath = Command.getFieldValue(p, FILE_PATH);\n\ndef result = p.commandResult(filepath ? Command.DataType.result : Command.DataType.form);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\n\nelse if (filepath == null) {\n\tCommand.addFieldValue(result, FILE_PATH, \"\", \"text-single\", \"File\");\n}\nelse {\n\tif (filepath == null) {\n\t\tCommand.addTextField(result, \"Error\", \"File not specified\");\n\t}\n\telse {\n\t\tdef file = new File(filepath);\n\t\tif (file.exists()) {\n\t\t\tdef lines = [];\n\t\t\tfile.eachLine { line -> lines += line; };\n\t\t\tCommand.addFieldMultiValue(result, \"Content\", lines);\n\t\t}\n\t\telse {\n\t\t\tCommand.addTextField(result, \"Error\", \"File not found\");\n\t\t}\n\t}\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetConfigFile.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet configuration file\n\nAS:Description: Get configuration file\nAS:CommandId: get-config-file\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport java.io.File;\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.conf.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef CFGFILE_TYPE = \"config-file\";\ndef CFGFILE_OPTIONS = [\"init.properties\", \"tigase.conf\"];\n\ndef cfgfile = Command.getFieldValue(p, CFGFILE_TYPE);\n\ndef result = p.commandResult(cfgfile ? Command.DataType.result : Command.DataType.form);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\nelse if (cfgfile == null) {\n\tdef filesArray = CFGFILE_OPTIONS.toArray(new String[CFGFILE_OPTIONS.size()]);\n\tCommand.addFieldValue(result, CFGFILE_TYPE, \"init.properties\", \"File\", filesArray, filesArray);\n}\nelse {\n\tdef filepath = []\n\tswitch (cfgfile) {\n\t\tcase \"init.properties\":\n\t\t\tif (initProperties.get(ConfiguratorAbstract.PROPERTY_FILENAME_PROP_KEY) != null ) {\n\t\t\t\tfilepath = initProperties.get(ConfiguratorAbstract.PROPERTY_FILENAME_PROP_KEY).tokenize(',');\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"tigase.conf\":\n\t\t\tdef filenames = [\"/etc/default/tigase\", \"/etc/tigase/tigase.conf\", \"etc/tigase.conf\"];\n\t\t\tfilenames.each { it ->\n\t\t\t\tdef file = new File(it);\n\t\t\t\tif (filepath.size() == 0 && file.exists()) {\n\t\t\t\t\tfilepath.add(it);\n\t\t\t\t}\n\t\t\t};\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (filepath == null) {\n\t\tCommand.addTextField(result, \"Error\", \"Config file not specified\");\n\t}\n\telse {\n\t\tfilepath.each{ it ->\n\t\t\tdef file = new File(it);\n\t\t\tdef lines = [];\n\t\t\tfile.eachLine { line -> lines += line; };\n\t\t\tCommand.addFieldMultiValue(result, \"Content\", lines);\n\t\t}\n\t}\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetInitPropertiesFromMemory.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nGet init.properties configuration from memory.\n\nAS:Description: Get init.properties configuration\nAS:CommandId: get-init-properties\nAS:Component: basic-conf\n*/\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.cert.*\nimport tigase.io.*\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef result = p.commandResult(Command.DataType.result);\n\nif (!isServiceAdmin) {\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n}\nelse {\n\tdef lines = [];\n\tinitProperties.each { key, value ->\n\t\tlines += key + \"=\" + value;\n\t}\n\n\tCommand.addFieldMultiValue(result, \"init.properties\", lines);\n}\n\nreturn result;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetListOfActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-active-users-list\n\n AS:Description: Get list of active users\n AS:CommandId: http://jabber.org/protocol/admin#get-active-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting List of Active Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the active users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of active users\", vhostsArr, vhostsArr);\n//\t}\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == true) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list active accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, active users not listed.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetListOfClusterNodes.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n/*\n Get list of all connected cluster nodes\n\n AS:Description: Get list of all connected cluster nodes\n AS:CommandId: cluster-nodes-list\n AS:Component: cl-comp\n AS:Group: Configuration\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.db.comp.ComponentRepository\nimport tigase.xml.*\n\ndef p = (Packet)packet\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef nodes = component.getNodesConnectedWithLocal().collect { return it.getDomain() }\n\tCommand.addFieldMultiValue(result, \"Cluster nodes:\", nodes);\n} catch (Exception ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem with retrieving list of all connected cluster nodes: \" + ex.getMessage());\n}\nreturn result\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetListOfIdleUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-idle-users-list\n\n AS:Description: Get list of idle users\n AS:CommandId: http://jabber.org/protocol/admin#get-idle-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting List of Idle Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the idle users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of idle users\", vhostsArr, vhostsArr);\n//\t}\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == false) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list idle accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, idle users not listed.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetListOfOnlineUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-online-users-list\n\n AS:Description: Get list of online users\n AS:CommandId: http://jabber.org/protocol/admin#get-online-users-list\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\n\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Requesting List of Online Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the online users\\nof this service.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of online users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tvhosts = vhosts.sort();\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of online users\", vhostsArr, vhostsArr);\n//\t}\n\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\n\t\t\t\tif (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\n\t\t\t\t\tusers_list += user;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list online accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, online users not listed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetNumberOfActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-active-users-num\n\n AS:Description: Get number of active users\n AS:CommandId: http://jabber.org/protocol/admin#get-active-users-num\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\nif (domainJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting Number of Active Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the number of active users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the number of active users\", vhostsArr, vhostsArr);\n//\t}\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\t//if (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == true) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t//}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldValue(result, \"activeusersnum\", String.valueOf(users_list.size()), \"fixed\", \"The number of active users\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to get number of active accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, active users not counted.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetNumberOfIdleUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of online users script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-idle-users-num\n\n AS:Description: Get number of idle users\n AS:CommandId: http://jabber.org/protocol/admin#get-idle-users-num\n AS:Component: sess-man\n AS:Group: Statistics\n */\npackage tigase.admin\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\ndef SECOND = 1000;\ndef MINUTE = 60 * SECOND;\ndef JID = \"domainjid\"\ndef TIME_BEFORE_IDLE = 5 * MINUTE;\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef users_sessions = (Map)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\ndef domainJid = Command.getFieldValue(packet, JID);\nif (domainJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\tCommand.addTitle(result, \"Requesting Number of Idle Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the number of idle users\\nof this service.\")\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of active users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the number of idle users\", vhostsArr, vhostsArr);\n//\t}\n\treturn result\n}\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tusers_sessions.entrySet().each {\n\t\t\tif (!it.getKey().toString().startsWith(\"sess-man\") && it.getKey().getDomain().equals(bareJID.getDomain())) {\n\t\t\t\t//if (!maxItems || users_list.size() < maxItems) {\n\t\t\t\t\tdef user = it.getKey().toString();\n\t\t\t\t\tdef session = it.getValue();\n\t\t\t\t\tdef active = false;\n\t\t\t\t\tsession.getActiveResources().each {\n\t\t\t\t\t\tactive = active || ((System.currentTimeMillis() - it.getLastAccessed()) < TIME_BEFORE_IDLE);\n\t\t\t\t\t}\n\t\t\t\t\tif (active == false) {\n//\t\t\t\t\t\tuser += \" (\" + session.getActiveResourcesSize() + \":\";\n//\t\t\t\t\t\tsession.getJIDs().each { user += it.getResource() + \", \"; }\n//\t\t\t\t\t\tuser = user[0..user.size() - 3] + \")\";\n\t\t\t\t\t\tusers_list += user;\n\t\t\t\t\t}\n\t\t\t\t//}\n\t\t\t}\n\t\t}\n\t\tCommand.addFieldValue(result, \"idleusersnum\", String.valueOf(users_list.size()), \"fixed\", \"The number of idle users\");\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to get number of idle accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, idle users not counted.\");\n}\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetRegisteredUserList.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Get registered user list script as described in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-registered-users-list\n\n AS:Description: Get registered user list\n AS:CommandId: http://jabber.org/protocol/admin#get-registered-users-list\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"domainjid\"\ndef MAX_ITEMS = \"max_items\"\n\ndef p = (Packet)packet\ndef auth_repo = (AuthRepository)authRepository\ndef user_repo = (UserRepository)userRepository\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef domainJid = Command.getFieldValue(packet, JID);\ndef maxItemsStr = Command.getFieldValue(packet, MAX_ITEMS);\n\nif (domainJid == null || maxItemsStr == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Requesting List of Registered Users\")\n\tCommand.addInstructions(result, \"Fill out this form to request the registered users \\n of this service.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n//\tif (isServiceAdmin) {\n\t//Command.addFieldValue(result, JID, domainJid ?: \"\", \"jid-single\",\n\t//\t\t\"The domain for the list of online users\")\n//\t}\n//\telse {\n\t\tdef vhosts = [];\n\t\tvhost_man.repo.allItems().each {\n\t\t\tif (it.isOwner(stanzaFromBare.toString()) || it.isAdmin(stanzaFromBare.toString()) || isServiceAdmin) {\n\t\t\t\tvhosts += it.getVhost().toString()\n\t\t\t}\n\t\t}\n\t\tvhosts = vhosts.sort();\n\t\tdef vhostsArr = vhosts.toArray(new String[vhosts.size()]);\n\t\tCommand.addFieldValue(result, JID, \"\", \"The domain for the list of registered users\", vhostsArr, vhostsArr);\n//\t}\n\n\tCommand.addFieldValue(result, MAX_ITEMS, maxItemsStr ?: \"\", \"Maximum number of items to show\", [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]),  [\"25\", \"50\", \"75\", \"100\", \"150\", \"200\", \"None\"].toArray(new String[7]));\n\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\ntry {\n\tdef maxItems = maxItemsStr ?  (maxItemsStr == \"None\" ? null : Integer.parseInt(maxItemsStr)) : 25;\n\n\tbareJID = BareJID.bareJIDInstance(domainJid)\n\tVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\tif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\tdef users_list = [];\n\t\tdef domain_user_repo = (user_repo instanceof tigase.db.UserRepositoryMDImpl) ? user_repo.getRepo(bareJID.getDomain()) : user_repo;\n\t\tdef users =  domain_user_repo.getUsers();\n\t\tfor (user in users) {\n\t\t\tif (!user.getDomain().equals(bareJID.getDomain()))\n\t\t\t\tcontinue;\n\n\t\t\tusers_list.add(user.toString());\n\t\t\tif (maxItems && users_list.size() > maxItems)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tCommand.addFieldMultiValue(result, \"Users: \"+users_list.size(), users_list);\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to list accounts for this domain.\");\n\t}\n} catch (TigaseDBException ex) {\n\tCommand.addTextField(result, \"Note\", \"Problem accessing database, users not listed.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetTopActiveUsers.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Retrieves from the server specified number of top active users\n AS:Description: Get top active users\n AS:CommandId: http://jabber.org/protocol/admin#get-top-active-users\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\n\ndef TOP_NUM = \"top-num\"\n\ndef p = (Packet)packet\n\ndef topNum = Command.getFieldValue(packet, TOP_NUM)\n\nif (topNum == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get top active users\")\n\tCommand.addInstructions(result, \"Fill out this form to get top active users.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, TOP_NUM, topNum ?: \"10\", \"text-single\",\n\t\t\t\"Number of top active users to show\")\n\n\treturn result\n}\n\ndef user_sessions = (Map)userSessions\n\ndef mc= [\n\t\t\tcompare: {XMPPSession a, XMPPSession b->\n\t\t\t\ta.getPacketsCounter() == b.getPacketsCounter() ? 0: a.getPacketsCounter()>b.getPacketsCounter()? -1: 1\n\t\t\t}\n\t\t] as Comparator\n\ndef sessions = []\n// TODO: this is memory inefficient way to do it. We need to find a more memory friendly way\nuser_sessions.entrySet().each {\n\tif (!it.getKey().toString().startsWith(\"sess-man\")) {\n\t\tsessions += it.getValue()\n\t}\n}\n\nsessions.sort(mc)\ndef max = topNum.toInteger()\nif (max > sessions.size() ) {\n\tmax = sessions.size()\n}\n\ndef usr_list = []\n\nsessions[0..(max-1)].each { XMPPSession it ->\n\tusr_list += it.getJIDs()[0].toString() + \" online \" + (it.getLiveTime()/1000) + \" sec, \" + it.getPacketsCounter() + \" packets\"\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Top active users \", usr_list);\nreturn result\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetUserInfo.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Obtaining informations about user\n AS:Description: Get User Info\n AS:CommandId: get-user-info\n AS:Component: sess-man\n AS:Group: Users\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xml.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.cluster.*;\nimport tigase.cluster.api.*;\nimport tigase.cluster.strategy.*;\n\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get User Info\")\n\tCommand.addInstructions(result, \"Fill out this form to gather informations about user.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for statistics\")\n\tCommand.addCheckBoxField(result, \"Show connected resources in table\", true)\n\n\treturn result\n}\n\ndef bareJID = BareJID.bareJIDInstance(userJid)\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\ndef resourcesAsTable = Command.getCheckBoxFieldValue(p, \"Show connected resources in table\");\ndef result = p.commandResult(Command.DataType.result)\n\nif (isServiceAdmin ||\n(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\n\t\tCommand.addTextField(result, \"JID\", \"JID: \" + userJid)\n\t\tdef userRes = [];\n\t\tif (binding.variables.containsKey(\"clusterStrategy\")) { \n            def cluster = (ClusteringStrategyIfc) clusterStrategy\n\t\t\tdef conns = cluster.getConnectionRecords(bareJID);\n\t\t\tif (cluster.containsJid(bareJID) && (conns != null)) {\n\t\t\t\tconns.each { rec ->\n\t\t\t\t\tuserRes.add([res:rec.getUserJid().getResource(), node:rec.getNode().getDomain()]);\n\t\t\t\t}\n\t\t\t}\n\t\t} \n\n\t\tXMPPSession session = sessions.get(BareJID.bareJIDInstanceNS(userJid))\n\t\tif (session != null) {\n\t\t\tList<XMPPResourceConnection> conns = session.getActiveResources()\n\t\t\tconns.each { con ->\n\t\t\t\tuserRes.add([res:con.getResource(), node:con.getConnectionId()?.getDomain()]);\n\t\t\t}\n\t\t\t\n\t\t}\n\t\tif (userRes.isEmpty()) {\n\t\t\tCommand.addTextField(result, \"Status\", \"Status: offline\")\n\t\t} else {\n\t\t\tuserRes.sort { it.res };\n\t\t\tCommand.addTextField(result, \"Status\", \"Status: \" + (userRes.size() ? \"online\" : \"offline\"))\n\t\t\tCommand.addTextField(result, \"Active connections\", \"Active connections: \" + userRes.size())\n\t\t\tif (resourcesAsTable) {\n\t\t\t\tElement reported = new Element(\"reported\");\n\t\t\t\treported.addAttribute(\"label\", \"Connected resources\");\n\t\t\t\tdef cols = [\"Resource\", \"Cluster node\"];\n\t\t\t\tcols.each {\n\t\t\t\t\tElement el = new Element(\"field\");\n\t\t\t\t\tel.setAttribute(\"var\", it);\n\t\t\t\t\treported.addChild(el);\n\t\t\t\t}\n\t\t\t\tresult.getElement().getChild('command').getChild('x').addChild(reported);\n\t\t\t\tuserRes.each { con ->\t\n\t\t\t\t\tElement item = new Element(\"item\");\n\t\t\t\t\tElement res = new Element(\"field\");\n\t\t\t\t\tres.setAttribute(\"var\", \"Resource\");\n\t\t\t\t\tres.addChild(new Element(\"value\", con.res));\n\t\t\t\t\titem.addChild(res);\n\t\t\t\t\n\t\t\t\t\tElement node = new Element(\"field\");\n\t\t\t\t\tnode.setAttribute(\"var\", \"Cluster node\");\n\t\t\t\t\tnode.addChild(new Element(\"value\", con.node));\n\t\t\t\t\titem.addChild(node);\n\t\t\t\t\tresult.getElement().getChild('command').getChild('x').addChild(item);\n\t\t\t\t}\t\t\t\t\n\t\t\t} else {\n\t\t\t\tfor (def con: userRes) {\n\t\t\t\t\tCommand.addTextField(result, con.res + \" is connected to\", con.res + \" is connected to \" + con.node);\n\t\t\t\t}\n\t\t\t}\t\t\t\t\n\t\t}\n\n\t\tdef sessionManager = component;\n\t\tdef offlineMsgsRepo = sessionManager.processors.values().find { it.hasProperty(\"msg_repo\") }?.msg_repo;\n\t\tif (offlineMsgsRepo && offlineMsgsRepo.metaClass.respondsTo(offlineMsgsRepo, \"getMessagesCount\", [tigase.xmpp.JID] as Object[])) {\n\t\t\tdef offlineStats = 0;\n\t\t\ttry {\n\t\t\t\tofflineStats = offlineMsgsRepo.getMessagesCount(tigase.xmpp.JID.jidInstance(bareJID));\n\t\t\t} catch (tigase.db.UserNotFoundException ex) {\n\t\t\t\t// ignoring this error for now as it is not important\n\t\t\t}\n\t\t\tdef msg = \"Offline messages: \" + (offlineStats ? (offlineStats[offlineStats.keySet().find { it.name() == \"message\" }] ?: 0) : 0);\n\t\t\tCommand.addTextField(result, msg, msg);\n\t\t}\t\t\n\t\t\n\t\tdef loginHistoryProcessor = sessionManager.outFilters[\"login-history\"];\n\t\tif (loginHistoryProcessor) {\n\t\t\tdef unifiedArchiveComp = tigase.server.XMPPServer.getComponent(loginHistoryProcessor.getComponentJid().getLocalpart())//sessionManager.parent.components_byId[loginHistoryProcessor.componentJid];\n\t\t\tif (unifiedArchiveComp) {\n\t\t\t\tdef ua_repo = unifiedArchiveComp.msg_repo;\n\t\t\t\tdef criteria = ua_repo.newCriteriaInstance();\n\t\t\t\tcriteria.setWith(bareJID.toString());\n\t\t\t\tcriteria.getRSM().hasBefore = true;\n\t\t\t\tcriteria.getRSM().max = 10;\n\t\t\t\tcriteria.itemType = \"login\";\n//\t\t\t\tdef logins = ua_repo.getItems(bareJID, criteria).reverse().collect { new java.util.Date(criteria.getStart().getTime() + \n//\t\t\t\t\t\t\t(Integer.parseInt(it.getAttribute(\"secs\"))*1000)).toString() + \" for resource '\" + it.getChildren().first().getCData() + \"'\" }.join(\"\\n\");\n\n\t\t\t\tElement reported = new Element(\"reported\");\n\t\t\t\treported.addAttribute(\"label\", \"Login times\");\n\t\t\t\tdef cols = [\"Resource\", \"Date\"];\n\t\t\t\tcols.each {\n\t\t\t\t\tElement el = new Element(\"field\");\n\t\t\t\t\tel.setAttribute(\"var\", it);\n\t\t\t\t\treported.addChild(el);\n\t\t\t\t}\n\t\t\t\tresult.getElement().getChild('command').getChild('x').addChild(reported);\n\t\t\t\n\t\t\t\tua_repo.getItems(bareJID, criteria).reverse().each {\n\t\t\t\t\tElement item = new Element(\"item\");\n\t\t\t\t\tElement res = new Element(\"field\");\n\t\t\t\t\tres.setAttribute(\"var\", \"Resource\");\n\t\t\t\t\tres.addChild(new Element(\"value\", it.getChildren().first().getCData()));\n\t\t\t\t\titem.addChild(res);\n\t\t\t\t\t\n\t\t\t\t\tString ts = new java.util.Date(criteria.getStart().getTime() + \n\t\t\t\t\t\t(Integer.parseInt(it.getAttribute(\"secs\"))*1000)).format(\"yyyy-MM-dd HH:mm:ss.S\");\n\t\t\t\t\tElement node = new Element(\"field\");\n\t\t\t\t\tnode.setAttribute(\"var\", \"Date\");\n\t\t\t\t\tnode.addChild(new Element(\"value\", ts));\n\t\t\t\t\titem.addChild(node);\n\t\t\t\t\tresult.getElement().getChild('command').getChild('x').addChild(item);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to obtain statistics for user in this domain.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/GetUserRoster.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nObtaining User Statistics as described in in XEP-0133:\nhttp://xmpp.org/extensions/xep-0133.html#get-user-roster\n\nAS:Description: Get User Roster\nAS:CommandId: http://jabber.org/protocol/admin#get-user-roster\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.xmpp.impl.roster.*\n\ndef JID = \"accountjid\"\ndef SHOW_AS_TABLE = \"Present roster in table (required for UI)\";\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\ndef showAsTable = Command.getCheckBoxFieldValue(packet, SHOW_AS_TABLE) ?: false;\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Getting a User's Roster\")\n\tCommand.addInstructions(result, \"Fill out this form to get a user's roster.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n    Command.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for which to retrieve roster\")\n\tCommand.addCheckBoxField(result, SHOW_AS_TABLE, showAsTable);\t\n\n\treturn result\n}\n\ndef bareJID = BareJID.bareJIDInstance(userJid)\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\ndef result = p.commandResult(Command.DataType.result)\n\nif (isServiceAdmin ||\n\t(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\t\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for which to retrieve roster\")\n\t\n\tXMPPSession session = sessions.get(BareJID.bareJIDInstanceNS(userJid))\n\t\n\tif (!showAsTable) {\t\n\t\tElement query = new Element(\"query\");\n\t\tquery.setXMLNS(\"jabber:iq:roster\");\n\t\tif (session == null) {\n\t\t\tString rosterStr = repository.getData(bareJID, null,\n\t\t\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\t\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\t\troster.values().each {\n\t\t\t\tquery.addChild(it.getRosterItem());\n\t\t\t}\n\t\t} else {\n\t\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t\tquery.addChildren(rosterUtil.getRosterItems(session.getActiveResources().get(0)));\n\t\t}\n\t\tif (query != null) {\n\t\t\tresult.getElement().getChild(\"command\").getChild(\"x\", \"jabber:x:data\").addChild(query);\n\t\t}\t\t\n\t} else {\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\tif (session == null) {\n\t\t\tString rosterStr = repository.getData(bareJID, null,\n\t\t\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\t\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\t} else {\n\t\t\tdef conn = session.getActiveResources().get(0)\n\t\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t\trosterUtil.getBuddies(conn).each { buddyJid ->\n\t\t\t\troster.put(buddyJid.getBareJID(), rosterUtil.getRosterElement(conn, buddyJid));\n\t\t\t}\n\t\t}\n\t\tif (roster.isEmpty()) {\n\t\t\tCommand.addTextField(result, \"Note\", \"Not found any roster entries for \" + bareJID);\n\t\t} else {\n\t\t\tCommand.addTextField(result, \"Note\", \"Found \" + roster.size() + \" entries in roster for \" + bareJID);\n\t\t\tElement reported = new Element(\"reported\");\n\t\t\treported.addAttribute(\"label\", \"Connected resources\");\n\t\t\tdef cols = [\"JID\", \"Name\", \"Subscription\", \"Groups\"];\n\t\t\tcols.each {\n\t\t\t\tElement el = new Element(\"field\");\n\t\t\t\tel.setAttribute(\"var\", it);\n\t\t\t\treported.addChild(el);\n\t\t\t}\n\t\t\tresult.getElement().getChild('command').getChild('x').addChild(reported);\n\t\t\troster.each { jid, rosterEntry ->\n\t\t\t\tElement item = new Element(\"item\");\n\t\t\t\tcols.each { col ->\n\t\t\t\t\tElement res = new Element(\"field\");\n\t\t\t\t\tres.setAttribute(\"var\", col);\n\t\t\t\t\tdef val = null;\n\t\t\t\t\tif (col == \"JID\")\n\t\t\t\t\t\tval = rosterEntry.getJid().toString();\n\t\t\t\t\telse if (col == \"Name\")\n\t\t\t\t\t\tval = rosterEntry.getName();\n\t\t\t\t\telse if (col == \"Subscription\")\n\t\t\t\t\t\tval = rosterEntry.getSubscription()?.name() ?: \"none\";\n\t\t\t\t\telse if (col == \"Groups\")\n\t\t\t\t\t\tval = rosterEntry.getGroups()?.join(\", \")?: \"\";\n\t\t\t\t\tres.addChild(new Element(\"value\", val));\n\t\t\t\t\titem.addChild(res);\n\t\t\t\t}\n\t\t\t\tresult.getElement().getChild('command').getChild('x').addChild(item);\n\t\t\t}\n\t\t}\n\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to retrieve roster for user in this domain.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ListCommands.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n/*\n Get list of available adhoc commands with additional metadata.\n\n AS:Description: Get list available commands\n AS:CommandId: list-commands\n AS:Group: Example scripts\n AS:ComponentClass: tigase.server.BasicComponent\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xml.Element\nimport tigase.xmpp.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef result = p.commandResult(Command.DataType.form)\nCommand.addTitle(result, \"Retrieving list of commands\");\n\ndef type = Command.getFieldValue(p, \"type\");\nif (!type) {\t\n\tCommand.addInstructions(result, \"Select a informations to retrieve\")\n\tCommand.addFieldValue(result, \"type\", \"\", \"Informations to retrive\", [\"Groups\", \"Commands\"].toArray(new String[2]), [\"groups\", \"commands\"].toArray(new String[2]));\n\treturn result;\n}\nelse if (type == \"groups\") {\n\tdef groups = [];\n\tCommand.addInstructions(result, \"Select a group for which to retrieve commands\");\n\tCommand.addFieldValue(result, \"type\", \"commands\", \"hidden\");\n\tadminCommands.each { id, script -> \n\t\tif (!component.canCallCommand(p.getStanzaFrom(), id))\n\t\t\treturn;\n\t\t\n\t\tdef group = script.getGroup();\n\t\tif (group == null) {\n\t\t\tgroup = \"--\";\n\t\t}\n\t\tif (!groups.contains(group))\n\t\t\tgroups.add(group);\n\t}\n\tCommand.addFieldValue(result, \"group\", \"\", \"Group\", groups.toArray(new String[groups.size()]), groups.toArray(new String[groups.size()]));\n\treturn result;\n}\nelse if (type == \"commands\") {\n\tdef group = Command.getFieldValue(p, \"group\");\n\tCommand.addHiddenField(result, \"group\", group ?: \"\");\n\tCommand.addInstructions(result, \"Following commands are available\" + (group ? \" for group $group\" : \"\"));\n\tdef x = Command.getData(result).find { it.getName() == \"x\" && it.getXMLNS() };\n\tdef reported = new Element(\"reported\");\n\tdef fields = [\"node\", \"group\", \"name\", \"jid\"];\n\treported.addChildren(fields.collect {\n\t\tnew Element(\"field\", [\"var\"].toArray(new String[1]), [it].toArray(new String[1]));\t\n\t});\n\tx.addChild(reported);\n\tdef scripts = [];\n\tadminCommands.each { id, script -> \n\t\tif (!component.canCallCommand(p.getStanzaFrom(), id))\n\t\t\treturn;\n\t\t\t\n\t\tif (group && !group.equals(script.getGroup()))\n\t\t\treturn;\n\t\t\t\n\t\tdef item = new Element(\"item\");\n\t\tfields.each {\n\t\t\tdef value = new Element(\"value\");\n\t\t\tdef field = new Element(\"field\");\n\t\t\tfield.setAttribute(\"var\", it);\n\t\t\tfield.addChild(value);\n\t\t\titem.addChild(field);\n\t\t\t\n\t\t\tif (it == \"node\") {\n\t\t\t\tvalue.setCData(id);\n\t\t\t} else if (it == \"group\") {\n\t\t\t\tvalue.setCData(script.getGroup());\n\t\t\t} else if (it == \"name\") {\n\t\t\t\tvalue.setCData(script.getDescription());\n\t\t\t} else if (it == \"jid\") {\n\t\t\t\tvalue.setCData(packet.getStanzaTo().toString());\n\t\t\t}\n\t\t}\n\t\tx.addChild(item);\n\t\t\n\t\tscripts.add([id:id, name:script.getDescription()]);\n\t}\t\n\t\n\tCommand.addFieldValue(result, \"commands\", \"\", \"Commands\", scripts.collect{ it.name }.toArray(new String[scripts.size()]), scripts.collect{ it.id }.toArray(new String[scripts.size()]));\n\treturn result;\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/ListServiceKeys.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nList all keys for active IOServices from the connection manager.\n\nAS:Description: List Service Keys\nAS:CommandId: service-keys\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\nMap services = (Map)servicesMap\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\nreturn services.keySet().toString()\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/LoadErrors.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nLoad errors caught by the server during execution:\n\nAS:Description: Load errors\nAS:CommandId: load-errors\nAS:Component: monitor\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef result = []\n\ndef size = LogFormatter.errors.size()\nif (size > 0) {\n\tLogFormatter.errors.each {\n\t\tdef entry = it.getValue()\n\t\tresult += \"\";\n\t\tresult += entry.getMessage() + \": \" + entry.getCounter()\n\t\tentry.getRecord().split(\"\\n\").each {\n\t\t\tresult += it\n\t\t}\n\t}\n} else {\n\tresult += \"No errors so far!\"\n}\n\ndef res = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(res, \"Errors: \" + size, result)\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/OAuthCredentials.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nAdHoc Command for setting OAuth credentials for JabberIQRegister\n\nAS:Description: OAuth credentials\nAS:CommandId: oauth-credentials\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\n\ndef p = (Packet)packet\n\ndef oauthTokenKey = Command.getFieldValue(packet, \"oauthTokenKey\")\ndef oauthTokenSecret = Command.getFieldValue(packet, \"oauthTokenSecret\")\ndef signedFormRequired = Command.getFieldValue(packet, \"signedFormRequired\")\n\nif (signedFormRequired == null) {\n\tdef res = p.commandResult(Command.DataType.form)\n\tCommand.addTitle(res, \"OAuth Credentials\")\n\tCommand.addInstructions(res, \"It allows to set new OAuth credentials and enable or disable requirement of registration with Signed Form.\")\n\tCommand.addFieldValue(res, \"oauthTokenKey\", \"\", \"text-single\", \"OAuth Token Key\")\n\tCommand.addFieldValue(res, \"oauthTokenSecret\", \"\", \"text-single\", \"OAuth Token Secret\")\n\tCommand.addFieldValue(res, \"signedFormRequired\", Boolean.toString(JabberIqRegister.isSignedFormRequired()), \"boolean\", \"Signed Form required to registration\") \n\treturn res\n} else {\n\tJabberIqRegister.setOAuthCredentials(oauthTokenKey, oauthTokenSecret)\n\tJabberIqRegister.setSignedFormRequired(signedFormRequired.equals(\"1\") || signedFormRequired.equals(\"true\"))\n\t\n\tdef res = p.commandResult(Command.DataType.result)\n\tCommand.addTitle(res, \"OAuth Credentials\")\n\tCommand.addInstructions(res, \"Credentials set.\")\n\treturn res\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/PluginManager.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nManage active server plugins\n\nAS:Description: Manage active server plugins\nAS:CommandId: plugin-manager\nAS:Component: basic-conf\nAS:Group: Configuration\n */\n\npackage tigase.admin\n\nimport tigase.conf.ConfigRepositoryIfc\nimport tigase.conf.Configurable;\nimport tigase.conf.Configurator;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.*\n\nclass DelayedReloadTaskPlugMan extends Thread {\n\tvoid run() {\n\t\tThread.sleep(5000);\n\t    ((Configurator) XMPPServer.getConfigurator()).updateMessageRouter();\n\t}\n}\n\ntry {\n\ndef SUBMIT = \"exec\";\n        \ndef p = (Iq)packet\n\n// check permission\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n        def result = p.commandResult(Command.DataType.result)\n        Command.addTextField(result, \"Error\", \"You do not have enough permissions to access this data.\");\n        return result\n}\n\n        \n//def submit = Command.getFieldValue(p, SUBMIT);\ndef submit = p.getElement().findChild([\"iq\",\"command\",\"x\"] as String[])?.getAttribute(\"type\");\n\nif (!submit) {\n        def res = (Iq)p.commandResult(Command.DataType.form)\n                \n        def pluginsAll = [];\n\t\tif (XMPPServer.isOSGi()) {\n\t\t\tpluginsAll.addAll(ModulesManagerImpl.getInstance().plugins.keySet());\n\t\t}\n\t\telse {\n\t\t\tpluginsAll.addAll(tigase.xmpp.ProcessorFactory.processors.keySet());\n\t\t}\n        def conf = XMPPServer.getConfigurator();\n        def pluginsEnabled = [];\n        pluginsEnabled.addAll(tigase.server.xmppsession.SessionManagerConfig.PLUGINS_FULL_PROP_VAL);\n        \n        def pluginsStr = conf.getDefConfigParams().get(Configurable.GEN_SM_PLUGINS);\n        if (pluginsStr) {\n                pluginsStr.split(\",\").each { tmp ->\n                        def id = tmp;\n                        switch (tmp.charAt(0)) {\n                                case '+':\n                                        id = tmp.substring(1);\n                                        if (!pluginsAll.contains(id)) {\n                                                pluginsAll.add(id);\n                                        }\n                                        if (!pluginsEnabled.contains(id)) {\n                                                pluginsEnabled.add(id);\n                                        }\n                                        break;\n                                case '-':\n                                        id = tmp.substring(1);\n                                        if (!pluginsAll.contains(id)) {\n                                                pluginsAll.add(id);\n                                        }\n                                        pluginsEnabled.remove(id);\n                                        break;\n                                default:\n                                        pluginsEnabled.add(id);\n                                        break;\n                        }\n                }\n        }\n        \n        Command.addHiddenField(res, SUBMIT, SUBMIT);\n                \n        pluginsAll.sort();\n        pluginsAll.each { id ->\n                Command.addCheckBoxField(res, id, pluginsEnabled.contains(id));\n        }\n        \n        return res;\n}\nelse {\n        def pluginsEnabled = [];\n        pluginsEnabled.addAll(tigase.server.xmppsession.SessionManagerConfig.PLUGINS_FULL_PROP_VAL);\n        \n        def str = \"\";\n                \n        def data = Command.getData(p, \"x\", \"jabber:x:data\");\n        data.getChildren().each { child ->\n                if (child.getName() != 'field') return;\n                if (child.getAttribute(\"value\") == SUBMIT) return;\n                def id = tigase.xml.XMLUtils.escape(child.getAttribute(\"var\"));\n                def enable = Command.getCheckBoxFieldValue(p, id);\n                if (enable && pluginsEnabled.contains(id)) return;\n                if (!enable && !pluginsEnabled.contains(id)) return;\n                if (enable && !pluginsEnabled.contains(id)) {\n                        if (!str.isEmpty()) str += \",\";\n                        str += \"+\" + id;\n                        pluginsEnabled.add(id);\n                }\n                else if (!enable && pluginsEnabled.contains(id)) {\n                        if (!str.isEmpty()) str += \",\";\n                        str += \"-\" + id;\n\t\t\t\t\t\tpluginsEnabled.remove(id);\n                }\n        }\n\n        def conf = XMPPServer.getConfigurator();\n        conf.getDefConfigParams().put(Configurable.GEN_SM_PLUGINS, str.isEmpty() ? null : str);\n\t\n        def props = [:];\n        props[tigase.server.xmppsession.SessionManagerConfig.PLUGINS_PROP_KEY] = (pluginsEnabled as String[]);\n        conf.putProperties(\"sess-man\", props);\n                \n\t\tnew DelayedReloadTaskPlugMan().start();\n\t\t\n        def res = (Iq)p.commandResult(Command.DataType.result)\n\n        Command.addTextField(res, \"Note\", \"Operation successful.\");\n                \n        return res;\n}        \n\n}\ncatch (Exception ex) {\n        ex.printStackTrace();\n        throw ex;\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/RemoveUserTracker.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n/*\n Activate on the server user tracking mechanisms to aid in problem resolution.\n AS:Description: Remove log tracker for a user\n AS:CommandId: http://jabber.org/protocol/admin#remove-user-tracker\n AS:Component: sess-man\n */\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.util.*\nimport java.util.logging.*\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Removing a User Log Tracker\")\n\t//Command.addInstructions(result, \"Fill out this form to add a user log tracker.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\n\t\t\t\"The Jabber ID for the tracker to be removed\")\n\treturn result\n}\n\ndef result = p.commandResult(Command.DataType.result)\n\ndef hand = null\n\nHandler[] handlers = Logger.getLogger(\"\").getHandlers()\nhandlers.each {\n\tFilter filt = it.getFilter()\n\tif (filt != null && filt.class == LogUserFilter && ((LogUserFilter)filt).getId() == userJid) {\n\t\thand = it\n\t}\n}\n\nif (hand != null) {\n\tLogger.getLogger(\"\").removeHandler(hand)\n\thand.close()\n\tCommand.addTextField(result, \"Note\", \"Operation successful, tracker removed for \" + userJid);\n} else {\n\tCommand.addTextField(result, \"Note\", \"No tracker found for user \" + userJid)\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/RosterFixer.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\n\nThe roster fixer scripts is used in a case if for whatever reason user's roster got\nbroken, lost or otherwise messed up. If we know the user's contact list, this script\ncan be used to restore the contact list. It adds missing entries to the user's roster.\nIf the user is online, he gets a roster push with updated entries to make sure\nhe is up to date with all the changes.\nThe script accepts a user JID, action (update or remove) and a list of buddies in\na following format:\nbuddy_jid,buddy_name,subscription\nbuddy_jid is a JID (bare JID)\nbuddy_name is just a string, it is optional, if omit, localpart of the JID is used\nsubscription is one of following (none, from, to, both), it is optional, if omit 'both' is used\n\n\nAS:Description: Fixes user's roster\nAS:CommandId: roster-fixer\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\ndef ROSTER_BUDDY_LIST = \"roster-buddy-list\"\n\ndef ROSTER_ACTION = \"roster-action\"\n\ndef UPDATE = \"update\"\ndef REMOVE = \"remove\"\ndef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\ndef actions = [UPDATE, REMOVE]\ndef actions_descr = [\"Add/Update item\", \"Remove item\"]\n//def notify_cluster = [\"no\", \"yes\"]\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\n\ndef stanzaFromBare = p.getStanzaFrom().getBareJID();\ndef isServiceAdmin = admins.contains(stanzaFromBare);\n\ndef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\ndef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\ndef rosterBuddyList = Command.getFieldValues(packet, ROSTER_BUDDY_LIST) as List;\n\n//def rosterNotifyCluster = Command.getFieldValue(packet, ROSTER_NOTIFY_CLUSTER)\n\nif (rosterOwnerJid == null || rosterBuddyList == null ||\n\trosterAction == null) {\n\tdef res = p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\",\n    \"jid-single\", \"Roster owner JID\")\n\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0],\n    \"Action\", (String[])actions_descr, (String[])actions)\n\n\tif (rosterBuddyList == null) {\n\t\trosterBuddyList = [\"\"]\n\t}\n\tCommand.addFieldMultiValue(res, ROSTER_BUDDY_LIST, rosterBuddyList)\n\n//\tCommand.addFieldValue(res, ROSTER_NOTIFY_CLUSTER, notify_cluster[0],\n//    \"Notify cluster\", (String[])notify_cluster, (String[])notify_cluster)\n\n\treturn res\n}\n\ndef remove_item = rosterAction == REMOVE\n\ndef Queue<Packet> results = new LinkedList<Packet>()\n\ndef res_report = []\n\ndef updateRoster = { sess, online, jid, i_jid, i_name, i_subscr ->\n\n\tif (online) {\n//\t\tsess.getActiveResources().each{ conn ->\n\t\tdef conn = sess.getActiveResources()[0]\n\t\t  // Update online\n\t\t  RosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t  if (remove_item) {\n\t\t\t  rosterUtil.removeBuddy(conn, i_jid)\n  \t\t  Element item = new Element(\"item\",\n\t  \t\t  (String[])[\"jid\", \"subscription\"], (String[])[i_jid, \"remove\"])\n  \t\t  rosterUtil.updateBuddyChange(conn, results, item)\n\t\t\t  Element pres = new Element(\"presence\",\n\t\t\t\t  (String[])[\"from\", \"to\", \"type\", \"xmlns\"], (String[])[jid, i_jid, \"unsubscribed\", \"jabber:client\"]);\n\t\t\t  results.offer(Packet.packetInstance(pres))\n\t\t\t  pres = new Element(\"presence\",\n\t\t\t\t  (String[])[\"from\", \"to\", \"type\", \"xmlns\"], (String[])[jid, i_jid, \"unsubscribe\", \"jabber:client\"]);\n\t\t\t  results.offer(Packet.packetInstance(pres))\n\t\t\t  res_report += \"Buddy: \"+ i_jid + \" removed\"\n\t\t  } else {\n\t\t\t  if (rosterUtil.containsBuddy(conn, i_jid)) {\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n\t\t\t\t} else {\n  \t\t\t  rosterUtil.addBuddy(conn, i_jid, i_name, null, null)\n\t  \t\t  rosterUtil.setBuddySubscription(conn,\n\t\t  \t\t  RosterAbstract.SubscriptionType.valueOf(i_subscr), i_jid)\n\t\t\t    item = rosterUtil.getBuddyItem(conn, i_jid)\n    \t\t  rosterUtil.updateBuddyChange(conn, results, item)\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n\t\t\t\t}\n\t\t  }\n//\t\t}\n\t} else {\n\t\t// Update offline\n\t\tString rosterStr = repository.getData(jid.getBareJID(), null,\n\t\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\tif (remove_item) {\n\t\t\troster.remove(i_jid.getBareJID())\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" removed\"\n\t\t} else {\n      if (roster.get(i_jid.getBareJID()) == null) {\n\t\t\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, null, null)\n\t\t\t\t  rel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\t    roster.put(i_jid, rel)\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n      } else {\n\t\t\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n      }\n\t\t}\n\t\tStringBuilder sb = new StringBuilder(200)\n\t\tfor (RosterElement relem: roster.values())\n\t\t\tsb.append(relem.getRosterElement().toString())\n\t\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\t}\n}\n\ndef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid);\n\nPacket result = p.commandResult(Command.DataType.result)\ndef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\nif (vhost == null ||\n\t(!isServiceAdmin &&\n\t !vhost.isOwner(stanzaFromBare.toString()) &&\n\t !vhost.isAdmin(stanzaFromBare.toString()))) {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\tresults.add(result);\n\treturn results;\n}\n\ndef rosterItemJid = null\ndef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID());\ndef conn = sess != null ? sess.getActiveResources().get(0) : null;\ndef online = true\nif (conn) {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is online, updating database and online connections\"\n} else {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is offline, updating database only\"\n\tonline = false\n}\n\nrosterBuddyList.each {\n  def\tbuddy = it.split(\",\")\n\tif (it.contains(';')) {\n  \tbuddy = it.split(\";\")\n\t}\n\trosterItemJid = buddy[0]\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid)\n\tdef rosterItemName = (buddy as List)[1] ?: jidRosterItemJid.getLocalpart()\n\tdef rosterItemSubscr = (buddy as List)[2] ?: \"both\"\n\n  updateRoster(sess, online, jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemSubscr)\n\n\t\tif (!remove_item) {\n\n\t\t\tElement pres = new Element(\"presence\",\n\t\t\t\t(String[])[\"from\", \"to\", \"type\", \"xmlns\"], (String[])[rosterOwnerJid, rosterItemJid,\n\t\t\t\t\t\"probe\", \"jabber:client\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t\tpres = new Element(\"presence\",\n\t\t\t\t(String[])[\"from\", \"to\", \"type\", \"xmlns\"], (String[])[rosterItemJid, rosterOwnerJid,\n\t\t\t\t\t\"probe\", \"jabber:client\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t}\n\n}\n\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addFieldMultiValue(result, \"Report: \", res_report)\nresults.add(result)\n\nreturn results\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/RosterFixerCluster.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\nThe roster fixer scripts is used in a case if for whatever reason user's roster got\nbroken, lost or otherwise messed up. If we know the user's contact list, this script\ncan be used to restore the contact list. It adds missing entries to the user's roster.\nIf the user is online, he gets a roster push with updated entries to make sure\nhe is up to date with all the changes.\nThe script accepts a user JID, action (update or remove) and a list of buddies in\na following format:\nbuddy_jid,buddy_name,subscription\nbuddy_jid is a JID (bare JID)\nbuddy_name is just a string, it is optional, if omit, localpart of the JID is used\nsubscription is one of following (none, from, to, both), it is optional, if omit 'both' is used\nAS:Description: Fixes user's roster on Tigase cluster\nAS:CommandId: roster-fixer-cluster\nAS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport java.util.Set;\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.cluster.strategy.*\n\ndef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\ndef ROSTER_BUDDY_LIST = \"roster-buddy-list\"\n\ndef ROSTER_ACTION = \"roster-action\"\n\ndef DISCONNECTED_PHASE = \"disconnected-phase\"\n\ndef UPDATE = \"update\"\ndef REMOVE = \"remove\"\ndef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\ndef actions = [UPDATE, REMOVE]\ndef actions_descr = [\"Add/Update item\", \"Remove item\"]\n//def notify_cluster = [\"no\", \"yes\"]\n\ndef p = (Packet)packet\ndef repository = (UserRepository)userRepository\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\n\ndef stanzaFromBare = p.getStanzaFrom().getBareJID();\ndef isServiceAdmin = admins.contains(stanzaFromBare);\n\ndef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\ndef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\ndef rosterBuddyList = Command.getFieldValues(packet, ROSTER_BUDDY_LIST) as List;\n\n//def rosterNotifyCluster = Command.getFieldValue(packet, ROSTER_NOTIFY_CLUSTER)\n\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\n\nif (rosterOwnerJid == null || rosterBuddyList == null ||\n\trosterAction == null) {\n\tdef res = p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\",\n\t\t\t\"jid-single\", \"Roster owner JID\")\n\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0],\n\t\t\t\"Action\", (String[])actions_descr, (String[])actions)\n\n\tif (rosterBuddyList == null) {\n\t\trosterBuddyList = [\"\"]\n\t}\n\tCommand.addFieldMultiValue(res, ROSTER_BUDDY_LIST, rosterBuddyList)\n\n\t//\tCommand.addFieldValue(res, ROSTER_NOTIFY_CLUSTER, notify_cluster[0],\n\t//    \"Notify cluster\", (String[])notify_cluster, (String[])notify_cluster)\n\n\treturn res\n}\n\ndef remove_item = rosterAction == REMOVE\ndef res_report = []\ndef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid)\ndef Queue<Packet> results = new LinkedList<Packet>()\n\nPacket result = p.commandResult(Command.DataType.result)\ndef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\nif (vhost == null ||\n\t(!isServiceAdmin &&\n\t\t!vhost.isOwner(stanzaFromBare.toString()) &&\n\t\t!vhost.isAdmin(stanzaFromBare.toString()))) {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\tresults.offer(result);\n\treturn results;\n}\n\ndef disconnected = Command.getFieldValue(p, DISCONNECTED_PHASE)\n\n// Disconnecting all user's connections on the whole cluster\n\nif (!disconnected) {\n\n\tdef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID())\n\tdef online = false\n\n\tif (sess && sess.getActiveResourcesSize() > 0) {\n\t\tsess.getActiveResources().each{ conn ->\n\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), conn.getConnectionId(),\n\t\t\t\tStanzaType.set, conn.nextStanzaId())\n\t\t\tresults.offer(commandClose)\n\t\t\tres_report += \"User: \" + conn.getjid() + \" is online, disconnected.\"\n\t\t}\n\t\tonline = true\n\t}\n\n\tif \t( clusterMode ) {\n\t\tif ( null != clusterStrategy ) {\n\t\t\tdef cluster = (ClusteringStrategyIfc)clusterStrategy\n\t\t\tSet<ConnectionRecord> cl_conns = cluster.getConnectionRecords(jidRosterOwnerJid.getBareJID())\n\t\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\t\tcl_conns.each {\n\t\t\t\t\tdef commandClose = Command.CLOSE.getPacket(p.getStanzaTo(), it.getConnectionId(),\n\t\t\t\t\t\tStanzaType.set, \"77\")\n\t\t\t\t\tresults.offer(commandClose)\n\t\t\t\t\tres_report += \"User: \" + it.getUserJid() + \" is online on node: \" + it.getNode() + \", disconnected.\"\n\n\t\t\t\t}\n\t\t\t\tonline = true\n\t\t\t}\n\t\t}\n\t}\n\n\tif (online) {\n\t\tCommand.addFieldMultiValue(p, \"Report: \", res_report)\n\t\tCommand.addHiddenField(p, DISCONNECTED_PHASE, DISCONNECTED_PHASE)\n\t\tresults.offer(p)\n\n\t\treturn results\n\t}\n} else {\n\n\tCommand.getFieldValues(packet, \"Report: \").each {\n\t\tres_report += it\n\t}\n}\n\n// Waiting 2 secs\n\nsleep(2000)\n\n// Updating user's roster in DB\n\ndef updateRoster = { sess, online, jid, i_jid, i_name, i_subscr ->\n\n\t// Update offline\n\tString rosterStr = repository.getData(jid.getBareJID(), null,\n\t\tRosterAbstract.ROSTER, null) ?: \"\"\n\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\tif (remove_item) {\n\t\troster.remove(i_jid.getBareJID())\n\t\tres_report += \"Buddy: \"+ i_jid + \" removed\"\n\t} else {\n\t\tif (roster.get(i_jid.getBareJID()) == null) {\n\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, null, null)\n\t\t\trel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\troster.put(i_jid, rel)\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" added to the roster\"\n\t\t} else {\n\t\t\tres_report += \"Buddy: \"+ i_jid + \" already in the roster, skipping\"\n\t\t}\n\t}\n\tStringBuilder sb = new StringBuilder(200)\n\tfor (RosterElement relem: roster.values())\n\tsb.append(relem.getRosterElement().toString())\n\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\n}\n\n\ndef rosterItemJid = null\ndef sess = sessions == null ? null : sessions.get(jidRosterOwnerJid.getBareJID());\ndef conn = sess != null ? sess.getActiveResources().get(0) : null;\ndef online = true\nif (conn) {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is online, updating database and online connections\"\n} else {\n\tres_report += \"User: \" + jidRosterOwnerJid + \" is offline, updating database only\"\n\tonline = false\n}\n\nrosterBuddyList.each {\n\tdef\tbuddy = it.split(\",\")\n\tif (it.contains(';')) {\n\t\tbuddy = it.split(\";\")\n\t}\n\trosterItemJid = buddy[0]\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid)\n\tdef rosterItemName = (buddy as List)[1] ?: jidRosterItemJid.getLocalpart()\n\tdef rosterItemSubscr = (buddy as List)[2] ?: \"both\"\n\n\tupdateRoster(sess, online, jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemSubscr)\n\n\tif (!remove_item) {\n\n\t\tElement pres = new Element(\"presence\",\n\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterOwnerJid, rosterItemJid,\n\t\t\t\t\t\"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t\tpres = new Element(\"presence\",\n\t\t\t(String[])[\"from\", \"to\", \"type\"], (String[])[rosterItemJid, rosterOwnerJid,\n\t\t\t\t\t\"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t}\n\n}\n\n// Finishing the work and completing script\n\nCommand.addTextField(result, \"Note\", \"Operation successful\");\nCommand.addFieldMultiValue(result, \"Report: \", res_report)\nresults.add(result)\n\nreturn results\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/S2SBadConnectionStates.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Script tries to find S2S connection in a bad state and reports connection details.\n AS:Description: S2S Bad State Connections\n AS:CommandId: s2s-bad-state-conns\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef p = (Packet)packet\ndef cidConns = (Map)cidConnections\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef conns = []\n\nconns += \"Total count: \" + cidConns.size()\n\ncidConns.entrySet().each {\n\tCIDConnections con = it.getValue()\n\tif (con.getWaitingCount() > 0) {\n\t\tconns += it.getKey().toString() +\n\t\t\t\t\", out in progress: \" + con.getOutgoingInProgress() +\n\t\t\t\t\", waiting: \" + con.getWaitingCount() +\n\t\t\t\t\", control: \" + con.getWaitingControlCount() +\n\t\t\t\t\", incoming: \" + con.getIncomingCount() +\n\t\t\t\t\", outgoing: \" + con.getOutgoingCount() +\n\t\t\t\t\", out-handshaking: \" + con.getOutgoingHandshakingCount()\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Connections with waiting packets\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/S2SCIDState.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Returns S2S connection state for given CID\n AS:Description: S2S get CID connection state\n AS:CommandId: s2s-get-cid-connection\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef CID_KEY = \"cid\"\n\ndef cid = Command.getFieldValue(packet, CID_KEY)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\nif (cid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get S2S connection state\")\n\tCommand.addInstructions(result, \"Fill out this form to get S2S connection state\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\",\n\t\t\t\"hidden\")\n\tCommand.addFieldValue(result, CID_KEY, cid ?: \"\", \"text-single\",\n\t\t\t\"S2S connection CID\")\n\n\treturn result\n}\n\ndef conns = []\ndef cidConns = (Map)cidConnections\n\nCID c = new CID(cid)\nCIDConnections con = cidConns.get(c)\n\nif (con == null) {\n\tconns += \"No such CID connection found\"\n} else {\n\tconns += cid\n\tconns += \"out in progress: \" + con.getOutgoingInProgress()\n\tconns += \"waiting: \" + con.getWaitingCount()\n\tconns += \"control: \" + con.getWaitingControlCount()\n\tconns += \"incoming: \" + con.getIncomingCount()\n\tconns += \"outgoing: \" + con.getOutgoingCount()\n\tconns += \"out-handshaking: \" + con.getOutgoingHandshakingCount()\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"S2S connection\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/S2SResetBadConnections.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\n\n/*\n Script tries to find S2S connection in a bad state and resets their state\n AS:Description: S2S Reset Bad State Connections\n AS:CommandId: s2s-reset-bad-state-conns\n AS:Component: s2s\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.server.xmppserver.*\n\ndef cidConns = (Map)cidConnections\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\n\ndef conns = []\n\nconns += \"Total count: \" + cidConns.size()\n\ncidConns.entrySet().each {\n\tCIDConnections con = it.getValue()\n\t// Bad state is when the OutgoingInProgress is set to true but there is no outgoing\n\t// or outgoing handshaking connections.\n\tif (con.getOutgoingInProgress() && (con.getOutgoingCount() == 0) &&\n\t(con.getOutgoingHandshakingCount() == 0)) {\n\t\tconns += it.getKey().toString() + \", waiting: \" + con.getWaitingCount()\n\t\tcon.resetOutgoingInProgress()\n\t}\n}\n\ndef result = p.commandResult(Command.DataType.result)\nCommand.addFieldMultiValue(result, \"Reset connections\", conns);\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/SSLCertificateAdd.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nAdd an SSL certificate for a given domain.\n\nAS:Description: Add SSL Certificate\nAS:CommandId: ssl-certificate-add\nAS:Component: vhost-man\n */\n\npackage tigase.admin\n\nimport tigase.db.*\nimport tigase.db.comp.*\nimport tigase.server.*\nimport tigase.cert.*\nimport tigase.io.*\nimport tigase.xmpp.JID\nimport tigase.cluster.*\nimport tigase.conf.ConfiguratorAbstract;\n\ndef MARKER = \"command-marker\"\n//def ITEMS = \"item-list\"\n\ntry {\n\ndef VHOST = \"VHost\"\ndef CERTIFICATE = \"Certificate in PEM format\"\ndef SAVE_TO_DISK = \"Save to disk\"\n\ndef repo = (ComponentRepository)comp_repo\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef itemKey = Command.getFieldValue(packet, VHOST)\ndef marker = Command.getFieldValue(packet, MARKER)\ndef pemCertVals = Command.getFieldValues(packet, CERTIFICATE)\ndef saveToDisk = Command.getCheckBoxFieldValue(packet, SAVE_TO_DISK)\n\nQueue results = new LinkedList()\ndef supportedComponents = [\"vhost-man\"]\ndef NOTIFY_CLUSTER = \"notify-cluster\"\nboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\nboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\n// The first step - provide a list of all vhosts for the user\nif (itemKey == null) {\n\tdef items = repo.allItems()\n\tdef itemsStr = []\n\tif (items.size() > 0) {\n\t\titems.each {\n\t\t\tif (isServiceAdmin || it.isOwner(stanzaFromBare.toString())) {\n\t\t\t\titemsStr += it.getKey()\n\t\t\t}\n\t\t}\n\t}\n\tif(itemsStr.size() > 0) {\n\t\tdef result = p.commandResult(Command.DataType.form)\n\t\tCommand.addFieldValue(result, VHOST, itemsStr[0], \"List of VHosts\",\n\t\t\t(String[])itemsStr, (String[])itemsStr)\n\t\treturn result\n\t} else {\n\t\tdef result = p.commandResult(Command.DataType.result)\n\t\tCommand.addTextField(result, \"Note\", \"You have no VHosts to manage\");\n\t\treturn result\n\t}\n}\n\n// The second step - provide a form to fill be by the user for selected vhost\nif (marker == null) {\n\tdef item = repo.getItem(itemKey)\n\tif (item == null) {\n\t\tCommand.addTextField(result, \"Error\", \"No such VHost, adding SSL Certificate impossible.\");\n\t} else {\n\t\tif (isServiceAdmin || item.isOwner(stanzaFromBare.toString()) || item.isAdmin(stanzaFromBare.toString())) {\n\t\t\tdef result = p.commandResult(Command.DataType.form)\n      Command.addFieldValue(result, VHOST, itemKey, \"text-single\")\n\t\t\tCommand.addFieldMultiValue(result, CERTIFICATE, [\"\"])\n\t\t\tCommand.addCheckBoxField(result, SAVE_TO_DISK, true)\n\t\t\tCommand.addHiddenField(result, MARKER, MARKER)\n\t\t\tif \t( clusterMode  ) {\n\t\t\t\tCommand.addHiddenField(result, NOTIFY_CLUSTER, true.toString())\n\t\t\t}\n\t\t\treturn result\n\t\t} else {\n\t\t\tdef result = p.commandResult(Command.DataType.result)\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this VHost.\")\n\t\t\treturn result\n\t\t}\n\t}\n}\n\nif \t( clusterMode && notifyCluster && supportedComponents.contains(componentName) ) {\n\tdef nodes = (List)connectedNodes\n\tif (nodes && nodes.size() > 0 ) {\n\t\tnodes.each { node ->\n\t\t\tdef forward = p.copyElementOnly();\n\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\tforward.setPacketTo( node );\n\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\tresults.offer(forward)\n\t\t}\n\t}\n}\n\n// The last step - process the form submitted by the user\ndef result = p.commandResult(Command.DataType.result)\ndef item = repo.getItem(itemKey)\n\nif (item == null) {\n\tCommand.addTextField(result, \"Error\", \"No such VHost, loading SSL certificate impossible.\")\n} else {\n  if (isServiceAdmin || item.isOwner(stanzaFromBare.toString())) {\n\t\tdef pemCert = pemCertVals.join('\\n')\n    // Basic certificate checks\n\t\t// For XMPP service nonAdmins (domain owners) the alias must match CN name in the certificate\n\t\tCertificateEntry certEntry = CertificateUtil.parseCertificate(new CharArrayReader(pemCert.toCharArray()))\n\t\tif (certEntry.getPrivateKey() == null) {\n\t\t\tCommand.addTextField(result, \"Error\", \"Missing private key or private key encoded in uknown format.\")\n\t\t\tCommand.addTextField(result, \"Note\", \"Private key cannot be encoded with a password.\")\n\t\t\t//println(pemCert);\n\t\t} else {\n\t\t\tdef certCName = CertificateUtil.getCertCName(certEntry.getCertChain()[0])\n\t\t\tdef subjectAltName = CertificateUtil.getCertAltCName(certEntry.getCertChain()[0])\n\t\t\tif (certCName != itemKey && !subjectAltName.contains(itemKey) && !isServiceAdmin) {\n\t\t\t\tCommand.addTextField(result, \"Error\", \"Neither certificate CName nor any of SubjectAlternativeNames match the domain name!\")\n\t\t\t} else {\n\t\t\t\tdef params = new HashMap()\n\t\t\t\tparams.put(SSLContextContainerIfc.PEM_CERTIFICATE_KEY, pemCert)\n\t\t\t\tparams.put(SSLContextContainerIfc.CERT_ALIAS_KEY, itemKey)\n\t\t\t\tparams.put(SSLContextContainerIfc.CERT_SAVE_TO_DISK_KEY, saveToDisk.toString())\n\t\t\t\tTLSUtil.addCertificate(params)\n\t\t\t\tCommand.addTextField(result, \"Note\", \"SSL Certificate for domain: \" + itemKey + \" loaded successfully\")\n\t\t\t}\n\t\t}\n\t} else {\n\t\tCommand.addTextField(result, \"Error\", \"You are not the VHost owner or you have no \"\n\t\t\t+ \"enough permission to change the VHost.\")\n\t}\n}\n\nresults.add(result);\nreturn results;\n\n} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\treturn e.getLocalizedMessage();\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/SimServiceStopped.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nSimulate service stopped uncontrolled execution to help with testing weird network\nproblems.\n\nAS:Description: Simulate serviceStopped method call\nAS:CommandId: sim-serv-stopped\nAS:Component: cl-comp\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.net.*\nimport tigase.cluster.*\n\ndef p = (Packet)packet\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nif (!isServiceAdmin) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You are not service administrator\");\n\treturn result\n}\n\ndef KEY = \"key\"\n\ndef key = Command.getFieldValue(packet, KEY)\n\nif (key == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n  Command.addTitle(result, \"Simulate serviceStopped method call\")\n\tCommand.addInstructions(result, \"Provide a key for IOService you wish to test.\")\n\tCommand.addFieldValue(result, KEY, key ?: \"\", \"text-single\",  \"Key\")\n\n\treturn result\n}\n\nMap services = (Map)servicesMap\n\nIOService serv = services.get(key)\n\nif (serv == null) {\n\treturn \"IOService for key: ${key} not found!\"\n} else {\n  ClusterConnectionManager clCM = (ClusterConnectionManager)clusterCM\n\tclCM.serviceStopped(serv)\n\treturn \"serviceStopped called for IOService for key: ${key}.\"\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/UserDomainFilter.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nAS:Description: Change user inter-domain communication permission.\nAS:CommandId: user-domain-perm\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.xmpp.impl.DomainFilter\nimport tigase.vhosts.filter.CustomDomainFilter\nimport tigase.vhosts.filter.DomainFilterPolicy\nimport tigase.db.UserRepository\nimport tigase.db.UserNotFoundException\n\nimport tigase.vhosts.*\n\ndef vhost_man = (VHostManagerIfc)vhostMan\n\ndef JID = \"jid\"\ndef FILTERING_POLICY = \"fiteringPolicy\"\ndef FILTERING_LIST = \"filteringList\"\n\ndef p = (Iq)packet\ndef jid = Command.getFieldValue(p, JID)\ndef domain = Command.getFieldValue(p, FILTERING_POLICY)\ndef domainList = Command.getFieldValue(p, FILTERING_LIST)\n\nif (jid == null || domain == null ||\n\t(domain == DomainFilterPolicy.LIST.name() && domainList == null)) {\n\tdef res = (Iq)p.commandResult(Command.DataType.form);\n\tCommand.addFieldValue(res, JID, jid ?: \"\", \"jid-single\", \"User JID\")\n\tdef domainStr = []\n  DomainFilterPolicy.values().each { domainStr += it.name() }\n\tCommand.addFieldValue(res, FILTERING_POLICY, domain ?: domainStr[0], \"List of domains\",\n\t\t(String[])domainStr, (String[])domainStr)\n\tCommand.addFieldValue(res, FILTERING_LIST, domainList ?: \"\", \"text-single\", \"Domains List\")\n\treturn res\n}\n\njid = JIDUtils.getNodeID(jid)\n\nbareJID = BareJID.bareJIDInstance(jid)\n\ndef repo = (UserRepository)userRepository\n\n\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\n\nif ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\tdef result = p.commandResult(Command.DataType.result);\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to manage this domain\");\n\treturn result\n}\n\n\ntry {\n\tdef old_value = repo.getData(bareJID, null,\n\t\tDomainFilter.ALLOWED_DOMAINS_KEY, null)\n\tdef old_value_domains = \"\";\n\n\tif (DomainFilterPolicy.valuePoliciesWithDomainListStr().contains(old_value) ) {\n\t\told_value_domains = repo.getData(bareJID, null, DomainFilter.ALLOWED_DOMAINS_LIST_KEY, null)\n\t}\n\n\tif (domainList != null ) {\n\t\tdomainList = domainList.replaceAll(\"\\\\s\",\"\")\n\t}\n\tdef new_value = domain\n\tif ( DomainFilterPolicy.valuePoliciesWithDomainListStr().contains(domain) ) {\n\t\tif (DomainFilterPolicy.valueof(domain) == DomainFilterPolicy.CUSTOM)\n\t\t{\n\t\t\ttry {\n\t\t\t\tCustomDomainFilter.parseRules(domainList)\n\t\t\t} catch (Exception e) {\n\t\t\t\treturn \"Error parsing rules: \" + domainList\n\t\t\t}\n\t\t}\n\t\trepo.setData(bareJID, null, DomainFilter.ALLOWED_DOMAINS_LIST_KEY, domainList)\n\t}\n\trepo.setData(bareJID, null, DomainFilter.ALLOWED_DOMAINS_KEY, new_value)\n\n\treturn \"Changed an old value: $old_value (domains list: $old_value_domains) to a new value: $new_value (domains list: $domainList) for user: $jid\"\n} catch (e) {\n  if (e in UserNotFoundException)\t{\n\t\treturn \"The user $jid was not found in the user repository\"\n\t} else {\n\t\treturn \"Unexpected error: \" + e\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/UserRosterManagement.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nUpdate user roster entry.\n\nAS:Description: Update user roster entry\nAS:CommandId: user-roster-management\nAS:Component: sess-man\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.xmpp.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.db.UserRepository\nimport tigase.vhosts.*\n\nclass Field { String name; String label; String type; String defVal = \"\"}\n\nclass RosterChangesControler {\n\tUserRepository repository\n\tVHostManagerIfc vhost_man\n\tSet<BareJID> admins\n\n\n\tMap<String, XMPPSession> sessions\n\n\tField addOperation = new Field(name: \"addJid\", label: \"Add\")\n\tField removeOperation = new Field(name: \"removeJid\", label: \"Remove\")\n\tList<Field> operationTypes = [addOperation, removeOperation]\n\n\tField subscriptionNone = new Field(name: \"none\", label: \"None\")\n\tField subscriptionFrom = new Field(name: \"from\", label: \"From\")\n\tField subscriptionTo = new Field(name: \"to\", label: \"To\")\n\tField subscriptionBoth = new Field(name: \"both\", label: \"Both\")\n\tList<Field> subscriptionTypes = [subscriptionNone, subscriptionFrom, subscriptionTo, subscriptionBoth]\n\n\tField ownerJid = new Field(name: \"rosterOwnerJID\", label: \"Roster owner JID\", type: \"jid-single\")\n\tField jidToChange= new Field(name: \"jidToManipulate\", label: \"JID to manipulate\", type: \"jid-single\")\n\tField groups = new Field(name: \"groups\", label: \"Comma separated groups\", type: \"text-single\")\n\tField operationType = new Field(name: \"operationType\", label: \"Operation type\",\n\t\t\tdefVal: addOperation.name)\n\tField subscriptionType = new Field(name: \"subscriptionType\",\n\t\t\tlabel: \"Subscription type\", defVal: subscriptionBoth.name)\n\tList<Field> formFields = [ownerJid, jidToChange, groups, operationType, subscriptionType]\n\n\tdef addField(Packet form, Field field, List<Field> listFields = []) {\n\t\tif (listFields != null && listFields.size() == 0)\n\t\t\tCommand.addFieldValue(form, field.name, field.defVal, field.type, field.label)\n\t\telse {\n\t\t\tdef listValues = (listFields.collect { it.name }).toArray(new String[0])\n\t\t\tdef listLabels = (listFields.collect { it.label }).toArray(new String[0])\n\t\t\tCommand.addFieldValue(form, field.name, field.defVal, field.label, listLabels, listValues)\n\t\t}\n\t}\n\n\tdef getFieldValue(Packet form, Field field) { return Command.getFieldValue(form, field.name) }\n\n\tdef processPacket(Packet p) {\n\t\tif ((formFields.find { it.name != groups.name && Command.getFieldValue(p, it.name) == null}) == null) {\n\t\t\tString ownerJidStr = getFieldValue(p, ownerJid)\n\t\t\tString jidToManipulate = getFieldValue(p, jidToChange)\n\t\t\tString[] groups = (getFieldValue(p, groups) ?: \"\").split(\",\")\n\t\t\tString operationTypeStr = getFieldValue(p, operationType)\n\t\t\tString subscriptionTypeStr = getFieldValue(p, subscriptionType)\n\n\t\t\tPacket result = p.commandResult(Command.DataType.result)\n\n\t\t\tBareJID stanzaFromBare = p.getStanzaFrom().getBareJID();\n\t\t\tboolean isServiceAdmin = admins.contains( stanzaFromBare );\n\n\t\t\tJID jidRosterOwnerJid = JID.jidInstanceNS(ownerJidStr);\n\t\t\tJID jidRosterItemJid = JID.jidInstanceNS(jidToManipulate);\n\n\t\t\tVHostItem vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\n\n\t\t\tif (!isServiceAdmin && vhost != null && !(vhost.isOwner(stanzaFromBare.toString())) && !(vhost.isAdmin(stanzaFromBare.toString()))) {\n\n\t\t\t//if ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\t\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+ownerJidStr);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tvhost = vhost_man.getVHostItem(jidRosterItemJid.getDomain());\n\n\t\t\tif (!isServiceAdmin && vhost != null && !(vhost.isOwner(stanzaFromBare.toString())) && !(vhost.isAdmin(stanzaFromBare.toString()))) {\n\n\t\t\t//if ( !(isServiceAdmin || (vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) ) {\n\n\t\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+jidToManipulate);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tQueue<Packet> results;\n\t\t\tif (operationTypeStr == addOperation.name)\n\t\t\t\tresults = addJidToRoster(ownerJidStr, jidToManipulate, groups, subscriptionTypeStr)\n\t\t\telse\n\t\t\t\tresults = removeJidFromRoster(ownerJidStr, jidToManipulate)\n\n\t\t\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\t\t\tresults.add(result)\n\t\t\treturn results\n\t\t}\n\t\telse {\n\t\t\tPacket result = p.commandResult(Command.DataType.form)\n\t\t\taddField(result, ownerJid)\n\t\t\taddField(result, jidToChange)\n\t\t\taddField(result, groups)\n\t\t\taddField(result, operationType, operationTypes)\n\t\t\taddField(result, subscriptionType, subscriptionTypes)\n\t\t\treturn result\n\t\t}\n\t}\n\n\tdef getActiveConnections(String ownerJid) {\n\t\tBareJID ownerBareJID = BareJID.bareJIDInstance(ownerJid)\n\t\tXMPPSession session = sessions.get(ownerBareJID)\n\t\treturn (session == null) ? [] : session.getActiveResources()\n\t}\n\n\tdef subscription(String str) { return RosterAbstract.SubscriptionType.valueOf(str) }\n\n\tQueue<Packet> updateLiveRoster(String jid, String jidToChange, boolean remove,\n\t\t\tString[] groups = null, String subStr = null) {\n\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\tQueue<Packet> packets = new LinkedList<Packet>()\n\t\tJID jidToChangeJID = JID.jidInstance(jidToChange)\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(jid)\n\t\tfor (XMPPResourceConnection conn : activeConnections) {\n\t\t\tif (remove == false) {\n\t\t\t\trosterUtil.addBuddy(conn, jidToChangeJID, jidToChange, groups, null)\n\t\t\t\trosterUtil.setBuddySubscription(conn, subscription(subStr), jidToChangeJID)\n\t\t\t\trosterUtil.updateBuddyChange(conn, packets,\n\t\t\t\t\t\trosterUtil.getBuddyItem(conn, jidToChangeJID))\n\t\t\t} else {\n\t\t\t\tElement it = new Element(\"item\")\n\t\t\t\tit.setAttribute(\"jid\", jidToChange)\n\t\t\t\tit.setAttribute(\"subscription\", \"remove\")\n\t\t\t\trosterUtil.updateBuddyChange(conn, packets, it)\n\t\t\t\trosterUtil.removeBuddy(conn, jidToChangeJID)\n\t\t\t}\n\t\t}\n\t\treturn packets\n\t}\n\n\tdef modifyDbRoster(String ownerJid, modifyFunc) {\n\t\tBareJID ownerBareJID = BareJID.bareJIDInstance(ownerJid)\n\t\tString rosterStr = repository.getData(ownerBareJID, null, RosterAbstract.ROSTER, null)\n\t\trosterStr = (rosterStr == null) ? \"\" : rosterStr\n\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\n\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\tmodifyFunc(roster)\n\t\tStringBuilder sb = new StringBuilder()\n\t\tfor (RosterElement relem: roster.values())\n\t\t\tsb.append(relem.getRosterElement().toString())\n\t\trepository.setData(ownerBareJID, null, RosterAbstract.ROSTER, sb.toString());\n\t}\n\n\tQueue<Packet> addJidToRoster(ownerJid, jidToAdd, groups, subscriptionType) {\n\t\tJID ownerBareJID = JID.jidInstance(ownerJid)\n\t\tJID jidToAddJID = JID.jidInstance(jidToAdd)\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(ownerJid)\n\t\tif (activeConnections.size() == 0) {\n\t\t\tprintln ([\"activeConnections.size() == 0\"])\n\n\t\t\tmodifyDbRoster(ownerJid, { roster ->\n\t\t\t\tRosterElement userToAdd = roster.get(jidToAdd)\n\t\t\t\tif (userToAdd == null) {\n\t\t\t\t\tuserToAdd = new RosterElement(\n\t\t\t\t\t\tjidToAddJID, jidToAdd, groups, null)\n\t\t\t\t}\n\t\t\t\tuserToAdd.setSubscription(subscription(subscriptionType))\n\t\t\t\tuserToAdd.setGroups(groups)\n\t\t\t\troster.put(jidToAdd, userToAdd)\n\t\t\t})\n\t\t\treturn new LinkedList<Packet>()\n\t\t}\n\t\telse\n\t\t\treturn updateLiveRoster(ownerJid, jidToAdd, false, groups, subscriptionType)\n\t}\n\n\tQueue<Packet> removeJidFromRoster(ownerJid, jidToRemove) {\n\t\tList<XMPPResourceConnection> activeConnections = getActiveConnections(ownerJid)\n\t\tif (activeConnections.size() == 0) {\n\t\t\tmodifyDbRoster(ownerJid, { roster ->\n\t\t\t\tRosterElement userToRemove = roster.get(jidToRemove)\n\t\t\t\tif (userToRemove == null) {\n\t\t\t\t\tthrow new Exception(\"User to be deleted is not on roster\")\n\t\t\t\t}\n\t\t\t\troster.remove(jidToRemove)\n\t\t\t})\n\t\t\treturn new LinkedList<Packet>()\n\t\t}\n\t\telse\n\t\t\treturn updateLiveRoster(ownerJid, jidToRemove, true)\n\t}\n}\n\nnew RosterChangesControler(repository: userRepository, admins: adminsSet, vhost_man: vhostMan,\n\t\tsessions: userSessions).processPacket((Packet)packet)"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/UserRosterManagementExt.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n\n/*\n\nUpdate user roster entry, extended version.\nIf both given JIDs are local, rosters for both users are updated accordingly.\n\nAS:Description: Update user roster entry, extended version.\nAS:CommandId: user-roster-management-ext\nAS:Component: sess-man\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xml.*\nimport tigase.vhosts.*\nimport tigase.cluster.*;\nimport tigase.cluster.api.*;\nimport tigase.cluster.strategy.*;\n\n\ntry {\n\tprintln \"==========================\"\n\n\tdef ROSTER_OWNER_JID = \"roster-owner-jid\"\n\tdef ROSTER_OWNER_PRESENCE = \"roster-owner-presence\"\n\tdef ROSTER_OWNER_NAME = \"roster-owner-name\"\n\tdef ROSTER_OWNER_GROUPS = \"roster-owner-groups\"\n\tdef ROSTER_ITEM_JID = \"roster-item-jid\"\n\tdef ROSTER_ITEM_NAME = \"roster-item-name\"\n\tdef ROSTER_ITEM_GROUPS = \"roster-item-groups\"\n\tdef ROSTER_ITEM_SUBSCR = \"roster-item-subscr\"\n\tdef ROSTER_ACTION = \"roster-action\"\n\tdef NOTIFY_CLUSTER = \"notify-cluster\"\n\n\tdef UPDATE = \"update\"\n\tdef REMOVE = \"remove\"\n\tdef UPDATE_EXT = \"update-ext\"\n\tdef REMOVE_EXT = \"remove-ext\"\n\tdef subscriptions = [\"both\", \"from\", \"to\", \"none\"]\n\tdef actions = [UPDATE, REMOVE, UPDATE_EXT, REMOVE_EXT]\n\tdef actions_descr = [\"Add/Update item\", \"Remove item\", \"Add/Update both rosters\", \"Remove from both rosters\"]\n\n\tQueue results = new LinkedList()\n\tdef p = (Packet)packet\n\tdef repository = (UserRepository)userRepository\n\tdef sessions = (Map<BareJID, XMPPSession>)userSessions\n\tdef vhost_man = (VHostManagerIfc)vhostMan\n\tdef admins = (Set)adminsSet\n\n\tdef stanzaFromBare = p.getStanzaFrom().getBareJID();\n\tdef isServiceAdmin = admins.contains(stanzaFromBare);\n\n\tdef rosterOwnerJid = Command.getFieldValue(packet, ROSTER_OWNER_JID)\n\tdef rosterOwnerName = Command.getFieldValue(packet, ROSTER_OWNER_NAME)\n\tdef rosterOwnerGroups = Command.getFieldValue(packet, ROSTER_OWNER_GROUPS)\n\tdef rosterItemJid = Command.getFieldValue(packet, ROSTER_ITEM_JID)\n\tdef rosterItemName = Command.getFieldValue(packet, ROSTER_ITEM_NAME)\n\tdef rosterItemGroups = Command.getFieldValue(packet, ROSTER_ITEM_GROUPS)\n\tdef rosterItemSubscr = Command.getFieldValue(packet, ROSTER_ITEM_SUBSCR)\n\tdef rosterAction = Command.getFieldValue(packet, ROSTER_ACTION)\n\tboolean clusterMode =  Boolean.valueOf( System.getProperty(\"cluster-mode\", false.toString()) );\n\tboolean notifyCluster = Boolean.valueOf( Command.getFieldValue(packet, NOTIFY_CLUSTER) )\n\n\tif (rosterOwnerJid == null || rosterItemJid == null ||\n\t\trosterItemSubscr == null || rosterAction == null) {\n\t\tdef res = p.commandResult(Command.DataType.form);\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_JID, rosterOwnerJid ?: \"\", \"jid-single\", \"Roster owner JID\")\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_NAME, rosterOwnerName ?: \"\",  \"text-single\", \"Roster owner name\")\n\t\tCommand.addFieldValue(res, ROSTER_OWNER_GROUPS, rosterOwnerGroups ?: \"\", \"text-single\", \"Comma separated list of owner groups\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_JID, rosterItemJid ?: \"\", \"jid-single\", \"Roster item JID\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_NAME, rosterItemName ?: \"\",  \"text-single\", \"Roster item name\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_GROUPS, rosterItemGroups ?: \"\", \"text-single\", \"Comma separated list of item groups\")\n\t\tCommand.addFieldValue(res, ROSTER_ITEM_SUBSCR, subscriptions[0], \"Roster item Subscription\", (String[])subscriptions, (String[])subscriptions)\n\t\tCommand.addFieldValue(res, ROSTER_ACTION, actions[0], \"Action\", (String[])actions_descr, (String[])actions)\n\t\tif \t( clusterMode  ) {\n\t\t\tCommand.addHiddenField(res, NOTIFY_CLUSTER, true.toString())\n\t\t}\n\t\treturn res\n\t}\n\n\tif \t( clusterMode && notifyCluster ) {\n\t\tif ( null != clusterStrategy ) {\n\t\t\tdef cluster = (ClusteringStrategyIfc) clusterStrategy\n\t\t\tList<JID> cl_conns = cluster.getNodesConnected()\n\t\t\tif (cl_conns && cl_conns.size() > 0) {\n\t\t\t\tcl_conns.each { node ->\n\n\t\t\t\t\tdef forward = p.copyElementOnly();\n\t\t\t\t\tCommand.removeFieldValue(forward, NOTIFY_CLUSTER)\n\t\t\t\t\tCommand.addHiddenField(forward, NOTIFY_CLUSTER, false.toString())\n\t\t\t\t\tforward.setPacketTo( node );\n\t\t\t\t\tforward.setPermissions( Permissions.ADMIN );\n\n\t\t\t\t\tresults.offer(forward)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tdef remove_item = rosterAction == REMOVE || rosterAction == REMOVE_EXT\n\n\tdef updateRoster = { jid, i_jid, i_name, i_groups, i_subscr, i_original_node ->\n\n\t\tdef sess = sessions == null ? null : sessions.get(jid.getBareJID());\n\t\tdef conn = (sess != null && sess.getActiveResourcesSize() > 0) ? sess.getActiveResources().get(0) : null;\n\t\tif (conn) {\n\t\t\t// Update online\n\t\t\tRosterAbstract rosterUtil = RosterFactory.getRosterImplementation(true)\n\t\t\tElement item = new Element(\"item\",\n\t\t\t\t(String[])[\"jid\", \"subscription\"], (String[])[i_jid, \"remove\"])\n\t\t\tif (remove_item) {\n\t\t\t\trosterUtil.removeBuddy(conn, i_jid)\n\t\t\t} else {\n\t\t\t\trosterUtil.addBuddy(conn, i_jid, i_name ?: i_jid.getLocalpart(), i_groups ? i_groups.split(\",\") : null, null)\n\t\t\t\trosterUtil.setBuddySubscription(conn, RosterAbstract.SubscriptionType.valueOf(i_subscr), i_jid)\n\t\t\t\titem = rosterUtil.getBuddyItem(conn, i_jid)\n\t\t\t}\n\t\t\trosterUtil.updateBuddyChange(conn, results, item)\n\t\t} else if (i_original_node) {\n\t\t\t// We need to synchronize on some object (ie. on UserRepository instance) to fix issue with\n\t\t\t// race condition when we modify roster of user which is offline\n\t\t\t// Is there a better object to use for synchronization?\n\t\t\tsynchronized (repository) {\n\t\t\t\t// Update offline and only on original node\n\t\t\t\tString rosterStr = repository.getData(jid.getBareJID(), null, RosterAbstract.ROSTER, null) ?: \"\"\n\t\t\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>()\n\t\t\t\tRosterFlat.parseRosterUtil(rosterStr, roster, null)\n\t\t\t\tif (remove_item) {\n\t\t\t\t\troster.remove(i_jid.getBareJID())\n\t\t\t\t} else {\n\t\t\t\t\tRosterElement rel = new RosterElement(i_jid, i_name, i_groups ? i_groups.split(\",\") : null, null)\n\t\t\t\t\trel.setSubscription(RosterAbstract.SubscriptionType.valueOf(i_subscr))\n\t\t\t\t\trel.setPersistent(true);\n\t\t\t\t\troster.put(i_jid, rel)\n\t\t\t\t}\n\t\t\t\tStringBuilder sb = new StringBuilder(200)\n\t\t\t\tfor (RosterElement relem: roster.values())\n\t\t\t\tsb.append(relem.getRosterElement().toString())\n\t\t\t\trepository.setData(jid.getBareJID(), null, RosterAbstract.ROSTER, sb.toString());\n\t\t\t}\n\t\t}\n\t}\n\n\tdef jidRosterOwnerJid = JID.jidInstanceNS(rosterOwnerJid);\n\tdef jidRosterItemJid = JID.jidInstanceNS(rosterItemJid);\n\n\tPacket result = p.commandResult(Command.DataType.result)\n\tdef vhost = vhost_man.getVHostItem(jidRosterOwnerJid.getDomain());\n\tif (vhost == null || (!isServiceAdmin && !vhost.isOwner(stanzaFromBare.toString()) && !vhost.isAdmin(stanzaFromBare.toString()))) {\n\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterOwnerJid);\n\t\tresults.add(result);\n\t\treturn results;\n\t}\n\n\tupdateRoster(jidRosterOwnerJid, jidRosterItemJid, rosterItemName, rosterItemGroups, rosterItemSubscr, notifyCluster)\n\n\tElement pres;\n\tif (rosterAction == UPDATE_EXT || rosterAction == REMOVE_EXT) {\n\t\tdef subscr = rosterItemSubscr;\n\t\tswitch (rosterItemSubscr) {\n\t\tcase \"to\" : subscr = \"from\"; break;\n\t\tcase \"from\" : subscr = \"to\"; break;\n\t\t}\n\n\t\tvhost = vhost_man.getVHostItem(jidRosterItemJid.getDomain());\n\t\tif (vhost == null || (!isServiceAdmin && !vhost.isOwner(stanzaFromBare.toString()) && !vhost.isAdmin(stanzaFromBare.toString()))) {\n\t\t\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to modify roster of \"+rosterItemJid);\n\t\t\tresults.add(result);\n\t\t\treturn results;\n\t\t}\n\n\t\tupdateRoster(jidRosterItemJid, jidRosterOwnerJid, rosterOwnerName, rosterOwnerGroups, subscr, notifyCluster)\n\t\t\n\t\tif (!remove_item) {\n\t\t\tpres = new Element(\"presence\", (String[])[\"from\", \"to\", \"type\"], (String[])[rosterOwnerJid, rosterItemJid, \"probe\"])\n\t\t\tresults.offer(Packet.packetInstance(pres))\n\t\t}\n\t}\n\tif (!remove_item) {\n\t\tpres = new Element(\"presence\", (String[])[\"from\", \"to\", \"type\"], (String[])[rosterItemJid, rosterOwnerJid, \"probe\"])\n\t\tresults.offer(Packet.packetInstance(pres))\n\t}\n\n\tCommand.addTextField(result, \"Note\", \"Operation successful\");\n\tresults.add(result)\n\n\t//return results\n\treturn (Queue)results\n\n}  catch (Exception ex) { ex.printStackTrace(); }"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/UserStatistics.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n Obtaining User Statistics as described in in XEP-0133:\n http://xmpp.org/extensions/xep-0133.html#get-user-stats\n AS:Description: Get User Statistics\n AS:CommandId: http://jabber.org/protocol/admin#user-stats\n AS:Component: sess-man\n AS:Group: Statistics\n */\n\npackage tigase.admin\n\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.xml.*\nimport tigase.vhosts.*\n\ndef JID = \"accountjid\"\n\ndef p = (Packet)packet\ndef sessions = (Map<BareJID, XMPPSession>)userSessions\ndef vhost_man = (VHostManagerIfc)vhostMan\ndef admins = (Set)adminsSet\ndef stanzaFromBare = p.getStanzaFrom().getBareJID()\ndef isServiceAdmin = admins.contains(stanzaFromBare)\n\ndef userJid = Command.getFieldValue(packet, JID)\n\nif (userJid == null) {\n\tdef result = p.commandResult(Command.DataType.form);\n\n\tCommand.addTitle(result, \"Get User Statistics\")\n\tCommand.addInstructions(result, \"Fill out this form to gather user statistics.\")\n\n\tCommand.addFieldValue(result, \"FORM_TYPE\", \"http://jabber.org/protocol/admin\", \"hidden\")\n\tCommand.addFieldValue(result, JID, userJid ?: \"\", \"jid-single\",\"The Jabber ID for statistics\")\n\n\treturn result\n}\n\nbareJID = BareJID.bareJIDInstance(userJid)\nVHostItem vhost = vhost_man.getVHostItem(bareJID.getDomain())\ndef result = p.commandResult(Command.DataType.result)\n\nif (isServiceAdmin ||\n(vhost != null && (vhost.isOwner(stanzaFromBare.toString()) || vhost.isAdmin(stanzaFromBare.toString())))) {\n\tXMPPSession session = sessions.get(BareJID.bareJIDInstanceNS(userJid))\n\n\tif (session == null) {\n\t\treturn \"There is no user's ${userJid} active session on the server\"\n\t} else {\n\t\tList<XMPPResourceConnection> conns = session.getActiveResources()\n\t\tString conns_str = \"Connections: \"\n\t\tfor (XMPPResourceConnection con: conns)\n\t\t\tconns_str += con.toString() + \"###\\n\"\n\t\treturn \"There is ${conns?.size()} active user's ${userJid} sessions, packets: ${session.getPacketsCounter()}\\n\" +\n\t\t\"user connections:\\n\" + conns_str\n\t}\n} else {\n\tCommand.addTextField(result, \"Error\", \"You do not have enough permissions to obtain statistics for user in this domain.\");\n}\n\nreturn result\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/example_HelloWorld.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\nExample Hello World admin script for the script development guide.\n\nAS:Description: [example] Hello World Script.\nAS:CommandId: hello\nAS:Component: sess-man\nAS:Group: Example scripts\n*/\n\npackage tigase.admin\n\nimport tigase.server.*\n\ndef p = (Packet)packet\n\ndef name = Command.getFieldValue(packet, \"name\")\n\nif (name == null) {\n\tdef res = p.commandResult(Command.DataType.form)\n\tCommand.addTitle(res, \"Hello World Script\")\n\tCommand.addInstructions(res, \"Please provide some details\")\n\tCommand.addFieldValue(res, \"name\", name ?: \"\", \"text-single\",\n\t  \"Your name\")\n\treturn res\n}\n\ndef res = p.commandResult(Command.DataType.result)\nCommand.addTitle(res, \"Hello World Script\")\nCommand.addInstructions(res, \"Hello ${name}, how are you?\")\n\nreturn res\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/example_TigaseScriptingGuide.groovy",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2008 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\n/*\n\nThis is an example script for Tigase scripting support.\n\nAS:Description: [example] Tigase scripting guide\nAS:CommandId: groovy-example\nAS:Component: sess-man\nAS:Group: Example scripts\n*/\n\npackage tigase.admin\n\nimport tigase.server.Command\nimport tigase.server.Packet\n\nPacket p = (Packet)packet\nnum1 = Command.getFieldValue(p, \"num1\")\nnum2 = Command.getFieldValue(p, \"num2\")\n\nif (num1 == null || num2 == null) {\n\tPacket res = p.commandResult(Command.DataType.form)\n\tCommand.addTextField(res, \"Note\", \"This is Groovy script!\")\n\tCommand.addFieldValue(res, \"num1\", \"\", \"text-single\")\n\tCommand.addFieldValue(res, \"num2\", \"\", \"text-single\")\n\treturn res\n}\n\nreturn num1 + num2\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/admin/template.html",
    "content": "<html>\n<head>\n<title>Tigase XMPP Server - Admin console</title>\n<style>\nbody {\n    margin: 0px;\n}\n.root {\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n}\n.header {\n    height: 100px;\n    background-color: #306799;\n    color: white;\n    box-shadow: 0px 3px 3px 0px lightgray;\n}\n.header > div {\n\tfloat: left;\n}\n.header > div > span.title {\npadding-left: 30px;\ndisplay: block;\nwidth: 300px;\npadding-top: 30px;\n/*float: left;*/\nfont-size: 1.6em;\n}\n.header > div > span.subtitle {\n/*float: left;*/\ndisplay: block;\nmargin: 5px 0px;\nfont-size: 0.9em;\n/*clear: left;*/\n}\n.content {\n    min-height: 600px;\n}\n.content > form > h3, .content > form > div {\n\tclear: both;\n}\n.content > form > * {\n\tdisplay: block;\n\tfloat: left;\n\tpadding: 3px;\n}\n.footer {\n    font-size: 0.9em;\n    text-align: center;\n\tclear: both;\n}\nul {\n\tpadding: 0px 0px;\n\tlist-style: none;\n}\nli {\n\tpadding: 0px 1em;\n}\nli > ul > li {\n\tmargin: 0px -1em;\n\tpadding: 0px 2em;\n}\nli > a {\n\tcolor: darkblue;\n\tfont-weight: bold;\n\ttext-decoration: none;\n}\ntable {\n\tclear: both;\n\tborder-spacing: 0px;\n\t\n}\nth, td {\n\tpadding: 5px 10px;\t\n\tborder: 1px solid gray;\n}\nlabel {\n\tclear: both;\n\tmin-width: 220px;\n}\ninput {\n\tmin-width: 300px;\n}\ninput.submit {\n\tclear: both;\n}\n</style>\n<% imports.each { \n      if (it.type == 'css' && it.src) { %>\n<link rel='stylesheet' type='text/css' href='${src}'></link>\n<%    } else if (it.type == 'css' && it.content) { %>\n<style>.test { ${it.content} }</style>\n<%    } else if (it.type == 'script') { %>\n<script src=\"${it.src}\"></script>\n<%    } %>\n<%  } %>\n</head>\n<body>\n<div class=\"root\">\n<div class=\"header\">\n<img style=\"width: 64px;\nheight: 64px;\npadding: 15 15;\nfloat: left;\nbackground: radial-gradient(white 5%, rgba(255,255,255,0) 72%);\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAtCAYAAAAeA21aAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAASrAAAEqwEnCx5kAAAX6ElEQVRo3s2aeZRcV3Xuf3euea7u6nmSWqMl2ZZlbBnHAxh7AZ4w2OAHhscQeHmQNxHg5QUMyWJcZIUXQhheICTBjMGBZbAx2MY2kmVLsuW2ZHWrWz1XdVd3zXPVHc77o0styZKNnaxAdq27Vvequvec79vf3meffa7E79j2fuibAJ22I/YKxCW6ptywtT+2UVUVt6EqUtO0EQgUWUaWJVGtm0JT5FYyW16YSxdOeAxtTJalE4rMbKZYfyyZKTvFn370Xz0f6XcFfPcHvk7DtHSPS78x4NbfNdAZvGrrQNyTqzRQZBnbdjAMDY9LQ1FkipUmrZaJEAJdU3EcgWXb9MUDZIo15leKybl06adLufLfvGpzz/MtyxH/8NGb/+MRsP09f4sqy163rl0Y8Onv7I353zyYCAcMl47mMuiM+XEkGdNykKS1KUkSCAFCCABURcZQFSrVOqVqg3Kljl9XqFQbTCxkp1LZ8lddmvoNR4jS/Z+58/dPwOUf/CaqIkulWjMSC3hut4Vz6Whv9A198UDEMDQ0r5toNIihqyBJLzkJCRCwToojBBJQqzepl2vYjSYnUzlzfD7zo5Zpf39sJv2Ix1Drl23psR0hnB98/PbfHQHb3vMVhEDzubQBkN7UFw/c2dcR2NgXD7hMB3xBLx6fB5/XhbTm7hf1OoBl20zNpClWGvR3RwgHPbhdOiAhhMC2HUqlKrlMAcl2xPRSPl+utxZzpVqj2jAfLNaaP+7vCJ6UFbX000+++d+PAO/rP0P1Zx9jz3/9f5t9Lv1OQ5Vv3zbYMRINeuREPECxaePyuAgHfcjy2uSFgEq1TqFcp9FoUSjX6YgGGOiJIrVVUSjX+KefHCBfquF16/QlInR1BEnEgwx0R1FVBUmCfLFKq1rHpcis5MpkizVcmuIs5crlVK7yQKnafNyy7Qee/PJ7T3L7+yGVgMfv/rcTsPGuv0aRZcXn0gaDPtddnWHvbd3RwKZY0C07kozhceFIMn6fi2qlwVK2RKtlsZItU6k3EY6DaTs4jkM44OHKS0ZJxEPrz7cdh2eOzXP42ByWZYMQeA0Nl6ERDHjYONRJf08MXVMRQlCuNGi0TDyagtlskc2VCXl1ZlJ5cy5dnGi0rGcmFrNfT4R9E8PdkcxqoSr+VQRseueX+cib9vCth44OybL81q6I711DidCQ160rusuF7nExvbBKrdFCUxVyhSq1pgkCfG4NQ9ewHAchoDceYKAjiNA0OjtDnIoAIQSStKYW07QRgGyZbIj7qFQaHJ1dIVdu4A74GBroOCukhADLdpCBSqVGo9ZEcWxSmZJTrbfqCyvFZ1dLtS95Df2Xr4iAXR/4Gv6oi9xyLeJ363f2xwPvGOmOXCzLkjSzlEd16Vxz+VY8Lp3HD51gYibNpRcMsqk7TH/Ux1KuQqNl4jI0kCTiATcD8QAL6QKH5vMMDnSuJzloJ78zxi8Wqyyn8yiyhK4qjPTFKDUtXG5jnYDzmeM4FMt1VOFQLFZp1pvky/Xi+HzmO8rLBb/jvV/FshyvIZTr/R7jr0Z7Iu+6cudAv5Bl6ZEjs6RyFa6+dBNd8RCSBF63weRMmucmU8iqwnBXmN0jCXYNd7C5N8rmnjAbusIA/GT/CXSvm6Dfc9aYL4SkaSqBgIdA0Is/6EXICrquvSR4IQSyLONx62iGjsvjRkgShiy5hHAuVH8b8Js/8UNURZZnlnPDca/nYz0x/02jvdGox21gqjpN2ca0bDb2xelNhHHaGo6GfPzBnk38+qkJ9h2ZYWG5wCWbe9i5IUEi6MGxbVYKVY4v5GjICgPxYDs5inVAjuOcIW0JRZFRFPkF3hXIcnsplc4Ezvp9lu0ghKDZsphLZYmHfQRDPopTS+pLKmDHe7/K7HJedRzxvuGu0Jd3b+q+JugxvLm6xcBQF+Gwj+NTKU4uZNi1uY+hvvg6AZIkEQl5GeqNIUmwmC5wdGaZJ44uMJ7KMZup4A76cfs89CTCqIqy5i1JotmymF1YoVFv4fe7kSQJxxHUGy0URUaSJGzbYTGVpVlvIssSpWqTaqNFrX1Zpg3CwWpZlAplCvky0/OrpNN5CoUqsaAbx3F4UQXc+onvIwTKTLrwxyPdoT/fOhB3H5lKs1Ksctv1uwkFPGTzFcanl/F7DIbb4E957JQnw0Ev11y2hR2bekmmC5SrDQrlGvlKA5dLR9POmIKA1Gqep4/No8gyr969EVmWME2bI8fn0TWV7aM92LbNU2OzBFWJ112xiYblUKi12jXEWunk1lV8hoYQDtENcVy6SipTor8jSLVhcuD4IiWf6/wE7HjPV7nviSn1mosG/tslm7rv3tgTcT/8zAyLqyUu2zlMRzQAYq0ayxaqxMI+QsEXxO8ZcSlJEh3RAJ3xILSlKASobQFKElSqDfYdnuLEbJrB3hhX7hnF53FRa7R4/OAJZpMZ3nDVDizL5rGDJ1hZKfDJu65i22DHeR1oWjaKIiO31eMIQbw9R0NTifg9PPT0zLkE/NW9h2lKDX7wi2N/GPG7794x3Okdm10hna/iMjQGeqLomoLtCHKFKgII+91I8ksvKAJwbIEkcZbXhRAspHLsf2aalWyJLSNd7L1oBK/HRbZQ4TeHpxifXuLyXcMEfW6eeHqKp4/Nc8dV29g+GH/R8WpNC69LAxlKtSYuXUWRJSRJQlNlJAmy5frZBIy8/f8ibJOf75+8dUt/7O7doz3ehiRTM9cKlv6uCP3dEWxnLVnlSjUAQn43svTbV9QX/sS0bMbGFxmbWMDj0rn5NTvp6gyjqQor2RIP7nuek/MrbNvQzaahTh4+cJyxEyk29ES49dVbXjL7B70GANlijVK9xUBHkEKlQdDrot60qNRbdEV9pwnY+b6vEvG7+c7Dz23pjfk/tm0wHpPdBrGgj8KhKUDgcml43AaOEAjAshxAsPbfKzfLsgn63bzuim10RANoqgISrObKPPD4UWYWswz3xrhkxxD7j8zw7ESSLX0xPnz75QwmQi9rjLDfjdetU2+ZBL2utZxi20wlc9QaZnGdgKFEiGK1GY74XZ/aNZLY7Qv4iMRD1BsmuVK9LR2lvTOTEI7AaVdz2UKtvRy9fPBCCNwunQ0DZ8SwBPlijV/tP87MYoaBnhjXXbGNybkVxiYW2b2xi/9x22Vsewnpv9BkWUKRJYSQkNthupyrUG2YLOeqX5EBtr77K/zLD/ZLkiT998HO0K2xsA+X34NL1xBiDagiy4S8rrPkrGprhJRqzVfs/fPJt9m02Hd4ksnZNN3xIDe8ehsAR44vEA96eN8bLv6t4IUQlGpNMqUatuMAoKkKbkMDYKVQZXwxi8tQnVqjdVS95k++jSwkOl5/0YVdEd/btg93ykLXCfo9OEKgKjJ+j0GjadKy7LNBnKo8hEA+FQhnLYXnxv1L2bHJJM+dSNLTEeL6K7fj9Rjc/9hRGs0WH7rlUi7e2PWi91q2w4HjixycSBH2uTg2lyHoMRjpDhP0Ggig1jTRVYWJhSwHx5O/aFnOb1QJiXKzpYc9rj8e6Q6PNGxBXyy4DkJTFaIhH8vZEqVq4xxUEiArMqJNhyRJmKYFp0LmDEJeymr1JoePzRMJennD1TuIRfw8tP84k7NpbrtyCzddNoqqvHiMPXJklk/f8zi2EHz2Pddy5GSaX4/NMpXK4XPr9HUEcBwhlrKV6WS2/EAyU/6MpshJVZdlvLp2XU8scGO1YVI0qwwOy+sTlxUZt0sDJEqVOsVyjWDAuya1ah2A3s4Qkny6szO/lGN2McNF2/oJBbzr0nwxIiRgfHoJy7a5/optJOJBjk2mODK+yO7Rbt553a51CZ/PsqUa9+4bJxr00BPzMzadpjPiFbYTd8I+l12sNosHJ1L3larNZ31u7Tc3v/8th+/64kH41Q9R77/3oHT9rXtu6Yn5Q/uOLuDzuXnVhSPrRYoqywTbsS+1P7BWg69kyvg9Bjs396Eo8nr9bZo2lWKViCzI5Ur4Aj407fxqkCRIZ0qMjS+y98JhhvvjZApVHjs8yXAiyEfv2Esi4ntR8C3T5nuPHEOWJTb3x8RMKp99cGW6KkmS23HEpx8dm3tUArMv7p9362r53k/ewb2fvGP9fnXv9Tv3BD3GFYamUqg2qLYsZhZWGR1OrPfgGi0LCYiEvAQDbgSQK1YRQvCqXcN0xgKc0cmiOx7kN4dOYKgye/tjHJrNINxudF09a58vSRKtlsVTYzMEfG5Gh7twBBydSNJqmLzzlj0MJkJMJrMMdIQo1hoUK01GusPrRO5/foHn51bpDHut/c8v3nfF9v6vPfrsrGFo6g0DnaFvBb2u0rc/chNjL0KgbNtix3BXeGOhYdLdEaJaa3Lw6CyVagNJWksu5VoTTVMY6o2txboEpXKdS3cOcdG2AZT2RuaUabpKvWXz4KGTJMJeXru9F7nZwGyZZ4G3bIenj87RaplcuWcUt6GztFLg2FSSmy7fxNW7hlgpVHnyeJKWZfPLw9M8O51eB3/g+CLffeQoiYiPI9PpB2fThQ/98vD0A5qiPuQx9M+Ypl09yzPnMdXQlTcFvIYU74pieNwsZ0rMJrOk0gVGhxPrcu/tCLFxqLMdzzDQG0ORJWRZPkfaqqrQ3xXmwPEkj43NcfPezVx7QS8PH0thyfJ6Ly+br2A7DtddsQ2/z02jZXLo6Cz9MT9vvWYbiizxswOTRINuKvUWBydS3HntBQCk81W++cARWpZNplibWy3U7u6LBxdMy+H+z76tAlR+a+YF5OFEeG+1YeJyG4wOddLbGcJxBKnV4tphhGUjHIc9O4dwGfp6QtNUBbld+bwwrjVVoS8RodGyeHRsDtO2iQe9bOzwU6vU1+vGSNDDJTuH8fvcIGB8epnZxQz/6TU76Ir4OTCe5NCJFLtGEozNpFFkmU29UQAWVos8ezJNLOCh1jQNn1u7a3a5sMu27Y7d/+XrHTd87Duxt3zqh5vf+Kf3bLrz8/8Cu/7X+RUQ8BleXVexbIHXYzDYE2UmmcW214oI2xEM9MYYHUysg3/JDgygSBLxqB+vW2cymeNkMs/m/hhb+qIsF6oU6w3KTQtNU3EZGs2WxcJSjkcOjLNntIs9m7qpN01+sm+c3Zu66Qh5uefho1x74RB+z1qN7zE0PIbK83OrvP7SjQmXpr5/Q3fkDkWWzFrTQpHlVjpfIVdpHEpmK1+gJR0433yV17353XfHIj50jwuXrmFaNkcnU2wc7KA3EUHXVDoiftSXuaafOsgwdJV0psj8Up5NfVG2DsTRVIXBjiB+TcYlQyZbZmYhw7MTixw+NofP0PjgLXsYSoR5ajyFZTvccfX2tapTldk92oVLX6ve/R6D/o4g2XKDZ6aW8Lg0WVVkz2qx5lMV2edz60G3oQY39ca2FCqNgXh3+Puvv/0P7cMP3nO2AoA1b7d7CafO5/oSkXYPH/T2oC+noDmlArdLY/NwFyfnMzw2Ns9rLhom5HOhtfuDg4kQu4biVBsmlXqL2XSReNDD9qEOHCHoivjY3B/D59YRQnDZlt6zCiGXrvLai4e5bFsf2WKNw5NLPDezQrVhYjsO2VKNWMBDwGsw0h25cHG1dN1irnjfOSGQL9eFQJKC8QiItXV/+4YuomHfWQnUcdb28i8kQZynCySxlihHBzuZ3bDKwYkkvzh0ktuu3ILSzhuyJOFzG/jcBp1hGOmOnPXc4e4wtE+KhGD9QOWFjRa/W8fv1hlMhLj1is0IAbVmi3K9hRDwswOTVBut2InF7AWW7ZxDgNJ36U23dUV9HbFoAEVVkCWIhXwEAp51b0rA1Ewan9e1XiCdOQnbdjBN65zvNE3B73VzYnaFJ48vslqs4XPpqIqMI0S7MXEakGnZFCoN8uU6y7kKc6tF5ldKHJ9fZTFTolhpUqo1abbW9iS6qpxDiCRJ6JqK323g9xioqkyp2uT4fObZazcP/9K/43VMPP6j0wqYSxf/Ycdw5+eXVwr093fgdunt87c1N651WyVOzK+g6QqDvfFzPFGq1JlPZdm1tb+tlNOboc5YgL0XjfDoUyf43iNHefDQSUa6w0QDHjb1RdnQHUbXVJKZEghommvgnp9fXQs/TaFp2kKWJHRFxrQdaTgRojvmx+fRGekK0xHyvmh4DneFeezZOQY6g7f/6vj0twxNOXrm/JUtV71ZEnBVT9QXVjQNw9Da+x0JAaQzRQxNYTGVo1iuM9gbO2ewydk02XyFjYMdCAG5QmV9mTzVD+xNhPF7XQT9bhotm6lUniePJ3lyPIksQaZUY3whWzs2t7KQLzVW51aKqXrTPGlazs8R4ht+t/69RsvOza0UW8v5SnV8IdO0beFfylWkcq1FZ9h73s2SKkuUak2y5bp/tVDLjU1mfn3/wSlmnrh37ftffeHt+278s+9+qVSuf86RZJeqKRjtPgDASqZEq2mytT9KrlhlKZ2ntyuK3e7ZCyHI5SvYlk2t3sLQNZ6fSq21z3piCCFQFJmBnii9icjaplkIbEeQyZY4MZXCtB3zsefmH/Z79H/2Gtq933zgmUataTHQGXB2jiTMXKVuPvT5d/DBv37gh/uPLWpzKwUu3ti1YWG1/KGt/bFbFldLkWjAzeb+2DkEKIpMbzyAZdmSz61fXW419IZlrjcw1N1/9A1W8tW/dwQ3XLG9//psOk+sM7JetzeaJs8tZdnWH8dnaCSXssSiAfR2Y9MRAsu06Iv5KNea2I4A22ZmMUN/z+kJnUpkp04vFGWtSTrYGeDI1PJTjhD/ud40U//88becVlb7ApC+cBeA2b5oDHxtLF9pvP/IdDp54Uji/xSqDdm07LW22hlWqjaZTOZQFdmuNcy//+z7rmz+/InZ0wSFLrie4e5IM1OsTZi28+rBmD+eLVZxeww0VaVUqtHhNdAUae1sr2Hidrvw+9xr3SIB6ZU8m7rDVG2Badl0+deKlVDIf85Jzqn4K1XqiHqd5Uy5MZXM/4XX0B6/7y/exsu19OH72H7NW5xipb7k8+g3WpYTalk2lu2gKBKFSoOZ5TwHnl9kdrnAkZPpw8ls6bPH53LFh7/4jtMEZJ75OdP7fkzi4jemVou1Zwq15o5EwN1dr7ckZJl8uUbIrTK7XMiPz2d+4DW0rU3TUmLtJqZAsLJaJOozkDWdbLFG1FDQdZWaJfC1u7Nngrdtm9WVHNVKXUwkc//o82hf0FXFfO6hH7xsAgC2Xn0b/R3+4sxysSpJ0kW5ct3ftCyml/LMLheZSuaYWMyaE8ns4ZmlwgdkSRo/8OV3n50jTv0hyxKyI/afTOXeZZr2hy8Y6rhFESKgC4dyzSZTrO2rN62PJrNl/B79roXFVYaHEsiShKyp+D0GlfbOsa5LRIMe5sstTteGrB9xLafzOM0Wh04s/Spbqt8thKg9+pd3cc//fkX4+emfv403/ul3LLemfOvozMqBYrX54RPJbNdStoKuKkQCHrtlWvcFvMYPn/qb9yyd7xkvWDtC8Lqv0S9Pylt2Dr43Efb9z9HeaO/CavEXcyvFjyA4UW2Ye/o7At8d7okOd3ZFiceCjI0vEFJh22AHP3nqJHtHE6iKzPHVKju39GHbpxNmoVChkisyMb+69Oz0ylv9Hv3RX37u7a8M+Qvtgg9D0AOTSxKrJ8FxAbU2vEq7nHvqvLeed/G87iP/iFtX1FS2OlhrWj5JEotAZrgrguk4yPCmvnjgGwNd4bDu9aLqKmPPzXDDJSOU602qDZN8uUEVhT07BtcSI5BczmFXa8wt5auTqdwf3X/fQ9++7U038KNPnP/9nd+FveI3RF77kX8CcCmy9L6dw52figW9wZYk8cTYLK+5cIhyrbl6MpWXOkKemOL1cMmOIUzLplisUsmXWM2Vzalk7m//5PbLP76ULRdvvHzz7w08wMt+QeKUTe/7MaN/cJtVrDWfTq2WpqqN1sUxn8u3pT+qrBZqlQPPL/6l21Dtjb3RzaWWTTTkI7NaxGnUmVvK5TPF6t+l85VP//zJyezn3vva3yt4+De8JJV48xdZns9Kl106siHkcb096HNtqLfMg784dPIrt+zd/PVdI53vkDUNv0enXK4zlcxNTi/n/+xDN13yozdctsmGl7+7/A9JwJnWrhoNwPno3z1kjs2sXNsd9n1fU+WorinOwkrpnpVC9UvFcuvQ0W++//eN+Sz7/ymfZnBjMeG6AAAAInpUWHRTb2Z0d2FyZQAAeNorLy/Xy8zLLk5OLEjVyy9KBwA22AZYEFPKXAAAAABJRU5ErkJggg==\"/>\n<div>\n<span class=\"title\" style=\"padding-left: 20px;\">Tigase XMPP Server</span>\n<% def currentCommand = model.commands.find { command -> command.node == request.getParameter('_node') && command.jid == request.getParameter('_jid') };\nif (currentCommand) { %><span class=\"subtitle\" style=\"padding-left: 20px;\">${currentCommand.name}</span><% } %>\n</div>\n</div>\n<div class=\"sidebar\" style=\"width:300px; float: left; background: lightgray;\">\n\t<ul>\n<% model.commands.findAll { !it.group }.each { it.group = \"Other\" };\ndef groups = model.commands.collect { it.group }.unique().sort().each { group -> %>\n<li ${ (group == request.getParameter('_group')) ? 'style=\"background: rgba(255,255,255,0.3)\"' : '' }><a href=\"?_group=${java.net.URLEncoder.encode(group ?: '')}\">${group}</a><% if (request.getParameter(\"_group\") == group) { %>\n\t<ul><% model.commands.findAll { it.group == group }.sort { it.name }.each { command -> %>\n\t\t<li ${ (command.node == request.getParameter('_node') && command.jid == request.getParameter('_jid')) ? 'style=\"background: rgba(255,255,255,0.4)\"' : ''}><a href=\"?_group=${java.net.URLEncoder.encode(group ?: '')}&_jid=${java.net.URLEncoder.encode(command.jid)}&_node=${java.net.URLEncoder.encode(command.node)}\">${command.name}</a><br/><small>${command.jid}</small></li>\n\t<% } %></ul><% } %>\n</li>\n<% } %>\t\t\n\t</ul>\n</div>\n<div class=\"content\" style=\"float:left; padding: 0px 50px;\">\n<% if (model.formFields) { %>\n<% def table = null; %>\n<form method=\"POST\">\n<% model.formFields?.each { formField -> %>\n<% if (formField.getName() == 'item' && table) { \n%><tr><% table.each { col ->\n%><td>${ formField.getChildren().find { it.getAttribute(\"var\") == col }?.getChildCData('field/value') ?: '' }</td><%\n\t} %></tr><%\n\treturn;\n} \nif (table != null) {%></table><%}\ntable = null;\n%>\n<% if (formField.getName() == 'title') { %><div class=\"title\"><h3>${formField.getCData()}</h3></div><% return; } %>\n<% if (formField.getName() == 'instructions') { %><div class=\"instructions\">${formField.getCData()}</div><% return; } %>\n<% if (formField.getName() == 'reported') { \nif (formField.getAttribute(\"label\")) { %><div><b>${formField.getAttribute(\"label\")}</b></div><% }\ntable = formField.getChildren().findAll { it.getName() == 'field' }.collect { it.getAttribute(\"var\") } %>\n<table><thead><% table.each { %><th>${it}</th><% } %></thead>\n<% return; } %>\n<% def type = formField.getAttribute('type') ?: 'text-single'; \nif (type == 'hidden') { %>\n\t\t<input type='hidden' name=\"${formField.getAttribute('var')}\" value=\"${formField.getChildCData('field/value') ?: ''}\" /><br/>\n<% } else if (type == 'boolean') { %>\n\t\t<label for=\"${formField.getAttribute('var')}\">${formField.getAttribute('label') ?: (formField.getAttribute('var') ?: '')}</label>\n\t\t<input type=\"checkbox\" name=\"${formField.getAttribute('var')}\" ${(formField.getChildCData('field/value') == 'true' || formField.getChildCData('field/value') == '1') ? 'checked' : ''}/><br/>\n<% } else if (type == 'text-private') { %>\n\t\t<label for=\"${formField.getAttribute('var')}\">${formField.getAttribute('label') ?: (formField.getAttribute('var') ?: '')}</label>\n\t\t<input type=\"password\" name=\"${formField.getAttribute('var')}\" value=\"${formField.getChildCData('field/value') ?: ''}\"/><br/>\n<% } else if (type == 'text-multi' || type == 'jid-multi') { %>\n\t\t<label for=\"${formField.getAttribute('var')}\">${formField.getAttribute('label') ?: (formField.getAttribute('var') ?: '')}</label>\n\t\t<textarea name=\"${formField.getAttribute('var')}\" rows='6' cols='50'>${formField.getChildren().findAll{ it.getName() == 'value' }.collect {it.getCData()?:''}.join('\\n')}</textarea><br/>\n<% } else if (type == 'list-single' || type == 'list-multi') { %>\n\t\t<label for=\"${formField.getAttribute('var')}\">${formField.getAttribute('label') ?: (formField.getAttribute('var') ?: '')}</label>\n\t\t<select name=\"${formField.getAttribute('var')}\" ${ (type == 'list-multi') ? 'multiple' : ''}><% formField.getChildren().findAll { it.getName() == 'option' }.each { %>\n\t\t\t<option value='${it.getChildCData(it.getName()+'/value') ?: it.getAttribute('label')}' ${formField.getChildren().find{ child -> (child.getName() == 'value') && (child.getCData() == (it.getChildCData(it.getName()+'/value') ?: it.getAttribute('label'))) } ? 'selected' : ''}>${it.getAttribute('label') ?: it.getChildCData(it.getName()+'/value')}</option>\n<% } %></select><br/>\n<% } else if (type == 'text-single' || type == 'jid-single') { %>\n\t\t<label for=\"${formField.getAttribute('var')}\">${formField.getAttribute('label') ?: (formField.getAttribute('var') ?: '')}</label><input type=\"text\" name=\"${formField.getAttribute('var')}\" value=\"${formField.getChildCData('field/value') ?: ''}\"/><br/>\n<% } else if (type == 'fixed') { %>\n\t\t<input style=\"clear:both;\" disabled type=\"text\" name=\"${formField.getAttribute('var')}\" value=\"${formField.getChildCData('field/value') ?: ''}\"/><br/>\t\t\n\t\t<input type='hidden' name=\"${formField.getAttribute('var')}\" value=\"${formField.getChildCData('field/value') ?: ''}\" /><br/>\n<% } else { %>\n\t\t<label>${formField.getCData() ?: ''}</label>\n<% } %>\n<% } %>\n<% if (table != null) { %></table><% } %>\n<input class='submit' name=\"submit\" type=\"submit\"/>\n</form>\n<% } %>\n</div>\n<div class=\"footer\">Powered by Tigase XMPP Server ${tigase.server.XMPPServer.getImplementationVersion()}</div>\n</body>\n</html>"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/Feeder.groovy",
    "content": "/*\n * Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n * License: (either of)\n * a. Creative Commons Attribution-Share Alike 3.0 Unported\n *    http://creativecommons.org/licenses/by-sa/3.0/\n * b. GNU Lesser General Public License v3\n *    http://www.gnu.org/licenses/lgpl-3.0.html\n */\nimport groovy.sql.Sql\nimport tigase.util.*\n\ndef sql\ndef sourceSQL = [:]\n\ndef Feeder(jdbc) {\n\tprintln \"INFO: Source database connection: $jdbc\"\n\tsql = Sql.newInstance(jdbc)\n\tsql.execute(sourceSQL[\"PRE\"])\n}\n\ndef eachUser(DOMAIN, closure) {\n\tsql.eachRow(sourceSQL[\"users\"], [DOMAIN], {\n\t\tdef JID = JIDUtils.getNodeID(it.jid)\n\t\tprint \"$JID -- \"\n\t\tclosure(it.jid, JID, it.password, it.email)\n\t\tprintln \"--\"\n\t})\n}\n\ndef eachRoster(UID, closure) {\n\tsql.eachRow(sourceSQL[\"rosteritems\"], [UID], {\n\t\tclosure(it.jid, it.name, getRosterGroups(UID, it.jid), it.s10n)\n\t})\n}\n\ndef getRosterGroups(UID, ITEM) {\n\treturn sql.rows(sourceSQL[\"rostergroups\"], [UID, ITEM]).collect{it.group}\n}\n\ndef eachVcard(UID, closure) {\n\tdef vcard = sql.firstRow(sourceSQL[\"vCard\"], [UID])\n\tif(vcard != null) {\n\t\tclosure(vcard.vcard)\n\t}\n}\n\ndef eachPrivacy(UID, closure) {\n\tsql.eachRow(sourceSQL[\"privacylists\"], [UID], {\n\t\tclosure(it.name, it.list)\n\t})\n}\n\ndef setPrivacyDefault(UID, closure) {\n\tdef prdef = sql.firstRow(sourceSQL[\"privacydefault\"], [UID])\n\tif (prdef != null) closure(prdef.name)\n}\n\ndef eachPrivate(UID, closure) {\n\tsql.eachRow(sourceSQL[\"privatestorage\"], [UID], {\n\t\tclosure(it.ns, it.xml)\n\t})\n}\n\ndef Finish() {\n\tsql.execute(sourceSQL[\"POST\"])\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/OpenFire.groovy",
    "content": "/*\n * Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n * License: (either of)\n * a. Creative Commons Attribution-Share Alike 3.0 Unported\n *    http://creativecommons.org/licenses/by-sa/3.0/\n * b. GNU Lesser General Public License v3\n *    http://www.gnu.org/licenses/lgpl-3.0.html\n */\n\nimport groovy.xml.MarkupBuilder\nimport groovy.sql.Sql\nimport tigase.util.*\n\nclass OpenFire extends Feeder {\n\ndef sourceDefinitions = [\nhsqldb: [\n\tusers: \"SELECT username, COALESCE(plainPassword, '{blowfish}{'+(SELECT propValue FROM OFProperty WHERE name='passwordKey' ORDER BY propValue LIMIT 1)+'}'+encryptedPassword) AS password, email FROM OFUser\",\n\trosteritems: \"SELECT rosterid, jid, nick AS name, sub FROM OFRoster WHERE userName = ?\",\n\trostergroups: 'SELECT groupName AS \"group\" FROM OFRosterGroups WHERE rosterid = ?',\n\tvCard: 'SELECT vcard FROM OFvcard WHERE username = ?',\n\tprivacylists: 'SELECT name, list FROM OFprivacyList WHERE username = ?',\n\tprivacydefault: 'SELECT name FROM OFprivacyList WHERE isDefault != 0 AND username = ? LIMIT 1',\n\tprivatestorage: 'SELECT namespace AS ns, privatedata AS xml FROM OFprivate WHERE username = ?'\n\n]\n\n]\n\ndef OpenFire(jdbc) {\n\tdef driver = jdbc.split(\":\")[1]\n\tsourceSQL = sourceDefinitions[driver]\n\tprintln \"INFO: Source database connection: $jdbc\"\n\tif (driver == 'hsqldb') Sql.loadDriver(\"org.hsqldb.jdbcDriver\")\n\tsql = Sql.newInstance(jdbc)\n}\n\ndef eachUser(DOMAIN, closure) {\n\tsql.eachRow(sourceSQL[\"users\"], {\n\t\tdef JID = JIDUtils.getNodeID(it.username + '@' + DOMAIN)\n\t\tprint \"$JID -- \"\n\t\tclosure(it.username, JID, it.password, it.email)\n\t\tprintln \"--\"\n\t})\n}\n\ndef eachRoster(JID, closure) {\n\tsql.eachRow(sourceSQL[\"rosteritems\"], [JID], {\n\t\tdef subscr = \"none\"\n\t\tif (it.sub == '3') subscr = \"both\"\n\t\telse if (it.sub == '2') subscr = \"to\"\n\t\telse if (it.sub == '1') subscr = \"from\"\n\n\t\tclosure(it.jid, it.name, getRosterGroups(it.rosterid), subscr)\n\t})\n}\n\ndef getRosterGroups(ROSTERID) {\n\treturn sql.rows(sourceSQL[\"rostergroups\"], [ROSTERID]).collect{it.group}\n}\n\ndef Finish() {}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/README",
    "content": "Tigase Converter\n\n Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n\n License: (either of)\n a. Creative Commons Attribution-Share Alike 3.0 Unported\n    http://creativecommons.org/licenses/by-sa/3.0/\n b. GNU Lesser General Public License v3\n    http://www.gnu.org/licenses/lgpl-3.0.html\n\n\n* Supported source servers:\n  - jabberd 2.2.x\n  - ejabberd 2.x ODBC\n  - OpenFire 3.6.x\n\n\n* Configuration\n  - Edit converter.groovy:\n    - enter correct path to tigase.xml\n    - uncomment relevant source and feeder definitions\n      (and comment-out unneded ones)\n\n* Running\n  - Give executable permission to converter.groovy and converter.sh\n    $ chmod +x converter.groovy converter.sh\n  - Launch converter.sh\n    (You may need to alter libraries paths)\n\n* Bugs/Suggestions/Patches\n  - Drop me an e-mail at: tomek@xiaoka.com\n\n\nGood luck!\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/converter.groovy",
    "content": "#!/usr/bin/env groovy\n/*\n * Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n * License: (either of)\n * a. Creative Commons Attribution-Share Alike 3.0 Unported\n *    http://creativecommons.org/licenses/by-sa/3.0/\n * b. GNU Lesser General Public License v3\n *    http://www.gnu.org/licenses/lgpl-3.0.html\n *\n * Version: 2.3\n */\n\n/* Configure here vvv */\ndef tigase_config = \"/etc/tigase/tigase.xml\"\n\ndef source = \"jdbc:postgresql://jabberd.db.host/jabberd?user=tigase\"\ndef feeder = new jabberd2(source)\n\n//def source = \"jdbc:mysql://localhost/ejabberd?useOldAliasMetadataBehavior=true&user=tigase&password=secret\"\n//def feeder = new ejabberd(source)\n\n//def source = \"jdbc:hsqldb:/var/lib/openfire/embedded-db/openfire\"\n//def feeder = new OpenFire(source)\n/* Configure here ^^^ */\n\n\n\n/* you definitely not need to change anything below */\nimport tigase.server.*\nimport tigase.util.*\nimport tigase.xmpp.*\nimport tigase.db.*\nimport tigase.conf.*\nimport tigase.xmpp.impl.roster.*\nimport tigase.xmpp.impl.VCardTemp\nimport tigase.xmpp.impl.Privacy\nimport tigase.xmpp.impl.JabberIqPrivate\nimport tigase.vhosts.*\nimport groovy.xml.StreamingMarkupBuilder\n\n\ndef conf_repo = new ConfigRepository(false, tigase_config)\ndef auth_repo = RepositoryFactory.getAuthRepository(\"util\",\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.AUTH_REPO_CLASS_PROP_KEY , null),\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.AUTH_REPO_URL_PROP_KEY , null),\n\t\t\tnull)\ndef user_repo = RepositoryFactory.getUserRepository(\"util\",\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.USER_REPO_CLASS_PROP_KEY, null),\n\t\t\tconf_repo.get(\"basic-conf\", null, Configurable.USER_REPO_URL_PROP_KEY, null),\n\t\t\tnull)\ndef vhost_repo = (VHostRepository) Class.forName(conf_repo.get(Configurable.DEF_VHOST_MAN_NAME, null, VHostManager.VHOSTS_REPO_CLASS_PROP_KEY, null)).newInstance()\nvhost_repo.setProperties([\n\t\t(Configurable.SHARED_USER_REPO_PROP_KEY): user_repo,\n\t\t(Configurable.HOSTNAMES_PROP_KEY): conf_repo.get(Configurable.DEF_VHOST_MAN_NAME, null, Configurable.HOSTNAMES_PROP_KEY, null)\n\t])\n\ndef domains = vhost_repo.localDomains().collect{ it.getVhost() }\n\ndomains.each{ DOMAIN ->\n\tprintln \"Converting domain `$DOMAIN'\"\n\tfeeder.eachUser(DOMAIN, { UID, JID, PASSWORD, EMAIL ->\n\t\t// user and authentication data\n\t\ttry {\n\t\t\tauth_repo.addUser(JID, PASSWORD )\n\t\t\tuser_repo.setData(JID, null, \"email\", EMAIL)\n\t\t}\n\t\tcatch (UserExistsException e) { /*e.printStackTrace()*/ }\n\t\tcatch (TigaseDBException e) { /*e.printStackTrace()*/ }\n\n\t\tdef roster = \"\"\n\t\tfeeder.eachRoster(UID, { RJID, NAME, GROUPS, S10N ->\n\t\t\tdef rel = new RosterElement(RJID, NAME, (String[]) GROUPS )\n\t\t\trel.setSubscription(RosterAbstract.SubscriptionType.valueOf(S10N))\n\t\t\troster += rel.getRosterElement().toString()\n\t\t})\n\t\tif (roster != \"\") user_repo.setData(JID, null, RosterAbstract.ROSTER, roster);\n\n\t\tfeeder.eachVcard(UID, { VCARD ->\n\t\t\tuser_repo.setData(JID, NonAuthUserRepository.PUBLIC_DATA_NODE + \"/\" + VCardTemp.ID,\n\t\t\t\t\tVCardTemp.VCARD_KEY, VCARD);\n\t\t})\n\n\t\tfeeder.eachPrivacy(UID, { NAME, LIST ->\n\t\t\tuser_repo.setData(JID, Privacy.listNode(NAME), Privacy.PRIVACY_LIST, LIST)\n\t\t})\n\t\tfeeder.setPrivacyDefault(UID, { DEFAULT ->\n\t\t\tuser_repo.setData(JID, Privacy.PRIVACY, Privacy.DEFAULT, DEFAULT)\n\t\t})\n\n\t\tfeeder.eachPrivate(UID, { NS, XML ->\n\t\t\tdef xmlstring = ((String) XML)\n\t\t\txmlstring = xmlstring.substring(xmlstring.indexOf('<'))\n\t\t\tdef xml = new XmlSlurper().parseText(xmlstring)\n\t\t\tdef nodes = []\n\t\t\txml.'**'.grep{ it.name() == 'query' && it.namespaceURI() == \"jabber:iq:private\" }.each{ it.children().each{ nodes.add(it) } }\n\t\t\tif (nodes.size() == 0 && NS != null) {\n\t\t\t\tnodes = xml\n\t\t\t}\n\t\t\t\n\t\t\tnodes.each { node ->\n\t\t\t\tif (NS == null || node.namespaceURI() == NS) {\n\t\t\t\t\tdef outputBuilder = new StreamingMarkupBuilder()\n\t\t\t\t\tString result = outputBuilder.bind{ mkp.yield node }\n\t\t\t\t\tdef pairKey = node.name() + node.namespaceURI()\n\t\t\t\t\tuser_repo.setData(JID, JabberIqPrivate.PRIVATE_KEY, node.name() + node.namespaceURI(), result)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t})\n}\n\nfeeder.Finish()\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/converter.sh",
    "content": "#!/bin/bash\nLIBS=\"/usr/share/tigase/lib /usr/share/openfire/lib\"\n\n# Locale check\nif ! locale | grep -iq '^LC_CTYPE=.*\\.utf8.\\?$'; then\n\techo \"You need to set UTF8 based locale first\" >&2; exit 1\nfi\n\nfor DIR in $LIBS; do CLASSPATH=\"`ls -d $DIR/*.jar 2>/dev/null | grep -v groovy | tr '\\n' :`$CLASSPATH\"; done\nexport CLASSPATH\n#echo $CLASSPATH\nexec ${0/%.sh/.groovy}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/ejabberd.groovy",
    "content": "/*\n * Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n * License: (either of)\n * a. Creative Commons Attribution-Share Alike 3.0 Unported\n *    http://creativecommons.org/licenses/by-sa/3.0/\n * b. GNU Lesser General Public License v3\n *    http://www.gnu.org/licenses/lgpl-3.0.html\n */\n\nimport groovy.xml.MarkupBuilder\nimport groovy.sql.Sql\nimport tigase.util.*\n\nclass ejabberd extends Feeder {\n\ndef sourceDefinitions = [\nmysql: [\n\tPRE: 'SELECT 1',\n\tPOST: 'SELECT 1',\n\tusers: 'SELECT username, password, NULL AS email FROM users',\n\trosteritems: 'SELECT jid,nick AS name,subscription FROM rosterusers WHERE username = ?',\n\trostergroups: 'SELECT grp AS \"group\" FROM rostergroups WHERE username = ? AND jid = ?',\n\tvCard: 'SELECT vcard FROM vcard WHERE username = ?',\n\tprivacylists: 'SELECT name,id FROM privacy_list WHERE username = ?',\n\tprivacyitems: 'SELECT t AS type,value,action,ord AS \"order\",match_all,match_iq,match_message,match_presence_in,match_presence_out FROM privacy_list_data WHERE id = ?',\n\tprivacydefault: 'SELECT name FROM privacy_default_list WHERE username = ?',\n\tprivatestorage: 'SELECT namespace AS ns, data AS xml FROM private_storage WHERE username = ?'\n]\n\n]\n\ndef ejabberd(jdbc) {\n\tsourceSQL = sourceDefinitions[jdbc.split(\":\")[1]]\n\tprintln \"INFO: Source database connection: $jdbc\"\n\tsql = Sql.newInstance(jdbc)\n\tsql.execute(sourceSQL[\"PRE\"])\n}\n\ndef eachUser(DOMAIN, closure) {\n\tsql.eachRow(sourceSQL[\"users\"], {\n\t\tdef JID = JIDUtils.getNodeID(it.username + '@' + DOMAIN)\n\t\tprint \"$JID -- \"\n\t\tclosure(it.username, JID, it.password, it.email)\n\t\tprintln \"--\"\n\t})\n}\n\ndef eachRoster(JID, closure) {\n\tsql.eachRow(sourceSQL[\"rosteritems\"], [JID], {\n\t\tdef subscr = \"none\"\n\t\tif (it.subscription == 'B') subscr = \"both\"\n\t\telse if (it.subscription == 'T') subscr = \"to\"\n\t\telse if (it.subscription == 'F') subscr = \"from\"\n\n\t\tclosure(it.jid, it.name, getRosterGroups(JID, it.jid), subscr)\n\t})\n}\n\ndef eachPrivacy(JID, closure) {\n\tsql.eachRow(sourceSQL[\"privacylists\"], [JID], {\n\t\tdef listname = it.name\n\t\tdef listid = it.id\n\t\tdef writer = new StringWriter()\n\t\tdef xml = new MarkupBuilder(writer)\n\t\txml.setOmitNullAttributes(true)\n\t\txml.list(name:listname) {\n\t\t\tsql.eachRow(sourceSQL[\"privacyitems\"], [listid], { row ->\n\t\t\t\tdef type = null\n\t\t\t\tswitch (row.type) {\n\t\t\t\t\tcase \"j\":\n\t\t\t\t\t\ttype = \"jid\"\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"g\":\n\t\t\t\t\t\ttype = \"group\"\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"s\":\n\t\t\t\t\t\ttype = \"subscription\"\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdef action = row.action==\"d\" ? 'deny' : 'allow'\n\t\t\t\txml.item(type:type, value:row.value, action:action, order:row.order) {\n\t\t\t\t\tif (! (row.match_all != \"0\" && row.match_all) ) {\n\t\t\t\t\t\tif (row.match_message != \"0\" && row.match_message) xml.message()\n\t\t\t\t\t\tif (row.match_presence_in != \"0\" && row.match_presence_in) xml.\"presence-in\"()\n\t\t\t\t\t\tif (row.match_presence_out != \"0\" && row.match_presence_out) xml.\"presence-out\"()\n\t\t\t\t\t\tif (row.match_iq != \"0\" && row.match_iq) xml.iq()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tclosure(listname, writer.toString())\n\t})\n}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/groovy/tigase/converter/jabberd2.groovy",
    "content": "/*\n * Copyright (c) 2009 \"Tomasz Sterna\" <tomek@xiaoka.com>\n * License: (either of)\n * a. Creative Commons Attribution-Share Alike 3.0 Unported\n *    http://creativecommons.org/licenses/by-sa/3.0/\n * b. GNU Lesser General Public License v3\n *    http://www.gnu.org/licenses/lgpl-3.0.html\n */\n\nimport groovy.xml.MarkupBuilder\nimport groovy.sql.Sql\n\nclass jabberd2 extends Feeder {\n\ndef sourceDefinitions = [\npostgresql: [\n\tPRE: '''\nCREATE OR REPLACE FUNCTION public.wrap_tag(text, text)\n RETURNS text AS\n $$SELECT COALESCE('<'||$1||'>'||$2||'</'||$1||'>', '<'||$1||'/>', '')$$\n LANGUAGE 'sql' VOLATILE''',\n\tPOST: 'DROP FUNCTION wrap_tag(text, text)',\n\tusers: \"SELECT username||'@'||realm AS jid, password, email FROM authreg WHERE realm = ? ORDER BY jid\",\n\trosteritems: 'SELECT jid,name,\"to\",\"from\" FROM \"roster-items\" WHERE \"collection-owner\" = ?',\n\trostergroups: 'SELECT \"group\" FROM \"roster-groups\" WHERE \"collection-owner\" = ? AND jid = ?',\n\tvCard: '''SELECT\nwrap_tag('FN',\"fn\") ||\nwrap_tag('N',wrap_tag('FAMILY',\"n-family\")||wrap_tag('GIVEN',\"n-given\")||wrap_tag('MIDDLE',\"n-middle\")||wrap_tag('PREFIX',\"n-prefix\")||wrap_tag('SUFFIX',\"n-suffix\")) ||\nwrap_tag('NICKNAME',\"nickname\") ||\nwrap_tag('PHOTO',wrap_tag('TYPE',\"photo-type\")||wrap_tag('BINVAL',\"photo-binval\")||wrap_tag('EXTVAL',\"photo-extval\")) ||\nwrap_tag('BDAY',\"bday\") ||\nwrap_tag('ADR',wrap_tag('POBOX',\"adr-pobox\")||wrap_tag('EXTADD',\"adr-extadd\")||wrap_tag('STREET',\"adr-street\")||wrap_tag('LOCALITY',\"adr-locality\")||wrap_tag('REGION',\"adr-region\")||wrap_tag('PCODE',\"adr-pcode\")||wrap_tag('CTRY',\"adr-country\")) ||\nwrap_tag('TEL',wrap_tag('NUMBER',\"tel\")) ||\nwrap_tag('EMAIL',wrap_tag('USERID',\"email\")) ||\nwrap_tag('JABBERID',\"jabberid\") ||\nwrap_tag('MAILER',\"mailer\") ||\nwrap_tag('TZ',\"tz\") ||\nwrap_tag('GEO',wrap_tag('LAT',\"geo-lat\")||wrap_tag('LON',\"geo-lon\")) ||\nwrap_tag('TITLE',\"title\") ||\nwrap_tag('ROLE',\"role\") ||\nwrap_tag('LOGO',wrap_tag('TYPE',\"logo-type\")||wrap_tag('BINVAL',\"logo-binval\")||wrap_tag('EXTVAL',\"logo-extval\")) ||\nwrap_tag('AGENT',wrap_tag('EXTVAL',\"agent-extval\")) ||\nwrap_tag('ORG',wrap_tag('ORGNAME',\"org-orgname\")||wrap_tag('ORGUNIT',\"org-orgunit\")) ||\nwrap_tag('NOTE',\"note\") ||\nwrap_tag('REV',\"rev\") ||\nwrap_tag('SORT-STRING',\"sort-string\") ||\nwrap_tag('SOUND',wrap_tag('PHONETIC',\"sound-phonetic\")||wrap_tag('BINVAL',\"sound-binval\")||wrap_tag('EXTVAL',\"sound-extval\")) ||\nwrap_tag('UID',\"uid\") ||\nwrap_tag('URL',\"url\") ||\nwrap_tag('DESC',\"desc\") ||\nwrap_tag('KEY',wrap_tag('TYPE',\"key-type\")||wrap_tag('CRED',\"key-cred\")) ||\n'' AS vcard\nFROM vcard WHERE \"collection-owner\" = ?''',\n\tprivacylists: 'SELECT DISTINCT list AS name FROM \"privacy-items\" WHERE \"collection-owner\" = ?',\n\tprivacyitems: 'SELECT type,value,deny,\"order\",block FROM \"privacy-items\" WHERE \"collection-owner\" = ? AND list = ?',\n\tprivacydefault: 'SELECT \"default\" AS \"name\" FROM \"privacy-default\" WHERE \"collection-owner\" = ?',\n\tprivatestorage: 'SELECT ns,xml FROM \"private\" WHERE \"collection-owner\" = ?'\n]\n\n]\n\ndef jabberd2(jdbc) {\n\tsourceSQL = sourceDefinitions[jdbc.split(\":\")[1]]\n\tprintln \"INFO: Source database connection: $jdbc\"\n\tsql = Sql.newInstance(jdbc)\n\tsql.execute(sourceSQL[\"PRE\"])\n}\n\ndef eachRoster(JID, closure) {\n\tsql.eachRow(sourceSQL[\"rosteritems\"], [JID], {\n\t\tdef subscr = \"none\"\n\t\tif (it.to && it.from) subscr = \"both\"\n\t\telse if (it.to) subscr = \"to\"\n\t\telse if (it.from) subscr = \"from\"\n\n\t\tclosure(it.jid, it.name, getRosterGroups(JID, it.jid), subscr)\n\t})\n}\n\ndef eachVcard(JID, closure) {\n\tdef vcard = sql.firstRow(sourceSQL[\"vCard\"], [JID])\n\tif(vcard != null) {\n\t\tvcard = '<vCard prodid=\"-//HandGen//NONSGML vGen v1.0//EN\" xmlns=\"vcard-temp\" version=\"2.0\">' + vcard.vcard + '</vCard>'\n\t\tclosure(vcard)\n\t}\n}\n\ndef eachPrivacy(JID, closure) {\n\tsql.eachRow(sourceSQL[\"privacylists\"], [JID], {\n\t\tdef listname = it.name\n\t\tdef writer = new StringWriter()\n\t\tdef xml = new MarkupBuilder(writer)\n\t\txml.setOmitNullAttributes(true)\n\t\txml.list(name:listname) {\n\t\t\tsql.eachRow(sourceSQL[\"privacyitems\"], [JID, listname], { row ->\n\t\t\t\tdef action = row.deny ? 'deny' : 'allow'\n\t\t\t\txml.item(type:row.type, value:row.value, action:action, order:row.order) {\n\t\t\t\t\tif (row.block & 0x01) xml.message()\n\t\t\t\t\tif (row.block & 0x02) xml.\"presence-in\"()\n\t\t\t\t\tif (row.block & 0x04) xml.\"presence-out\"()\n\t\t\t\t\tif (row.block & 0x08) xml.iq()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tclosure(listname, writer.toString())\n\t})\n}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/README.txt",
    "content": "How to generate installer:\n---------------------------\n\nTigase installer modifications are of two kinds:\n1. Tigase panels are provided in src/main/izpack/java directory for easy tracking in svn.\n\n2. Modifications related to the IzPack installer are provided as a patch file. Unfortunately one of \nsrc/main/izpack/changes.patch\n\nimportant: build.xml for izpack has conflicting changes related to both TigasePanels and to generic IzPack\nfunctionality. This is why it is only provided in the patch. If you add/remove panels you will need to\nmodify the patch too. \n\n\nThe first time after checking Tigase server source code and after you change some installation code i.e. \nimprove IzPack installer or add some panels, you will need to build the patched installer.\nYou can use the scripts/prepare-installer.sh to download needed IzPack version, install it in a local\ndirectory, automaticaly patch it and build at the end. If the IzPack version of installer gets\ndownloaded you can comment the svn checkout line to not download it every time when you prepare\ninstaller generator. \n\n\nAfter creating compiler generator it will sit in the installer/izpack.patched directory. You can use\nthe script/generate-installer.sh to create TigaseInstaller from it without regeneratting installer\ngenerator every time.\n\nRequirements to build the installer (various steps):\n- git\n- python2\n- the docutils module (see http://docutils.sourceforge.net/)\n- a LaTeX distribution to invoke 'pdflatex' (MikTeX, TeXLive, teTeX, ...)"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/RegistrySpec.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n\n<registry>\n\t<pack name=\"UninstallStuff\">\n\t\t<!-- Special \"pack\", if not defined an uninstall key will be generated automatically -->\n\t\t<!-- The variable $UNINSTALL_NAME can be only used if CheckedHelloPanel will be used\n\t\t\t\t because there the variable will be declared. With that variable it is possible\n\t\t\t\t to install more as one instances of the product on one machine each with an\n\t\t\t\t unique uninstall key. -->\n\t\t<value\n\t\t\t\tname=\"DisplayName\"\n\t\t\t\tkeypath=\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$UNINSTALL_NAME\"\n\t\t\t\troot=\"HKLM\"\n\t\t\t\tstring=\"$UNINSTALL_NAME\"/>\n\t\t<value\n\t\t\t\tname=\"UninstallString\"\n\t\t\t\tkeypath=\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$UNINSTALL_NAME\"\n\t\t\t\troot=\"HKLM\"\n\t\t\t\tstring=\"&quot;$JAVA_HOME\\bin\\javaw.exe&quot; -jar &quot;$INSTALL_PATH\\uninstaller\\uninstaller.jar&quot;\"/>\n\t\t<value\n\t\t\t\tname=\"DisplayIcon\"\n\t\t\t\tkeypath=\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$UNINSTALL_NAME\"\n\t\t\t\troot=\"HKLM\"\n\t\t\t\tstring=\"$INSTALL_PATH\\Tigase.ico\"/>\n\t\t<value\n\t\t\t\tname=\"HelpLink\"\n\t\t\t\tkeypath=\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$UNINSTALL_NAME\"\n\t\t\t\troot=\"HKLM\"\n\t\t\t\tstring=\"$APP_URL\"/>\n\t</pack>\n\t<pack name=\"Base\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\Base\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Unix Files\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\UnixFiles\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Windows Files\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\WindowsFiles\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Docs\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\Docs\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Extras\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\Extras\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Derby Database\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\DerbyDatabase\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"MySQL Database\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\MySQLDatabase\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"PostgreSQL Database\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\PostgreSQLDatabase\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"SQL Server Database\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\SQLServerDatabase\" root=\"HKLM\"/>\n\t</pack>\n\t<pack name=\"Sources\">\n\t\t<key keypath=\"SOFTWARE\\Tigase\\Server\\$UNINSTALL_NAME\\Sources\" root=\"HKLM\"/>\n\t</pack>\n</registry>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/Unix_shortcutSpec.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<shortcuts>\n\n <programGroup defaultName=\"Tigase-$APP_VER\" location=\"applications\"/>\n\n\n <shortcut\n\t\t name=\"Start Tigase-$APP_VER\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"yes\"\n\t\t applications=\"no\"\n\t\t startMenu=\"yes\"\n     startup=\"no\"\n\t\t target=\"$INSTALL_PATH/scripts/tigase.sh\"\n\t\t commandLine=\"start etc/tigase.conf\"\n\t\t workingDirectory=\"$INSTALL_PATH\"\n\t\t description=\"Start the Tigase server manually\"\n\t\t iconFile=\"$INSTALL_PATH/icons/Tigase48x48.png\"\n\t\t iconIndex=\"0\"\n\t\t type=\"Application\"\n\t\t encoding=\"UTF-8\"\n\t\t terminal=\"true\"\n\t\t KdeSubstUID=\"false\"\n\t\t Categories=\"Application;System;\"\n\t\t initialState=\"normal\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER Online Documentation\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"yes\"\n\t\t startup=\"no\"\n\t\t target=\"firefox\"\n\t\t workingDirectory=\"http://www.tigase.org/en/content/configuration-4-0\"\n\t\t commandLine=\"\"\n\t\t initialState=\"noShow\"\n\t\t iconFile=\"help\"\n\t\t iconIndex=\"0\"\n\t\t url=\"http://www.tigase.org/en/content/configuration-4-0\"\n\t\t type=\"Application\"\n\t\t encoding=\"UTF-8\"\n\t\t createForAll=\"false\"\n\t\t Categories=\"Application;System;\"\n\t\t description=\"This opens a WebBrowser to look into the Tigase-$APP_VER (HTML) online documentation\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER README\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"yes\"\n\t\t startup=\"no\"\n\t\t target=\"firefox\"\n\t\t workingDirectory=\"\"\n\t\t commandLine=\"$INSTALL_PATH/package.html\"\n\t\t initialState=\"noShow\"\n\t\t iconFile=\"help\"\n\t\t iconIndex=\"0\"\n\t\t url=\"$INSTALL_PATH/package.html\"\n\t\t type=\"Application\"\n\t\t encoding=\"UTF-8\"\n\t\t createForAll=\"false\"\n\t\t Categories=\"Application;System;\"\n\t\t description=\"This opens a WebBrowser to look into the Tigase-$APP_VER (HTML) README\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER Uninstaller\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"yes\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"java\"\n\t\t commandLine=\"-jar $INSTALL_PATH/Uninstaller/uninstaller.jar\"\n\t\t initialState=\"noShow\"\n\t\t iconFile=\"trashcan_full\"\n\t\t iconIndex=\"0\"\n\t\t workingDirectory=\"\"\n\t\t type=\"Application\"\n\t\t encoding=\"UTF-8\"\n\t\t KdeSubstUID=\"false\"\n\t\t createForAll=\"false\"\n\t\t Categories=\"Application;System;\"\n\t\t TryExec=\"java -jar $INSTALL_PATH/Uninstaller/uninstaller.jar\"\n\t\t description=\"This uninstalls Tigase-$APP_VER\">\n </shortcut>\n\n</shortcuts>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/changes.patch",
    "content": "diff --git a/.gitignore b/.gitignore\nindex 330ec13..dcc7292 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,3 +1,37 @@\n+\n+# /\n /_build\n /_dist\n /eclipse-bin\n+\n+# /bin/\n+/bin/panels\n+/bin/customActions\n+\n+# /doc/\n+/doc/izpack\n+\n+# /lib/\n+/lib/compiler.jar\n+/lib/installer.jar\n+/lib/izevent.jar\n+/lib/standalone-compiler.jar\n+/lib/uninstaller-ext.jar\n+/lib/uninstaller.jar\n+\n+# /src/dist-files/\n+/src/dist-files/.xvpics\n+\n+# /src/native/COIOSHelper/src/\n+/src/native/COIOSHelper/src/Release\n+\n+# /src/native/ShellLink/\n+/src/native/ShellLink/ShellLink.vcproj.BISSOLDOM.blf.user\n+\n+# /src/native/ShellLink/src/\n+/src/native/ShellLink/src/Release\n+\n+# /utils/\n+#\n+#\n+*.class\ndiff --git a/src/build.xml b/src/build.xml\nindex 60e52dc..b29e756 100644\n--- a/src/build.xml\n+++ b/src/build.xml\n@@ -572,7 +572,6 @@\n             <!-- sourcepath is cleared so there's no mistaking what goes into the Panel -->\n             <javac srcdir=\"@{srcdir}\"\n                    destdir=\"${bin.dir}/panels/@{name}\"\n-                   classpath=\"${installer.jar}\"\n                    sourcepath=\"\"\n                    optimize=\"on\"\n                    deprecation=\"on\"\n@@ -581,6 +580,12 @@\n                    target=\"${compat.target}\"\n                    debuglevel=\"${debuglevel}\">\n                 <panel-fileset/>\n+\t\t\t\t<classpath> \n+\t\t\t\t\t<pathelement location=\"${installer.jar}\"/> \n+\t\t\t\t\t<pathelement location=\"${basedir}/tigaseLib/tigase-server.jar\"/> \n+\t\t\t\t\t<pathelement location=\"${basedir}/tigaseLib/tigase-utils.jar\"/> \n+\t\t\t\t\t<pathelement location=\"${basedir}/tigaseLib/tigase-xmltools.jar\"/> \n+\t\t\t\t</classpath> \n             </javac>\n             <jar jarfile=\"${bin.dir}/panels/@{name}.jar\" basedir=\"${bin.dir}/panels/@{name}\"/>\n         </sequential>\n@@ -611,7 +616,9 @@\n         </build-panel>\n         <build-panel name=\"CheckedHelloPanel\">\n             <include name=\"com/izforge/izpack/panels/CheckedHelloPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/CheckedHelloPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/panels/HelloPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/HelloPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/util/os/*RegistryHandler.java\"/>\n             <include name=\"com/izforge/izpack/util/OSClassHelper.java\"/>\n             <include name=\"com/izforge/izpack/util/os/WrappedNativeLibException.java\"/>\n@@ -642,6 +649,7 @@\n             <include name=\"com/izforge/izpack/panels/PacksModel.java\"/>\n             <include name=\"com/izforge/izpack/panels/PacksPanel.java\"/>\n             <include name=\"com/izforge/izpack/panels/PacksPanelAutomationHelper.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/PacksPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/panels/PacksPanelBase.java\"/>\n             <include name=\"com/izforge/izpack/panels/PacksPanelInterface.java\"/>\n         </build-panel>\n@@ -655,12 +663,15 @@\n         </build-panel>\n         <build-panel name=\"HTMLLicencePanel\">\n             <include name=\"com/izforge/izpack/panels/HTMLLicencePanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/HTMLLicencePanelConsoleHelper.java\"/>\n         </build-panel>\n         <build-panel name=\"HTMLInfoPanel\">\n             <include name=\"com/izforge/izpack/panels/HTMLInfoPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/HTMLInfoPanelConsoleHelper.java\"/>\n         </build-panel>\n         <build-panel name=\"TargetPanel\">\n             <include name=\"com/izforge/izpack/panels/PathInputPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/PathInputPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/panels/PathSelectionPanel.java\"/>\n             <include name=\"com/izforge/izpack/panels/TargetPanel.java\"/>\n             <include name=\"com/izforge/izpack/panels/TargetPanelAutomationHelper.java\"/>\n@@ -674,7 +685,9 @@\n         </build-panel>\n         <build-panel name=\"JDKPathPanel\">\n             <include name=\"com/izforge/izpack/panels/JDKPathPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/JDKPathPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/panels/PathInputPanel.java\"/>\n+\t        <include name=\"com/izforge/izpack/panels/PathInputPanelConsoleHelper.java\"/>\n             <include name=\"com/izforge/izpack/panels/PathSelectionPanel.java\"/>\n             <include name=\"com/izforge/izpack/util/os/*RegistryHandler.java\"/>\n             <include name=\"com/izforge/izpack/util/OSClassHelper.java\"/>\n@@ -684,6 +697,22 @@\n             <include name=\"com/coi/tools/os/izpack/Registry.java\"/>\n             <include name=\"com/coi/tools/os/izpack/COIOSHelper.java\"/>\n         </build-panel>\n+\t <build-panel name=\"TigaseJDKPathPanel\">\n+            <include name=\"com/izforge/izpack/panels/TigaseJDKPathPanel.java\"/>\n+\t    <include name=\"com/izforge/izpack/panels/TigaseJDKPathPanelConsoleHelper.java\"/>\n+\t    <include name=\"com/izforge/izpack/panels/JDKPathPanelConsoleHelper.java\"/>\n+            <include name=\"com/izforge/izpack/panels/PathInputPanel.java\"/>\n+\t    <include name=\"com/izforge/izpack/panels/PathInputPanelConsoleHelper.java\"/>\n+            <include name=\"com/izforge/izpack/panels/PathSelectionPanel.java\"/>\n+            <include name=\"com/izforge/izpack/panels/TigaseInstallerCommon.java\"/>\t\t\n+            <include name=\"com/izforge/izpack/util/os/*RegistryHandler.java\"/>\n+            <include name=\"com/izforge/izpack/util/OSClassHelper.java\"/>\n+            <include name=\"com/izforge/izpack/util/os/WrappedNativeLibException.java\"/>\n+            <include name=\"com/coi/tools/os/win/*.java\"/>\n+            <include name=\"com/coi/tools/os/win/resources/NativeLibErr*.java\"/>\n+            <include name=\"com/coi/tools/os/izpack/Registry.java\"/>\n+            <include name=\"com/coi/tools/os/izpack/COIOSHelper.java\"/>\n+        </build-panel>\n         <build-panel name=\"XInfoPanel\">\n             <include name=\"com/izforge/izpack/panels/XInfoPanel.java\"/>\n         </build-panel>\n@@ -776,6 +805,40 @@\n             <include name=\"com/izforge/izpack/panels/HTMLHelloPanel.java\"/>\n             <include name=\"com/izforge/izpack/panels/HTMLInfoPanel.java\"/>\n         </build-panel>\n+\n+        <!-- tigase panels -->\n+        <build-panel name=\"DerbyPathPanel\">\n+            <include name=\"com/izforge/izpack/panels/DerbyPathPanel.java\"/>\n+             <include name=\"com/izforge/izpack/panels/TigaseInstallerCommon.java\"/>\t\t\n+\t     <include name=\"com/izforge/izpack/panels/DerbyPathPanelConsoleHelper.java\"/>\n+           <include name=\"com/izforge/izpack/panels/TigaseConfigConst.java\"/>\n+             <include name=\"com/izforge/izpack/panels/TargetPanel.java\"/>\n+           <include name=\"com/izforge/izpack/panels/TargetPanelAutomationHelper.java\"/>\n+            <include name=\"com/izforge/izpack/panels/PathInputPanel.java\"/>\n+        </build-panel>\n+\n+        <build-panel name=\"TigaseConfigLoadPanel\">\n+            <include name=\"com/izforge/izpack/panels/TigaseConfigLoadPanel.java\"/>\n+              <include name=\"com/izforge/izpack/panels/TigaseInstallerCommon.java\"/>\t\t\n+\t\t<include name=\"com/izforge/izpack/panels/TigaseConfigLoadPanelConsoleHelper.java\"/>\n+          <include name=\"com/izforge/izpack/panels/TigaseConfigConst.java\"/>\n+        </build-panel>\n+\n+        <build-panel name=\"TigaseConfigSavePanel\">\n+            <include name=\"com/izforge/izpack/panels/TigaseConfigSavePanel.java\"/>\n+               <include name=\"com/izforge/izpack/panels/TigaseInstallerCommon.java\"/>\t\t\n+\t\t<include name=\"com/izforge/izpack/panels/TigaseConfigSavePanelConsoleHelper.java\"/>\n+         <include name=\"com/izforge/izpack/panels/TigaseConfigConst.java\"/>\n+        </build-panel>\n+\n+        <build-panel name=\"TigaseDBCheckPanel\">\n+            <include name=\"com/izforge/izpack/panels/TigaseDBCheckPanel.java\"/>\n+                <include name=\"com/izforge/izpack/panels/TigaseInstallerCommon.java\"/>\t\t\n+\t\t<include name=\"com/izforge/izpack/panels/TigaseDBCheckPanelConsoleHelper.java\"/>\n+        <include name=\"com/izforge/izpack/panels/TigaseConfigConst.java\"/>\n+\t\t<include name=\"com/izforge/izpack/panels/TigaseInstallerDBHelper.java\"/>\n+        </build-panel>\n+\n     </target>\n \n     <!--\n@@ -811,6 +874,7 @@\n             <fileset dir=\"${build.dir}\">\n                 <include name=\"com/izforge/izpack/event/*.class\"/>\n                 <include name=\"com/izforge/izpack/util/IoHelper.class\"/>\n+<!--                <exclude name=\"com/izforge/izpack/event/*Compiler*.class\"/> -->\n             </fileset>\n         </jar>\n     </target>\ndiff --git a/src/lib/com/izforge/izpack/installer/ConsoleHelper.java b/src/lib/com/izforge/izpack/installer/ConsoleHelper.java\nnew file mode 100644\nindex 0000000..6a40663\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ConsoleHelper.java\n@@ -0,0 +1,172 @@\n+package com.izforge.izpack.installer;\n+\n+import java.io.BufferedReader;\n+import java.io.IOException;\n+import java.io.InputStreamReader;\n+\n+public class ConsoleHelper \n+{\n+\tpublic void readEnter() \n+\tthrows IOException \n+\t{\n+\t\tsystemInAsReader().readLine();\n+\t}\n+\t\n+\tpublic void displayAndBlock(String msg) \n+\tthrows IOException \n+\t{\n+\t\tSystem.out.println(msg);\n+\t\treadEnter();\n+\t}\n+\t\n+\t\n+\tprivate BufferedReader reader = null;\n+\tpublic BufferedReader systemInAsReader() \n+\t{\n+\t\tif (reader == null)\n+\t\t{\n+\t\t\treader = new BufferedReader(\n+\t\t\t\t\tnew InputStreamReader(System.in));\n+\t\t}\n+\t\treturn reader;\n+\t}\n+\n+\tpublic void displayLabel(String label) {\n+\t\tSystem.out.println(label);\n+\t}\n+\t\n+\tpublic void displayPrompt(String prompt) {\n+\t\t\n+\t\t// cut : or :SPACE suffix\n+\t\tString[] suffixesToCut = { \":\", \": \" };\n+\t\tString newPrompt = prompt;\n+\t\tfor (String suffix : suffixesToCut) {\n+\t\t\tif (newPrompt.endsWith(suffix)) \n+\t\t\t{\n+\t\t\t\tint endIndex = newPrompt.length()-suffix.length();\n+\t\t\t\tnewPrompt = newPrompt.substring(0, endIndex);\n+\t\t\t}\n+\t\t}\n+\t\t\n+\t\tSystem.out.print(newPrompt + \": \");\n+\t}\n+\n+\tpublic <T> T readUntilValid(\n+\t\t\tString prompt, \n+\t\t\tValidatingConverter<String, T> converter) \n+\tthrows IOException \n+\t{\n+\t\tBufferedReader sysIn = systemInAsReader(); \n+\t\t\n+\t\tT result = null;\n+\t\tdo \n+\t\t{\n+\t\t\tdisplayPrompt(prompt);\n+\t\t\tString line = sysIn.readLine();\n+\t\t\tOption<T> validationResult = \n+\t\t\t\tconverter.convert(line);\n+\t\t\tif (validationResult.isDefined) \n+\t\t\t{\n+\t\t\t\tresult = validationResult.value;\n+\t\t\t} else {\n+\t\t\t\tString errorMsg = validationResult.msg;\n+\t\t\t\tdisplayLabel(errorMsg);\n+\t\t\t}\n+\t\t\t\n+\t\t} while (result == null);\n+\t\t\n+\t\treturn result;\n+\t\t\n+\t}\n+\n+\tpublic int chooseAction(String... actions) \n+\tthrows IOException {\n+\t\tfinal int numberOfActions = actions.length;\n+\t\tif (numberOfActions < 2) {\n+\t\t\tthrow new IllegalArgumentException(\"Invalid number of \" +\n+\t\t\t\t\t\"actions to choose from\");\n+\t\t}\n+\t\t\n+\t\tfor (int i = 0 ; i < numberOfActions ; i++) {\n+\t\t\tdisplayLabel( (i+1) + \".  \" + actions[i]);\n+\t\t}\n+\t\t\n+\t\tString prompt = \"Choose number (1-\" + numberOfActions + \")\";\n+\t\treturn readUntilValid(prompt, new ValidatingConverter<String, Integer>() {\n+\t\t\tpublic Option<Integer> convert(String from) {\n+\t\t\t\tint number = 0;\n+\t\t\t\ttry {\n+\t\t\t\t\tnumber = Integer.parseInt(from);\n+\t\t\t\t} catch (NumberFormatException nfe)  {\n+\t\t\t\t\treturn Option.empty(\"Illegal number\");\n+\t\t\t\t}\n+\t\t\t\t\n+\t\t\t\tif (number < 1 || number > numberOfActions) {\n+\t\t\t\t\treturn Option.empty(\"Choice not in range\");\n+\t\t\t\t}\n+\t\t\t\t\n+\t\t\t\treturn Option.full(number);\n+\t\t\t}\n+\t\t});\n+\t}\n+\n+\tpublic void displayEmptyLine() {\n+\t\tSystem.out.println();\n+\t\t\n+\t}\n+\n+\tprivate interface IPasswordReader {\n+\t\tString getPassword(String prompt) throws IOException;\n+\t}\n+\tprivate IPasswordReader passwordReader = null;\n+\n+\tprivate IPasswordReader getPasswordReader() \n+\t{\n+\t\tif (passwordReader == null)  // create only once\n+\t\t{\n+// doesn't seem to work for me anyway :/\n+//\t\t\tif (System.console() != null) \n+//\t\t\t{\n+//\t\t\t\t// java 6 passwords support\n+//\t\t\t\tpasswordReader = new IPasswordReader() \n+//\t\t\t\t{\n+//\t\t\t\t\tpublic String getPassword(String prompt) throws IOException \n+//\t\t\t\t\t{\n+//\t\t\t\t\t\tdisplayPrompt(prompt);\n+//\t\t\t\t\t\tchar[] pwd = System.console().readPassword(); \n+//\t\t\t\t\t\treturn pwd == null ? null : pwd.toString();\n+//\t\t\t\t\t}\n+//\t\t\t\t};\n+//\t\t\t} \n+//\t\t\telse \n+//\t\t\t{\n+\t\t\t\t// fall back to display password on console :(\n+\t\t\t\tpasswordReader = new IPasswordReader() \n+\t\t\t\t{\n+\t\t\t\t\tpublic String getPassword(String prompt) throws IOException \n+\t\t\t\t\t{\n+\t\t\t\t\t\tSystem.out.println(\"WARNING: password will be visible while entering\");\n+\t\t\t\t\t\tdisplayPrompt(prompt);\n+\t\t\t\t\t\treturn systemInAsReader().readLine();\n+\t\t\t\t\t}\n+\t\t\t\t};\n+//\t\t\t}\n+\t\t}\n+\t\treturn passwordReader;\n+\t}\n+\t\n+\tpublic String askForPassword(String prompt) \n+\tthrows IOException \n+\t{\n+\t\treturn getPasswordReader().getPassword(prompt);\n+\t}\n+\n+\tpublic void displayMessage(String msg) {\n+\t\tSystem.out.println(msg);\n+\t}\n+\n+\tpublic void displayRaw(String msg) {\n+\t\tSystem.out.print(msg);\n+\t}\t\n+\t\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/ConsoleInstallHelper.java b/src/lib/com/izforge/izpack/installer/ConsoleInstallHelper.java\nnew file mode 100644\nindex 0000000..e9284c1\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ConsoleInstallHelper.java\n@@ -0,0 +1,55 @@\n+package com.izforge.izpack.installer;\n+\n+import java.io.BufferedReader;\n+import java.io.IOException;\n+import java.util.Arrays;\n+import java.util.List;\n+\n+\n+public class ConsoleInstallHelper {\n+\t// helpers\n+\tpublic final ConsoleHelper console = new ConsoleHelper();\n+\tpublic final IOHelper io = new IOHelper();\n+\tpublic final ResourceHelper resource = new ResourceHelper();\n+\tpublic final ConsolePager pager = new ConsolePager();\n+\tpublic final HTMLHelper html = new HTMLHelper();\n+\tpublic final VariablesHelper variables = new VariablesHelper();\n+\t\n+\t// singleton, use getInstance\n+\tpublic static ConsoleInstallHelper getInstance() { return instance; }\n+\tprivate ConsoleInstallHelper() {}\n+\tprivate static final ConsoleInstallHelper instance = new ConsoleInstallHelper();\n+\t\t\n+}\n+\n+\n+class IOHelper {\n+\t\n+\tpublic String readAll(BufferedReader reader) \n+\tthrows IOException \n+\t{\n+\t\tStringBuilder builder = new StringBuilder();\n+\t\t\n+\t\tString line = \"\";\n+\t\tdo \n+\t\t{\n+\t\t\tline = reader.readLine();\n+\t\t\tif (line != null) \n+\t\t\t{\n+\t\t\t\tbuilder.append(line);\n+\t\t\t\tbuilder.append(\"\\n\");\n+\t\t\t}\n+\t\t} while (line != null);\n+\t\t\n+\t\treturn builder.toString();\n+\t}\n+\t\n+}\n+\n+\n+class TextHelper {\n+\tList<String> convertToLines(String stringWithNewlines) {\n+\t\tString[] lines = stringWithNewlines.split(\"\\n\");\n+\t\treturn Arrays.asList(lines);\n+\t}\n+}\ndiff --git a/src/lib/com/izforge/izpack/installer/ConsoleMenu.java b/src/lib/com/izforge/izpack/installer/ConsoleMenu.java\nnew file mode 100644\nindex 0000000..da3246c\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ConsoleMenu.java\n@@ -0,0 +1,116 @@\n+package com.izforge.izpack.installer;\n+\n+import java.io.IOException;\n+import java.util.List;\n+\n+\n+public abstract class ConsoleMenu {\n+\tprivate final ConsoleHelper console;\n+\tprivate boolean done = false;\n+\t\n+\tpublic ConsoleMenu(ConsoleHelper console) {\n+\t\tthis.console = console;\n+\t}\n+\n+\tpublic void run() \n+\tthrows IOException \n+\t{\n+\t\twhile (isDone() == false) \n+\t\t{\n+\t\t\tdisplayMenu();\t\t\t\n+\t\t\tconsole.displayEmptyLine();\n+\t\t\tconsole.displayPrompt(\"Choose action\");\n+\t\t\tString userChoice = console.systemInAsReader().readLine();\n+\t\t\trunAction(userChoice);\n+\t\t}\n+\t}\n+\n+\tpublic boolean isDone() {\n+\t\treturn done;\n+\t}\n+\n+\tprotected abstract List<IConsoleMenuItem> getMenuItems();\n+\tprotected abstract String getHeader();\n+\n+\tprivate IConsoleMenuItem redisplayMenuItem = new IConsoleMenuItem() {\n+\t\tpublic String renderToString() {\n+\t\t\treturn \"Redisplay menu\";\n+\t\t}\n+\t\tpublic void runAction() {\n+\t\t\tdisplayMenu();\n+\t\t}\n+\t};\n+\n+\tprivate IConsoleMenuItem doneMenuItem = new IConsoleMenuItem() {\n+\t\tpublic String renderToString() {\n+\t\t\treturn \"Done\";\n+\t\t}\n+\t\tpublic void runAction() {\n+\t\t\tdone = true;\n+\t\t}\n+\t};\n+\n+\tprivate IConsoleMenuItem invalidActionMenuItem = new IConsoleMenuItem() {\n+\t\tpublic String renderToString() {\n+\t\t\treturn \"ZONK !!\"; // shouldn't be called\n+\t\t}\n+\t\tpublic void runAction() {\n+\t\t\tconsole.displayLabel(\"Invalid command\");\n+\t\t}\n+\t};\n+\n+\n+\tprivate void displayItem(IConsoleMenuItem item, String prefix) {\n+\t\tString itemStr = item.renderToString();\n+\t\tconsole.displayLabel(prefix + \" => \" + itemStr);\n+\t}\n+\t\n+\tprivate void displayMenu() {\n+\t\tList<IConsoleMenuItem> items = getMenuItems();\n+\t\tconsole.displayLabel(\"------\");\n+\t\tconsole.displayLabel(getHeader());\n+\t\tconsole.displayEmptyLine();\n+\t\t\n+\t\tfor (int i = 0 ; i < items.size() ; i++) {\n+\t\t\tIConsoleMenuItem item = items.get(i);\n+\t\t\tdisplayItem(item, \"\" + (i+1));\n+\t\t}\n+\t\tdisplayItem(redisplayMenuItem, \"r\");\n+\t\tdisplayItem(doneMenuItem, \"d\");\n+\t}\n+\n+\tvoid runAction(String cmd) {\n+\t\t\n+\t\tList<? extends IConsoleMenuItem> menuItems = getMenuItems();\n+\n+\t\tint nmbOfItems = menuItems.size();\n+\t\tint nmb = 0;\n+\t\ttry {\n+\t\t\tnmb = Integer.parseInt(cmd);\n+\t\t}\n+\t\tcatch (NumberFormatException nfe) {\n+\t\t\tnmb = -1;\n+\t\t}\n+\n+\t\tIConsoleMenuItem chosenAction = null;\n+\t\tif (nmb >= 1 && nmb <= nmbOfItems) \n+\t\t{\n+\t\t\tchosenAction = menuItems.get(nmb-1);\n+\t\t} \n+\t\telse if (\"r\".equals(cmd)) \n+\t\t{\n+\t\t\tchosenAction = redisplayMenuItem;\n+\t\t} \n+\t\telse if (\"d\".equals(cmd)) \n+\t\t{\n+\t\t\tchosenAction = doneMenuItem;\n+\t\t} else \n+\t\t{\n+\t\t\tchosenAction = invalidActionMenuItem;\n+\t\t}\n+\t\t\n+\t\tchosenAction.runAction();\n+\t}\n+\t\n+\t\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/ConsolePager.java b/src/lib/com/izforge/izpack/installer/ConsolePager.java\nnew file mode 100644\nindex 0000000..bf2ad7f\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ConsolePager.java\n@@ -0,0 +1,41 @@\n+package com.izforge.izpack.installer;\n+\n+import java.io.IOException;\n+import java.util.List;\n+\n+public class ConsolePager \n+{\n+\tprivate static TextHelper textHelper = new TextHelper();\n+\t\n+\tprivate static int DEFAULT_NO_OF_LINES = 20;\n+\tprivate static String DEFAULT_PROMPT = \"--- Press ENTER to continue ---\";\n+\t\n+\tpublic void displayLongText(String text) \n+\tthrows IOException \n+\t{\n+\t\tdisplayLongText(\n+\t\t\t\ttext, \n+\t\t\t\tDEFAULT_NO_OF_LINES,\n+\t\t\t\tDEFAULT_PROMPT);\n+\t}\n+\t\n+\tpublic void displayLongText(\n+\t\t\tString text, \n+\t\t\tint noOfLinesEach, \n+\t\t\tString continuePrompt) \n+\tthrows IOException \n+\t{\n+\t\tList<String> lines = textHelper.convertToLines(text);\n+\t\t\n+\t\tConsoleHelper helper = new ConsoleHelper();\n+\t\tfor (int i = 0 ; i < lines.size() ; i++) \n+\t\t{\n+\t\t\tSystem.out.println(lines.get(i));\n+\t\t\tif (i != 0 && i % noOfLinesEach == 0) \n+\t\t\t{\n+\t\t\t\thelper.displayAndBlock(continuePrompt);\n+\t\t\t}\n+\t\t}\n+\t}\n+\t\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/HTMLHelper.java b/src/lib/com/izforge/izpack/installer/HTMLHelper.java\nnew file mode 100644\nindex 0000000..1c0e7d6\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/HTMLHelper.java\n@@ -0,0 +1,40 @@\n+package com.izforge.izpack.installer;\n+\n+\n+public class HTMLHelper {\n+\t\n+\tpublic String extractTextFromSimplifiedHTML(String htmlString) {\n+\t\t// pattern relates to replace, when updating\n+\t\t// be careful to keep the indexes in order\n+\t\t// replacements will be performed in the same order\n+\t\t// as they are in the two arrays\n+\t\tString[] patterns = {\n+\t\t\t\t\"<[^>]*>\",\n+\t\t\t\t\"&lt;\",\n+\t\t\t\t\"&gt;\",\n+\t\t\t\t\"&amp;\",\n+\t\t\t\t\"&copy;\",\n+\t\t\t\t\"&ldquo;\",\n+\t\t\t\t\"&rdquo;\"\n+\t\t};\n+\t\tString[] replaces = {\n+\t\t\t\t\"\", // remove tags\n+\t\t\t\t\"<\", // resolve <\n+\t\t\t\t\">\", // resolve >\n+\t\t\t\t\"&\", // resolve &\n+\t\t\t\t\"(C)\", // turns &copy; to \"(C)\"\n+\t\t\t\t\"\\\"\", // resolve left quotation\n+\t\t\t\t\"\\\"\", // resolve right quotation\n+\t\t};\n+\t\t\n+\t\tString result = htmlString;\n+\t\tfor (int i = 0 ; i < patterns.length ; i++) {\n+\t\t\tString pattern = patterns[i];\n+\t\t\tString replace = replaces[i];\n+\t\t\tresult = result.replaceAll(pattern, replace);\n+\t\t}\n+\t\t\n+\t\treturn result;\n+\t}\n+\t\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/IConsoleMenuItem.java b/src/lib/com/izforge/izpack/installer/IConsoleMenuItem.java\nnew file mode 100644\nindex 0000000..b737d3b\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/IConsoleMenuItem.java\n@@ -0,0 +1,6 @@\n+package com.izforge.izpack.installer;\n+\n+public interface IConsoleMenuItem {\n+\tpublic String renderToString();\n+\tpublic void runAction();\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/Option.java b/src/lib/com/izforge/izpack/installer/Option.java\nnew file mode 100644\nindex 0000000..f3abcae\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/Option.java\n@@ -0,0 +1,25 @@\n+package com.izforge.izpack.installer;\n+\n+// Optional parameter (makes optional parameters handling explicit)\n+// it has two states:\n+//   defined -> isDefined == true, value holds value\n+//   undefined -> isDefined == false, msg holds reason of emptiness\n+public class Option<T> {\n+\tpublic final boolean isDefined;\n+\tpublic final T value;\n+\tpublic final String msg;\n+\t\n+\tprivate Option(boolean isDefined, T value, String msg) {\n+\t\tthis.isDefined = isDefined;\n+\t\tthis.value = value;\n+\t\tthis.msg = msg;\n+\t}\n+\t\n+\tpublic static <T> Option<T> full(T value) {\n+\t\treturn new Option<T>(true, value, null);\n+\t}\n+\t\n+\tpublic static <T> Option<T> empty(String msg) {\n+\t\treturn new Option<T>(false, null, msg);\n+\t}\n+}\ndiff --git a/src/lib/com/izforge/izpack/installer/PanelConsoleHelper.java b/src/lib/com/izforge/izpack/installer/PanelConsoleHelper.java\nindex b6d9daa..053c035 100644\n--- a/src/lib/com/izforge/izpack/installer/PanelConsoleHelper.java\n+++ b/src/lib/com/izforge/izpack/installer/PanelConsoleHelper.java\n@@ -24,6 +24,9 @@ import java.io.BufferedReader;\n import java.io.IOException;\n import java.io.InputStreamReader;\n \n+import com.izforge.izpack.Panel;\n+import com.izforge.izpack.util.VariableSubstitutor;\n+\n /**\n  * Abstract class implementing basic functions needed by all panel console helpers.\n  * \n@@ -32,9 +35,9 @@ import java.io.InputStreamReader;\n abstract public class PanelConsoleHelper \n {\n \n+\tpublic enum PanelContinuation { CONTINUE, QUIT, REDISPLAY };\n \n-\n-    public int askEndOfConsolePanel()\n+    private PanelContinuation askEndOfConsolePanel()\n     {\n         try\n         {\n@@ -45,13 +48,15 @@ abstract public class PanelConsoleHelper\n                 String strIn = br.readLine();\n                 if (strIn.equals(\"1\"))\n                 {\n-                    return 1;\n+                    return PanelContinuation.CONTINUE;\n                 }\n                 else if (strIn.equals(\"2\"))\n                 {\n-                    return 2;\n+                    return PanelContinuation.QUIT;\n+                }\n+                else if (strIn.equals(\"3\")) { \n+                \treturn PanelContinuation.REDISPLAY; \n                 }\n-                else if (strIn.equals(\"3\")) { return 3; }\n             }\n \n         }\n@@ -59,7 +64,94 @@ abstract public class PanelConsoleHelper\n         {\n             e.printStackTrace();\n         }\n-        return 2;\n+        return PanelContinuation.QUIT;\n+    }\n+    \n+    protected boolean continueQuitOrReboot(\n+    \t\tAutomatedInstallData idata, PanelConsole panel\n+    \t\t) {\n+    \tPanelContinuation userChoice = askEndOfConsolePanel();\n+        if (userChoice == PanelContinuation.CONTINUE)\n+        {\n+            return true;\n+        }\n+        else if (userChoice == PanelContinuation.QUIT)\n+        {\n+            return false;\n+        }\n+        else\n+        {\n+            return panel.runConsole(idata);\n+        }\n+    }\n+    \n+\n+    \n+    private String extractPanelNameFromConsoleHelperClassName(String className) {\n+        final String consoleHelperSuffix = \"ConsoleHelper\";\n+        final int suffixIndex = className.indexOf(consoleHelperSuffix);\n+        if (suffixIndex == -1) {\n+        \tthrow new IllegalStateException(\"Trying to get i18n info from a \" +\n+        \t\t\t\"class which is not a ConsoleHelper, not allowed\");\n+        }\n+    \treturn className.substring(0, suffixIndex);\n+    }\n+\n+    // this method gets i18n string for the panel related to the caller \n+    // console helper object, to be used only from classes with name ending with \n+    // ConsoleHelper suffix\n+    protected String getI18nStringForClass(String subkey, String alternateClass, AutomatedInstallData idata)\n+    {\n+        final String thisClassName = getClass().getName();\n+        final String panelClassName = extractPanelNameFromConsoleHelperClassName(thisClassName);\n+        \n+    \treturn (getI18nStringForClass(panelClassName, subkey, alternateClass, null, idata));\n+    }\n+\n+    private String getI18nStringForClass(\n+    \t\tString curClassName, \n+    \t\tString subkey, \n+    \t\tString alternateClass,\n+    \t\tPanel metadata,\n+    \t\tAutomatedInstallData idata)\n+    {\n+\n+        int nameStart = curClassName.lastIndexOf('.') + 1;\n+        curClassName = curClassName.substring(nameStart, curClassName.length());\n+        StringBuffer buf = new StringBuffer();\n+        buf.append(curClassName).append(\".\").append(subkey);\n+        String fullkey = buf.toString();\n+        String panelid = null;\n+        if (metadata != null)\n+        {\n+            panelid = metadata.getPanelid();\n+        }\n+        String retval = null;\n+        if (panelid != null)\n+        {\n+            buf.append(\".\");\n+            buf.append(panelid);\n+            retval = idata.langpack.getString(buf.toString());\n+        }\n+        if (retval == null || retval.startsWith(fullkey))\n+        {\n+            retval = idata.langpack.getString(fullkey);\n+        }\n+        if (retval == null || retval.startsWith(fullkey))\n+        {\n+            if (alternateClass == null) { return (null); }\n+            buf.delete(0, buf.length());\n+            buf.append(alternateClass).append(\".\").append(subkey);\n+            retval = idata.langpack.getString(buf.toString());\n+        }\n+        if (retval != null && retval.indexOf('$') > -1)\n+        {\n+            VariableSubstitutor substitutor = new VariableSubstitutor(idata.getVariables());\n+            retval = substitutor.substitute(retval, null);\n+        }\n+        return (retval);\n     }\n \n+    \n+    \n }\ndiff --git a/src/lib/com/izforge/izpack/installer/ResourceHelper.java b/src/lib/com/izforge/izpack/installer/ResourceHelper.java\nnew file mode 100644\nindex 0000000..2f5a28f\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ResourceHelper.java\n@@ -0,0 +1,31 @@\n+package com.izforge.izpack.installer;\n+\n+import java.io.BufferedReader;\n+import java.io.InputStreamReader;\n+import java.net.URL;\n+\n+public class ResourceHelper {\n+\t\n+\tpublic String getResourceAsString(String resourceId) \n+\tthrows ResourceNotFoundException\n+\t{\n+        try\n+        {\n+            URL url = ResourceManager.getInstance().getURL(resourceId);\n+            if (url == null) \n+            {\n+            \tthrow new RuntimeException(\"Invalid resource URL\");\n+            }\n+            \n+            InputStreamReader reader = new InputStreamReader(url.openStream());\n+            BufferedReader bufferedReader = new BufferedReader(reader);\n+            return new IOHelper().readAll(bufferedReader);\n+        }\n+        catch (Exception ex)\n+        {\n+            throw new ResourceNotFoundException(\n+            \t\t\"Error loading resource \" + resourceId);\n+        }\n+\t}\n+\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/installer/ValidatingConverter.java b/src/lib/com/izforge/izpack/installer/ValidatingConverter.java\nnew file mode 100644\nindex 0000000..36542e3\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/ValidatingConverter.java\n@@ -0,0 +1,8 @@\n+package com.izforge.izpack.installer;\n+\n+//does conversion and validates results\n+//see Option for result description\n+public abstract class ValidatingConverter<F, T> {\n+\tpublic abstract Option<T> convert(F from);\n+}\n+\ndiff --git a/src/lib/com/izforge/izpack/installer/VariablesHelper.java b/src/lib/com/izforge/izpack/installer/VariablesHelper.java\nnew file mode 100644\nindex 0000000..55c7f9b\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/installer/VariablesHelper.java\n@@ -0,0 +1,28 @@\n+package com.izforge.izpack.installer;\n+\n+import java.util.Properties;\n+\n+import com.izforge.izpack.util.VariableSubstitutor;\n+\n+\n+public class VariablesHelper {\n+\tpublic String expand(String string_to_parse, Properties variables) {\n+        try\n+        {\n+            // Initialize the variable substitutor\n+            VariableSubstitutor vs = new VariableSubstitutor(variables);\n+\n+            // Parses the info text\n+            string_to_parse = vs.substitute(string_to_parse, null);\n+        }\n+        catch (Exception err)\n+        {\n+            err.printStackTrace();\n+        }\n+        return string_to_parse;\n+\t}\n+\t\n+\tpublic String expand(String string_to_parse, AutomatedInstallData idata) {\n+\t\treturn expand(string_to_parse, idata.getVariables());\n+\t}\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/panels/CheckedHelloPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/CheckedHelloPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..d5feff3\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/CheckedHelloPanelConsoleHelper.java\n@@ -0,0 +1,4 @@\n+package com.izforge.izpack.panels;\n+\n+public class CheckedHelloPanelConsoleHelper \n+extends HelloPanelConsoleHelper {}\ndiff --git a/src/lib/com/izforge/izpack/panels/DerbyPathPanel.java b/src/lib/com/izforge/izpack/panels/DerbyPathPanel.java\nnew file mode 100644\nindex 0000000..7d66dc2\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/DerbyPathPanel.java\n@@ -0,0 +1,167 @@\n+package com.izforge.izpack.panels;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.InstallData;\n+import com.izforge.izpack.installer.InstallerFrame;\n+import com.izforge.izpack.util.AbstractUIHandler;\n+import com.izforge.izpack.util.FileExecutor;\n+import com.izforge.izpack.util.OsVersion;\n+import com.izforge.izpack.util.os.RegistryDefaultHandler;\n+import com.izforge.izpack.util.os.RegistryHandler;\n+import com.izforge.izpack.util.VariableSubstitutor;\n+\n+import java.io.File;\n+import java.util.Arrays;\n+import java.util.HashSet;\n+import java.util.Set;\n+import java.util.StringTokenizer;\n+\n+/**\n+ * Panel which asks for the Derby database path.\n+ *\n+ * @author Klaus Bartz\n+ */\n+public class DerbyPathPanel extends PathInputPanel {\n+\n+\tprivate static final long serialVersionUID = 1L;\n+\n+\tprivate String variableName = null;\n+\n+\tprivate DerbyPathPanelHelper helper = new DerbyPathPanelHelper();\n+\t\n+\t/**\n+\t * The constructor.\n+\t *\n+\t * @param parent The parent window.\n+\t * @param idata  The installation data.\n+\t */\n+\tpublic DerbyPathPanel(InstallerFrame parent, InstallData idata) {\n+\t\tsuper(parent, TigaseInstallerCommon.init(idata));\n+\t\tsetMustExist(false);\n+\t\tsetVariableName(helper.getVariableName());\n+\t}\n+\n+\t/**\n+\t * Indicates wether the panel has been validated or not.\n+\t *\n+\t * @return Wether the panel has been validated or not.\n+\t */\n+\tpublic boolean isValidated()\n+\t{\n+\t\tboolean retval = false;\n+\t\tif (super.isValidated()) {\n+\t\t\tidata.setVariable(getVariableName(), pathSelectionPanel.getPath());\n+\t\t\treturn true;\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+\t/**\n+\t * Called when the panel becomes active.\n+\t */\n+\tpublic void panelActivate()\n+\t{\n+\t\t// Resolve the default for chosenPath\n+\t\tsuper.panelActivate();\n+\t\t// The variable will be exist if we enter this panel\n+\t\t// second time. We would maintain the previos\n+\t\t// selected path.\n+//\t\tif (idata.getVariable(getVariableName()) != null) {\n+//\t\t\tchosenPath = idata.getVariable(getVariableName());\n+//\t\t} else {\n+//\t\t\tif (OsVersion.IS_WINDOWS)\t{\n+//\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".windows\");\n+//\t\t\t}\n+//\t\t\tif (OsVersion.IS_OSX)\t{\n+//\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".mac\");\n+//\t\t\t} else {\n+//\t\t\t\tif (OsVersion.IS_UNIX)\t{\n+//\t\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".unix\");\n+//\t\t\t\t}\n+//\t\t\t}\n+//\t\t}\n+//\t\tVariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n+//\t\tchosenPath = vs.substitute(chosenPath, null);\n+//\t\t// Set the path for method pathIsValid ...\n+\t\t\n+\t\tString chosenPath = helper.getDefaultPath(idata);\n+\t\tpathSelectionPanel.setPath(chosenPath);\n+\n+\t\tif (!pathIsValid())\n+\t\t{\n+\t\t\tchosenPath = \"\";\n+\t\t}\n+\t\t// Set the default to the path selection panel.\n+\t\tpathSelectionPanel.setPath(chosenPath);\n+// \t\tString var = idata.getVariable(\"DerbyPathPanel.skipIfValid\");\n+// \t\t// Should we skip this panel?\n+// \t\tif (chosenPath.length() > 0 && var != null && \"yes\".equalsIgnoreCase(var))\n+// \t\t{\n+// \t\t\tidata.setVariable(getVariableName(), chosenPath);\n+// \t\t\tparent.skipPanel();\n+// \t\t}\n+\n+\t}\n+\n+\t/**\n+\t * Returns the name of the variable which should be used for the path.\n+\t *\n+\t * @return the name of the variable which should be used for the path\n+\t */\n+\tpublic String getVariableName()\n+\t{\n+\t\treturn variableName;\n+\t}\n+\n+\t/**\n+\t * Sets the name for the variable which should be set with the path.\n+\t *\n+\t * @param string variable name to be used\n+\t */\n+\tpublic void setVariableName(String string)\n+\t{\n+\t\tvariableName = string;\n+\t}\n+\n+\t/*\n+\t * (non-Javadoc)\n+\t * \n+\t * @see com.izforge.izpack.installer.IzPanel#getSummaryBody()\n+\t */\n+\tpublic String getSummaryBody()\n+\t{\n+\t\treturn (idata.getVariable(getVariableName()));\n+\t}\n+}\n+\n+class DerbyPathPanelHelper {\n+\t\n+\tString getVariableName() {\n+\t\treturn \"DerbyDBPath\";\n+\t}\n+\t\n+\tString getDefaultPath(AutomatedInstallData idata) {\n+\t\tString chosenPath = \"\";\n+\t\tif (idata.getVariable(getVariableName()) != null) {\n+\t\t\tchosenPath = idata.getVariable(getVariableName());\n+\t\t} else {\n+\t\t\tif (OsVersion.IS_WINDOWS)\t{\n+\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".windows\");\n+\t\t\t}\n+\t\t\tif (OsVersion.IS_OSX)\t{\n+\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".mac\");\n+\t\t\t} else {\n+\t\t\t\tif (OsVersion.IS_UNIX)\t{\n+\t\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".unix\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tVariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n+\t\tchosenPath = vs.substitute(chosenPath, null);\n+\t\treturn chosenPath;\n+\t}\n+\n+\tpublic void setDefaultPath(AutomatedInstallData installData) {\n+\t\tinstallData.setVariable(getVariableName(), getDefaultPath(installData));\n+\t}\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/HTMLInfoPanel.java b/src/lib/com/izforge/izpack/panels/HTMLInfoPanel.java\nindex 8a14d89..a47d3ff 100644\n--- a/src/lib/com/izforge/izpack/panels/HTMLInfoPanel.java\n+++ b/src/lib/com/izforge/izpack/panels/HTMLInfoPanel.java\n@@ -46,6 +46,8 @@ public class HTMLInfoPanel extends IzPanel\n \n     private static final long serialVersionUID = 3257008769514025270L;\n \n+    static final String HTMLINFO_PANEL_NAME = \"HTMLInfoPanel\";\n+\n     /** Resource prefix for panel. */\n     protected String panelResourcePrefixStr;\n \n@@ -65,7 +67,7 @@ public class HTMLInfoPanel extends IzPanel\n      */\n     public HTMLInfoPanel(InstallerFrame parent, InstallData idata)\n     {\n-        this(parent,idata,\"HTMLInfoPanel\",true);\n+        this(parent,idata,HTMLINFO_PANEL_NAME,true);\n     }\n \n     /**\ndiff --git a/src/lib/com/izforge/izpack/panels/HTMLInfoPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/HTMLInfoPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..aac6d9a\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/HTMLInfoPanelConsoleHelper.java\n@@ -0,0 +1,63 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+import com.izforge.izpack.installer.ResourceNotFoundException;\n+\n+\n+// hardcoded resource name, should work only for standard one html panel\n+// uses simple html format, and extracts text from it using regex\n+// only interactive mode implemented\n+public class HTMLInfoPanelConsoleHelper extends PanelConsoleHelper implements PanelConsole \n+{\n+\tprivate ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n+\t\t\n+\tpublic boolean runConsole(AutomatedInstallData installData) \n+\t{\n+\t\ttry {\n+\t\t\t// load resource\n+\t\t\t//TODO how to get resource id from installData?\n+\t\t\tString resourceId = \"HTMLInfoPanel.info\"; \n+\t\t\tString htmlInfo = helper.resource.getResourceAsString(resourceId);\n+\t\t\thtmlInfo = helper.variables.expand(htmlInfo, installData);\n+\t\t\t\n+\t\t\t// convert from html\n+\t\t\tString info = helper.html.extractTextFromSimplifiedHTML(htmlInfo);\n+\n+\t\t\t// display using pager\n+\t\t\thelper.pager.displayLongText(info);\n+\t\t}\n+\t\tcatch (ResourceNotFoundException re) {\n+\t\t\tre.printStackTrace();\n+\t\t\treturn false;\n+\t\t}\n+\t\tcatch (IOException ioe) {\n+\t\t\tioe.printStackTrace();\n+\t\t\treturn false;\n+\t\t}\n+\t\t\t\t\n+\t\treturn continueQuitOrReboot(installData, this);\n+\t}\n+\n+\t\n+\t\n+\t\n+\t// not implemented\n+\t\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/HTMLLicencePanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/HTMLLicencePanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..c3e994c\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/HTMLLicencePanelConsoleHelper.java\n@@ -0,0 +1,69 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+import com.izforge.izpack.installer.ResourceNotFoundException;\n+\n+public class HTMLLicencePanelConsoleHelper \n+extends PanelConsoleHelper \n+implements PanelConsole\n+{\n+\n+\tprivate ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n+\t\n+\tpublic boolean runConsole(AutomatedInstallData installData) {\n+\t\tString headerLabel = installData.langpack.getString(\"LicencePanel.info\");\n+\t\thelper.console.displayLabel(headerLabel);\n+\t\t\n+\t\ttry {\n+\t\t\t// load resource\n+\t\t\t//TODO how to get resource id from installData?\n+\t\t\tString resourceId = \"HTMLLicencePanel.licence\"; \n+\t\t\tString htmlInfo = helper.resource.getResourceAsString(resourceId);\n+\t\t\thtmlInfo = helper.variables.expand(htmlInfo, installData);\n+\t\t\t\n+\t\t\t// convert from html\n+\t\t\tString info = helper.html.extractTextFromSimplifiedHTML(htmlInfo);\n+\n+\t\t\t// display using pager\n+\t\t\thelper.pager.displayLongText(info);\n+\t\t\t\n+\t\t\tString iAgree = installData.langpack.getString(\"LicencePanel.agree\");\n+\t\t\tString iDoNotAgree = installData.langpack.getString(\"LicencePanel.notagree\");\n+\t\t\tswitch (helper.console.chooseAction(iAgree, iDoNotAgree)) {\n+\t\t\tcase 1: return continueQuitOrReboot(installData, this);\n+\t\t\tcase 2: return false;\n+\t\t\t}\n+\t\t\t\n+\t\t}\n+\t\tcatch (ResourceNotFoundException re) {\n+\t\t\tre.printStackTrace();\n+\t\t\treturn false;\n+\t\t}\n+\t\tcatch (IOException ioe) {\n+\t\t\tioe.printStackTrace();\n+\t\t\treturn false;\n+\t\t}\n+\t\t\n+\t\t// should be unreachable\n+\t\treturn false;\n+\t}\n+\n+\t\n+\t// not implemented\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/HelloPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/HelloPanelConsoleHelper.java\nindex bfb075a..f42d5f0 100644\n--- a/src/lib/com/izforge/izpack/panels/HelloPanelConsoleHelper.java\n+++ b/src/lib/com/izforge/izpack/panels/HelloPanelConsoleHelper.java\n@@ -26,6 +26,7 @@ import java.util.Properties;\n \n import com.izforge.izpack.Info;\n import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n import com.izforge.izpack.installer.PanelConsole;\n import com.izforge.izpack.installer.PanelConsoleHelper;\n \n@@ -36,6 +37,8 @@ import com.izforge.izpack.installer.PanelConsoleHelper;\n  */\n public class HelloPanelConsoleHelper extends PanelConsoleHelper implements PanelConsole\n {\n+\t\n+\tprivate static ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n \n     public boolean runConsoleFromPropertiesFile(AutomatedInstallData installData, Properties p)\n     {\n@@ -53,6 +56,7 @@ public class HelloPanelConsoleHelper extends PanelConsoleHelper implements Panel\n         String str;\n         str = idata.langpack.getString(\"HelloPanel.welcome1\") + idata.info.getAppName() + \" \"\n                 + idata.info.getAppVersion() + idata.langpack.getString(\"HelloPanel.welcome2\");\n+        str = helper.variables.expand(str, idata);\n         System.out.println(str);\n         ArrayList<Info.Author> authors = idata.info.getAuthors();\n         int size = authors.size();\n@@ -75,18 +79,7 @@ public class HelloPanelConsoleHelper extends PanelConsoleHelper implements Panel\n             str = idata.langpack.getString(\"HelloPanel.url\") + idata.info.getAppURL();\n             System.out.println(str);\n         }\n-        int i = askEndOfConsolePanel();\n-        if (i == 1)\n-        {\n-            return true;\n-        }\n-        else if (i == 2)\n-        {\n-            return false;\n-        }\n-        else\n-        {\n-            return runConsole(idata);\n-        }\n+        \n+        return continueQuitOrReboot(idata, this);\n     }\n }\ndiff --git a/src/lib/com/izforge/izpack/panels/JDKPathPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/JDKPathPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..00d3b03\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/JDKPathPanelConsoleHelper.java\n@@ -0,0 +1,51 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.File;\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.Option;\n+import com.izforge.izpack.installer.ValidatingConverter;\n+\n+public class JDKPathPanelConsoleHelper extends PathInputPanelConsoleHelper {\n+\n+\tprivate final static String JDK_PATH_VARIABLE_NAME = \"JDKPath\";\n+\t\n+\tpublic boolean runConsole(AutomatedInstallData installData) {\n+\t\treturn super.runConsole(installData);\n+\t}\n+\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn super.runConsoleFromPropertiesFile(installData, p);\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn super.runGeneratePropertiesFile(installData, printWriter);\n+\t}\n+\n+\t// sorry, no proper version validation, no version check\n+\t// everything needs to be extracted\n+\t// or (preferably) accessed from JDKPathPanel, I couldn't do it, too complicated :/\n+\tpublic ValidatingConverter<String, File> getPathValidator() {\n+\t\treturn new ValidatingConverter<String, File>() {\n+\t\t\tpublic Option<File> convert(String line) {\n+\t\t\t\tFile file = new File(line);\n+\t\t\t\tif (file.exists() == false) {\n+\t\t\t\t\treturn Option.empty(\"Path doesn't exist\");\n+\t\t\t\t} else {\n+\t\t\t\t\treturn Option.full(file);\n+\t\t\t\t}\n+\t\t\t}        \t\n+\t\t};\n+\t}\t\n+\n+\tpublic void onResult(File inputPath, AutomatedInstallData iData) {\n+\t\tiData.setVariable(\n+\t\t\t\tJDK_PATH_VARIABLE_NAME, \n+\t\t\t\tinputPath.getAbsolutePath().toString());\n+\t}\n+\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/panels/PacksPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/PacksPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..9cf07d8\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/PacksPanelConsoleHelper.java\n@@ -0,0 +1,118 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.Pack;\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n+import com.izforge.izpack.installer.ConsoleMenu;\n+import com.izforge.izpack.installer.IConsoleMenuItem;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+import com.izforge.izpack.panels.PacksHelper.PackSelection;\n+public class PacksPanelConsoleHelper \n+extends PanelConsoleHelper \n+implements PanelConsole \n+{\n+\n+\tprivate PacksHelper packsHelper = new PacksHelper();\n+\tprivate ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n+\t\n+\tpublic boolean runConsole(final AutomatedInstallData installData) {\n+\n+\t\tfinal List<IConsoleMenuItem> items \n+\t\t\t= packsHelper.getPacksSelections(installData);\n+\t\ttry {\n+\t\t\tfinal String info = installData.langpack.getString(\"PacksPanel.info\");\n+\t\t\t\n+\t\t\tConsoleMenu consoleMenu = new ConsoleMenu(helper.console) {\n+\t\t\t\tprotected List<IConsoleMenuItem> getMenuItems() {\n+\t\t\t\t\treturn items;\n+\t\t\t\t}\n+\n+\t\t\t\tprotected String getHeader() {\n+\t\t\t\t\treturn info;\n+\t\t\t\t}\n+\t\t\t};\n+\t\t\tconsoleMenu.run();\n+\t\t\t\n+\t\t\tList<Pack> selectedPacks = new ArrayList<Pack>();\n+\t\t\tfor (IConsoleMenuItem pack : items) {\n+\t\t\t\tPackSelection selection = (PackSelection) pack;\n+\t\t\t\tif (selection.isSelected) \n+\t\t\t\t{\n+\t\t\t\t\tselectedPacks.add(selection.getPack());\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t\n+\t\t\tinstallData.selectedPacks = selectedPacks;\n+\t\t\t\n+\t\t} catch (IOException e) {\n+\t\t\te.printStackTrace();\n+\t\t\treturn false;\n+\t\t} \n+\t\t\n+\t\treturn continueQuitOrReboot(installData, this);\n+\t}\n+\n+\t\n+\t\n+\t\n+\t// not implemented\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+\n+}\n+\n+class PacksHelper {\n+\t\n+\tpublic List<IConsoleMenuItem> getPacksSelections(AutomatedInstallData installData) {\n+\t\tList<IConsoleMenuItem> result = new ArrayList<IConsoleMenuItem>();\n+\t\tfor (Pack pack : installData.availablePacks) {\n+\t\t\tresult.add(new PackSelection(pack)); \n+\t\t}\n+\t\treturn result;\n+\t}\n+\t\n+\tclass PackSelection implements IConsoleMenuItem {\n+\t\tfinal Pack pack;\n+\t\tboolean isSelected;\n+\t\t\n+\t\tpublic PackSelection(Pack pack) {\n+\t\t\tthis.pack = pack;\n+\t\t\tthis.isSelected = pack.preselected;\n+\t\t}\n+\n+\t\tpublic Pack getPack() {\n+\t\t\treturn pack;\n+\t\t}\n+\n+\t\tpublic String renderToString() {\n+\t\t\tString option = \"\";\n+\t\t\tif (pack.required == false) {\n+\t\t\t\tString selected = isSelected ? \"x\" : \" \";\n+\t\t\t\toption = \"[\" + selected + \"] \";\n+\t\t\t}\n+\t\t\treturn option + pack.name + \", \" + pack.description;\n+\t\t}\n+\n+\t\tpublic void runAction() {\n+\t\t\tif (pack.required == false) {\n+\t\t\t\tisSelected = !isSelected;\n+\t\t\t} \n+\t\t}\n+\t}\n+\t\n+}\n+\ndiff --git a/src/lib/com/izforge/izpack/panels/PathInputPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/PathInputPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..cfc0dd8\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/PathInputPanelConsoleHelper.java\n@@ -0,0 +1,68 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+import com.izforge.izpack.installer.ValidatingConverter;\n+\n+public abstract class PathInputPanelConsoleHelper extends PanelConsoleHelper implements PanelConsole {\n+\n+    protected ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n+    \n+    private String getIntroText(AutomatedInstallData installData) {\n+        String introText = getI18nStringForClass(\"extendedIntro\", \"PathInputPanel\", installData);\n+        if (introText == null || introText.endsWith(\"extendedIntro\")\n+                || introText.indexOf('$') > -1)\n+        {\n+            introText = getI18nStringForClass(\"intro\", \"PathInputPanel\", installData);\n+            if (introText == null || introText.endsWith(\"intro\"))\n+            {\n+                introText = \"\";\n+            }\n+        }\n+        return introText;\n+    }\n+    \n+\tpublic boolean runConsole(AutomatedInstallData installData) \n+\t{\n+\t\ttry {\n+\t\t\tfinal String introText = getIntroText(installData);\n+\t        helper.console.displayLabel(introText);\n+\t        \n+\t        // get valid path\n+\t        ValidatingConverter<String, File> pathValidator = getPathValidator();\n+\t\t\tFile inputPath = helper.console.readUntilValid(\n+\t\t\t\t\t\"Enter path\",\n+\t\t\t\t\tpathValidator);\t\n+\t\t\t\n+\t\t\tonResult(inputPath, installData);\n+\t\t}\n+\t\tcatch (IOException ioe) {\n+\t\t\tioe.printStackTrace();\n+\t\t\treturn false;\n+\t\t}\n+\t\t\n+\t\treturn true;\n+\t}\n+\n+\tpublic abstract ValidatingConverter<String, File> getPathValidator();\n+\t\n+\tabstract public void onResult(File inputPath, AutomatedInstallData iData);\n+\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TargetPanel.java b/src/lib/com/izforge/izpack/panels/TargetPanel.java\nindex 7cf4ce2..03004f0 100644\n--- a/src/lib/com/izforge/izpack/panels/TargetPanel.java\n+++ b/src/lib/com/izforge/izpack/panels/TargetPanel.java\n@@ -21,6 +21,8 @@\n \n package com.izforge.izpack.panels;\n \n+import java.io.File;\n+\n import com.izforge.izpack.installer.InstallData;\n import com.izforge.izpack.installer.InstallerFrame;\n import com.izforge.izpack.adaptator.IXMLElement;\n@@ -84,7 +86,22 @@ public class TargetPanel extends PathInputPanel\n      */\n     public boolean isValidated()\n     {\n-        // Standard behavior of PathInputPanel.\n+    \t{\n+    \t\t// TODO: to be removed later\n+    \t\t// currently it is done to avoid installation \n+    \t\t// over old Tigase directory, as there is a bug in the unpacker\n+    \t\t// http://jira.codehaus.org/browse/IZPACK-395\n+    \t\tFile testDir = new File(pathSelectionPanel.getPath());\n+    \t\tFile serverFile = new File(testDir, \"jars/tigase-server.jar\");\n+    \t\tif (serverFile.exists()) {\n+    \t\t\tString msg = \"Installation over existing Tigase directory \\n\" +\n+    \t\t\t\t\t\"is not supported right now.\";\n+    \t\t\temitError(\"Error\", msg);\n+    \t\t\treturn false;\n+    \t\t}\n+    \t}\n+    \t\n+    \t// Standard behavior of PathInputPanel.\n         if (!super.isValidated())\n         {\n             return (false);\ndiff --git a/src/lib/com/izforge/izpack/panels/TargetPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/TargetPanelConsoleHelper.java\nindex 964eec9..a3f0d85 100644\n--- a/src/lib/com/izforge/izpack/panels/TargetPanelConsoleHelper.java\n+++ b/src/lib/com/izforge/izpack/panels/TargetPanelConsoleHelper.java\n@@ -95,19 +95,7 @@ public class TargetPanelConsoleHelper extends PanelConsoleHelper implements Pane\n         strTargetPath = vs.substitute(strTargetPath, null);\n \n         idata.setInstallPath(strTargetPath);\n-        int i = askEndOfConsolePanel();\n-        if (i == 1)\n-        {\n-            return true;\n-        }\n-        else if (i == 2)\n-        {\n-            return false;\n-        }\n-        else\n-        {\n-            return runConsole(idata);\n-        }\n \n+        return continueQuitOrReboot(idata, this);\n     }\n }\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseConfigConst.java b/src/lib/com/izforge/izpack/panels/TigaseConfigConst.java\nnew file mode 100644\nindex 0000000..2952d2e\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseConfigConst.java\n@@ -0,0 +1,157 @@\n+/*  Tigase Project\n+ *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Affero General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU Affero General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Affero General Public License\n+ * along with this program. Look for COPYING file in the top folder.\n+ * If not, see http://www.gnu.org/licenses/.\n+ *\n+ * $Rev$\n+ * Last modified by $Author$\n+ * $Date$\n+ */\n+package com.izforge.izpack.panels;\n+\n+import java.util.LinkedHashMap;\n+import java.util.Properties;\n+\n+/**\n+ * Describe class TigaseConfigConst here.\n+ *\n+ *\n+ * Created: Sat Oct 25 21:23:06 2008\n+ *\n+ * @author <a href=\"mailto:artur.hefczyc@gmail.com\">Artur Hefczyc</a>\n+ * @version $Rev$\n+ */\n+public abstract class TigaseConfigConst {\n+\n+\tpublic static Properties props = null;\n+\n+\tpublic static LinkedHashMap<String, String> tigaseIzPackMap =\n+    new LinkedHashMap<String, String>();\n+// \tpublic static LinkedHashMap<String, String> izPackTigaseMap =\n+//     new LinkedHashMap<String, String>();\n+\n+\tpublic static LinkedHashMap<String, String> userDBMap =\n+    new LinkedHashMap<String, String>();\n+\n+\tpublic static LinkedHashMap<String, String> userDBUriMap =\n+    new LinkedHashMap<String, String>();\n+\n+\tpublic static final String SERVER_DEBUG = \"serverDebug\";\n+\tpublic static final String PLUGIN_DEBUG = \"pluginsDebug\";\n+\tpublic static final String DB_DEBUG = \"dbDebug\";\n+\tpublic static final String CLUSTER_DEBUG = \"clusterDebug\";\n+\n+\tpublic static String[] ALL_DEBUGS =\n+\t{SERVER_DEBUG, PLUGIN_DEBUG, DB_DEBUG, CLUSTER_DEBUG};\n+\tpublic static LinkedHashMap<String, String> debugMap =\n+    new LinkedHashMap<String, String>();\n+\n+\tpublic static String[] ALL_PLUGINS =\n+\t{\"nonSaslAuthPlugin\", \"saslAuthPlugin\", \"resBindPlugin\",\n+\t \"sessionBindPlugin\", \"registerPlugin\", \"rosterPlugin\", \"presencePlugin\", \"privacyPlugin\",\n+\t \"versionPlugin\", \"statsPlugin\", \"tlsPlugin\", \"msgOfflinePlugin\",\n+\t \"vcardPlugin\", \"commandsPlugin\", \"privatePlugin\", \"pingPlugin\",\n+\t \"basicFilterPlugin\", \"domainFilterPlugin\", \"pepPlugin\", \"zlibPlugin\"};\n+\tpublic static LinkedHashMap<String, String> pluginsMap =\n+    new LinkedHashMap<String, String>();\n+\n+\t// Special variable names:\n+\tpublic static final String DB_TYPE = \"dbType\";\n+\tpublic static final String AUTH_DB = \"authDB\";\n+\tpublic static final String AUTH_HANDLE = \"dbAuthHandle\";\n+\tpublic static final String MUC_COMP = \"mucComponent\";\n+\tpublic static final String PUBSUB_COMP = \"pubsubComponent\";\n+\tpublic static final String PLUGINS = \"plugins\";\n+\tpublic static final String DEBUG = \"debug\";\n+\tpublic static final String USER_DB_URI = \"userDBUri\";\n+\tpublic static final String AUTH_DB_URI = \"dbAuthType\";\n+\n+\tstatic {\n+\t\ttigaseIzPackMap.put(\"config-type\", \"configType\");\n+\t\ttigaseIzPackMap.put(\"--virt-hosts\", \"virtualDomains\");\n+\t\ttigaseIzPackMap.put(\"--admins\", \"admins\");\n+\t\ttigaseIzPackMap.put(\"--user-db\", DB_TYPE);\n+\t\ttigaseIzPackMap.put(\"--auth-db\", AUTH_HANDLE);\n+\t\ttigaseIzPackMap.put(\"--muc\", MUC_COMP);\n+\t\ttigaseIzPackMap.put(\"--pubsub\", PUBSUB_COMP);\n+\t\ttigaseIzPackMap.put(\"--cluster-mode\", \"clusterMode\");\n+\t\ttigaseIzPackMap.put(\"--cluster-nodes\", \"clusterNodes\");\n+\t\ttigaseIzPackMap.put(\"--debug\", DEBUG);\n+\t\ttigaseIzPackMap.put(\"--sm-plugins\", PLUGINS);\n+\t\ttigaseIzPackMap.put(\"--user-db-uri\", USER_DB_URI);\n+\t\ttigaseIzPackMap.put(\"--auth-db-uri\", AUTH_DB_URI);\n+// \t\tfor (Map.Entry entry: tigaseIzPackMap.entrySet()) {\n+// \t\t\tizPackTigaseMap.put(entry.getValue(), entry.getKey());\n+// \t\t}\n+\n+\t\tuserDBMap.put(\"Derby\", \"derby\");\n+\t\tuserDBMap.put(\"MySQL\", \"mysql\");\n+\t\tuserDBMap.put(\"PostgreSQL\", \"pgsql\");\n+\t\tuserDBMap.put(\"SQLServer\", \"jtds:sqlserver\");\n+\n+\t\tuserDBUriMap.put(\"derby\", \"Derby\");\n+\t\tuserDBUriMap.put(\"mysql\", \"MySQL\");\n+\t\tuserDBUriMap.put(\"postgresql\", \"PostgreSQL\");\n+\t\tuserDBUriMap.put(\"pgsql\", \"PostgreSQL\");\n+\t\tuserDBUriMap.put(\"jtds:sqlserver\", \"SQLServer\");\n+\n+\t\tdebugMap.put(\"server\", SERVER_DEBUG);\n+\t\tdebugMap.put(\"db\", DB_DEBUG);\n+\t\tdebugMap.put(\"xmpp.impl\", PLUGIN_DEBUG);\n+\t\tdebugMap.put(\"cluster\", CLUSTER_DEBUG);\n+\n+\t\tpluginsMap.put(\"jabber:iq:auth\", \"nonSaslAuthPlugin\");\n+\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-sasl\", \"saslAuthPlugin\");\n+\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-bind\", \"resBindPlugin\");\n+\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-session\", \"sessionBindPlugin\");\n+\t\tpluginsMap.put(\"jabber:iq:register\", \"registerPlugin\");\n+\t\tpluginsMap.put(\"jabber:iq:roster\", \"rosterPlugin\");\n+\t\tpluginsMap.put(\"presence\", \"presencePlugin\");\n+\t\tpluginsMap.put(\"jabber:iq:privacy\", \"privacyPlugin\");\n+\t\tpluginsMap.put(\"jabber:iq:version\", \"versionPlugin\");\n+\t\tpluginsMap.put(\"http://jabber.org/protocol/stats\", \"statsPlugin\");\n+\t\tpluginsMap.put(\"starttls\", \"tlsPlugin\");\n+\t\tpluginsMap.put(\"msgoffline\", \"msgOfflinePlugin\");\n+\t\tpluginsMap.put(\"vcard-temp\", \"vcardPlugin\");\n+\t\tpluginsMap.put(\"http://jabber.org/protocol/commands\", \"commandsPlugin\");\n+\t\tpluginsMap.put(\"jabber:iq:private\", \"privatePlugin\");\n+\t\tpluginsMap.put(\"urn:xmpp:ping\", \"pingPlugin\");\n+\t\tpluginsMap.put(\"basic-filter\", \"basicFilterPlugin\");\n+\t\tpluginsMap.put(\"domain-filter\", \"domainFilterPlugin\");\n+\t\tpluginsMap.put(\"pep\", \"pepPlugin\");\n+\t\tpluginsMap.put(\"zlib\", \"zlibPlugin\");\n+\t}\n+\n+\tpublic static String getPluginId(String pluginVarNameToFind) {\n+\t\tfor (String pluginId : pluginsMap.keySet()) {\n+\t\t\tString pluginVarName = pluginsMap.get(pluginId);\n+\t\t\tif (pluginVarName.equals(pluginVarNameToFind)) {\n+\t\t\t\treturn pluginId;\n+\t\t\t}\n+\t\t}\n+\t\treturn null;\n+\t}\n+\t\n+\tpublic static final String PGSQL_DRIVER = \"org.postgresql.Driver\";\n+\tpublic static final String MYSQL_DRIVER = \"com.mysql.jdbc.Driver\";\n+\tpublic static final String DERBY_DRIVER = \"org.apache.derby.jdbc.EmbeddedDriver\";\n+\n+\tpublic static final String JDBC_CHECKUSERTABLE_QUERY\n+    = \"select count(*) from tig_users\";\n+\n+\tpublic static final String JDBC_GETSCHEMAVER_QUERY\n+    = \"select TigGetDBProperty('schema-version')\";\n+\tpublic static final String DERBY_GETSCHEMAVER_QUERY\n+    = \"values TigGetDBProperty('schema-version')\";\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanel.java b/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanel.java\nnew file mode 100644\nindex 0000000..576c754\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanel.java\n@@ -0,0 +1,339 @@\n+/*\n+ * Tigase Jabber/XMPP Server\n+ * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Affero General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU Affero General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Affero General Public License\n+ * along with this program. Look for COPYING file in the top folder.\n+ * If not, see http://www.gnu.org/licenses/.\n+ *\n+ * $Rev$\n+ * Last modified by $Author$\n+ * $Date$\n+ */\n+\n+package com.izforge.izpack.panels;\n+\n+import java.io.File;\n+import java.io.FileReader;\n+import java.util.Properties;\n+import java.util.Set;\n+import java.util.regex.Matcher;\n+import java.util.regex.Pattern;\n+\n+import javax.swing.JScrollPane;\n+import javax.swing.JTextArea;\n+\n+import com.izforge.izpack.gui.IzPanelLayout;\n+import com.izforge.izpack.gui.LabelFactory;\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.InstallData;\n+import com.izforge.izpack.installer.InstallerFrame;\n+import com.izforge.izpack.installer.IzPanel;\n+import com.izforge.izpack.util.Debug;\n+\n+/**\n+ * The Hello panel class.\n+ *\n+ * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n+ * @version $Rev$\n+ */\n+public class TigaseConfigLoadPanel extends IzPanel {\n+\n+\t/**\n+\t *\n+\t */\n+\tprivate static final long serialVersionUID = 1L;\n+\n+\tprivate JTextArea textArea = null;\n+\n+\t/**\n+\t * The constructor.\n+\t *\n+\t * @param parent The parent.\n+\t * @param idata  The installation data.\n+\t */\n+\tpublic TigaseConfigLoadPanel(InstallerFrame parent, InstallData idata) {\n+\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n+\n+\t\t// The config label.\n+\t\tadd(LabelFactory.create(parent.langpack.getString(\"TigaseConfigLoadPanel.info\"),\n+\t\t\t\tparent.icons.getImageIcon(\"edit\"), LEADING), NEXT_LINE);\n+\t\t// The text area which shows the info.\n+\t\ttextArea = new JTextArea(\"\");\n+\t\ttextArea.setCaretPosition(0);\n+\t\ttextArea.setEditable(false);\n+\t\tJScrollPane scroller = new JScrollPane(textArea);\n+\t\tadd(scroller, NEXT_LINE);\n+\t\t// At end of layouting we should call the completeLayout method also they do nothing.\n+\t\tgetLayoutHelper().completeLayout();\n+\t}\n+\n+\tpublic void panelActivate() {\n+\t\tsuper.panelActivate();\n+\t\t// Existing configuration loading\n+\t\tDebug.trace(\"panelActivate called for load pael\");\n+\t\tString config = new TigaseConfigLoadHelper().loadConfig(idata);\n+\t\ttextArea.setText(config);\n+\t}\n+\n+\n+\t/**\n+\t * Indicates whether the panel has been validated or not.\n+\t *\n+\t * @return Always true.\n+\t */\n+\tpublic boolean isValidated() {\n+\t\treturn true;\n+\t}\n+\n+}\n+\n+class TigaseConfigLoadHelper {\n+\t\n+\tString loadConfig(AutomatedInstallData idata) {\n+\t\t// Try to read the config file.\n+\t\tFile configPath = null;\n+\t\tStringBuilder config = new StringBuilder();\n+\t\ttry {\n+\t\t\tif (idata.getVariable(\"searchTigaseHome\") == null\n+\t\t\t\t|| idata.getVariable(\"searchTigaseHome\").isEmpty()) {\n+\t\t\t\tconfigPath = new File(idata.getVariable(\"INSTALL_PATH\"),\n+\t\t\t\t\t\"etc/init.properties\");\n+\t\t\t} else {\n+\t\t\t\tconfigPath = new File(idata.getVariable(\"searchTigaseHome\"),\n+\t\t\t\t\t\"etc/init.properties\");\n+\t\t\t}\n+\t\t\tif (configPath.exists()) {\n+\t\t\t\tProperties props = new Properties();\n+\t\t\t\tprops.load(new FileReader(configPath));\n+\t\t\t\tDebug.trace(\"Loading init.properties file...\");\n+\t\t\t\tfor (String name: props.stringPropertyNames()) {\n+\t\t\t\t\tconfig.append(name + \" = \" + props.getProperty(name) + \"\\n\");\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(config);\n+\t\t\t\tDebug.trace(\"Done.\");\n+\t\t\t\tDebug.trace(\"Loading variables....\");\n+\t\t\t\tfor (String name: TigaseConfigConst.tigaseIzPackMap.keySet()) {\n+\t\t\t\t\tString varName = TigaseConfigConst.tigaseIzPackMap.get(name);\n+\t\t\t\t\tif (varName != null) {\n+\t\t\t\t\t\tDebug.trace(\"Loading: \" + varName + \" = \" + props.getProperty(name));\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.DEBUG)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tparseDebugs(props.getProperty(name), idata);\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.PLUGINS)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tparsePlugins(props.getProperty(name), idata);\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.USER_DB_URI)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tparseUserDbUri(props.getProperty(name), idata);\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.DB_TYPE)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tString dbType =\n+                  TigaseConfigConst.userDBUriMap.get(props.getProperty(name));\n+\t\t\t\t\t\t\t\tif (dbType == null) {\n+\t\t\t\t\t\t\t\t\tdbType = \"Other\";\n+\t\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.DB_TYPE, dbType);\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + dbType);\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.AUTH_HANDLE)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.AUTH_HANDLE,\n+\t\t\t\t\t\t\t\t\tprops.getProperty(name));\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.MUC_COMP)) {\n+\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-1\") != null\n+\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-1\").equals(\"muc\"))\n+\t\t\t\t\t\t\t\t|| (props.getProperty(\"--comp-name-2\") != null\n+\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-2\").equals(\"muc\"))) {\n+\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.MUC_COMP, \"on\");\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n+\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.MUC_COMP));\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.PUBSUB_COMP)) {\n+\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-1\") != null\n+\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-1\").equals(\"pubsub\"))\n+\t\t\t\t\t\t\t\t|| (props.getProperty(\"--comp-name-2\") != null\n+\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-2\").equals(\"pubsub\"))) {\n+\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.PUBSUB_COMP, \"on\");\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tDebug.trace(\"Load: \" + \"--comp-name-\" + \" = \" + \"pubsub\");\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.AUTH_DB_URI)) {\n+\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\t\tparseAuthDbUri(props.getProperty(name), idata);\n+\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tif (props.getProperty(name) != null) {\n+\t\t\t\t\t\t\tidata.setVariable(varName, props.getProperty(name));\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(\"Done.\");\n+\t\t\t} else {\n+\t\t\t\tconfig.append(\"The config file: \" + configPath + \" seems to not exist...\");\n+\t\t\t}\n+\t\t} catch (Exception err) {\n+\t\t\tStringBuilder errorConfig = new StringBuilder();\n+\t\t\terrorConfig.append(\"Error : could not load the config file: \" + configPath + \"\\n\");\n+\t\t\terrorConfig.append(err.toString() + \"\\n\");\n+\t\t\tfor (StackTraceElement ste: err.getStackTrace()) {\n+\t\t\t\terrorConfig.append(ste.toString() + \"\\n\");\n+\t\t\t}\n+\t\t\treturn errorConfig.toString();\n+\t\t}\n+\t\treturn config.toString();\n+\t}\n+\n+\tprivate void parseDebugs(String debugs, AutomatedInstallData idata) {\n+\t\tString[] ardebugs = debugs.split(\",\");\n+\t\tSet<String> knownDebugs = TigaseConfigConst.debugMap.keySet();\n+\t\tfor (String debug: ardebugs) {\n+\t\t\tif (knownDebugs.contains(debug)) {\n+\t\t\t\tidata.setVariable(TigaseConfigConst.debugMap.get(debug), debug);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tprivate void parsePlugins(String plugins, AutomatedInstallData idata) {\n+\t\tString[] arplugins = plugins.split(\",\");\n+\t\tSet<String> knownPlugins = TigaseConfigConst.pluginsMap.keySet();\n+\t\tfor (String plugin: arplugins) {\n+\t\t\tif (knownPlugins.contains(plugin)) {\n+\t\t\t\tidata.setVariable(TigaseConfigConst.pluginsMap.get(plugin), plugin);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tprivate static Pattern dbUriPattern =\n+    Pattern.compile(\n+\t\t\t\"jdbc:([^:]+(:[^:]+)?):(//([^/]+))?/?([0-9.a-zA-Z_/-]+)[;\\\\?]?(user=([^;&]+))?[;&]?(password=([^;&]+))?[;&]?(.*)\");\n+\n+\tprivate void parseUserDbUri(String dbUri, AutomatedInstallData idata) {\n+\t\tMatcher m = dbUriPattern.matcher(dbUri);\n+\t\tif (m.matches()) {\n+\t\t\tString jdbcDriver = m.group(1);\n+\t\t\tString host = m.group(4);\n+\t\t\tString dbName = m.group(5);\n+\t\t\tString userName = m.group(7);\n+\t\t\tString userPass = m.group(9);\n+\t\t\tString otherPars = m.group(10);\n+// \t\tidata.setVariable(TigaseConfigConst.DB_TYPE,\n+// \t\t\tTigaseConfigConst.userDBUriMap.get(jdbcDriver));\n+\t\t\tif (jdbcDriver.equals(\"mysql\")) {\n+\t\t\t\tidata.setVariable(\"dbSuperuser\", \"root\");\n+\t\t\t}\n+\t\t\tif (jdbcDriver.equals(\"postgresql\")) {\n+\t\t\t\tidata.setVariable(\"dbSuperuser\", \"postgres\");\n+\t\t\t}\n+\t\t\tif (host != null) {\n+\t\t\t\tidata.setVariable(\"dbHost\", host);\n+\t\t\t}\n+\t\t\tif (dbName != null) {\n+\t\t\t\tif (jdbcDriver.equals(\"derby\")) {\n+\t\t\t\t\tidata.setVariable(\"DerbyDBPath\", \"/\" + dbName);\n+\t\t\t\t\tDebug.trace(\"DerbyDBPath set to /\" + dbName);\n+\t\t\t\t} else {\n+\t\t\t\t\tidata.setVariable(\"dbName\", dbName);\n+\t\t\t\t\tDebug.trace(\"dbName read: \" + dbName);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (userName != null) {\n+\t\t\t\tidata.setVariable(\"dbUser\", userName);\n+\t\t\t}\n+\t\t\tif (userPass != null) {\n+\t\t\t\tidata.setVariable(\"dbPass\", userPass);\n+\t\t\t}\n+\t\t\tif (otherPars != null) {\n+\t\t\t\tidata.setVariable(\"dbParams\", otherPars);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tDebug.trace(\"Hm, the dbUri doesn't match regex: \" + dbUri);\n+\t\t}\n+\t}\n+\n+\tprivate void parseAuthDbUri(String dbUri, AutomatedInstallData idata) {\n+\t\tMatcher m = dbUriPattern.matcher(dbUri);\n+\t\tif (m.matches()) {\n+\t\t\tString jdbcDriver = m.group(1);\n+\t\t\tString host = m.group(4);\n+\t\t\tString dbName = m.group(5);\n+\t\t\tString userName = m.group(7);\n+\t\t\tString userPass = m.group(9);\n+\t\t\tString otherPars = m.group(10);\n+\t\t\tif (jdbcDriver != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthType\", jdbcDriver);\n+\t\t\t}\n+\t\t\tif (host != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthHost\", host);\n+\t\t\t}\n+\t\t\tif (dbName != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthName\", dbName);\n+\t\t\t}\n+\t\t\tif (userName != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthUser\", userName);\n+\t\t\t}\n+\t\t\tif (userPass != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthPass\", userPass);\n+\t\t\t}\n+\t\t\tif (otherPars != null) {\n+\t\t\t\tidata.setVariable(\"dbAuthParams\", otherPars);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tDebug.trace(\"Hm, the dbAuthUri doesn't match regex: \" + dbUri);\n+\t\t}\n+\t}\n+\t\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..8b418b1\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseConfigLoadPanelConsoleHelper.java\n@@ -0,0 +1,29 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+\n+public class TigaseConfigLoadPanelConsoleHelper  extends PanelConsoleHelper implements PanelConsole {\n+\n+\tpublic boolean runConsole(AutomatedInstallData installData) {\n+\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n+\t\treturn true;\n+\t}\n+\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n+\t\treturn true;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n+\t\treturn true;\n+\t}\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanel.java b/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanel.java\nnew file mode 100644\nindex 0000000..05cd89b\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanel.java\n@@ -0,0 +1,414 @@\n+/*\n+ * Tigase Jabber/XMPP Server\n+ * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Affero General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU Affero General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Affero General Public License\n+ * along with this program. Look for COPYING file in the top folder.\n+ * If not, see http://www.gnu.org/licenses/.\n+ *\n+ * $Rev$\n+ * Last modified by $Author$\n+ * $Date$\n+ */\n+\n+package com.izforge.izpack.panels;\n+\n+import java.io.File;\n+import java.io.FileWriter;\n+import java.util.Map;\n+import java.util.Properties;\n+\n+import javax.swing.JScrollPane;\n+import javax.swing.JTextArea;\n+\n+import com.izforge.izpack.gui.IzPanelLayout;\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.InstallData;\n+import com.izforge.izpack.installer.InstallerFrame;\n+import com.izforge.izpack.installer.IzPanel;\n+import com.izforge.izpack.util.Debug;\n+import com.izforge.izpack.util.OsVersion;\n+\n+/**\n+ * The Hello panel class.\n+ *\n+ * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n+ * @version $Rev$\n+ */\n+public class TigaseConfigSavePanel extends IzPanel {\n+\n+\t/**\n+\t *\n+\t */\n+\tprivate static final long serialVersionUID = 1L;\n+\n+\tprivate JTextArea textArea = null;\n+\n+\tprivate final TigaseConfigSaveHelper helper = new TigaseConfigSaveHelper();\n+\n+\n+\t/**\n+\t * The constructor.\n+\t *\n+\t * @param parent The parent.\n+\t * @param idata  The installation data.\n+\t */\n+\tpublic TigaseConfigSavePanel(InstallerFrame parent, InstallData idata) {\n+\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n+\n+\t\t// The config label.\n+\t\tString msg = parent.langpack.getString(\"TigaseConfigSavePanel.info\");\n+\t\tadd(createMultiLineLabel(msg));\n+\t\tadd(IzPanelLayout.createParagraphGap());\n+\t\t// The text area which shows the info.\n+\t\ttextArea = new JTextArea(\"\");\n+\t\ttextArea.setCaretPosition(0);\n+\t\ttextArea.setEditable(true);\n+\t\tJScrollPane scroller = new JScrollPane(textArea);\n+\t\tadd(scroller, NEXT_LINE);\n+\t\t// At end of layouting we should call the completeLayout method also they do nothing.\n+\t\tgetLayoutHelper().completeLayout();\n+\t}\n+\n+\tpublic void panelActivate() {\n+\t\tsuper.panelActivate();\n+\t\tString config = helper.showConfig(\n+\t\t\t\tnew IzPackInstallDataVariablesSource(idata));\n+\t\ttextArea.setText(config);\n+\t}\n+\n+\n+\n+\t/**\n+\t * Indicates wether the panel has been validated or not.\n+\t *\n+\t * @return Always true.\n+\t */\n+\tpublic boolean isValidated() {\n+\t\tString errorStr =  helper.saveConfig(idata, textArea.getText());\n+\t\tif (errorStr != null) {\n+\t\t\temitError(\"Can not write to config file\", errorStr);\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+}\n+\n+abstract class VariablesSource {\n+\tabstract String getVariable(String key);\n+}\n+\n+class IzPackInstallDataVariablesSource extends VariablesSource {\n+\tprivate final AutomatedInstallData idata;\n+\n+\tpublic IzPackInstallDataVariablesSource(AutomatedInstallData idata) {\n+\t\tthis.idata = idata;\n+\t\t\n+\t}\n+\n+\t@Override\n+\tString getVariable(String key) {\n+\t\treturn idata.getVariable(key);\n+\t}\n+}\n+\n+class TigaseConfigSaveHelper {\n+\t\n+\tString showConfig(VariablesSource variablesSource) {\n+\t\tTigaseConfigConst.props = new Properties();\n+\t\tStringBuilder config = new StringBuilder();\n+\t\tint comp_idx = 0;\n+\t\tfor (Map.Entry<String, String> entry:\n+        TigaseConfigConst.tigaseIzPackMap.entrySet()) {\n+\t\t\tString varName = entry.getValue();\n+\t\t\tString varValue = variablesSource.getVariable(varName);\n+\n+\t\t\tif (varName.equals(TigaseConfigConst.DEBUG)) {\n+\t\t\t\tString debugVar = getDebugs(variablesSource);\n+\t\t\t\tif (!debugVar.isEmpty()) {\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), debugVar);\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + debugVar);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.PLUGINS)) {\n+\t\t\t\tString pluginsVar = getPlugins(variablesSource);\n+\t\t\t\tif (!pluginsVar.isEmpty()) {\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), pluginsVar);\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + pluginsVar);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.USER_DB_URI)) {\n+\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), getDBUri(variablesSource));\n+\t\t\t\tTigaseConfigConst.props.setProperty(\"root-tigase-db-uri\",\n+\t\t\t\t\tgetRootTigaseDBUri(variablesSource));\n+\t\t\t\tTigaseConfigConst.props.setProperty(\"root-db-uri\", getRootDBUri(variablesSource));\n+\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getDBUri(variablesSource));\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tif (varValue == null) continue;\n+\n+\t\t\tif (varName.equals(TigaseConfigConst.DB_TYPE)) {\n+\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), getUserDB(variablesSource));\n+\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getUserDB(variablesSource));\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.AUTH_HANDLE)) {\n+\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(),\n+\t\t\t\t\tgetAuthHandler(varValue, variablesSource));\n+\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getAuthHandler(varValue, variablesSource));\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.MUC_COMP)) {\n+\t\t\t\tif (varValue.equals(\"on\")) {\n+\t\t\t\t\t++comp_idx;\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"muc\");\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n+\t\t\t\t\t\t\"tigase.muc.MUCComponent\");\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"muc\");\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.PUBSUB_COMP)) {\n+\t\t\t\tif (varValue.equals(\"on\")) {\n+\t\t\t\t\t++comp_idx;\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"pubsub\");\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n+\t\t\t\t\t\t\"tigase.pubsub.PubSubClusterComponent\");\n+\t\t\t\t}\n+\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"pubsub\");\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (varName.equals(TigaseConfigConst.AUTH_DB_URI)) {\n+\t\t\t\tString auth_db_uri = getAuthUri(variablesSource);\n+\t\t\t\tif (auth_db_uri != null) {\n+\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), auth_db_uri);\n+\t\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + auth_db_uri);\n+\t\t\t\t} else {\n+\t\t\t\t\tDebug.trace(\"Not set: \" + entry.getKey());\n+\t\t\t\t}\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!varValue.trim().isEmpty()) {\n+\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), varValue);\n+\t\t\t}\n+\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + varValue);\n+\t\t}\n+\t\tfor (String name: TigaseConfigConst.props.stringPropertyNames()) {\n+\t\t\tif (!name.startsWith(\"root\")) {\n+\t\t\t\tconfig.append(name + \" = \" + TigaseConfigConst.props.getProperty(name) + \"\\n\");\n+\t\t\t}\n+\t\t}\n+\t\treturn config.toString();\n+\t}\n+\n+\tprivate String getDBUri(VariablesSource variablesSource) {\n+\t\tString db_uri = \"jdbc:\";\n+\t\tString database = getUserDB(variablesSource);\n+\t\tif (database.equals(\"pgsql\")) {\n+\t\t\tdb_uri += \"postgresql:\";\n+\t\t} else {\n+\t\t\tdb_uri += database + \":\";\n+\t\t}\n+\t\tif (database.equals(\"derby\")) {\n+\t\t\tString derby_path = variablesSource.getVariable(\"DerbyDBPath\");\n+\t\t\tif (OsVersion.IS_WINDOWS && derby_path != null) {\n+\t\t\t\tderby_path = derby_path.replace(\"\\\\\", \"\\\\\\\\\");\n+\t\t\t}\n+\t\t\tdb_uri += derby_path;\n+\t\t} else {\n+\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n+\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbName\");\n+\t\t\tdb_uri += \"?user=\" + variablesSource.getVariable(\"dbUser\");\n+\t\t\tif (variablesSource.getVariable(\"dbPass\") != null\n+\t\t\t\t&& !variablesSource.getVariable(\"dbPass\").isEmpty()) {\n+\t\t\t\tdb_uri += \"&password=\" + variablesSource.getVariable(\"dbPass\");\n+\t\t\t}\n+\t\t}\n+\t\treturn db_uri;\n+\t}\n+\n+\tprivate String getRootTigaseDBUri(VariablesSource variablesSource) {\n+\t\tString db_uri = \"jdbc:\";\n+\t\tString database = getUserDB(variablesSource);\n+\t\tif (database.equals(\"pgsql\")) {\n+\t\t\tdb_uri += \"postgresql:\";\n+\t\t} else {\n+\t\t\tdb_uri += database + \":\";\n+\t\t}\n+\t\tif (database.equals(\"derby\")) {\n+\t\t\tdb_uri += variablesSource.getVariable(\"DerbyDBPath\") + \";create=true\";\n+\t\t} else {\n+\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n+\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbName\");\n+\t\t\tdb_uri += \"?user=\" + variablesSource.getVariable(\"dbSuperuser\");\n+\t\t\tif (variablesSource.getVariable(\"dbSuperpass\") != null\n+\t\t\t\t&& !variablesSource.getVariable(\"dbSuperpass\").isEmpty()) {\n+\t\t\t\tdb_uri += \"&password=\" + variablesSource.getVariable(\"dbSuperpass\");\n+\t\t\t}\n+\t\t}\n+\t\treturn db_uri;\n+\t}\n+\n+\tprivate String getRootDBUri(VariablesSource variablesSource) {\n+\t\tString db_uri = \"jdbc:\";\n+\t\tString db = \"\";\n+\t\tString database = getUserDB(variablesSource);\n+\t\tif (database.equals(\"pgsql\")) {\n+\t\t\tdb_uri += \"postgresql:\";\n+\t\t\tdb = \"/postgres\";\n+\t\t} else {\n+\t\t\tdb_uri += database + \":\";\n+\t\t\tif (database.equals(\"mysql\")) {\n+\t\t\t\tdb = \"/mysql\";\n+\t\t\t}\n+\t\t}\n+\t\tif (database.equals(\"derby\")) {\n+\t\t\tdb_uri += variablesSource.getVariable(\"DerbyDBPath\") + \";create=true\";\n+\t\t} else {\n+\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n+\t\t\tdb_uri += db;\n+\t\t\tdb_uri += \"?user=\" + variablesSource.getVariable(\"dbSuperuser\");\n+\t\t\tif (variablesSource.getVariable(\"dbSuperpass\") != null\n+\t\t\t\t&& !variablesSource.getVariable(\"dbSuperpass\").isEmpty()) {\n+\t\t\t\tdb_uri += \"&password=\" + variablesSource.getVariable(\"dbSuperpass\");\n+\t\t\t}\n+\t\t}\n+\t\treturn db_uri;\n+\t}\n+\n+\tprivate String getAuthUri(VariablesSource variablesSource) {\n+\t\tString db_uri = \"jdbc:\";\n+\t\tString database = variablesSource.getVariable(TigaseConfigConst.AUTH_DB_URI);\n+\t\tdb_uri += database + \":\";\n+\t\tif (database.equals(\"derby\")) {\n+\t\t\tString derby_path = variablesSource.getVariable(\"DerbyDBPath\");\n+\t\t\tif (derby_path != null) {\n+\t\t\t\tdb_uri += derby_path;\n+\t\t\t} else {\n+\t\t\t\treturn null;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbAuthHost\");\n+\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbAuthName\");\n+\t\t\tdb_uri += \"?user=\" + variablesSource.getVariable(\"dbAuthUser\");\n+\t\t\tif (variablesSource.getVariable(\"dbAuthPass\") != null\n+\t\t\t\t&& !variablesSource.getVariable(\"dbAuthPass\").isEmpty()) {\n+\t\t\t\tdb_uri += \"&password=\" + variablesSource.getVariable(\"dbAuthPass\");\n+\t\t\t}\n+\t\t}\n+\t\treturn db_uri;\n+\t}\n+\n+\tprivate String getPlugins(VariablesSource variablesSource) {\n+\t\tString plugins = \"\";\n+\t\tif (variablesSource.getVariable(TigaseConfigConst.ALL_PLUGINS[0]) == null) {\n+\t\t\t// The Panel with debuging settings was not shown so all\n+\t\t\t// settins are null, then we set a default: 'server'\n+\t\t\treturn \"\";\n+\t\t}\n+\t\tfor (String plugin: TigaseConfigConst.ALL_PLUGINS) {\n+\t\t\tif (variablesSource.getVariable(plugin) == null) {\n+\t\t\t\tDebug.trace(\"Missing variables for: \" + plugin);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\t\n+\t\t\tfinal String value = variablesSource.getVariable(plugin);\n+\t\t\tfinal String prefix;\n+\t\t\tfinal String pluginId = TigaseConfigConst.getPluginId(plugin);\n+\t\t\tif (value.equals(\"off\")) {\n+\t\t\t\tprefix = \"-\";\n+\t\t\t} else {\n+\t\t\t\tprefix = \"+\";\n+\t\t\t} \n+\t\t\t\n+\t\t\tif (!plugins.isEmpty()) {\n+\t\t\t\tplugins += \",\";\n+\t\t\t}\n+\t\t\tplugins += prefix + pluginId;\n+\t\t}\n+\t\t\n+\t\treturn plugins;\n+\t}\n+\n+\tprivate String getDebugs(VariablesSource variablesSource) {\n+\n+\t\tString debugs = \"\";\n+\t\tif (variablesSource.getVariable(TigaseConfigConst.ALL_DEBUGS[0]) == null) {\n+\t\t\t// The Panel with debuging settings was not shown so all\n+\t\t\t// settins are null, then we set a default: 'server'\n+\t\t\treturn \"server\";\n+\t\t}\n+\t\tfor (String deb: TigaseConfigConst.ALL_DEBUGS) {\n+\t\t\tif (variablesSource.getVariable(deb) == null \n+\t\t\t\t\t|| variablesSource.getVariable(deb).equals(\"off\")) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!debugs.isEmpty()) {\n+\t\t\t\tdebugs += \",\";\n+\t\t\t}\n+\t\t\tdebugs += variablesSource.getVariable(deb);\n+\t\t}\n+\t\treturn debugs;\n+\t}\n+\n+\tprivate String getAuthHandler(String var, VariablesSource variablesSource) {\n+\t\tif (var.equals(\"Standard\")) {\n+\t\t\treturn getUserDB(variablesSource);\n+\t\t}\n+\t\treturn var;\n+\t}\n+\n+\tprivate String getUserDB(VariablesSource variablesSource) {\n+\t\tString dbVar = variablesSource.getVariable(TigaseConfigConst.DB_TYPE);\n+\t\tString result = TigaseConfigConst.userDBMap.get(dbVar);\n+\t\treturn result != null ? result : \"derby\";\n+\t}\n+\t\n+\t// returns null if ok, error string on error\n+\tString saveConfig(AutomatedInstallData variablesSource, String config) {\n+\t\t// Try to read the config file.\n+\t\tFile configPath = null;\n+\t\tFile xmlConfigPath = null;\n+\t\ttry {\n+\t\t\tif (variablesSource.getVariable(\"searchTigaseHome\") == null\n+\t\t\t\t|| variablesSource.getVariable(\"searchTigaseHome\").isEmpty()) {\n+\t\t\t\tconfigPath = new File(variablesSource.getVariable(\"INSTALL_PATH\"),\n+\t\t\t\t\t\"etc/init.properties\");\n+\t\t\t\txmlConfigPath = new File(variablesSource.getVariable(\"INSTALL_PATH\"),\n+\t\t\t\t\t\"etc/tigase.xml\");\n+\t\t\t} else {\n+\t\t\t\tconfigPath = new File(variablesSource.getVariable(\"searchTigaseHome\"),\n+\t\t\t\t\t\"etc/init.properties\");\n+\t\t\t\txmlConfigPath = new File(variablesSource.getVariable(\"searchTigaseHome\"),\n+\t\t\t\t\t\"etc/tigase.xml\");\n+\t\t\t}\n+\t\t\tFileWriter fw = new FileWriter(configPath, false);\n+\t\t\tfw.write(config);\n+\t\t\tfw.close();\n+\t\t\tif (xmlConfigPath.exists()) {\n+\t\t\t\txmlConfigPath.delete();\n+\t\t\t}\n+\t\t} catch (Exception err) {\n+\t\t\tString error = \"Error : could not write to the config file: \" + configPath + \"\\n\";\n+\t\t\terror += err.toString() + \"\\n\";\n+\t\t\tfor (StackTraceElement ste: err.getStackTrace()) {\n+\t\t\t\terror += ste.toString() + \"\\n\";\n+\t\t\t}\n+\t\t\treturn error;\n+\t\t}\n+\t\treturn null;\n+\t}\n+\n+}\n\\ No newline at end of file\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..1858e6f\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseConfigSavePanelConsoleHelper.java\n@@ -0,0 +1,35 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+\n+public class TigaseConfigSavePanelConsoleHelper  \n+extends PanelConsoleHelper implements PanelConsole {\n+\n+\tpublic boolean runConsole(AutomatedInstallData installData) {\n+\t\tTigaseConfigSaveHelper helper = new TigaseConfigSaveHelper();\n+\t\t\n+\t\tString config =  helper.showConfig(\n+\t\t\t\tnew IzPackInstallDataVariablesSource(installData));\n+\t\thelper.saveConfig(installData, config);\n+\t\t\n+\t\treturn true;\n+\t}\n+\n+\t\n+\t\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanel.java b/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanel.java\nnew file mode 100644\nindex 0000000..dd0cc46\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanel.java\n@@ -0,0 +1,160 @@\n+/*\n+ * Tigase Jabber/XMPP Server\n+ * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Affero General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU Affero General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Affero General Public License\n+ * along with this program. Look for COPYING file in the top folder.\n+ * If not, see http://www.gnu.org/licenses/.\n+ *\n+ * $Rev$\n+ * Last modified by $Author$\n+ * $Date$\n+ */\n+\n+package com.izforge.izpack.panels;\n+\n+import java.util.Timer;\n+import java.util.TimerTask;\n+\n+import javax.swing.JScrollPane;\n+import javax.swing.JTable;\n+import javax.swing.SwingUtilities;\n+import javax.swing.table.AbstractTableModel;\n+import javax.swing.table.TableModel;\n+\n+import com.izforge.izpack.gui.IzPanelLayout;\n+import com.izforge.izpack.installer.InstallData;\n+import com.izforge.izpack.installer.InstallerFrame;\n+import com.izforge.izpack.installer.IzPanel;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.MsgTarget;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n+\n+/**\n+ * The Hello panel class.\n+ *\n+ * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n+ * @version $Rev$\n+ */\n+public class TigaseDBCheckPanel extends IzPanel {\n+\n+\t/**\n+\t *\n+\t */\n+\tprivate static final long serialVersionUID = 1L;\n+\n+\tprivate JTable table = null;\n+\tprivate Timer delayedTasks = new Timer(\"DelayedTasks\", true);\n+\n+\tprivate final InstallData idata;\n+\n+\t/**\n+\t * The constructor.\n+\t *\n+\t * @param parent The parent.\n+\t * @param idata  The installation data.\n+\t */\n+\tpublic TigaseDBCheckPanel(InstallerFrame parent, InstallData idata) {\n+\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n+\t\tthis.idata = idata;\n+\n+\t\t// The config label.\n+\t\tString msg = parent.langpack.getString(\"TigaseDBCheckPanel.info\");\n+\t\tadd(createMultiLineLabel(msg));\n+\t\tadd(IzPanelLayout.createParagraphGap());\n+\n+\t\tfinal String[] columnNames = new String[] {\"Action\", \"Result\"};\n+\t\t\n+\t\tTigaseDBTask[] tasks = TigaseInstallerDBHelper.Tasks.getTasksInOrder();\n+\t\tfinal String[][] data = new String[tasks.length][];\n+\t\tfor (int i = 0 ; i < tasks.length ; i++) {\n+\t\t\tTigaseDBTask task = tasks[i];\n+\t\t\tdata[i] = new String[] { task.getDescription(), \"\" };\n+\t\t}\n+\t\t\n+\t\tTableModel dataModel = new AbstractTableModel() {\n+//\t\t\t\tprivate String[] columnNames = names;\n+//\t\t\t\tprivate Object[][] data = datas;\n+\t\t\t\tpublic int getColumnCount() { return columnNames.length; }\n+\t\t\t\tpublic int getRowCount() { return data.length; }\n+\t\t\t\tpublic String getColumnName(int col) { return columnNames[col]; }\n+\t\t\t\tpublic Object getValueAt(int row, int col) { return data[row][col]; }\n+\t\t\t\tpublic Class getColumnClass(int c) { return getValueAt(0, c).getClass(); }\n+\t\t\t\tpublic boolean isCellEditable(int row, int col) { return false; }\n+\t\t\t\tpublic void setValueAt(Object value, int row, int col) {\n+\t\t\t\t\tdata[row][col] = value.toString();\n+\t\t\t\t\tfireTableCellUpdated(row, col);\n+\t\t\t\t}\n+      };\n+\t\t// The table area which shows the info.\n+\t\ttable = new JTable(dataModel);\n+\t\t//\t\ttable.setEditable(false);\n+\t\t//add(table, NEXT_LINE);\n+\t\tJScrollPane scroller = new JScrollPane(table);\n+\t\ttable.setFillsViewportHeight(true);\n+\t\tadd(scroller, NEXT_LINE);\n+\t\t// At end of layouting we should call the completeLayout\n+\t\t// method also they do nothing.\n+\t\tgetLayoutHelper().completeLayout();\n+\t}\n+\n+\tpublic void panelActivate() {\n+\t\tsuper.panelActivate();\n+\t\tparent.lockNextButton();\n+\t\t\n+\t\tfinal TigaseInstallerDBHelper dbHelper = new TigaseInstallerDBHelper();\n+\t\t\n+\t\tdelayedTasks.schedule(new TimerTask() {\n+\t\t\t\t\n+\t\t\tpublic void run() {\n+\t\t\t\tTigaseDBTask[] tasks = TigaseInstallerDBHelper.Tasks.getTasksInOrder();\n+\t\t\t\t\n+\t\t\t\tfor (int i = 0 ; i < tasks.length ; i++) {\n+\t\t\t\t\tTigaseDBTask task = tasks[i];\n+\t\t\t\t\tfinal int row = i;\n+\t\t\t\t\t\n+\t\t\t\t\tMsgTarget msgTarget = new MsgTarget() {\n+\t\t\t\t\t\tpublic ResultMessage addResultMessage() {\n+\t\t\t\t\t\t\treturn new ResultMessage() {\n+\t\t\t\t\t\t\t\tprivate String fullMsg = \"\";\n+\n+\t\t\t\t\t\t\t\tpublic void append(String msg) {\n+\t\t\t\t\t\t\t\t\tfullMsg += msg;\n+\t\t\t\t\t\t\t\t\tSwingUtilities.invokeLater(new Runnable() {\n+\t\t\t\t\t\t\t\t\t\tpublic void run() {\n+\t\t\t\t\t\t\t\t\t\t\ttable.getModel().setValueAt(fullMsg, row, 1);\n+\t\t\t\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t\t\t});\n+\t\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t};\n+\t\t\t\t\t\t}\n+\t\t\t\t\t};\n+\t\t\t\t\t\t\n+\t\t\t\t\ttask.execute(dbHelper, idata.getVariables(), msgTarget);\n+\t\t\t\t}\n+\t\t\t\tparent.unlockNextButton();\n+\t\t\t}\n+\t\t}, 500);\n+\t}\n+\n+\t/**\n+\t * Indicates wether the panel has been validated or not.\n+\t *\n+\t * @return Always true.\n+\t */\n+\tpublic boolean isValidated() {\n+\t\treturn true;\n+\t}\n+\n+}\n+\n+\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanelConsoleHelper.java\nnew file mode 100644\nindex 0000000..101e248\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseDBCheckPanelConsoleHelper.java\n@@ -0,0 +1,62 @@\n+package com.izforge.izpack.panels;\n+\n+import java.io.PrintWriter;\n+import java.util.Properties;\n+\n+import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n+import com.izforge.izpack.installer.PanelConsole;\n+import com.izforge.izpack.installer.PanelConsoleHelper;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n+\n+public class TigaseDBCheckPanelConsoleHelper extends PanelConsoleHelper implements PanelConsole {\n+\n+\tprivate ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n+\t\n+\tpublic boolean runConsole(AutomatedInstallData installData) {\n+\t\t\n+\t\tTigaseInstallerDBHelper dbHelper = new TigaseInstallerDBHelper();\n+\t\n+\t\thelper.console.displayLabel(\"Performing DB tasks\");\n+\t\t\t\t\n+\t\tfor (TigaseDBTask task : TigaseInstallerDBHelper.Tasks.getTasksInOrder()) {\n+\t\t\thelper.console.displayEmptyLine();\n+\t\t\thelper.console.displayRaw(task.getDescription() + \"  \");\n+\t\t\t\n+\t\t\tTigaseInstallerDBHelper.MsgTarget msgTarget = new TigaseInstallerDBHelper.MsgTarget() {\n+\t\t\t\tpublic ResultMessage addResultMessage() {\n+\t\t\t\t\thelper.console.displayEmptyLine();\n+\t\t\t\t\treturn new ResultMessage() {\n+\t\t\t\t\t\tpublic void append(String msg) {\n+\t\t\t\t\t\t\thelper.console.displayRaw(msg);\n+\t\t\t\t\t\t}\n+\t\t\t\t\t};\n+\t\t\t\t}\n+\t\t\t};\n+\n+\t\t\ttask.execute(dbHelper, installData.getVariables(), msgTarget);\n+\t\t}\n+\t\t\n+\t\thelper.console.displayEmptyLine();\n+\t\thelper.console.displayEmptyLine();\n+\t\thelper.console.displayEmptyLine();\n+\n+\t\treturn true;\n+\t}\n+\n+\n+\t\n+\t// not implemented\n+\t\n+\tpublic boolean runConsoleFromPropertiesFile(\n+\t\t\tAutomatedInstallData installData, Properties p) {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n+\t\t\tPrintWriter printWriter) {\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/TigaseInstallerDbHelperFunctionalTest.java b/src/lib/com/izforge/izpack/panels/TigaseInstallerDbHelperFunctionalTest.java\nnew file mode 100644\nindex 0000000..f1d2afb\n--- /dev/null\n+++ b/src/lib/com/izforge/izpack/panels/TigaseInstallerDbHelperFunctionalTest.java\n@@ -0,0 +1,39 @@\n+package com.izforge.izpack.panels;\n+\n+import java.util.Properties;\n+\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.MsgTarget;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\n+import com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n+\n+public class TigaseInstallerDbHelperFunctionalTest {\n+\n+\tpublic static void main(String[] args) {\n+\t\ttestPostgres();\n+\t}\n+\n+\tprivate static void testPostgres() {\n+\t\t\n+\t\tTigaseInstallerDBHelper helper = new TigaseInstallerDBHelper();\n+\t\tProperties variables = new Properties();\n+\t\t\n+\t\tfor (final TigaseDBTask task : \n+\t\t\tTigaseInstallerDBHelper.Tasks.getTasksInOrder()) \n+\t\t{\n+\t\t\tMsgTarget msgTarget = new MsgTarget() {\n+\t\t\t\tpublic ResultMessage addResultMessage() {\n+\t\t\t\t\tSystem.err.println(\"Task: \" + task.getDescription());\n+\t\t\t\t\treturn new ResultMessage() {\n+\t\t\t\t\t\tpublic void append(String msg) {\n+\t\t\t\t\t\t\tSystem.err.print(msg);\n+\t\t\t\t\t\t}\n+\t\t\t\t\t};\n+\t\t\t\t}\n+\t\t\t};\n+\t\t\t\n+\t\t\ttask.execute(helper, variables, msgTarget);\n+\t\t}\n+\t\t\n+\t}\n+\t\n+}\ndiff --git a/src/lib/com/izforge/izpack/panels/UserInputPanel.java b/src/lib/com/izforge/izpack/panels/UserInputPanel.java\nindex fbda7e9..5e46d4e 100644\n--- a/src/lib/com/izforge/izpack/panels/UserInputPanel.java\n+++ b/src/lib/com/izforge/izpack/panels/UserInputPanel.java\n@@ -2456,6 +2456,8 @@ public class UserInputPanel extends IzPanel implements ActionListener, ItemListe\n                 if (value.equals(trueValue))\n                 {\n                     set = TRUE;\n+                } else {\n+                \tset = FALSE;\n                 }\n             }\n         }\ndiff --git a/src/lib/com/izforge/izpack/panels/UserInputPanel.java b/src/lib/com/izforge/izpack/panels/UserInputPanel.java\nindex 73b9c58..308941f 100644\n--- a/src/lib/com/izforge/izpack/panels/UserInputPanel.java\n+++ b/src/lib/com/izforge/izpack/panels/UserInputPanel.java\n@@ -69,10 +69,7 @@ import com.izforge.izpack.gui.ButtonFactory;\n import com.izforge.izpack.gui.LabelFactory;\n import com.izforge.izpack.gui.TwoColumnConstraints;\n import com.izforge.izpack.gui.TwoColumnLayout;\n-import com.izforge.izpack.installer.InstallData;\n-import com.izforge.izpack.installer.InstallerFrame;\n-import com.izforge.izpack.installer.IzPanel;\n-import com.izforge.izpack.installer.ResourceManager;\n+import com.izforge.izpack.installer.*;\n import com.izforge.izpack.rules.RulesEngine;\n import com.izforge.izpack.rules.VariableExistenceCondition;\n import com.izforge.izpack.util.Debug;\n@@ -372,11 +369,16 @@ public class UserInputPanel extends IzPanel implements ActionListener, ItemListe\n             String resource = LANG_FILE_NAME + \"_\" + idata.localeISO3;\n             this.langpack.add(ResourceManager.getInstance().getInputStream(resource));\n         }\n-        catch (Throwable exception)\n+        catch (ResourceNotFoundException e)\n         {\n-            exception.printStackTrace();\n+            Debug.trace(e);\n+        }\n+        catch (Exception e)\n+        {\n+            e.printStackTrace();\n         }\n \n+\n         // ----------------------------------------------------\n         // read the specifications\n         // ----------------------------------------------------\ndiff --git a/src/lib/com/izforge/izpack/panels/UserInputPanelConsoleHelper.java b/src/lib/com/izforge/izpack/panels/UserInputPanelConsoleHelper.java\nindex ca9a659..1245897 100644\n--- a/src/lib/com/izforge/izpack/panels/UserInputPanelConsoleHelper.java\n+++ b/src/lib/com/izforge/izpack/panels/UserInputPanelConsoleHelper.java\n@@ -25,6 +25,7 @@ import java.io.IOException;\n import java.io.InputStreamReader;\n import java.io.PrintWriter;\n import java.util.ArrayList;\n+import java.util.Arrays;\n import java.util.Iterator;\n import java.util.List;\n import java.util.Properties;\n@@ -33,6 +34,8 @@ import java.util.Vector;\n import com.izforge.izpack.Panel;\n import com.izforge.izpack.adaptator.IXMLElement;\n import com.izforge.izpack.installer.AutomatedInstallData;\n+import com.izforge.izpack.installer.ConsoleHelper;\n+import com.izforge.izpack.installer.ConsoleInstallHelper;\n import com.izforge.izpack.installer.PanelConsole;\n import com.izforge.izpack.installer.PanelConsoleHelper;\n import com.izforge.izpack.util.Debug;\n@@ -68,6 +71,8 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n     private static final String SET = \"set\";\n \n     private static final String TEXT = \"txt\";\n+    \n+    private static final String ID = \"id\";\n \n     private static final String SPEC = \"spec\";\n \n@@ -78,16 +83,28 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n     private static final String COMBO_FIELD = \"combo\";\n \n     private static final String STATIC_TEXT = \"staticText\";\n-\n+    \n+    private static final String TITLE_TEXT = \"title\";\n+\n+    private static final String SPACE_TEXT = \"space\";\n+    \n+    private static final String DIVIDER_TEXT = \"divider\";\n+    \n+    private static final String CHECK_FIELD = \"check\";\n+    \n     private static final String CHOICE = \"choice\";\n \n     private static final String VALUE = \"value\";\n \n     private static final String RADIO_FIELD = \"radio\";\n+    \n+    private static final String PASSWORD_FIELD = \"password\";\n \n     private static final String DESCRIPTION = \"description\";\n \n     private static final String TRUE = \"true\";\n+    \n+    private static final String FALSE = \"false\";\n \n     public List<Input> listInputs;\n \n@@ -103,7 +120,7 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n         Iterator<Input> inputIterator = listInputs.iterator();\n         while (inputIterator.hasNext())\n         {\n-            String strVariableName = ((Input) inputIterator.next()).strVariableName;\n+            String strVariableName = ((Input) inputIterator.next()).getVariableName();\n             String strVariableValue = p.getProperty(strVariableName);\n             if (strVariableValue != null)\n             {\n@@ -120,7 +137,7 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n         Iterator<Input> inputIterator = listInputs.iterator();\n         while (inputIterator.hasNext())\n         {\n-            printWriter.println(((Input) inputIterator.next()).strVariableName + \"=\");\n+            printWriter.println(((Input) inputIterator.next()).getVariableName() + \"=\");\n         }\n         return true;\n     }\n@@ -133,37 +150,14 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n         while (inputsIterator.hasNext())\n         {\n             Input input = inputsIterator.next();\n-            String text = input.strText;\n-            if (text != null)\n-            {\n-                System.out.println(text);\n-            }\n-            if (TEXT_FIELD.equals(input.strFieldType))\n-            {\n-                status = status && processTextField(input, idata);\n-            }\n-            else if (COMBO_FIELD.equals(input.strFieldType)\n-                    || RADIO_FIELD.equals(input.strFieldType))\n-            {\n-                status = status && processComboRadioField(input, idata);\n-            }\n-\n-        }\n-\n-        int i = askEndOfConsolePanel();\n-        if (i == 1)\n-        {\n-            return true;\n-        }\n-        else if (i == 2)\n-        {\n-            return false;\n-        }\n-        else\n-        {\n-            return runConsole(idata);\n+            try {\n+\t\t\t\tstatus = status && input.process(idata);\n+\t\t\t} catch (IOException e) {\n+\t\t\t\tthrow new RuntimeException(\"I/O error\", e);\n+\t\t\t} \n         }\n \n+        return continueQuitOrReboot(idata, this);\n     }\n \n     public boolean collectInputs(AutomatedInstallData idata)\n@@ -215,147 +209,10 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n             }\n             listInputs.add(getInputFromField(field));\n         }\n+        \n         return true;\n     }\n \n-    boolean processTextField(Input input, AutomatedInstallData idata)\n-    {\n-        String variable = input.strVariableName;\n-        String set;\n-        String fieldText;\n-        if ((variable == null) || (variable.length() == 0)) { return false; }\n-\n-        if (input.listChoices.size() == 0)\n-        {\n-            Debug.trace(\"Error: no spec element defined in file field\");\n-            return false;\n-        }\n-        set = input.strDefaultValue;\n-        if (set == null)\n-        {\n-            set = idata.getVariable(variable);\n-            if (set == null)\n-            {\n-                set = \"\";\n-            }\n-        }\n-        else\n-        {\n-            if (set != null && !\"\".equals(set))\n-            {\n-\n-                VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n-                set = vs.substitute(set, null);\n-            }\n-        }\n-\n-        fieldText = input.listChoices.get(0).strText;\n-        System.out.println(fieldText + \" [\" + set + \"] \");\n-        try\n-        {\n-            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n-            String strIn = br.readLine();\n-            if (!strIn.trim().equals(\"\"))\n-            {\n-                idata.setVariable(variable, strIn);\n-            }\n-            else\n-            {\n-                idata.setVariable(variable, set);\n-            }\n-        }\n-        catch (IOException e)\n-        {\n-            e.printStackTrace();\n-        }\n-        return true;\n-\n-    }\n-\n-    boolean processComboRadioField(Input input, AutomatedInstallData idata)\n-    {// TODO protection if selection not valid and no set value\n-        String variable = input.strVariableName;\n-        if ((variable == null) || (variable.length() == 0)) { return false; }\n-        String currentvariablevalue = idata.getVariable(variable);\n-        boolean userinput = false;\n-        List<Choice> lisChoices = input.listChoices;\n-        if (lisChoices.size() == 0)\n-        {\n-            Debug.trace(\"Error: no spec element defined in file field\");\n-            return false;\n-        }\n-        if (currentvariablevalue != null)\n-        {\n-            userinput = true;\n-        }\n-        for (int i = 0; i < lisChoices.size(); i++)\n-        {\n-            Choice choice = lisChoices.get(i);\n-            String value = choice.strValue;\n-            if (userinput)\n-            {\n-                if ((value != null) && (value.length() > 0) && (currentvariablevalue.equals(value)))\n-                {\n-                    input.iSelectedChoice = i;\n-                }\n-            }\n-            else\n-            {\n-                String set = choice.strSet;\n-                if (set != null)\n-                {\n-                    if (set != null && !\"\".equals(set))\n-                    {\n-                        VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n-                        set = vs.substitute(set, null);\n-                    }\n-                    if (set.equals(TRUE))\n-                    {\n-                        input.iSelectedChoice = i;\n-                    }\n-                }\n-            }\n-            System.out.println(i + \"  [\" + (input.iSelectedChoice == i ? \"x\" : \" \") + \"] \"\n-                    + (choice.strText != null ? choice.strText : \"\"));\n-        }\n-\n-        try\n-        {\n-            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n-            boolean bKeepAsking = true;\n-\n-            while (bKeepAsking)\n-            {\n-                System.out.println(\"input selection:\");\n-                String strIn = br.readLine();\n-                // take default value if default value exists and no user input\n-                if (strIn.trim().equals(\"\") && input.iSelectedChoice != -1)\n-                {\n-                    bKeepAsking = false;\n-                }\n-                int j = -1;\n-                try\n-                {\n-                    j = Integer.valueOf(strIn).intValue();\n-                }\n-                catch (Exception ex)\n-                {}\n-                // take user input if user input is valid\n-                if (j >= 0 && j < lisChoices.size())\n-                {\n-                    input.iSelectedChoice = j;\n-                    bKeepAsking = false;\n-                }\n-            }\n-        }\n-        catch (IOException e)\n-        {\n-            e.printStackTrace();\n-        }\n-        idata.setVariable(variable, input.listChoices.get(input.iSelectedChoice).strValue);\n-        return true;\n-\n-    }\n \n     public Input getInputFromField(IXMLElement field)\n     {\n@@ -365,11 +222,10 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n         {\n             String strText = null;\n             strText = field.getAttribute(TEXT);\n-            return new Input(strVariableName, null, null, STATIC_TEXT, strText, 0);\n+            return new StaticText(strVariableName, strText);\n         }\n         if (TEXT_FIELD.equals(strFieldType))\n         {\n-            List<Choice> choicesList = new ArrayList<Choice>();\n             String strFieldText = null;\n             String strSet = null;\n             String strText = null;\n@@ -384,9 +240,29 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n             {\n                 strFieldText = description.getAttribute(TEXT);\n             }\n-            choicesList.add(new Choice(strText, null, strSet));\n-            return new Input(strVariableName, strSet, choicesList, TEXT_FIELD, strFieldText, 0);\n-\n+            Choice choice = new Choice(strText, null, strSet);\n+            return new Text(strVariableName, true, strSet, choice, strFieldText);\n+        }\n+        else if (PASSWORD_FIELD.equals(strFieldType)) {\n+            IXMLElement spec = field.getFirstChildNamed(SPEC);\n+            String pwd1, pwd2;\n+            if (spec != null)\n+            {\n+            \tList<IXMLElement> pwdElements = field.getChildrenNamed(\"pwd\");\n+            \tif (pwdElements.size() != 2) {\n+            \t\tthrow new RuntimeException(\"Currently only two pwd values\" +\n+            \t\t\t\t\" are supported in a password field\");\n+            \t}\n+            \tpwd1 = pwdElements.get(0).getAttribute(\"txt\");\n+            \tpwd2 = pwdElements.get(1).getAttribute(\"txt\");\n+            \tif (pwd1 == null || pwd2 == null) {\n+            \t\tthrow new RuntimeException(\"Pwd elements need to specify \" +\n+            \t\t\t\t\"a text attribute in a password field\");\n+            \t}\n+            } else {\n+            \tthrow new RuntimeException(\"Password field needs specification\");\n+            }\n+            return new Password(strVariableName, pwd1, pwd2);\n         }\n         else if (COMBO_FIELD.equals(strFieldType) || RADIO_FIELD.equals(strFieldType))\n         {\n@@ -409,44 +285,384 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n                 choicesList.add(new Choice(choice.getAttribute(TEXT), choice.getAttribute(VALUE),\n                         choice.getAttribute(SET)));\n             }\n-            return new Input(strVariableName, null, choicesList, COMBO_FIELD, strFieldText, -1);\n+            return new Combo(strVariableName, choicesList, strFieldText);\n+            \n+//            return new Input(strVariableName, null, choicesList, COMBO_FIELD, strFieldText, -1);\n+        } \n+        else if (CHECK_FIELD.equals(strFieldType))\n+        {\n+            Description description = null;\n+            Spec spec = null;\n+        \t\n+        \tIXMLElement descriptionElem = field.getFirstChildNamed(DESCRIPTION);\n+        \tif (descriptionElem != null)\n+            {\n+                description = new Description(descriptionElem);\n+            }\n+        \t\n+        \tIXMLElement specElem = field.getFirstChildNamed(SPEC);\n+            if (specElem != null) {\n+            \tspec = new Spec(specElem);\n+            }\n+        \t\n+        \treturn new Check(strVariableName, spec, description);\n+        }\n+        else if (TITLE_TEXT.equals(strFieldType))\n+        {\n+            String strText = null;\n+            strText = field.getAttribute(TEXT);\n+            return new Title(strText);        \t\n+        } \n+        else if (SPACE_TEXT.equals(strFieldType)) \n+        {\n+        \treturn new Space();\n+        }\n+        else if (DIVIDER_TEXT.equals(strFieldType))\n+        {\n+        \n+        \treturn new Divider();\n         }\n         else\n         {\n-            System.out.println(strFieldType + \" field collection not implemented\");\n+        \tSystem.out.println(strFieldType + \" field collection not implemented\");\n \n         }\n         return null;\n     }\n \n-    public class Input\n-    {\n-\n-        public Input(String strVariableName, String strDefaultValue, List<Choice> listChoices,\n-                String strFieldType, String strText, int iSelectedChoice)\n-        {\n-            this.strVariableName = strVariableName;\n-            this.strDefaultValue = strDefaultValue;\n-            this.listChoices = listChoices;\n-            this.strFieldType = strFieldType;\n-            this.strText = strText;\n-            this.iSelectedChoice = iSelectedChoice;\n-        }\n-\n-        String strVariableName;\n-\n-        String strDefaultValue;\n+    \n+    abstract class Input {\n+    \t\n+    \tprotected ConsoleInstallHelper helper \n+    \t\t= ConsoleInstallHelper.getInstance();\n+    \t\n+    \tprivate final String variableName;\n+\n+    \tpublic String getVariableName() {\n+\t\t\treturn variableName;\n+\t\t}\n+\t\t\n+\t\tprotected Input(String variableName) {\n+    \t\tthis.variableName = variableName;\n+    \t}\n+\t\t\n+    \tabstract boolean process(AutomatedInstallData idata)\n+    \tthrows IOException;\n+    \n+    \t// string input, default is always valid\n+    \tprotected boolean isValid(String value) \n+    \t{\n+    \t\treturn true;\n+    \t}\n+    \t\n+    \tString inputValidValue() throws IOException {\n+    \t\tboolean isValidValue = false;\n+    \t\t\n+            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n+    \t\twhile (false == isValidValue) {\n+                String strIn = br.readLine();\n+                if (isValid(strIn))\n+                {\n+                \treturn strIn;\n+                } \n+                else \n+                {\n+                \tSystem.out.print(\"Invalid value. Try again: \");\n+                }\n+    \t\t}\n+    \t\t\n+    \t\t// should be unreachable in practice\n+    \t\treturn \"\";\n+    \t}\n+    \t\n+    \t\n+    }\n+    \n+    public class Text extends Input {\n+\t\tprivate final String strDefaultValue;\n+\t\tprotected final String text;\n+\t\tprivate final Choice choice;\n+\t\tprivate final boolean doesInput;\n+\n+\t\tpublic Text(String variableName, boolean doesInput,\n+\t\t\t\tString defaultValue, Choice choice, String text) {\n+\t\t\tsuper(variableName);\n+\t\t\tthis.doesInput = doesInput;\n+\t\t\tthis.strDefaultValue = defaultValue;\n+\t\t\tthis.choice = choice;\n+\t\t\tthis.text = text;\n+\t\t}\n+\n+\t\tboolean process(AutomatedInstallData idata) {\n+            String variable = getVariableName();\n+            String set;\n+            String fieldText;\n+            if (doesInput)\n+            \tif ((variable == null) || (variable.length() == 0)) \n+            \t{ \n+            \t\treturn false; \n+            \t}\n+\n+            set = strDefaultValue;\n+            if (set == null)\n+            {\n+                if (variable != null) {\n+                \tset = idata.getVariable(variable);\n+                }\n+                if (set == null)\n+                {\n+                    set = \"\";\n+                }\n+            }\n+            else\n+            {\n+                if (set != null && !\"\".equals(set))\n+                {\n+                    VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n+                    set = vs.substitute(set, null);\n+                }\n+            }\n \n-        List<Choice> listChoices;\n+            fieldText = (choice == null) ? text  : choice.strText;\n+            fieldText = helper.variables.expand(fieldText, idata);\n+            System.out.print(fieldText);\n+            if (doesInput) System.out.print(\" [\" + set + \"] \");\n+            System.out.println();\n+            \n+            if (doesInput) {\n+\t            try\n+\t            {\n+\t                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n+\t                String strIn = br.readLine();\n+\t                if (!strIn.trim().equals(\"\"))\n+\t                {\n+\t                    idata.setVariable(variable, strIn);\n+\t                }\n+\t                else\n+\t                {\n+\t                    idata.setVariable(variable, set);\n+\t                }\n+\t            }\n+\t            catch (IOException e)\n+\t            {\n+\t                e.printStackTrace();\n+\t            }\n+            }\n+            return true;\n \n-        String strFieldType;\n+\t\t}\n+    }\n+    \n+    class Password extends Input {\n+\n+\t\tprivate final String pwd1;\n+\t\tprivate final String pwd2;\n+\n+\t\tprotected Password(String variableName, String pwd1, String pwd2) {\n+\t\t\tsuper(variableName);\n+\t\t\tthis.pwd1 = pwd1;\n+\t\t\tthis.pwd2 = pwd2;\n+\t\t}\n+\n+\t\tboolean process(AutomatedInstallData idata) throws IOException {\n+\t\t\t\n+\t\t\tString input1 = null;\n+\t\t\tString input2 = null;\n+\t\t\t\n+\t\t\twhile (true) {\n+\t\t\t\tinput1 = helper.console.askForPassword(pwd1);\n+\t\t\t\tinput2 = helper.console.askForPassword(pwd2);\n+\t\t\t\t\n+\t\t\t\tif (input1 != null && input1.equals(input2)) \n+\t\t\t\t{\n+\t\t\t\t\tbreak; // we have two the same non-null passwords\n+\t\t\t\t} \n+\t\t\t\telse \n+\t\t\t\t{\n+\t\t\t\t\thelper.console.displayMessage(\"Please enter two \" +\n+\t\t\t\t\t\t\t\"non-empty passwords\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t\n+            idata.setVariable(getVariableName(), input1);\n+\t\t\t\n+\t\t\treturn true;\n+\t\t}\n+    }\n+    \n+    class StaticText extends Text {\n+    \tpublic StaticText(String strVariableName, String text) {\n+    \t\tsuper(strVariableName, false, null, null, text);\n+\t\t}\n+    }\n \n-        String strText;\n+    class Title extends Text {\n+    \tpublic Title(String text) {\n+\t\t\tsuper(null, false, null, null, text);\n+\t\t}\n \n-        int iSelectedChoice = -1;\n+\t\tboolean process(AutomatedInstallData idata) {\n+\t\t\tString expandedTxt = helper.variables.expand(text, idata);\n+\t\t\tSystem.out.println(\"*** \" + expandedTxt);\n+\t\t\treturn true;\n+\t\t}\n     }\n-\n-    public class Choice\n+    \n+    class Space extends Text {\n+    \tpublic Space() {\n+    \t\tsuper(null, false, null, null, \"\");\n+    \t}\n+    }\n+    \n+    class Divider extends Text {\n+    \tpublic Divider() {\n+    \t\tsuper(null, false, null, null, \"-------------------\");\n+    \t}\n+    }\n+    \n+    class Combo extends Input{\n+    \t\n+\t\tprivate final List<Choice> listChoices;\n+\t\tprivate int iSelectedChoice = -1;\n+\n+\t\tpublic Combo(String strVariableName, List<Choice> listChoices,\n+\t\t\t\tString strFieldText) {\n+\t\t\tsuper(strVariableName);\n+\t\t\tthis.listChoices = listChoices;\n+\t\t}\n+\n+\t\tboolean process(AutomatedInstallData idata) {\n+\t\t\t\n+\t\t\tString variable = getVariableName();\n+\t        if ((variable == null) || (variable.length() == 0)) { return false; }\n+\t        String currentvariablevalue = idata.getVariable(variable);\n+\t        boolean userinput = false;\n+\t        List<Choice> lisChoices = listChoices;\n+\t        if (lisChoices.size() == 0)\n+\t        {\n+\t            Debug.trace(\"Error: no spec element defined in file field\");\n+\t            return false;\n+\t        }\n+\t        if (currentvariablevalue != null)\n+\t        {\n+\t            userinput = true;\n+\t        }\n+\t        for (int i = 0; i < lisChoices.size(); i++)\n+\t        {\n+\t            Choice choice = lisChoices.get(i);\n+\t            String value = choice.strValue;\n+\t            if (userinput)\n+\t            {\n+\t                if ((value != null) && (value.length() > 0) && (currentvariablevalue.equals(value)))\n+\t                {\n+\t                    iSelectedChoice = i;\n+\t                }\n+\t            }\n+\t            else\n+\t            {\n+\t                String set = choice.strSet;\n+\t                if (set != null)\n+\t                {\n+\t                    if (set != null && !\"\".equals(set))\n+\t                    {\n+\t                        VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n+\t                        set = vs.substitute(set, null);\n+\t                    }\n+\t                    if (set.equals(TRUE))\n+\t                    {\n+\t                        iSelectedChoice = i;\n+\t                    }\n+\t                }\n+\t            }\n+\t            System.out.println(i + \"  [\" + (iSelectedChoice == i ? \"x\" : \" \") + \"] \"\n+\t                    + (choice.strText != null ? choice.strText : \"\"));\n+\t        }\n+\n+\t        try\n+\t        {\n+\t            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n+\t            boolean bKeepAsking = true;\n+\n+\t            while (bKeepAsking)\n+\t            {\n+\t                System.out.println(\"input selection:\");\n+\t                String strIn = br.readLine();\n+\t                // take default value if default value exists and no user input\n+\t                if (strIn.trim().equals(\"\") && iSelectedChoice != -1)\n+\t                {\n+\t                    bKeepAsking = false;\n+\t                }\n+\t                int j = -1;\n+\t                try\n+\t                {\n+\t                    j = Integer.valueOf(strIn).intValue();\n+\t                }\n+\t                catch (Exception ex)\n+\t                {}\n+\t                // take user input if user input is valid\n+\t                if (j >= 0 && j < lisChoices.size())\n+\t                {\n+\t                    iSelectedChoice = j;\n+\t                    bKeepAsking = false;\n+\t                }\n+\t            }\n+\t        }\n+\t        catch (IOException e)\n+\t        {\n+\t            e.printStackTrace();\n+\t        }\n+\t        idata.setVariable(variable, listChoices.get(iSelectedChoice).strValue);\n+\t        return true;\n+\t\t}\n+    \n+    }\n+ \n+    class Check extends Input {\n+    \tprivate final Spec spec;\n+\t\tprivate final Description description;\n+\n+\t\tpublic Check(String strVariableName, Spec spec, Description description) {\n+    \t\tsuper(strVariableName);\n+\t\t\tthis.spec = spec;\n+\t\t\tthis.description = description;\n+    \t}\n+\n+\t\tboolean process(AutomatedInstallData idata) \n+\t\tthrows IOException {\n+\t\t\tSystem.out.println(getInitialPrompt());\n+\t\t\tString input = inputValidValue();\n+\t\t\tidata.setVariable(getVariableName(), input);\n+\t\t\treturn true;\n+\t\t}\n+\t\t\n+\t\tprivate String getInitialPrompt() {\n+\t\t\tList<Object> choices = Arrays.asList(spec.getIsTrue(), spec.getIsFalse());\n+\t\t\tStringBuilder result = new StringBuilder();\n+\t\t\tif (description != null)\n+\t\t\t{\n+\t\t\t\tresult.append(description.getText() + \"\\n\");\n+\t\t\t}\n+\t\t\tresult.append(spec.getTxt() + \"\\n\");\n+\t\t\tresult.append(formatChoices(choices));\n+\t\t\treturn result.toString();\n+\t\t}\n+\t\t\n+\t\tprivate String formatChoices(Object ...choices) {\n+\t\t\tStringBuilder result = new StringBuilder();\n+\t\t\tfor (Object choice : choices) {\n+\t\t\t\tresult.append(choice);\n+\t\t\t}\n+\t\t\treturn result.toString();\n+\t\t}\n+\t\t\n+\t\tprotected boolean isValid(String input) {\n+\t\t\treturn spec.isTrue.equals(input) || spec.isFalse.equals(input);\n+\t\t}\n+\t\t\n+\t\t\n+    }\n+    \n+    class Choice\n     {\n \n         public Choice(String strText, String strValue, String strSet)\n@@ -457,9 +673,59 @@ public class UserInputPanelConsoleHelper extends PanelConsoleHelper implements P\n         }\n \n         String strText;\n-\n         String strValue;\n-\n         String strSet;\n+        \n+    }\n+    \n+    class Description {\n+\n+    \tprivate final String text;\n+\t\tprivate final String id;\n+\n+\t\tpublic String getText() {\n+\t\t\treturn text;\n+\t\t}\n+\n+\t\tpublic String getId() {\n+\t\t\treturn id;\n+\t\t}\n+\n+\t\tpublic Description(IXMLElement elem) {\n+    \t\ttext = elem.getAttribute(TEXT);\n+    \t\tid = elem.getAttribute(ID);\n+\t\t}\n+    }\n+    \n+    class Spec {\n+\n+    \tprivate final Object txt;\n+\t\tprivate final Object id;\n+\t\tprivate final Object isTrue;\n+\t\tprivate final Object isFalse;\n+\t\t\n+\t\tpublic Object getTxt() {\n+\t\t\treturn txt;\n+\t\t}\n+\n+\t\tpublic Object getId() {\n+\t\t\treturn id;\n+\t\t}\n+\n+\t\tpublic Object getIsTrue() {\n+\t\t\treturn isTrue;\n+\t\t}\n+\n+\t\tpublic Object getIsFalse() {\n+\t\t\treturn isFalse;\n+\t\t}\n+\n+\t\tpublic Spec(IXMLElement spec) {\n+\t\t\ttxt = spec.getAttribute(TEXT);\n+\t\t\tid = spec.getAttribute(ID);\n+\t\t\tisTrue = spec.getAttribute(TRUE);\n+\t\t\tisFalse = spec.getAttribute(FALSE);\n+        \t// set attribute - what for?\n+\t\t}\n     }\n }\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/install.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n\n<!--\nTigase Jabber/XMPP Server\nCopyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program. Look for COPYING file in the top folder.\nIf not, see http://www.gnu.org/licenses/.\n\n\nIzPack insallation file for the Tigase server.\nBased on the IzPack sample installation file.\n\nTo compile it :\n- go in the bin directory where you installed IzPack\n- call \"compile ../sample/install.xml -b ../sample\"\n\n$Rev: 1190 $\nLast modified by $Author: kobit $\n$Date: 2008-10-22 14:32:10 +0100 (Wed, 22 Oct 2008) $\n-->\n\n<installation version=\"1.0\">\n\n\t<!--\n\t\t\t The info section.\n\t\t\t The meaning of the tags should be natural ...\n\t-->\n\t<info>\n\t\t<appname>Tigase XMPP (Jabber) Server</appname>\n\t\t<appversion>${ENV[TIGVER]}</appversion>\n\t\t<authors>\n\t\t\t<author name=\"Artur Hefczyc\" email=\"artur.hefczyc@tigase.org\"/>\n\t\t\t<author name=\"Bartosz Małkowski\" email=\"bmalkowski@tigase.pl\"/>\n\t\t\t<author name=\"Wojciech Kapcia\" email=\"wojciech.kapcia@tigase.org\"/>\n\t\t\t<author name=\"Andrzej Wójcik\" email=\"andrzejw@tigase.org\"/>\n\t\t\t<author name=\"Wojciech Czubaszek\" email=\"wojciech.czubaszek@tigase.org\"/>\n\t\t\t<author name=\"Eric Dziewa\" email=\"eric.dziewa@tigase.org\"/>\n\t\t\t<author name=\"Jacek Predki\" email=\"jacek.predki@tigase.com\"/>\n\t\t\t<author name=\"Piotr Kontek\" email=\"\"/>\n\t\t\t<author name=\"Alexander Gnauck\" email=\"\"/>\n\t\t\t<author name=\"Tomasz Sterna\" email=\"\"/>\n\t\t\t<author name=\"Mateusz Fiołka\" email=\"\"/>\n\t\t\t<author name=\"David Pache\" email=\"\"/>\n\t\t\t<author name=\"Peter Sandström\" email=\"\"/>\n\t\t\t<author name=\"Yonas Yanfa\" email=\"\"/>\n\t\t</authors>\n\t\t<url>http://www.tigase.org/</url>\n\t\t<appsubpath>Tigase-$APP_VER</appsubpath>\n\t\t<javaversion>1.6</javaversion>\n\t\t<requiresjdk>no</requiresjdk>\n\t</info>\n\n\t<jar src=\"jars/postgresql.jar\"/>\n\t<jar src=\"jars/mysql-connector-java.jar\"/>\n\t<jar src=\"jars/derby.jar\"/>\n\t<jar src=\"jars/jtds.jar\"/>\n\t<jar src=\"jars/tigase-server.jar\"/>\n\n\t<native type=\"izpack\" name=\"ShellLink.dll\"/>\n\t<native type=\"izpack\" name=\"ShellLink_x64.dll\"/>\n\n\t<variables>\n\t\t<variable name=\"InstallerFrame.logfilePath\" value=\"$INSTALL_PATH/install.log\"/>\n\t\t<variable name=\"JDKPathPanel.minVersion\" value=\"1.6\" />\n\t\t<variable name=\"JDKPathPanel.skipIfValid\" value=\"yes\"/>\n\t\t<variable name=\"DerbyDBPath.windows\" value=\"${INSTALL_PATH}\\tigasedb\"/>\n\t\t<variable name=\"DerbyDBPath.mac\" value=\"${INSTALL_PATH}/tigasedb\"/>\n\t\t<variable name=\"DerbyDBPath.unix\" value=\"${INSTALL_PATH}/tigasedb\"/>\n\t\t<variable name=\"mucComponent\" value=\"on\"/>\n\t\t<variable name=\"socks5Component\" value=\"on\"/>\n\t\t<variable name=\"PubSubComponent\" value=\"on\"/>\n\t\t<variable name=\"messageArchiveComponent\" value=\"on\"/>\n\t\t<variable name=\"clusterMode\" value=\"true\"/>\n\t\t<variable name=\"acsName\" value=\"\"/>\n\t\t<variable name=\"jarsDir\" value=\"jars\"/>\n<!--\t\t<variable name=\"JDKPath\" value=\"$JAVA_HOME\"/> -->\n\t</variables>\n\n\t<dynamicvariables>\n\t\t<variable name=\"messageArchivePlugin\" value=\"message-archive-xep-0136\" condition=\"messageArchive\" />\n\t\t<variable name=\"messageArchivePlugin\" value=\"off\" condition=\"!messageArchive\" />\n\n\t\t<variable name=\"osgiEnabled\" value=\"true\" condition=\"izpack.selected.osgi\" />\n\t\t<variable name=\"osgiEnabled\" value=\"false\" condition=\"!izpack.selected.osgi\" />\n\t</dynamicvariables>\n\t<conditions>\n\t\t<condition type=\"variable\" id=\"installSelected\">\n\t\t\t<name>serverInstall</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"configSelected\">\n\t\t\t<name>serverConfig</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"advancedSelected\">\n\t\t\t<name>advancedConfig</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"mysqlSelected\">\n\t\t\t<name>dbType</name>\n\t\t\t<value>MySQL</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"pgsqlSelected\">\n\t\t\t<name>dbType</name>\n\t\t\t<value>PostgreSQL</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"sqlserverSelected\">\n\t\t\t<name>dbType</name>\n\t\t\t<value>SQLServer</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"derbySelected\">\n\t\t\t<name>dbType</name>\n\t\t\t<value>Derby</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"authDBSelected\">\n\t\t\t<name>authDB</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"messageArchive\">\n\t\t\t<name>messageArchiveComponent</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"acsSelected\">\n\t\t\t<name>acsComponent</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"acsMUCSelected\">\n\t\t\t<name>acsMUCComponent</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t\t<condition type=\"variable\" id=\"acsPubSubSelected\">\n\t\t\t<name>acsPubSubComponent</name>\n\t\t\t<value>on</value>\n\t\t</condition>\n\t</conditions>\n\n\t<!--\n\t\t\tThe gui preferences indication.\n\t\t\tSets the installer window to 800x600. It will not be able to change the size.\n\t-->\n\t<guiprefs width=\"1024\" height=\"700\" resizable=\"yes\">\n\t\t<modifier key=\"useButtonIcons\" value=\"yes\"/>\n\t\t<modifier key=\"useLabelIcons\" value=\"no\"/>\n\t\t<modifier key=\"labelGap\" value=\"2\"/>\n\t\t<modifier key=\"layoutAnchor\" value=\"NORTH\"/>\n\t\t<modifier key=\"useHeadingPanel\" value=\"no\"/>\n\t\t<modifier key=\"headingImageOnLeft\" value=\"no\"/>\n\t\t<modifier key=\"headingLineCount\" value=\"1\"/>\n\t\t<modifier key=\"headingFontSize\" value=\"1.5\"/>\n\t\t<modifier key=\"headingBackgroundColor\" value=\"0x00ffffff\"/>\n\t\t<modifier key=\"headingPanelCounter\" value=\"progressbar\"/>\n\t\t<modifier key=\"headingPanelCounterPos\" value=\"inNavigationPanel\"/>\n\t</guiprefs>\n\t<!--\n\t\t\tThe locale section.\n\t\t\tAsks here to include the English and Polish langpacks.\n\t-->\n\t<locale>\n\t\t<langpack iso3=\"eng\"/>\n<!-- \t\t<langpack iso3=\"pol\"/> -->\n\t</locale>\n\n\t<!--\n\t\t\tThe resources section.\n\t\t\tThe ids must be these ones if you want to use the LicencePanel and/or the InfoPanel.\n\t-->\n\t<resources>\n\t\t<res id=\"HTMLInfoPanel.info\" src=\"package.html\"/>\n\t\t<res id=\"HTMLLicencePanel.licence\" src=\"License.html\"/>\n\t\t<res id=\"TigaseLogo\" src=\"src/main/izpack/resources/pics/tiger.png\"/>\n\n\t\t<!--images-->\n\t\t<res id=\"Installer.image\"\n\t\t\t\t src=\"src/main/izpack/resources/pics/tigase-5-1-0-install-logo.png\"/>\n\t\t<res id=\"Heading.image\" src=\"src/main/izpack/resources/pics/tiger.png\"/>\n\t\t<res id=\"JavaPowered.image\" src=\"src/main/izpack/resources/pics/Java_powered_logo_rgb.png\"/>\n\t\t<res id=\"SolarisReady.image\" src=\"src/main/izpack/resources/pics/solaris_ready.png\"/>\n\t\t<res id=\"Tiger.image\" src=\"src/main/izpack/resources/pics/tiger.png\"/>\n\n\t\t<res id=\"userInputSpec.xml\" src=\"src/main/izpack/userInputSpec.xml\" />\n\t\t<res id=\"packsLang.xml\" src=\"src/main/izpack/resources/packsLang.xml\"/>\n\t\t<res id=\"panelsLangPack.xml\" src=\"src/main/izpack/resources/panelsLangPack.xml\"/>\n\t\t<res id=\"shortcutSpec.xml\" src=\"src/main/izpack/shortcutSpec.xml\"/>\n\t\t<res id=\"Unix_shortcutSpec.xml\" src=\"src/main/izpack/Unix_shortcutSpec.xml\"/>\n\t\t<res id=\"RegistrySpec.xml\" src=\"src/main/izpack/RegistrySpec.xml\"/>\n\t\t<res id=\"TargetPanel.dir.windows\"\n\t\t\t\t src=\"src/main/izpack/resources/target_windows.dir\"/>\n\n\t\t<res id=\"mysql-installer-create-db\" src=\"database/mysql-installer-create-db.sql\"/>\n\t\t<res id=\"mysql-installer-post\" src=\"database/mysql-installer-post.sql\"/>\n\t\t<res id=\"mysql-schema-4-schema\" src=\"database/mysql-schema-4-schema.sql\"/>\n\t\t<res id=\"mysql-schema-4-sp\" src=\"database/mysql-schema-4-sp.sql\"/>\n\t\t<res id=\"mysql-schema-4-props\" src=\"database/mysql-schema-4-props.sql\"/>\n\t\t<res id=\"mysql-schema-5-1-schema\" src=\"database/mysql-schema-5-1-schema.sql\"/>\n\t\t<res id=\"mysql-schema-5-1-sp\" src=\"database/mysql-schema-5-1-sp.sql\"/>\n\t\t<res id=\"mysql-schema-5-1-props\" src=\"database/mysql-schema-5-1-props.sql\"/>\n\t\t<res id=\"mysql-schema-7-1-schema\" src=\"database/mysql-schema-7-1-schema.sql\"/>\n\t\t<res id=\"mysql-schema-7-1-sp\" src=\"database/mysql-schema-7-1-sp.sql\"/>\n\t\t<res id=\"mysql-schema-7-1-props\" src=\"database/mysql-schema-7-1-props.sql\"/>\n\t\t<res id=\"mysql-schema-upgrade-to-4\" src=\"database/mysql-schema-upgrade-to-4.sql\"/>\n\t\t<res id=\"mysql-schema-upgrade-to-5-1\" src=\"database/mysql-schema-upgrade-to-5-1.sql\"/>\n\t\t<res id=\"mysql-schema-upgrade-to-7-1\" src=\"database/mysql-schema-upgrade-to-7-1.sql\"/>\n\n\t\t<res id=\"postgresql-installer-create-db\" src=\"database/postgresql-installer-create-db.sql\"/>\n\t\t<res id=\"postgresql-installer-post\" src=\"database/postgresql-installer-post.sql\"/>\n\t\t<res id=\"postgresql-schema-4-schema\" src=\"database/postgresql-schema-4-schema.sql\"/>\n\t\t<res id=\"postgresql-schema-4-sp\" src=\"database/postgresql-schema-4-sp.sql\"/>\n\t\t<res id=\"postgresql-schema-4-props\" src=\"database/postgresql-schema-4-props.sql\"/>\n\t\t<res id=\"postgresql-schema-5-1-schema\" src=\"database/postgresql-schema-5-1-schema.sql\"/>\n\t\t<res id=\"postgresql-schema-5-1-sp\" src=\"database/postgresql-schema-5-1-sp.sql\"/>\n\t\t<res id=\"postgresql-schema-5-1-props\" src=\"database/postgresql-schema-5-1-props.sql\"/>\n\t\t<res id=\"postgresql-schema-7-1-schema\" src=\"database/postgresql-schema-7-1-schema.sql\"/>\n\t\t<res id=\"postgresql-schema-7-1-sp\"     src=\"database/postgresql-schema-7-1-sp.sql\"/>\n\t\t<res id=\"postgresql-schema-7-1-props\"  src=\"database/postgresql-schema-7-1-props.sql\"/>\n\t\t<res id=\"postgresql-schema-upgrade-to-4\" src=\"database/postgresql-schema-upgrade-to-4.sql\"/>\n\t\t<res id=\"postgresql-schema-upgrade-to-5-1\" src=\"database/postgresql-schema-upgrade-to-5-1.sql\"/>\n\t\t<res id=\"postgresql-schema-upgrade-to-7-1\" src=\"database/postgresql-schema-upgrade-to-7-1.sql\"/>\n\n\t\t<res id=\"derby-installer-create-db\" src=\"database/derby-installer-create-db.sql\"/>\n\t\t<res id=\"derby-installer-post\" src=\"database/derby-installer-post.sql\"/>\n\t\t<res id=\"derby-schema-4-schema\" src=\"database/derby-schema-4-schema.sql\"/>\n\t\t<res id=\"derby-schema-4-sp\" src=\"database/derby-schema-4-sp.sql\"/>\n\t\t<res id=\"derby-schema-4-props\" src=\"database/derby-schema-4-props.sql\"/>\n\t\t<res id=\"derby-schema-5-1-schema\" src=\"database/derby-schema-5-1-schema.sql\"/>\n\t\t<res id=\"derby-schema-5-1-sp\" src=\"database/derby-schema-5-1-sp.sql\"/>\n\t\t<res id=\"derby-schema-5-1-props\" src=\"database/derby-schema-5-1-props.sql\"/>\n\t\t<res id=\"derby-schema-7-1-schema\" src=\"database/derby-schema-7-1-schema.sql\"/>\n\t\t<res id=\"derby-schema-7-1-sp\"     src=\"database/derby-schema-7-1-sp.sql\"/>\n\t\t<res id=\"derby-schema-7-1-props\"  src=\"database/derby-schema-7-1-props.sql\"/>\n\t\t<res id=\"derby-schema-upgrade-to-5-1\" src=\"database/derby-schema-upgrade-to-5-1.sql\"/>\n\t\t<res id=\"derby-schema-upgrade-to-7-1\" src=\"database/derby-schema-upgrade-to-7-1.sql\"/>\n\n\t\t<res id=\"sqlserver-installer-create-db\" src=\"database/sqlserver-installer-create-db.sql\"/>\n\t\t<res id=\"sqlserver-installer-post\" src=\"database/sqlserver-installer-post.sql\"/>\n\t\t<res id=\"sqlserver-schema-5-1-schema\" src=\"database/sqlserver-schema-5-1-schema.sql\"/>\n\t\t<res id=\"sqlserver-schema-5-1-sp\" src=\"database/sqlserver-schema-5-1-sp.sql\"/>\n\t\t<res id=\"sqlserver-schema-5-1-props\" src=\"database/sqlserver-schema-5-1-props.sql\"/>\n\t\t<res id=\"sqlserver-schema-7-1-schema\" src=\"database/sqlserver-schema-7-1-schema.sql\"/>\n\t\t<res id=\"sqlserver-schema-7-1-sp\"     src=\"database/sqlserver-schema-7-1-sp.sql\"/>\n\t\t<res id=\"sqlserver-schema-7-1-props\"  src=\"database/sqlserver-schema-7-1-props.sql\"/>\n\t\t<res id=\"sqlserver-schema-upgrade-to-7-1\" src=\"database/sqlserver-schema-upgrade-to-7-1.sql\"/>\n\n\t\t<!-- Socks5 component schema files -->\n\t\t<res id=\"derby-socks5-schema\" src=\"database/derby-socks5-schema.sql\"/>\n\t\t<res id=\"postgresql-socks5-schema\" src=\"database/postgresql-socks5-schema.sql\"/>\n\t\t<res id=\"mysql-socks5-schema\" src=\"database/mysql-socks5-schema.sql\"/>\n\t\t<res id=\"sqlserver-socks5-schema\" src=\"database/sqlserver-socks5-schema.sql\"/>\n\n\t\t<!-- PubSub component schema files -->\n\t\t<res id=\"derby-pubsub-schema-3.0.0\" src=\"database/derby-pubsub-schema-3.0.0.sql\"/>\n\t\t<res id=\"derby-pubsub-schema-3.1.0\" src=\"database/derby-pubsub-schema-3.1.0.sql\"/>\n\t\t<res id=\"derby-pubsub-schema-3-2\" src=\"database/derby-pubsub-schema-3.2.0.sql\"/>\n\t\t<res id=\"mysql-pubsub-schema-3.0.0\" src=\"database/mysql-pubsub-schema-3.0.0.sql\"/>\n\t\t<res id=\"mysql-pubsub-schema-3.1.0\" src=\"database/mysql-pubsub-schema-3.1.0.sql\"/>\n\t\t<res id=\"mysql-pubsub-schema-3-2\" src=\"database/mysql-pubsub-schema-3.2.0.sql\"/>\n\t\t<res id=\"sqlserver-pubsub-schema-3.0.0\" src=\"database/sqlserver-pubsub-schema-3.0.0.sql\"/>\n\t\t<res id=\"sqlserver-pubsub-schema-3.1.0\" src=\"database/sqlserver-pubsub-schema-3.1.0.sql\"/>\n\t\t<res id=\"sqlserver-pubsub-schema-3-2\" src=\"database/sqlserver-pubsub-schema-3.2.0.sql\"/>\n\t\t<res id=\"postgresql-pubsub-schema-3.0.0\" src=\"database/postgresql-pubsub-schema-3.0.0.sql\"/>\n\t\t<res id=\"postgresql-pubsub-schema-3.1.0\" src=\"database/postgresql-pubsub-schema-3.1.0.sql\"/>\n\t\t<res id=\"postgresql-pubsub-schema-3-2\" src=\"database/postgresql-pubsub-schema-3.2.0.sql\"/>\n\n\n\t</resources>\n\n\t<!--\n\t\t\tThe panels section.\n\t\t\tWe indicate here which panels we want to use. The order will be respected.\n\t-->\n\t\t<panels>\n\t\t\t<panel classname=\"CheckedHelloPanel\" id=\"CheckedHelloPanel.id\"/>\n\t\t\t<panel classname=\"TigaseJDKPathPanel\" id=\"TigaseJDKPathPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" id=\"InstallConfigPanel.id\"/>\n\t\t\t<panel classname=\"HTMLInfoPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"HTMLReadmePanel.id\"/>\n\t\t\t<panel classname=\"HTMLLicencePanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"HTMLLicensePanel.id\"/>\n\t\t\t<panel classname=\"TargetPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"TargetPanel.id\"/>\n<!-- \t\t\t<panel classname=\"InstallationGroupPanel\" condition=\"installSelected\" -->\n<!-- \t\t\t\t\t\t id=\"InstallationGroupPanel.id\"/>> -->\n\t\t\t<panel classname=\"PacksPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"PacksPanel.id\"/>\n\t\t\t<panel classname=\"SummaryPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"SummaryPanel.id\"/>\n\t\t\t<panel classname=\"InstallPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"InstallPanel.id\"/>\n\t\t\t<panel classname=\"ShortcutPanel\" condition=\"installSelected\"\n\t\t\t\t\t\t id=\"ShortcutPanel.id\"/>\n\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"!installSelected\"\n\t\t\t\t\t\t id=\"InstallationPathForConfigPanel.id\"/>\n\n\t\t\t<panel classname=\"TigaseConfigLoadPanel\" condition=\"configSelected\"\n\t\t\t\t\t\t id=\"TigaseConfigLoadPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"configSelected\"\n\t\t\t\t\t\t id=\"BasicConfigurationPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"advancedSelected\"\n\t\t\t\t\t\t id=\"AdvancedConfigurationPanel.id\"/>\n\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"acsSelected|acsMUCSelected|acsPubSubSelected\"\n\t\t\t\t\t\t id=\"AdvancedClusteringStrategyPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"sqlserverSelected\"\n\t\t\t\t\t\t id=\"SqlServerPanel.id\"/>\n\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"advancedSelected\"\n\t\t\t\t\t\t id=\"PluginsListPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"mysqlSelected|pgsqlSelected|sqlserverSelected\"\n\t\t\t\t\t\t id=\"DatabaseConfigurationPanel.id\"/>\n\t\t\t<panel classname=\"DerbyPathPanel\" condition=\"derbySelected\"\n\t\t\t\t\t\t id=\"DerbyPathPanel.id\"/>\n\t\t\t<panel classname=\"UserInputPanel\" condition=\"authDBSelected\"\n\t\t\t\t\t\t id=\"AuthenticationDatabasePanel.id\"/>\n\t\t\t<panel classname=\"TigaseConfigSavePanel\" condition=\"configSelected\"\n\t\t\t\t\t\t id=\"TigaseConfigSavePanel.id\"/>\n\t\t\t<panel classname=\"TigaseDBCheckPanel\" condition=\"configSelected\"\n\t\t\t\t\t\t id=\"TigaseDBCheckPanel.id\"/>\n\t\t\t<panel classname=\"FinishPanel\" id=\"FinishPanel.id\"/>\n\t\t</panels>\n\n\t\t<!--\n\t\t\t\tThe packs section.\n\t\t\t\tWe specify here our packs.\n\t\t-->\n    <packs>\n\t\t\t<pack name=\"Base\" required=\"yes\">\n\t\t\t\t<description>The base files</description>\n\t\t\t\t<file src=\"etc/init.properties\" targetdir=\"$INSTALL_PATH/etc\"\n\t\t\t\t\t\t\toverride=\"askfalse\"/>\n\t\t\t\t<fileset dir=\".\" targetdir=\"$INSTALL_PATH\">\n\t\t\t\t\t<include name=\"package.html\"/>\n\t\t\t\t\t<include name=\"License.html\"/>\n\t\t\t\t\t<include name=\"Changelog\"/>\n\t\t\t\t\t<include name=\"etc/tigase.conf\"/>\n\t\t\t\t\t<include name=\"certs/rsa-keystore\"/>\n\t\t\t\t\t<include name=\"certs/truststore\"/>\n\t\t\t\t\t<include name=\"certs/localhost.pem\"/>\n\t\t\t\t\t<include name=\"logs\"/>\n\t\t\t\t\t<include name=\"database/*.sql\"/>\n\t\t\t\t\t<include name=\"database/*.schema\"/>\n<!-- \t\t\t\t\t<exclude name=\"logs/*.log*\"/> -->\n\t\t\t\t\t<include name=\"etc/jmx.access\"/>\n\t\t\t\t\t<include name=\"etc/jmx.password\"/>\"\n\t\t\t\t\t<include name=\"etc/cross-domain-policy.xml\"/>\"\n\t\t\t\t\t<include name=\"etc/bosh-extra-headers.txt\"/>\"\n\t\t\t\t\t<include name=\"etc/cross-domain-policy.xml\"/>\"\n\t\t\t\t\t<include name=\"etc/client-access-policy.xml\"/>\"\n\t\t\t\t\t<include name=\"etc/logback.xml\"/>\"\n\t\t\t\t\t<include name=\"etc/snmp.acl\"/>\"\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"tigase-server.jar\"/>\n\t\t\t\t</fileset>\n\n\t\t\t\t<parsable targetfile=\"$INSTALL_PATH/etc/init.properties\"/>\n\t\t\t\t<parsable targetfile=\"$INSTALL_PATH/etc/tigase.conf\"/>\n\t\t\t</pack>\n\n\n\t\t\t<pack name=\"Unix Files\" required=\"yes\">\n\t\t\t\t<os family=\"unix\"/>\n\t\t\t\t<description>Files needed to run the server on Unix like systems</description>\n\t\t\t\t<fileset dir=\".\" targetdir=\"$INSTALL_PATH\">\n\t\t\t\t\t<include name=\"scripts/config.sh\"/>\n\t\t\t\t\t<include name=\"scripts/repo.sh\"/>\n\t\t\t\t\t<include name=\"scripts/tigase.sh\"/>\n\t\t\t\t\t<include name=\"scripts/mandriva/**/*\"/>\n\t\t\t\t\t<include name=\"scripts/gentoo/**/*\"/>\n\t\t\t\t\t<include name=\"scripts/redhat/**/*\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<executable targetfile=\"${INSTALL_PATH}/scripts/tigase.sh\"/>\n\t\t\t\t<executable targetfile=\"${INSTALL_PATH}/scripts/repo.sh\"/>\n\t\t\t\t<executable targetfile=\"${INSTALL_PATH}/scripts/config.sh\"/>\n\t\t\t\t<singlefile src=\"src/main/resources/pictures/Tigase16x16.png\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/icons/Tigase16x16.png\"/>\n\t\t\t\t<singlefile src=\"src/main/resources/pictures/Tigase32x32.png\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/icons/Tigase32x32.png\"/>\n\t\t\t\t<singlefile src=\"src/main/resources/pictures/Tigase48x48.png\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/icons/Tigase48x48.png\"/>\n\t\t\t</pack>\n\t\t\t<pack name=\"Windows Files\" required=\"yes\">\n\t\t\t\t<os family=\"windows\"/>\n\t\t\t\t<description>Files needed to run the server in MS Windows platform</description>\n\t\t\t\t<singlefile src=\"win-stuff/wrapper/wrapper.exe\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"${INSTALL_PATH}/wrapper.exe\"/>\n\t\t\t\t<singlefile src=\"win-stuff/wrapper/wrapper.conf\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"${INSTALL_PATH}/wrapper.conf\"/>\n\n\t\t\t\t<singlefile src=\"win-stuff/wrapper/wrapper.dll\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/${jarsDir}/wrapper.dll\"/>\n\t\t\t\t<singlefile src=\"win-stuff/wrapper/wrapper.jar\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/${jarsDir}/wrapper.jar\"/>\n\n\t\t\t\t<singlefile src=\"win-stuff/scripts/InstallTigaseService.bat\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/InstallTigaseService.bat\"/>\n\t\t\t\t<singlefile src=\"win-stuff/scripts/Run.bat\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/Run.bat\"/>\n\t\t\t\t<singlefile src=\"win-stuff/scripts/Tigase.bat\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/Tigase.bat\"/>\n\t\t\t\t<singlefile src=\"win-stuff/scripts/UninstallTigaseService.bat\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/UninstallTigaseService.bat\"/>\n\t\t\t\t<singlefile src=\"win-stuff/Tigase.ico\"\n\t\t\t\t\t\t\t\t\t\ttarget=\"$INSTALL_PATH/Tigase.ico\"/>\n\t\t\t</pack>\n\t\t\t<pack name=\"Docs\" required=\"no\">\n\t\t\t\t<description>The documentation</description>\n\t\t\t\t<fileset dir=\".\" targetdir=\"${INSTALL_PATH}\">\n\t\t\t\t\t<include name=\"docs/**/*\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"Extras\" required=\"no\" preselected=\"yes\">\n\t\t\t\t<description>Extras libraries, MUC, PubSub, STUN, Socks5, Message Archiving, ACS</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"tigase-muc.jar\"/>\n\t\t\t\t\t<include name=\"tigase-pubsub.jar\"/>\n\t\t\t\t\t<include name=\"tigase-pubsub-2.2.0.jar.old\"/>\n\t\t\t\t\t<include name=\"tigase-extras.jar\"/>\n\t\t\t\t\t<include name=\"tigase-stun.jar\"/>\n\t\t\t\t\t<include name=\"jstun.jar\"/>\n\t\t\t\t\t<include name=\"tigase-socks5.jar\"/>\n\t\t\t\t\t<include name=\"tigase-message-archiving.jar\"/>\n\t\t\t\t\t<include name=\"jdmkrt.jar\"/>\n\t\t\t\t\t<include name=\"hamcrest-core.jar\"/>\n\t\t\t\t\t<include name=\"tigase-acs.jar\"/>\n\t\t\t\t\t<include name=\"tigase-acs-muc.jar\"/>\n\t\t\t\t\t<include name=\"tigase-acs-pubsub.jar\"/>\n\t\t\t\t\t<include name=\"licence-lib.jar\"/>\n\t\t\t\t\t<include name=\"tigase-stats-collector-library.jar\"/>\n\t\t\t\t\t<include name=\"tigase-stats-collector-provider.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\n\t\t\t<pack name=\"Groovy scripting\" required=\"no\">\n\t\t\t\t<description>Various Groovy scripts extending server functionality</description>\n\t\t\t\t<fileset dir=\"src/main/groovy/tigase/admin\" targetdir=\"$INSTALL_PATH/scripts/admin\">\n\t\t\t\t\t<include name=\"*.*\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"scripts/admin\" targetdir=\"$INSTALL_PATH/scripts/admin\">\n\t\t\t\t\t<include name=\"*.*\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"groovy-all.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\n\t\t\t<pack name=\"Derby Database (DB included)\" required=\"no\" preselected=\"yes\">\n<!-- \t\t\t\t\t\tinstallGroups=\"Derby Database\"> -->\n\t\t\t\t<description>Derby database (included) and JDBC driver</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"derby.jar\"/>\n\t\t\t\t\t<include name=\"derbytools.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"MySQL Database driver (DB not included)\" required=\"no\" preselected=\"yes\">\n<!-- \t\t\t\t\t\tinstallGroups=\"MySQL Database\"> -->\n\t\t\t\t<description>MySQL JDBC driver (MySQL has to be installed separately)</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"mysql-connector-java.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"PostgreSQL Database driver (DB not included)\" required=\"no\" preselected=\"yes\">\n<!-- \t\t\t\t\t\tinstallGroups=\"PostgreSQL Database\"> -->\n\t\t\t\t<description>PostgreSQL JDBC driver (PostgreSQL has to be installed separately)</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"postgresql.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"SQL Server Database driver (DB not included)\" required=\"no\" preselected=\"yes\">\n<!-- \t\t\t\t\t\tinstallGroups=\"SQL Server Database\"> -->\n\t\t\t\t<description>SQL Server JDBC driver (SQL Server has to be installed separately)</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"jtds.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\n\t\t\t<pack name=\"MongoDB Database support (DB not included)\" required=\"no\" preselected=\"yes\">\n<!-- \t\t\t\t\t\tinstallGroups=\"SQL Server Database\"> -->\n\t\t\t\t<description>Libraries need to use MongoDB from Tigase (includes driver)</description>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"$INSTALL_PATH/${jarsDir}\">\n\t\t\t\t\t<include name=\"mongo-java-driver.jar\"/>\n\t\t\t\t\t<include name=\"tigase-mongodb.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\n\t\t\t<pack name=\"OSGi dependencies\" required=\"no\" preselected=\"no\" id=\"osgi\">\n\t\t\t\t<description>If you intend to run Tigase in OSGi mode you need additional libraries. Enabling this Pack will also setup configuration files to start Tigase XMPP server in OSGi mode.</description>\n\t\t\t\t<fileset dir=\"./conf\" targetdir=\"${INSTALL_PATH}/conf\">\n\t\t\t\t\t<include name=\"config.properties\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"./etc\" targetdir=\"${INSTALL_PATH}/etc\">\n\t\t\t\t\t<include name=\"logback.xml\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"${INSTALL_PATH}/${jarsDir}\">\n\t\t\t\t\t<include name=\"org.osgi.core.jar\"/>\n\t\t\t\t\t<include name=\"org.apache.felix.bundlerepository.jar\"/>\n\t\t\t\t\t<include name=\"org.apache.felix.configadmin.jar\"/>\n\t\t\t\t\t<include name=\"org.apache.felix.shell.jar\"/>\n\t\t\t\t\t<include name=\"org.apache.felix.shell.remote.jar\"/>\n\t\t\t\t\t<include name=\"org.apache.felix.main.jar\"/>\n\t\t\t\t\t<include name=\"jetty-osgi-boot.jar\"/>\n\t\t\t\t\t<include name=\"logback-classic.jar\"/>\n\t\t\t\t\t<include name=\"logback-core.jar\"/>\n\t\t\t\t\t<include name=\"slf4j-api.jar\"/>\n\t\t\t\t\t<include name=\"jul-to-slf4j.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"HTTP API Component\" required=\"no\" preselected=\"no\">\n\t\t\t\t<description>Interface for the service administration, monitoring and exchange data between Tigase and external system</description>\n\t\t\t\t<fileset dir=\"./etc\" targetdir=\"${INSTALL_PATH}/etc\">\n\t\t\t\t\t<include name=\"tigase-http-context.xml\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\".\" targetdir=\"${INSTALL_PATH}\" defaultexcludes=\"yes\">\n\t\t\t\t\t<include name=\"scripts/rest/**/*\"/>\n\t\t\t\t</fileset>\n\t\t\t\t<fileset dir=\"./jars\" targetdir=\"${INSTALL_PATH}/${jarsDir}\">\n\t\t\t\t\t<include name=\"jetty-osgi-boot.jar\"/>\n\t\t\t\t\t<include name=\"tigase-http-api.jar\"/>\n\t\t\t\t\t<include name=\"javax.servlet-api.jar\"/>\n\t\t\t\t\t<include name=\"tigase-web-ui.war\"/>\n\t\t\t\t\t<include name=\"javax.servlet.jar\"/>\n\t\t\t\t\t<include name=\"jetty-continuation.jar\"/>\n\t\t\t\t\t<include name=\"jetty-deploy.jar\"/>\n\t\t\t\t\t<include name=\"jetty-http.jar\"/>\n\t\t\t\t\t<include name=\"jetty-io.jar\"/>\n\t\t\t\t\t<include name=\"jetty-security.jar\"/>\n\t\t\t\t\t<include name=\"jetty-server.jar\"/>\n\t\t\t\t\t<include name=\"jetty-servlet.jar\"/>\n\t\t\t\t\t<include name=\"jetty-util.jar\"/>\n\t\t\t\t\t<include name=\"jetty-webapp.jar\"/>\n\t\t\t\t\t<include name=\"jetty-xml.jar\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t\t<pack name=\"Sources\" required=\"no\" preselected=\"no\">\n\t\t\t\t<description>The server source files, tools and libraries sources are not included</description>\n\t\t\t\t<fileset dir=\".\" targetdir=\"${INSTALL_PATH}\" defaultexcludes=\"yes\">\n\t\t\t\t\t<include name=\"src/**/*\"/>\n\t\t\t\t</fileset>\n\t\t\t</pack>\n\t\t</packs>\n\n</installation>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/DerbyPathPanel.java",
    "content": "package com.izforge.izpack.panels;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.util.AbstractUIHandler;\nimport com.izforge.izpack.util.FileExecutor;\nimport com.izforge.izpack.util.OsVersion;\nimport com.izforge.izpack.util.os.RegistryDefaultHandler;\nimport com.izforge.izpack.util.os.RegistryHandler;\nimport com.izforge.izpack.util.VariableSubstitutor;\n\nimport java.io.File;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.StringTokenizer;\n\n/**\n * Panel which asks for the Derby database path.\n *\n * @author Klaus Bartz\n */\npublic class DerbyPathPanel extends PathInputPanel {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate String variableName = null;\n\n\tprivate DerbyPathPanelHelper helper = new DerbyPathPanelHelper();\n\t\n\t/**\n\t * The constructor.\n\t *\n\t * @param parent The parent window.\n\t * @param idata  The installation data.\n\t */\n\tpublic DerbyPathPanel(InstallerFrame parent, InstallData idata) {\n\t\tsuper(parent, TigaseInstallerCommon.init(idata));\n\t\tsetMustExist(false);\n\t\tsetVariableName(helper.getVariableName());\n\t}\n\n\t/**\n\t * Indicates wether the panel has been validated or not.\n\t *\n\t * @return Wether the panel has been validated or not.\n\t */\n\tpublic boolean isValidated()\n\t{\n\t\tboolean retval = false;\n\t\tif (super.isValidated()) {\n\t\t\tidata.setVariable(getVariableName(), pathSelectionPanel.getPath());\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Called when the panel becomes active.\n\t */\n\tpublic void panelActivate()\n\t{\n\t\t// Resolve the default for chosenPath\n\t\tsuper.panelActivate();\n\t\t// The variable will be exist if we enter this panel\n\t\t// second time. We would maintain the previos\n\t\t// selected path.\n//\t\tif (idata.getVariable(getVariableName()) != null) {\n//\t\t\tchosenPath = idata.getVariable(getVariableName());\n//\t\t} else {\n//\t\t\tif (OsVersion.IS_WINDOWS)\t{\n//\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".windows\");\n//\t\t\t}\n//\t\t\tif (OsVersion.IS_OSX)\t{\n//\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".mac\");\n//\t\t\t} else {\n//\t\t\t\tif (OsVersion.IS_UNIX)\t{\n//\t\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".unix\");\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\t\tVariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n//\t\tchosenPath = vs.substitute(chosenPath, null);\n//\t\t// Set the path for method pathIsValid ...\n\t\t\n\t\tString chosenPath = helper.getDefaultPath(idata);\n\t\tpathSelectionPanel.setPath(chosenPath);\n\n\t\tif (!pathIsValid())\n\t\t{\n\t\t\tchosenPath = \"\";\n\t\t}\n\t\t// Set the default to the path selection panel.\n\t\tpathSelectionPanel.setPath(chosenPath);\n// \t\tString var = idata.getVariable(\"DerbyPathPanel.skipIfValid\");\n// \t\t// Should we skip this panel?\n// \t\tif (chosenPath.length() > 0 && var != null && \"yes\".equalsIgnoreCase(var))\n// \t\t{\n// \t\t\tidata.setVariable(getVariableName(), chosenPath);\n// \t\t\tparent.skipPanel();\n// \t\t}\n\n\t}\n\n\t/**\n\t * Returns the name of the variable which should be used for the path.\n\t *\n\t * @return the name of the variable which should be used for the path\n\t */\n\tpublic String getVariableName()\n\t{\n\t\treturn variableName;\n\t}\n\n\t/**\n\t * Sets the name for the variable which should be set with the path.\n\t *\n\t * @param string variable name to be used\n\t */\n\tpublic void setVariableName(String string)\n\t{\n\t\tvariableName = string;\n\t}\n\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see com.izforge.izpack.installer.IzPanel#getSummaryBody()\n\t */\n\tpublic String getSummaryBody()\n\t{\n\t\treturn (idata.getVariable(getVariableName()));\n\t}\n}\n\nclass DerbyPathPanelHelper {\n\t\n\tString getVariableName() {\n\t\treturn \"DerbyDBPath\";\n\t}\n\t\n\tString getDefaultPath(AutomatedInstallData idata) {\n\t\tString chosenPath = \"\";\n\t\tif (idata.getVariable(getVariableName()) != null) {\n\t\t\tchosenPath = idata.getVariable(getVariableName());\n\t\t} else {\n\t\t\tif (OsVersion.IS_WINDOWS)\t{\n\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".windows\");\n\t\t\t}\n\t\t\tif (OsVersion.IS_OSX)\t{\n\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".mac\");\n\t\t\t} else {\n\t\t\t\tif (OsVersion.IS_UNIX)\t{\n\t\t\t\t\tchosenPath = idata.getVariable(getVariableName()+\".unix\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tVariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n\t\tchosenPath = vs.substitute(chosenPath, null);\n\t\treturn chosenPath;\n\t}\n\n\tpublic void setDefaultPath(AutomatedInstallData installData) {\n\t\tinstallData.setVariable(getVariableName(), getDefaultPath(installData));\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/DerbyPathPanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.PrintWriter;\nimport java.util.Properties;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.PanelConsole;\nimport com.izforge.izpack.installer.PanelConsoleHelper;\n\npublic class DerbyPathPanelConsoleHelper  extends PanelConsoleHelper implements PanelConsole {\n\n\tpublic boolean runConsole(AutomatedInstallData installData) {\n\t\tnew DerbyPathPanelHelper().setDefaultPath(installData);\n\t\treturn true;\n\t}\n\n\tpublic boolean runConsoleFromPropertiesFile(\n\t\t\tAutomatedInstallData installData, Properties p) {\n\t\tnew DerbyPathPanelHelper().setDefaultPath(installData);\n\t\treturn true;\n\t}\n\n\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n\t\t\tPrintWriter printWriter) {\n\t\tnew DerbyPathPanelHelper().setDefaultPath(installData);\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseCheckPanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\npublic class TigaseCheckPanelConsoleHelper {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseConfigConst.java",
    "content": "/*  Tigase Project\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage com.izforge.izpack.panels;\n\nimport java.util.LinkedHashMap;\nimport java.util.Properties;\n\n/**\n * Describe class TigaseConfigConst here.\n *\n *\n * Created: Sat Oct 25 21:23:06 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@gmail.com\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class TigaseConfigConst {\n\n\tpublic static Properties props = new Properties();\n\n\tpublic static LinkedHashMap<String, String> tigaseIzPackMap =\n    new LinkedHashMap<String, String>();\n// \tpublic static LinkedHashMap<String, String> izPackTigaseMap =\n//     new LinkedHashMap<String, String>();\n\n\tpublic static LinkedHashMap<String, String> userDBMap =\n    new LinkedHashMap<String, String>();\n\n\tpublic static LinkedHashMap<String, String> userDBUriMap =\n    new LinkedHashMap<String, String>();\n\n\tpublic static final String SERVER_DEBUG = \"serverDebug\";\n\tpublic static final String PLUGIN_DEBUG = \"pluginsDebug\";\n\tpublic static final String DB_DEBUG = \"dbDebug\";\n\tpublic static final String CLUSTER_DEBUG = \"clusterDebug\";\n\n\tpublic static String[] ALL_DEBUGS =\n\t{SERVER_DEBUG, PLUGIN_DEBUG, DB_DEBUG, CLUSTER_DEBUG};\n\tpublic static LinkedHashMap<String, String> debugMap =\n    new LinkedHashMap<String, String>();\n\n\tpublic static String[] ALL_PLUGINS =\n\t{\"messageArchivePlugin\", \"nonSaslAuthPlugin\", \"saslAuthPlugin\", \"resBindPlugin\",\n\t \"sessionBindPlugin\", \"registerPlugin\", \"rosterPlugin\", \"presencePlugin\", \"privacyPlugin\",\n\t \"versionPlugin\", \"statsPlugin\", \"tlsPlugin\", \"msgOfflinePlugin\",\n\t \"vcardPlugin\", \"commandsPlugin\", \"privatePlugin\", \"pingPlugin\",\n\t \"basicFilterPlugin\", \"domainFilterPlugin\", \"pepPlugin\", \"zlibPlugin\"};\n\tpublic static LinkedHashMap<String, String> pluginsMap =\n    new LinkedHashMap<String, String>();\n\n\t// Special variable names:\n\tpublic static final String DB_TYPE = \"dbType\";\n\tpublic static final String AUTH_DB = \"authDB\";\n\tpublic static final String AUTH_HANDLE = \"dbAuthHandle\";\n\tpublic static final String MUC_COMP = \"mucComponent\";\n\tpublic static final String PUBSUB_COMP = \"PubSubComponent\";\n\tpublic static final String STUN_COMP = \"stunComponent\";\n\tpublic static final String SOCKS5_COMP = \"socks5Component\";\n\tpublic static final String ARCHIVE_COMP = \"messageArchiveComponent\";\n\tpublic static final String HTTP_COMP = \"httpApiComponent\";\n\tpublic static final String ACS_COMP = \"acsComponent\";\n\tpublic static final String ACS_MUC_COMP = \"acsMUCComponent\";\n\tpublic static final String ACS_PUBSUB_COMP = \"acsPubSubComponent\";\n\tpublic static final String PLUGINS = \"plugins\";\n\tpublic static final String DEBUG = \"debug\";\n\tpublic static final String USER_DB_URI = \"userDBUri\";\n\tpublic static final String AUTH_DB_URI = \"dbAuthType\";\n\n\t// classes\n\tpublic static final String MUC_COMP_CLASS = \"tigase.muc.MUCComponent\";\n\tpublic static final String PUBSUB_COMP_CLASS = \"tigase.pubsub.PubSubComponent\";\n\tpublic static final String SOCKS5_COMP_CLASS = \"tigase.socks5.Socks5ProxyComponent\";\n\tpublic static final String STUN_COMP_CLASS = \"tigase.stun.StunComponent\";\n\tpublic static final String ARCHIVE_COMP_CLASS = \"tigase.archive.MessageArchiveComponent\";\n\tpublic static final String HTTP_COMP_CLASS = \"tigase.http.HttpMessageReceiver\";\n\tpublic static final String ACS_COMP_CLASS = \"tigase.cluster.strategy.OnlineUsersCachingStrategy\";\n\tpublic static final String ACS_MUC_COMP_CLASS = \"tigase.muc.cluster.MUCComponentClustered\";\n\tpublic static final String ACS_PUBSUB_COMP_CLASS = \"tigase.pubsub.cluster.PubSubComponentClustered\";\n\n\tstatic {\n\t\ttigaseIzPackMap.put(\"config-type\", \"configType\");\n\t\ttigaseIzPackMap.put(\"--virt-hosts\", \"virtualDomains\");\n\t\ttigaseIzPackMap.put(\"--admins\", \"admins\");\n\t\ttigaseIzPackMap.put(\"--user-db\", DB_TYPE);\n\t\ttigaseIzPackMap.put(\"--auth-db\", AUTH_HANDLE);\n\t\ttigaseIzPackMap.put(\"--muc\", MUC_COMP);\n\t\ttigaseIzPackMap.put(\"--pubsub\", PUBSUB_COMP);\n\t\ttigaseIzPackMap.put(\"--socks5\", SOCKS5_COMP);\n\t\ttigaseIzPackMap.put(\"--stun\", STUN_COMP);\n\t\ttigaseIzPackMap.put(\"--http\", HTTP_COMP);\n\t\ttigaseIzPackMap.put(\"--archive\", ARCHIVE_COMP);\n\t\ttigaseIzPackMap.put(\"--cluster-mode\", \"clusterMode\");\n//\t\ttigaseIzPackMap.put(\"--cluster-nodes\", \"clusterNodes\");\n\t\ttigaseIzPackMap.put(\"--debug\", DEBUG);\n\t\ttigaseIzPackMap.put(\"--sm-plugins\", PLUGINS);\n\t\ttigaseIzPackMap.put(\"--user-db-uri\", USER_DB_URI);\n\t\ttigaseIzPackMap.put(\"--auth-db-uri\", AUTH_DB_URI);\n\t\ttigaseIzPackMap.put(\"--sm-cluster-strategy-class\", ACS_COMP);\n\t\ttigaseIzPackMap.put(\"--muc_acs\", ACS_MUC_COMP);\n\t\ttigaseIzPackMap.put(\"--pubsub_acs\", ACS_PUBSUB_COMP);\n// \t\tfor (Map.Entry entry: tigaseIzPackMap.entrySet()) {\n// \t\t\tizPackTigaseMap.put(entry.getValue(), entry.getKey());\n// \t\t}\n\n\t\tuserDBMap.put(\"Derby\", \"derby\");\n\t\tuserDBMap.put(\"MySQL\", \"mysql\");\n\t\tuserDBMap.put(\"PostgreSQL\", \"pgsql\");\n\t\tuserDBMap.put(\"SQLServer\", \"sqlserver\");\n\n\t\tuserDBUriMap.put(\"derby\", \"Derby\");\n\t\tuserDBUriMap.put(\"mysql\", \"MySQL\");\n\t\tuserDBUriMap.put(\"postgresql\", \"PostgreSQL\");\n\t\tuserDBUriMap.put(\"pgsql\", \"PostgreSQL\");\n\t\tuserDBUriMap.put(\"sqlserver\", \"SQLServer\");\n\t\tuserDBUriMap.put(\"jtds:sqlserver\", \"SQLServer\");\n\n\t\tdebugMap.put(\"server\", SERVER_DEBUG);\n\t\tdebugMap.put(\"db\", DB_DEBUG);\n\t\tdebugMap.put(\"xmpp.impl\", PLUGIN_DEBUG);\n\t\tdebugMap.put(\"cluster\", CLUSTER_DEBUG);\n\n\t\tpluginsMap.put(\"jabber:iq:auth\", \"nonSaslAuthPlugin\");\n\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-sasl\", \"saslAuthPlugin\");\n\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-bind\", \"resBindPlugin\");\n\t\tpluginsMap.put(\"urn:ietf:params:xml:ns:xmpp-session\", \"sessionBindPlugin\");\n\t\tpluginsMap.put(\"jabber:iq:register\", \"registerPlugin\");\n\t\tpluginsMap.put(\"jabber:iq:roster\", \"rosterPlugin\");\n\t\tpluginsMap.put(\"presence\", \"presencePlugin\");\n\t\tpluginsMap.put(\"jabber:iq:privacy\", \"privacyPlugin\");\n\t\tpluginsMap.put(\"jabber:iq:version\", \"versionPlugin\");\n\t\tpluginsMap.put(\"http://jabber.org/protocol/stats\", \"statsPlugin\");\n\t\tpluginsMap.put(\"starttls\", \"tlsPlugin\");\n\t\tpluginsMap.put(\"msgoffline\", \"msgOfflinePlugin\");\n\t\tpluginsMap.put(\"vcard-temp\", \"vcardPlugin\");\n\t\tpluginsMap.put(\"http://jabber.org/protocol/commands\", \"commandsPlugin\");\n\t\tpluginsMap.put(\"jabber:iq:private\", \"privatePlugin\");\n\t\tpluginsMap.put(\"urn:xmpp:ping\", \"pingPlugin\");\n\t\tpluginsMap.put(\"basic-filter\", \"basicFilterPlugin\");\n\t\tpluginsMap.put(\"domain-filter\", \"domainFilterPlugin\");\n\t\tpluginsMap.put(\"pep\", \"pepPlugin\");\n\t\tpluginsMap.put(\"zlib\", \"zlibPlugin\");\n\t\tpluginsMap.put(\"message-archive-xep-0136\", \"messageArchivePlugin\");\n\t}\n\n\tpublic static String getPluginId(String pluginVarNameToFind) {\n\t\tfor (String pluginId : pluginsMap.keySet()) {\n\t\t\tString pluginVarName = pluginsMap.get(pluginId);\n\t\t\tif (pluginVarName.equals(pluginVarNameToFind)) {\n\t\t\t\treturn pluginId;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic static final String PGSQL_DRIVER = \"org.postgresql.Driver\";\n\tpublic static final String MYSQL_DRIVER = \"com.mysql.jdbc.Driver\";\n\tpublic static final String DERBY_DRIVER = \"org.apache.derby.jdbc.EmbeddedDriver\";\n\tpublic static final String SQLSERVER_DRIVER = \"net.sourceforge.jtds.jdbc.Driver\";\n\n\tpublic static final String JDBC_CHECKUSERTABLE_QUERY\n    = \"select count(*) from tig_users\";\n\n\tpublic static final String JDBC_GETSCHEMAVER_QUERY\n    = \"select TigGetDBProperty('schema-version')\";\n\tpublic static final String DERBY_GETSCHEMAVER_QUERY\n    = \"values TigGetDBProperty('schema-version')\";\n\tpublic static final String SQLSERVER_GETSCHEMAVER_QUERY\n    = \"select dbo.TigGetDBProperty('schema-version')\";\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseConfigLoadPanel.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage com.izforge.izpack.panels;\n\nimport java.io.File;\nimport java.io.FileReader;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\n\nimport com.izforge.izpack.gui.IzPanelLayout;\nimport com.izforge.izpack.gui.LabelFactory;\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.installer.IzPanel;\nimport com.izforge.izpack.util.Debug;\n\n/**\n * The Hello panel class.\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TigaseConfigLoadPanel extends IzPanel {\n\n\t/**\n\t *\n\t */\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate JTextArea textArea = null;\n\n\t/**\n\t * The constructor.\n\t *\n\t * @param parent The parent.\n\t * @param idata  The installation data.\n\t */\n\tpublic TigaseConfigLoadPanel(InstallerFrame parent, InstallData idata) {\n\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n\n\t\t// The config label.\n\t\tadd(LabelFactory.create(parent.langpack.getString(\"TigaseConfigLoadPanel.info\"),\n\t\t\t\tparent.icons.getImageIcon(\"edit\"), LEADING), NEXT_LINE);\n\t\t// The text area which shows the info.\n\t\ttextArea = new JTextArea(\"\");\n\t\ttextArea.setCaretPosition(0);\n\t\ttextArea.setEditable(false);\n\t\tJScrollPane scroller = new JScrollPane(textArea);\n\t\tadd(scroller, NEXT_LINE);\n\t\t// At end of layouting we should call the completeLayout method also they do nothing.\n\t\tgetLayoutHelper().completeLayout();\n\t}\n\n\tpublic void panelActivate() {\n\t\tsuper.panelActivate();\n\t\t// Existing configuration loading\n\t\tDebug.trace(\"panelActivate called for load pael\");\n\t\tString config = new TigaseConfigLoadHelper().loadConfig(idata);\n\t\ttextArea.setText(config);\n\t}\n\n\n\t/**\n\t * Indicates whether the panel has been validated or not.\n\t *\n\t * @return Always true.\n\t */\n\tpublic boolean isValidated() {\n\t\treturn true;\n\t}\n\n}\n\nclass TigaseConfigLoadHelper {\n\n\tString loadConfig(AutomatedInstallData idata) {\n\t\t// Try to read the config file.\n\t\tFile configPath = null;\n\t\tStringBuilder config = new StringBuilder();\n\t\ttry {\n\t\t\tif (idata.getVariable(\"searchTigaseHome\") == null\n\t\t\t\t|| idata.getVariable(\"searchTigaseHome\").isEmpty()) {\n\t\t\t\tconfigPath = new File(idata.getVariable(\"INSTALL_PATH\"),\n\t\t\t\t\t\"etc/init.properties\");\n\t\t\t} else {\n\t\t\t\tconfigPath = new File(idata.getVariable(\"searchTigaseHome\"),\n\t\t\t\t\t\"etc/init.properties\");\n\t\t\t}\n\t\t\tif (configPath.exists()) {\n\t\t\t\tProperties props = new Properties();\n\t\t\t\tprops.load(new FileReader(configPath));\n\t\t\t\tDebug.trace(\"Loading init.properties file...\");\n\t\t\t\tfor (String name: props.stringPropertyNames()) {\n\t\t\t\t\tconfig.append(name + \" = \" + props.getProperty(name) + \"\\n\");\n\t\t\t\t}\n\t\t\t\tDebug.trace(config);\n\t\t\t\tDebug.trace(\"Done.\");\n\t\t\t\tDebug.trace(\"Loading variables....\");\n\t\t\t\tfor (String name: TigaseConfigConst.tigaseIzPackMap.keySet()) {\n\t\t\t\t\tString varName = TigaseConfigConst.tigaseIzPackMap.get(name);\n\t\t\t\t\tif (varName != null) {\n\t\t\t\t\t\tDebug.trace(\"Loading: \" + varName + \" = \" + props.getProperty(name));\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.DEBUG)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tparseDebugs(props.getProperty(name), idata);\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.PLUGINS)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tparsePlugins(props.getProperty(name), idata);\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.USER_DB_URI)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tparseUserDbUri(props.getProperty(name), idata);\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.DB_TYPE)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tString dbType =\n                  TigaseConfigConst.userDBUriMap.get(props.getProperty(name));\n\t\t\t\t\t\t\t\tif (dbType == null) {\n\t\t\t\t\t\t\t\t\tdbType = \"Other\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.DB_TYPE, dbType);\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + dbType);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.AUTH_HANDLE)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.AUTH_HANDLE,\n\t\t\t\t\t\t\t\t\tprops.getProperty(name));\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.MUC_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"muc\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.MUC_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.MUC_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.PUBSUB_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"pubsub\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.PUBSUB_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.PUBSUB_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.SOCKS5_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"proxy\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.SOCKS5_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.SOCKS5_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.STUN_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"stun\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.STUN_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.STUN_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.HTTP_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"rest\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.HTTP_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.HTTP_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.ARCHIVE_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-name-\" + i).equals(\"message-archive\"))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.ARCHIVE_COMP, \"on\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.ARCHIVE_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.AUTH_DB_URI)) {\n\t\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\t\tparseAuthDbUri(props.getProperty(name), idata);\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" + props.getProperty(name));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDebug.trace(\"Missing configuration for \" + varName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.ACS_MUC_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-class-\" + i).equals(TigaseConfigConst.ACS_MUC_COMP_CLASS))) {\n\t\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.ACS_MUC_COMP, \"acs\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.MUC_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.ACS_PUBSUB_COMP)) {\n\t\t\t\t\t\t\tfor (int i = 1 ; i <= 10 ; i++ ) {\n\t\t\t\t\t\t\t\tif ((props.getProperty(\"--comp-name-\" + i) != null\n\t\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--comp-class-\" + i).equals(TigaseConfigConst.ACS_PUBSUB_COMP_CLASS))) {\n\t\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.ACS_PUBSUB_COMP, \"acs\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.PUBSUB_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (varName.equals(TigaseConfigConst.ACS_COMP)) {\n\t\t\t\t\t\t\tif ((props.getProperty(\"--sm-cluster-strategy-class\") != null\n\t\t\t\t\t\t\t\t\t&& props.getProperty(\"--sm-cluster-strategy-class\").equals(TigaseConfigConst.ACS_COMP_CLASS))) {\n\t\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.ACS_COMP, \"on\");\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tidata.setVariable(TigaseConfigConst.ACS_COMP, \"off\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tDebug.trace(\"Loaded: \" + varName + \" = \" +\n\t\t\t\t\t\t\t\t\tidata.getVariable(TigaseConfigConst.ACS_COMP));\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tif (props.getProperty(name) != null) {\n\t\t\t\t\t\t\tidata.setVariable(varName, props.getProperty(name));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Done.\");\n\t\t\t} else {\n\t\t\t\tconfig.append(\"The config file: \" + configPath + \" seems to not exist...\");\n\t\t\t}\n\t\t} catch (Exception err) {\n\t\t\tStringBuilder errorConfig = new StringBuilder();\n\t\t\terrorConfig.append(\"Error : could not load the config file: \" + configPath + \"\\n\");\n\t\t\terrorConfig.append(err.toString() + \"\\n\");\n\t\t\tfor (StackTraceElement ste: err.getStackTrace()) {\n\t\t\t\terrorConfig.append(ste.toString() + \"\\n\");\n\t\t\t}\n\t\t\treturn errorConfig.toString();\n\t\t}\n\t\treturn config.toString();\n\t}\n\n\tprivate void parseDebugs(String debugs, AutomatedInstallData idata) {\n\t\tString[] ardebugs = debugs.split(\",\");\n\t\tSet<String> knownDebugs = TigaseConfigConst.debugMap.keySet();\n\t\tfor (String debug: ardebugs) {\n\t\t\tif (knownDebugs.contains(debug)) {\n\t\t\t\tidata.setVariable(TigaseConfigConst.debugMap.get(debug), debug);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void parsePlugins(String plugins, AutomatedInstallData idata) {\n\t\tString[] arplugins = plugins.split(\",\");\n\t\tSet<String> knownPlugins = TigaseConfigConst.pluginsMap.keySet();\n\t\tfor (String plugin: arplugins) {\n\t\t\tif (knownPlugins.contains(plugin)) {\n\t\t\t\tidata.setVariable(TigaseConfigConst.pluginsMap.get(plugin), plugin);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static Pattern dbUriPattern =\n    Pattern.compile(\n\t\t\t\"jdbc:([^:]+(:[^:]+)?):(//([^/]+))?/?([0-9.a-zA-Z_/-]+)[;\\\\?]?(user=([^;&]+))?[;&]?(password=([^;&]+))?[;&]?(.*)\");\n\n\tprivate void parseUserDbUri(String dbUri, AutomatedInstallData idata) {\n\t\tMatcher m = dbUriPattern.matcher(dbUri);\n\t\tif (m.matches()) {\n\t\t\tString jdbcDriver = m.group(1);\n\t\t\tString host = m.group(4);\n\t\t\tString dbName = m.group(5);\n\t\t\tString userName = m.group(7);\n\t\t\tString userPass = m.group(9);\n\t\t\tString otherPars = m.group(10);\n// \t\tidata.setVariable(TigaseConfigConst.DB_TYPE,\n// \t\t\tTigaseConfigConst.userDBUriMap.get(jdbcDriver));\n\t\t\tif (jdbcDriver.equals(\"mysql\")) {\n\t\t\t\tidata.setVariable(\"dbSuperuser\", \"root\");\n\t\t\t}\n\t\t\tif (jdbcDriver.equals(\"postgresql\")) {\n\t\t\t\tidata.setVariable(\"dbSuperuser\", \"postgres\");\n\t\t\t}\n\t\t\tif (jdbcDriver.equals(\"sqlserver\")) {\n\t\t\t\tidata.setVariable(\"dbSuperuser\", \"root\");\n\t\t\t}\n\t\t\tif (host != null) {\n\t\t\t\tidata.setVariable(\"dbHost\", host);\n\t\t\t}\n\t\t\tif (dbName != null) {\n\t\t\t\tif (jdbcDriver.equals(\"derby\")) {\n\t\t\t\t\tidata.setVariable(\"DerbyDBPath\", \"/\" + dbName);\n\t\t\t\t\tDebug.trace(\"DerbyDBPath set to /\" + dbName);\n\t\t\t\t} else {\n\t\t\t\t\tidata.setVariable(\"dbName\", dbName);\n\t\t\t\t\tDebug.trace(\"dbName read: \" + dbName);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (userName != null) {\n\t\t\t\tidata.setVariable(\"dbUser\", userName);\n\t\t\t}\n\t\t\tif (userPass != null) {\n\t\t\t\tidata.setVariable(\"dbPass\", userPass);\n\t\t\t}\n\t\t\tif (otherPars != null) {\n\t\t\t\tidata.setVariable(\"dbParams\", otherPars);\n\t\t\t}\n\t\t} else {\n\t\t\tDebug.trace(\"Hm, the dbUri doesn't match regex: \" + dbUri);\n\t\t}\n\t}\n\n\tprivate void parseAuthDbUri(String dbUri, AutomatedInstallData idata) {\n\t\tMatcher m = dbUriPattern.matcher(dbUri);\n\t\tif (m.matches()) {\n\t\t\tString jdbcDriver = m.group(1);\n\t\t\tString host = m.group(4);\n\t\t\tString dbName = m.group(5);\n\t\t\tString userName = m.group(7);\n\t\t\tString userPass = m.group(9);\n\t\t\tString otherPars = m.group(10);\n\t\t\tif (jdbcDriver != null) {\n\t\t\t\tidata.setVariable(\"dbAuthType\", jdbcDriver);\n\t\t\t}\n\t\t\tif (host != null) {\n\t\t\t\tidata.setVariable(\"dbAuthHost\", host);\n\t\t\t}\n\t\t\tif (dbName != null) {\n\t\t\t\tidata.setVariable(\"dbAuthName\", dbName);\n\t\t\t}\n\t\t\tif (userName != null) {\n\t\t\t\tidata.setVariable(\"dbAuthUser\", userName);\n\t\t\t}\n\t\t\tif (userPass != null) {\n\t\t\t\tidata.setVariable(\"dbAuthPass\", userPass);\n\t\t\t}\n\t\t\tif (otherPars != null) {\n\t\t\t\tidata.setVariable(\"dbAuthParams\", otherPars);\n\t\t\t}\n\t\t} else {\n\t\t\tDebug.trace(\"Hm, the dbAuthUri doesn't match regex: \" + dbUri);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseConfigLoadPanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.PrintWriter;\nimport java.util.Properties;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.PanelConsole;\nimport com.izforge.izpack.installer.PanelConsoleHelper;\n\npublic class TigaseConfigLoadPanelConsoleHelper  extends PanelConsoleHelper implements PanelConsole {\n\n\tpublic boolean runConsole(AutomatedInstallData installData) {\n\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n\t\treturn true;\n\t}\n\n\tpublic boolean runConsoleFromPropertiesFile(\n\t\t\tAutomatedInstallData installData, Properties p) {\n\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n\t\treturn true;\n\t}\n\n\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n\t\t\tPrintWriter printWriter) {\n\t\tnew TigaseConfigLoadHelper().loadConfig(installData);\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseConfigSavePanel.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage com.izforge.izpack.panels;\n\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.net.URLEncoder;\n\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\n\nimport com.izforge.izpack.gui.IzPanelLayout;\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.installer.IzPanel;\nimport com.izforge.izpack.util.Debug;\nimport com.izforge.izpack.util.OsVersion;\nimport java.io.UnsupportedEncodingException;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * The Hello panel class.\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TigaseConfigSavePanel extends IzPanel {\n\n\t/**\n\t *\n\t */\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate JTextArea textArea = null;\n\n\tprivate final TigaseConfigSaveHelper helper = new TigaseConfigSaveHelper();\n\n\n\t/**\n\t * The constructor.\n\t *\n\t * @param parent The parent.\n\t * @param idata  The installation data.\n\t */\n\tpublic TigaseConfigSavePanel(InstallerFrame parent, InstallData idata) {\n\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n\n\t\t// The config label.\n\t\tString msg = parent.langpack.getString(\"TigaseConfigSavePanel.info\");\n\t\tadd(createMultiLineLabel(msg));\n\t\tadd(IzPanelLayout.createParagraphGap());\n\t\t// The text area which shows the info.\n\t\ttextArea = new JTextArea(\"\");\n\t\ttextArea.setCaretPosition(0);\n\t\ttextArea.setEditable(true);\n\t\tJScrollPane scroller = new JScrollPane(textArea);\n\t\tadd(scroller, NEXT_LINE);\n\t\t// At end of layouting we should call the completeLayout method also they do nothing.\n\t\tgetLayoutHelper().completeLayout();\n\t}\n\n\tpublic void panelActivate() {\n\t\tsuper.panelActivate();\n\t\tString config = helper.showConfig(\n\t\t\t\tnew IzPackInstallDataVariablesSource(idata));\n\t\ttextArea.setText(config);\n\t}\n\n\n\n\t/**\n\t * Indicates wether the panel has been validated or not.\n\t *\n\t * @return Always true.\n\t */\n\tpublic boolean isValidated() {\n\t\tString errorStr =  helper.saveConfig(idata, textArea.getText());\n\t\tif (errorStr != null) {\n\t\t\temitError(\"Can not write to config file\", errorStr);\n\t\t}\n\t\treturn true;\n\t}\n\n}\n\nabstract class VariablesSource {\n\tabstract String getVariable(String key);\n\tabstract String getEncodedVariable(String key);\n}\n\nclass IzPackInstallDataVariablesSource extends VariablesSource {\n\tprivate final AutomatedInstallData idata;\n\n\tpublic IzPackInstallDataVariablesSource(AutomatedInstallData idata) {\n\t\tthis.idata = idata;\n\n\t}\n\n\t@Override\n\tString getVariable(String key) {\n\t\treturn idata.getVariable(key);\n\t}\n\n\t@Override\n\tString getEncodedVariable(String key) {\n\n\t\tString variable = idata.getVariable(key);\n\t\tString value = null;\n\t\ttry {\n\t\t\tvalue = URLEncoder.encode(variable, \"UTF-8\");\n\t\t} catch ( Exception ex ) {\n\t\t\tLogger.getLogger( TigaseConfigSaveHelper.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\t\treturn value;\n\t}\n}\n\nclass TigaseConfigSaveHelper {\n\n\tString showConfig(VariablesSource variablesSource) {\n\t\tTigaseConfigConst.props.clear();\n\t\tStringBuilder config = new StringBuilder();\n\t\tint comp_idx = 0;\n\t\tfor (Map.Entry<String, String> entry:\n\t\tTigaseConfigConst.tigaseIzPackMap.entrySet()) {\n\t\t\tString varName = entry.getValue();\n\t\t\tString varValue = variablesSource.getVariable(varName);\n\n\t\t\tDebug.trace(\"=== Processing varName: varValue :: \" + varName + \" : \" + varValue);\n\t\t\t\n\t\t\tif (varName.equals(TigaseConfigConst.DEBUG)) {\n\t\t\t\tString debugVar = getDebugs(variablesSource);\n\t\t\t\tif (!debugVar.isEmpty()) {\n\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), debugVar);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + debugVar);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.PLUGINS)) {\n\t\t\t\tString pluginsVar = getPlugins(variablesSource);\n\t\t\t\tif (!pluginsVar.isEmpty()) {\n\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), pluginsVar);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + pluginsVar);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.USER_DB_URI)) {\n\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), getDBUri(variablesSource));\n\t\t\t\tTigaseConfigConst.props.setProperty(\"root-tigase-db-uri\",getRootTigaseDBUri(variablesSource));\n\t\t\t\tTigaseConfigConst.props.setProperty(\"root-db-uri\", getRootDBUri(variablesSource));\n\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getDBUri(variablesSource));\n\t\t\t\tDebug.trace(\"Set: \" + \"root-tigase-db-uri\" + \" = \" + getRootTigaseDBUri(variablesSource));\n\t\t\t\tDebug.trace(\"Set: \" + \"root-db-uri\" + \" = \" + getRootDBUri(variablesSource));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (varValue == null) continue;\n\n\t\t\tif (varName.equals(TigaseConfigConst.DB_TYPE)) {\n\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), getUserDB(variablesSource));\n\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getUserDB(variablesSource));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.AUTH_HANDLE)) {\n\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(),\n\t\t\t\t\tgetAuthHandler(varValue, variablesSource));\n\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + getAuthHandler(varValue, variablesSource));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.MUC_COMP))  {\n\t\t\t\tif ( varValue.equals( \"on\" ) ){\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-name-\" + comp_idx, \"muc\" );\n\n\t\t\t\t\tString acsMUC = TigaseConfigConst.tigaseIzPackMap.get( \"--muc_acs\" );\n\t\t\t\t\tString acsMUCValue = variablesSource.getVariable( acsMUC );\n\t\t\t\t\tDebug.trace( \" @@ Set: acsMUC \" + acsMUC + \" / acsMUCValue: \" + acsMUCValue );\n\n\t\t\t\t\tif ( acsMUC != null && acsMUCValue != null && acsMUCValue.equals( \"acs\" ) ){\n\t\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-class-\" + comp_idx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t TigaseConfigConst.ACS_MUC_COMP_CLASS );\n\t\t\t\t\t\tDebug.trace( \"Set: \" + \"--comp-name-\" + comp_idx + \" = \" + \"muc\" + \" % to:\" + \"--comp-class-\" + comp_idx + \"=\" + TigaseConfigConst.ACS_MUC_COMP_CLASS );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-class-\" + comp_idx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t TigaseConfigConst.MUC_COMP_CLASS );\n\t\t\t\t\t\tDebug.trace( \"Set: \" + \"--comp-name-\" + comp_idx + \" = \" + \"muc\" + \" % to:\" + \"--comp-class-\" + comp_idx + \"=\" + TigaseConfigConst.MUC_COMP_CLASS );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t\n\t\t\tif ( varName.equals( TigaseConfigConst.PUBSUB_COMP ) ){\n\t\t\t\tif ( varValue.equals( \"on\" ) ){\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-name-\" + comp_idx, \"pubsub\" );\n\t\t\t\t\tString acsPubSub = TigaseConfigConst.tigaseIzPackMap.get( \"--pubsub_acs\" );\n\t\t\t\t\tString acsPubSubValue = variablesSource.getVariable( acsPubSub );\n\t\t\t\t\tDebug.trace( \" @@ Set: acsMUC \" + acsPubSub + \" / acsMUCValue: \" + acsPubSubValue );\n\n\t\t\t\t\tif ( acsPubSub != null && acsPubSubValue != null && acsPubSubValue.equals( \"acs\" ) ){\n\t\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-class-\" + comp_idx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t TigaseConfigConst.ACS_PUBSUB_COMP_CLASS );\n\t\t\t\t\t\tDebug.trace( \"Set: \" + \"--comp-name-\" + comp_idx + \" = \" + \"pubsub\" + \" % to:\" + \"--comp-class-\" + comp_idx + \"=\" + TigaseConfigConst.ACS_PUBSUB_COMP_CLASS );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTigaseConfigConst.props.setProperty( \"--comp-class-\" + comp_idx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t TigaseConfigConst.PUBSUB_COMP_CLASS );\n\t\t\t\t\t\tDebug.trace( \"Set: \" + \"--comp-name-\" + comp_idx + \" = \" + \"pubsub\" + \" % to:\" + \"--comp-class-\" + comp_idx + \"=\" + TigaseConfigConst.PUBSUB_COMP_CLASS );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (varName.equals(TigaseConfigConst.ACS_PUBSUB_COMP) || varName.equals(TigaseConfigConst.ACS_MUC_COMP)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (varName.equals(TigaseConfigConst.SOCKS5_COMP)) {\n\t\t\t\tif (varValue.equals(\"on\")) {\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"proxy\");\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n\t\t\t\t\t\tTigaseConfigConst.SOCKS5_COMP_CLASS);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"proxy\" + \" % to:\" + \"--comp-class-\"+comp_idx + \"=\" + TigaseConfigConst.SOCKS5_COMP_CLASS);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.STUN_COMP)) {\n\t\t\t\tif (varValue.equals(\"on\")) {\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"stun\");\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n\t\t\t\t\t\tTigaseConfigConst.STUN_COMP_CLASS);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"stun\" + \" % to:\" + \"--comp-class-\"+comp_idx + \"=\" + TigaseConfigConst.STUN_COMP_CLASS);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.HTTP_COMP)) {\n\t\t\t\tif (varValue.equals(\"on\")) {\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"rest\");\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n\t\t\t\t\t\tTigaseConfigConst.HTTP_COMP_CLASS);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"rest\" + \" % to:\" + \"--comp-class-\"+comp_idx + \"=\" + TigaseConfigConst.HTTP_COMP_CLASS);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (varName.equals(TigaseConfigConst.ARCHIVE_COMP)) {\n\t\t\t\tif (varValue.equals(\"on\")) {\n\t\t\t\t\t++comp_idx;\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-name-\"+comp_idx, \"message-archive\");\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--comp-class-\"+comp_idx,\n\t\t\t\t\t\tTigaseConfigConst.ARCHIVE_COMP_CLASS);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + \"--comp-name-\"+comp_idx + \" = \" + \"message-archive\" + \" % to:\" + \"--comp-class-\"+comp_idx + \"=\" + TigaseConfigConst.HTTP_COMP_CLASS);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (varName.equals(TigaseConfigConst.ACS_COMP)) {\n\t\t\t\tif (varValue.equals(\"on\")) {\n\t\t\t\t\tTigaseConfigConst.props.setProperty(\"--sm-cluster-strategy-class\", TigaseConfigConst.ACS_COMP_CLASS);\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"Set: \" + \"--sm-cluster-strategy-class = \" + TigaseConfigConst.ACS_COMP_CLASS);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (varName.equals(TigaseConfigConst.AUTH_DB_URI)) {\n\t\t\t\tString auth_db_uri = getAuthUri(variablesSource);\n\t\t\t\tif (auth_db_uri != null) {\n\t\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), auth_db_uri);\n\t\t\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + auth_db_uri);\n\t\t\t\t} else {\n\t\t\t\t\tDebug.trace(\"Not set: \" + entry.getKey());\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!varValue.trim().isEmpty()) {\n\t\t\t\tTigaseConfigConst.props.setProperty(entry.getKey(), varValue);\n\t\t\t}\n\t\t\tDebug.trace(\"Set: \" + entry.getKey() + \" = \" + varValue);\n\t\t}\n\t\tfor (String name: TigaseConfigConst.props.stringPropertyNames()) {\n\t\t\tif (!name.startsWith(\"root\")) {\n\t\t\t\tconfig.append(name + \" = \" + TigaseConfigConst.props.getProperty(name) + \"\\n\");\n\t\t\t}\n\t\t}\n\t\treturn config.toString();\n\t}\n\n\tprivate String getDBUri(VariablesSource variablesSource) {\n\t\tString db_uri = \"jdbc:\";\n\t\tString database = getUserDB(variablesSource);\n\t\tDebug.trace(\"getDBUri | database: \"  +database);\n\t\tif (database.equals(\"pgsql\")) {\n\t\t\tdb_uri += \"postgresql:\";\n\t\t} else if (database.equals(\"sqlserver\")) {\n\t\t\tdb_uri += \"jtds:sqlserver:\";\n\t\t} else {\n\t\t\tdb_uri += database + \":\";\n\t\t}\n\t\tif (database.equals(\"derby\")) {\n\t\t\tString derby_path = variablesSource.getVariable(\"DerbyDBPath\");\n\t\t\tif (OsVersion.IS_WINDOWS) {\n\t\t\t\tderby_path = derby_path.replace(\"\\\\\", \"\\\\\\\\\");\n\t\t\t}\n\t\t\tdb_uri += derby_path;\n\t\t} else if ( database.equals( \"sqlserver\" ) ){\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += \";databaseName=\" + variablesSource.getVariable(\"dbName\");\n\t\t\tdb_uri += \";user=\" + variablesSource.getEncodedVariable(\"dbUser\");\n\t\t\tif ( variablesSource.getEncodedVariable( \"dbPass\" ) != null\n\t\t\t\t\t && !variablesSource.getEncodedVariable( \"dbPass\" ).isEmpty() ){\n\t\t\t\tdb_uri += \";password=\" + variablesSource.getEncodedVariable( \"dbPass\" );\n\t\t\t}\n\t\t\tdb_uri += \";schema=dbo\";\n\t\t\tdb_uri += \";lastUpdateCount=false\";\n\t\t\tdb_uri += \";cacheMetaData=false\";\n\t\t} else {\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbName\");\n\t\t\tdb_uri += \"?user=\" + variablesSource.getEncodedVariable(\"dbUser\");\n\t\t\tif (variablesSource.getEncodedVariable(\"dbPass\") != null\n\t\t\t\t&& !variablesSource.getEncodedVariable(\"dbPass\").isEmpty()) {\n\t\t\t\tdb_uri += \"&password=\" + variablesSource.getEncodedVariable(\"dbPass\");\n\t\t\t}\n\t\t}\n\t\treturn db_uri;\n\t}\n\n\tprivate String getRootTigaseDBUri(VariablesSource variablesSource) {\n\t\tString db_uri = \"jdbc:\";\n\t\tString database = getUserDB(variablesSource);\n\t\tDebug.trace(\"getDBUri | database: \" + database);\n\t\tif (database.equals(\"pgsql\")) {\n\t\t\tdb_uri += \"postgresql:\";\n\t\t} else if (database.equals(\"sqlserver\")) {\n\t\t\tdb_uri += \"jtds:sqlserver:\";\n\t\t} else {\n\t\t\tdb_uri += database + \":\";\n\t\t}\n\t\tif (database.equals(\"derby\")) {\n\t\t\tdb_uri += variablesSource.getVariable(\"DerbyDBPath\") + \";create=true\";\n\t\t} else if ( database.equals( \"sqlserver\" ) ){\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += \";databaseName=\" + variablesSource.getVariable(\"dbName\");\n\t\t\tdb_uri += \";user=\" + variablesSource.getEncodedVariable(\"dbSuperuser\");\n\t\t\tif ( variablesSource.getEncodedVariable( \"dbSuperpass\" ) != null\n\t\t\t\t\t && !variablesSource.getEncodedVariable( \"dbSuperpass\" ).isEmpty() ){\n\t\t\t\tdb_uri += \";password=\" + variablesSource.getEncodedVariable( \"dbSuperpass\" );\n\t\t\t}\n\t\t\tdb_uri += \";schema=dbo\";\n\t\t\tdb_uri += \";lastUpdateCount=false\";\n\t\t\tdb_uri += \";cacheMetaData=false\";\n\t\t} else {\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbName\");\n\t\t\tdb_uri += \"?user=\" + variablesSource.getEncodedVariable(\"dbSuperuser\");\n\t\t\tif (variablesSource.getEncodedVariable(\"dbSuperpass\") != null\n\t\t\t\t&& !variablesSource.getEncodedVariable(\"dbSuperpass\").isEmpty()) {\n\t\t\t\tdb_uri += \"&password=\" + variablesSource.getEncodedVariable(\"dbSuperpass\");\n\t\t\t}\n\t\t}\n\t\treturn db_uri;\n\t}\n\n\tprivate String getRootDBUri(VariablesSource variablesSource) {\n\t\tString db_uri = \"jdbc:\";\n\t\tString db = \"\";\n\t\tString database = getUserDB(variablesSource);\n\t\tDebug.trace(\"getDBUri | database: \" + database);\n\t\tif (database.equals(\"pgsql\")) {\n\t\t\tdb_uri += \"postgresql:\";\n\t\t\tdb = \"/postgres\";\n\t\t} else if (database.equals(\"sqlserver\")) {\n\t\t\tdb_uri += \"jtds:sqlserver:\";\n\t\t\tdb = \";databaseName=master\";\n\t\t} else {\n\t\t\tdb_uri += database + \":\";\n\t\t\tif (database.equals(\"mysql\")) {\n\t\t\t\tdb = \"/mysql\";\n\t\t\t}\n\t\t}\n\t\tif (database.equals(\"derby\")) {\n\t\t\tdb_uri += variablesSource.getVariable(\"DerbyDBPath\") + \";create=true\";\n\t\t} else if ( database.equals( \"sqlserver\" ) ){\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += \";databaseName=master\";\n\t\t\tdb_uri += \";user=\" + variablesSource.getEncodedVariable(\"dbSuperuser\");\n\t\t\tif ( variablesSource.getEncodedVariable( \"dbSuperpass\" ) != null\n\t\t\t\t\t && !variablesSource.getEncodedVariable( \"dbSuperpass\" ).isEmpty() ){\n\t\t\t\tdb_uri += \";password=\" + variablesSource.getEncodedVariable( \"dbSuperpass\" );\n\t\t\t}\n\t\t\tdb_uri += \";schema=dbo\";\n\t\t\tdb_uri += \";lastUpdateCount=false\";\n\t\t\tdb_uri += \";cacheMetaData=false\";\n\t\t} else {\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbHost\");\n\t\t\tdb_uri += db;\n\t\t\tdb_uri += \"?user=\" + variablesSource.getEncodedVariable(\"dbSuperuser\");\n\t\t\tif (variablesSource.getEncodedVariable(\"dbSuperpass\") != null\n\t\t\t\t&& !variablesSource.getEncodedVariable(\"dbSuperpass\").isEmpty()) {\n\t\t\t\tdb_uri += \"&password=\" + variablesSource.getEncodedVariable(\"dbSuperpass\");\n\t\t\t}\n\t\t}\n\t\treturn db_uri;\n\t}\n\n\tprivate String getAuthUri(VariablesSource variablesSource) {\n\t\tString db_uri = \"jdbc:\";\n\t\tString database = variablesSource.getVariable(TigaseConfigConst.AUTH_DB_URI);\n\t\tdb_uri += database + \":\";\n\t\tif (database.equals(\"derby\")) {\n\t\t\tString derby_path = variablesSource.getVariable(\"DerbyDBPath\");\n\t\t\tif (derby_path != null) {\n\t\t\t\tdb_uri += derby_path;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else if ( database.equals( \"sqlserver\" ) ){\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbAuthHost\");\n\t\t\tdb_uri += \";databaseName=\" + variablesSource.getVariable(\"dbAuthName\");\n\t\t\tdb_uri += \";user=\" + variablesSource.getEncodedVariable(\"dbAuthUser\");\n\t\t\tif ( variablesSource.getEncodedVariable( \"dbAuthPass\" ) != null\n\t\t\t\t\t && !variablesSource.getEncodedVariable( \"dbAuthPass\" ).isEmpty() ){\n\t\t\t\tdb_uri += \";password=\" + variablesSource.getEncodedVariable( \"dbAuthPass\" );\n\t\t\t}\n\t\t\tdb_uri += \";schema=dbo\";\n\t\t\tdb_uri += \";lastUpdateCount=false\";\n\t\t\tdb_uri += \";cacheMetaData=false\";\n\t\t} else {\n\t\t\tdb_uri += \"//\" + variablesSource.getVariable(\"dbAuthHost\");\n\t\t\tdb_uri += \"/\" + variablesSource.getVariable(\"dbAuthName\");\n\t\t\tdb_uri += \"?user=\" + variablesSource.getEncodedVariable(\"dbAuthUser\");\n\t\t\tif (variablesSource.getEncodedVariable(\"dbAuthPass\") != null\n\t\t\t\t&& !variablesSource.getEncodedVariable(\"dbAuthPass\").isEmpty()) {\n\t\t\t\tdb_uri += \"&password=\" + variablesSource.getEncodedVariable(\"dbAuthPass\");\n\t\t\t}\n\t\t}\n\t\treturn db_uri;\n\t}\n\n\tprivate String getPlugins(VariablesSource variablesSource) {\n\t\tString plugins = \"\";\n\t\tif (variablesSource.getVariable(TigaseConfigConst.ALL_PLUGINS[0]) == null) {\n\t\t\t// The Panel with debuging settings was not shown so all\n\t\t\t// settins are null, then we set a default: 'server'\n\t\t\treturn \"\";\n\t\t}\n\t\tfor (String plugin: TigaseConfigConst.ALL_PLUGINS) {\n\t\t\tif (variablesSource.getVariable(plugin) == null) {\n\t\t\t\tDebug.trace(\"Missing variables for: \" + plugin);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfinal String value = variablesSource.getVariable(plugin);\n\t\t\tfinal String prefix;\n\t\t\tfinal String pluginId = TigaseConfigConst.getPluginId(plugin);\n\t\t\tif (value.equals(\"off\")) {\n\t\t\t\tprefix = \"-\";\n\t\t\t} else {\n\t\t\t\tprefix = \"+\";\n\t\t\t}\n\n\t\t\tif (!plugins.isEmpty()) {\n\t\t\t\tplugins += \",\";\n\t\t\t}\n\t\t\tplugins += prefix + pluginId;\n\t\t}\n\n\t\treturn plugins;\n\t}\n\n\tprivate String getDebugs(VariablesSource variablesSource) {\n\n\t\tString debugs = \"\";\n\t\tif (variablesSource.getVariable(TigaseConfigConst.ALL_DEBUGS[0]) == null) {\n\t\t\t// The Panel with debuging settings was not shown so all\n\t\t\t// settins are null, then we set a default: 'server'\n\t\t\treturn \"server\";\n\t\t}\n\t\tfor (String deb: TigaseConfigConst.ALL_DEBUGS) {\n\t\t\tif (variablesSource.getVariable(deb) == null\n\t\t\t\t\t|| variablesSource.getVariable(deb).equals(\"off\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!debugs.isEmpty()) {\n\t\t\t\tdebugs += \",\";\n\t\t\t}\n\t\t\tdebugs += variablesSource.getVariable(deb);\n\t\t}\n\t\treturn debugs;\n\t}\n\n\tprivate String getAuthHandler(String var, VariablesSource variablesSource) {\n\t\tif (var.equals(\"Standard\")) {\n\t\t\treturn getUserDB(variablesSource);\n\t\t}\n\t\treturn var;\n\t}\n\n\tprivate String getUserDB( VariablesSource variablesSource ) {\n\t\tString dbVar = variablesSource.getVariable( TigaseConfigConst.DB_TYPE );\n\t\tDebug.trace( \"@@ getUserDB | dbVar: \" + dbVar );\n\t\tString result = TigaseConfigConst.userDBMap.get( dbVar );\n\t\tDebug.trace( \"@@ getUserDB | result: \" + result );\n\t\treturn result != null ? result : \"derby\";\n\t}\n\n\t// returns null if ok, error string on error\n\tString saveConfig(AutomatedInstallData variablesSource, String config) {\n\t\t// Try to read the config file.\n\t\tFile configPath = null;\n\t\tFile xmlConfigPath = null;\n\t\ttry {\n\t\t\tif (variablesSource.getVariable(\"searchTigaseHome\") == null\n\t\t\t\t|| variablesSource.getVariable(\"searchTigaseHome\").isEmpty()) {\n\t\t\t\tconfigPath = new File(variablesSource.getVariable(\"INSTALL_PATH\"),\n\t\t\t\t\t\"etc/init.properties\");\n\t\t\t\txmlConfigPath = new File(variablesSource.getVariable(\"INSTALL_PATH\"),\n\t\t\t\t\t\"etc/tigase.xml\");\n\t\t\t} else {\n\t\t\t\tconfigPath = new File(variablesSource.getVariable(\"searchTigaseHome\"),\n\t\t\t\t\t\"etc/init.properties\");\n\t\t\t\txmlConfigPath = new File(variablesSource.getVariable(\"searchTigaseHome\"),\n\t\t\t\t\t\"etc/tigase.xml\");\n\t\t\t}\n\t\t\tFileWriter fw = new FileWriter(configPath, false);\n\t\t\tfw.write(config);\n\t\t\tfw.close();\n\t\t\tif (xmlConfigPath.exists()) {\n\t\t\t\txmlConfigPath.delete();\n\t\t\t}\n\t\t} catch (Exception err) {\n\t\t\tString error = \"Error : could not write to the config file: \" + configPath + \"\\n\";\n\t\t\terror += err.toString() + \"\\n\";\n\t\t\tfor (StackTraceElement ste: err.getStackTrace()) {\n\t\t\t\terror += ste.toString() + \"\\n\";\n\t\t\t}\n\t\t\treturn error;\n\t\t}\n\t\treturn null;\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseConfigSavePanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.PrintWriter;\nimport java.util.Properties;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.PanelConsole;\nimport com.izforge.izpack.installer.PanelConsoleHelper;\n\npublic class TigaseConfigSavePanelConsoleHelper  \nextends PanelConsoleHelper implements PanelConsole {\n\n\tpublic boolean runConsole(AutomatedInstallData installData) {\n\t\tTigaseConfigSaveHelper helper = new TigaseConfigSaveHelper();\n\t\t\n\t\tString config =  helper.showConfig(\n\t\t\t\tnew IzPackInstallDataVariablesSource(installData));\n\t\thelper.saveConfig(installData, config);\n\t\t\n\t\treturn true;\n\t}\n\n\t\n\t\n\tpublic boolean runConsoleFromPropertiesFile(\n\t\t\tAutomatedInstallData installData, Properties p) {\n\t\treturn false;\n\t}\n\n\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n\t\t\tPrintWriter printWriter) {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseDBCheckPanel.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage com.izforge.izpack.panels;\n\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport javax.swing.JScrollPane;\nimport javax.swing.JTable;\nimport javax.swing.SwingUtilities;\nimport javax.swing.table.AbstractTableModel;\nimport javax.swing.table.TableModel;\n\nimport com.izforge.izpack.gui.IzPanelLayout;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.installer.IzPanel;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.MsgTarget;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n\n/**\n * The Hello panel class.\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TigaseDBCheckPanel extends IzPanel {\n\n\t/**\n\t *\n\t */\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate JTable table = null;\n\tprivate Timer delayedTasks = new Timer(\"DelayedTasks\", true);\n\n\tprivate final InstallData idata;\n\n\t/**\n\t * The constructor.\n\t *\n\t * @param parent The parent.\n\t * @param idata  The installation data.\n\t */\n\tpublic TigaseDBCheckPanel(InstallerFrame parent, InstallData idata) {\n\t\tsuper(parent, TigaseInstallerCommon.init(idata), new IzPanelLayout());\n\t\tthis.idata = idata;\n\n\t\t// The config label.\n\t\tString msg = parent.langpack.getString(\"TigaseDBCheckPanel.info\");\n\t\tadd(createMultiLineLabel(msg));\n\t\tadd(IzPanelLayout.createParagraphGap());\n\n\t\tfinal String[] columnNames = new String[] {\"Action\", \"Result\"};\n\t\t\n\t\tTigaseDBTask[] tasks = TigaseInstallerDBHelper.Tasks.getTasksInOrder();\n\t\tfinal String[][] data = new String[tasks.length][];\n\t\tfor (int i = 0 ; i < tasks.length ; i++) {\n\t\t\tTigaseDBTask task = tasks[i];\n\t\t\tdata[i] = new String[] { task.getDescription(), \"\" };\n\t\t}\n\t\t\n\t\tTableModel dataModel = new AbstractTableModel() {\n//\t\t\t\tprivate String[] columnNames = names;\n//\t\t\t\tprivate Object[][] data = datas;\n\t\t\t\tpublic int getColumnCount() { return columnNames.length; }\n\t\t\t\tpublic int getRowCount() { return data.length; }\n\t\t\t\tpublic String getColumnName(int col) { return columnNames[col]; }\n\t\t\t\tpublic Object getValueAt(int row, int col) { return data[row][col]; }\n\t\t\t\tpublic Class getColumnClass(int c) { return getValueAt(0, c).getClass(); }\n\t\t\t\tpublic boolean isCellEditable(int row, int col) { return false; }\n\t\t\t\tpublic void setValueAt(Object value, int row, int col) {\n\t\t\t\t\tdata[row][col] = value.toString();\n\t\t\t\t\tfireTableCellUpdated(row, col);\n\t\t\t\t}\n      };\n\t\t// The table area which shows the info.\n\t\ttable = new JTable(dataModel);\n\t\t//\t\ttable.setEditable(false);\n\t\t//add(table, NEXT_LINE);\n\t\tJScrollPane scroller = new JScrollPane(table);\n\t\ttable.setFillsViewportHeight(true);\n\t\tadd(scroller, NEXT_LINE);\n\t\t// At end of layouting we should call the completeLayout\n\t\t// method also they do nothing.\n\t\tgetLayoutHelper().completeLayout();\n\t}\n\n\tpublic void panelActivate() {\n\t\tsuper.panelActivate();\n\t\tparent.lockNextButton();\n\t\t\n\t\tfinal TigaseInstallerDBHelper dbHelper = new TigaseInstallerDBHelper();\n\t\t\n\t\tdelayedTasks.schedule(new TimerTask() {\n\t\t\t\t\n\t\t\tpublic void run() {\n\t\t\t\tTigaseDBTask[] tasks = TigaseInstallerDBHelper.Tasks.getTasksInOrder();\n\t\t\t\t\n\t\t\t\tfor (int i = 0 ; i < tasks.length ; i++) {\n\t\t\t\t\tTigaseDBTask task = tasks[i];\n\t\t\t\t\tfinal int row = i;\n\t\t\t\t\t\n\t\t\t\t\tMsgTarget msgTarget = new MsgTarget() {\n\t\t\t\t\t\tpublic ResultMessage addResultMessage() {\n\t\t\t\t\t\t\treturn new ResultMessage() {\n\t\t\t\t\t\t\t\tprivate String fullMsg = \"\";\n\n\t\t\t\t\t\t\t\tpublic void append(String msg) {\n\t\t\t\t\t\t\t\t\tfullMsg += msg;\n\t\t\t\t\t\t\t\t\tSwingUtilities.invokeLater(new Runnable() {\n\t\t\t\t\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\t\t\t\t\ttable.getModel().setValueAt(fullMsg, row, 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\ttask.execute(dbHelper, idata.getVariables(), msgTarget);\n\t\t\t\t}\n\t\t\t\tparent.unlockNextButton();\n\t\t\t}\n\t\t}, 500);\n\t}\n\n\t/**\n\t * Indicates wether the panel has been validated or not.\n\t *\n\t * @return Always true.\n\t */\n\tpublic boolean isValidated() {\n\t\treturn true;\n\t}\n\n}\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseDBCheckPanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.PrintWriter;\nimport java.util.Properties;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.ConsoleInstallHelper;\nimport com.izforge.izpack.installer.PanelConsole;\nimport com.izforge.izpack.installer.PanelConsoleHelper;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n\npublic class TigaseDBCheckPanelConsoleHelper extends PanelConsoleHelper implements PanelConsole {\n\n\tprivate ConsoleInstallHelper helper = ConsoleInstallHelper.getInstance();\n\t\n\tpublic boolean runConsole(AutomatedInstallData installData) {\n\t\t\n\t\tTigaseInstallerDBHelper dbHelper = new TigaseInstallerDBHelper();\n\t\n\t\thelper.console.displayLabel(\"Performing DB tasks\");\n\t\t\t\t\n\t\tfor (TigaseDBTask task : TigaseInstallerDBHelper.Tasks.getTasksInOrder()) {\n\t\t\thelper.console.displayEmptyLine();\n\t\t\thelper.console.displayRaw(task.getDescription() + \"  \");\n\t\t\t\n\t\t\tTigaseInstallerDBHelper.MsgTarget msgTarget = new TigaseInstallerDBHelper.MsgTarget() {\n\t\t\t\tpublic ResultMessage addResultMessage() {\n\t\t\t\t\thelper.console.displayEmptyLine();\n\t\t\t\t\treturn new ResultMessage() {\n\t\t\t\t\t\tpublic void append(String msg) {\n\t\t\t\t\t\t\thelper.console.displayRaw(msg);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttask.execute(dbHelper, installData.getVariables(), msgTarget);\n\t\t}\n\t\t\n\t\thelper.console.displayEmptyLine();\n\t\thelper.console.displayEmptyLine();\n\t\thelper.console.displayEmptyLine();\n\n\t\treturn true;\n\t}\n\n\n\t\n\t// not implemented\n\t\n\tpublic boolean runConsoleFromPropertiesFile(\n\t\t\tAutomatedInstallData installData, Properties p) {\n\t\treturn false;\n\t}\n\n\tpublic boolean runGeneratePropertiesFile(AutomatedInstallData installData,\n\t\t\tPrintWriter printWriter) {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseInstallerCommon.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.InputStream;\n\nimport com.izforge.izpack.LocaleDatabase;\nimport com.izforge.izpack.installer.ResourceManager;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.util.Debug;\n\nclass TigaseInstallerCommon {\n\n\tprivate static AutomatedInstallData installerData;\n\n\tpublic static AutomatedInstallData init(AutomatedInstallData iData) {\n\t\tinsertResource(iData.langpack);\n\t\tinstallerData = iData;\n\t\treturn iData;\n\t}\n\n\tpublic static InstallData init(InstallData iData) {\n\t\tinsertResource(iData.langpack);\n\t\tinstallerData = iData;\n\t\treturn iData;\n\t}\n\n\tpublic static AutomatedInstallData getInstallData() {\n\t\treturn installerData;\n\t}\n\n\tprivate final static String LANG_FILE_NAME = \"panelsLangPack.xml\";\n\tprivate static void insertResource(LocaleDatabase langpack) {\n\t\ttry {\n\t\t\tInputStream inputStream =\n\t\t\t\tResourceManager.getInstance().getInputStream(LANG_FILE_NAME);\n\t\t\tlangpack.add(inputStream);\n\t\t}\n\t\tcatch (Exception exc) {\n\t\t\tDebug.trace(exc);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseInstallerDBHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.BufferedReader;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.LinkedHashSet;\nimport java.util.Properties;\nimport java.util.Set;\n\nimport tigase.db.DBInitException;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.AuthRepository;\nimport tigase.db.UserExistsException;\nimport tigase.xmpp.BareJID;\n\nimport com.izforge.izpack.installer.ResourceManager;\nimport com.izforge.izpack.installer.ResourceNotFoundException;\nimport com.izforge.izpack.installer.AutomatedInstallData;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.installer.IzPanel;\nimport com.izforge.izpack.util.Debug;\nimport com.izforge.izpack.util.VariableSubstitutor;\nimport java.io.*;\nimport java.net.URLEncoder;\nimport java.sql.DatabaseMetaData;\nimport java.sql.Driver;\nimport java.sql.SQLException;\nimport java.util.Enumeration;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n\n\nclass TigaseInstallerDBHelper {\n\n\tprivate boolean schema_ok = false;\n\tprivate boolean connection_ok = false;\n\tprivate boolean db_ok = false;\n\tprivate String schema_ver_query = TigaseConfigConst.DERBY_GETSCHEMAVER_QUERY;\n\tprivate String res_prefix = \"\";\n\tprivate boolean schema_exists = false;\n\tprivate String schema_version;\n\n\tprivate AutomatedInstallData iData;\n\n\tprivate VariablesSource variablesSource;\n\n\n\n\tstatic final int DB_CONNEC_POS = 0;\n\tstatic final int DB_EXISTS_POS = 1;\n\tstatic final int DB_SCHEMA_POS = 2;\n\tstatic final int DB_CONVER_POS = 3;\n\n\n\tenum SQL_LOAD_STATE {\n\t\tINIT, IN_SQL;\n\t}\n\n\tpublic TigaseInstallerDBHelper() {\n\t\tiData = TigaseInstallerCommon.getInstallData();\n\t\tvariablesSource = new IzPackInstallDataVariablesSource(iData);\n\t}\n\n\n\n\n\tprivate ArrayList<String> loadSQLQueries(\n\t\t\tString resource,\n\t\t\tString res_prefix,\n\t\t\tProperties variables)\n\t\t\tthrows Exception\n\t\t\t{\n\t\tArrayList<String> results = new ArrayList<String>();\n\t\tVariableSubstitutor vs = new VariableSubstitutor(variables);\n\t\tBufferedReader br;\n\n\t\tif ( res_prefix == null ){\n\t\t\tbr = new BufferedReader( new InputStreamReader( getResourcePath( resource ) ) );\n\t\t} else {\n\t\t\tbr = new BufferedReader( new InputStreamReader( getResource( resource ) ) );\n\t\t}\n\n\t\tString line = null;\n\t\tString sql_query = \"\";\n\t\tSQL_LOAD_STATE state = SQL_LOAD_STATE.INIT;\n\t\twhile ((line = br.readLine()) != null) {\n\t\t\tswitch (state) {\n\t\t\tcase INIT:\n\t\t\t\tif (line.startsWith(\"-- QUERY START:\")) {\n\t\t\t\t\tsql_query = \"\";\n\t\t\t\t\tstate = SQL_LOAD_STATE.IN_SQL;\n\t\t\t\t}\n\t\t\t\tif (line.startsWith(\"-- LOAD SCHEMA:\")) {\n\t\t\t\t\tresults.addAll(loadSchemaQueries(res_prefix, variables));\n\t\t\t\t}\n\t\t\t\tif (  line.startsWith( \"-- LOAD FILE:\" )  && line.trim().contains( \"sql\" ) )\n\t\t\t\t{\n\t\t\t\t\tMatcher matcher = Pattern.compile( \"-- LOAD FILE:.*\" + res_prefix + \"-(.*).sql\" ).matcher( line );\n\t\t\t\t\tif ( matcher.find() ){\n\t\t\t\t\t\tDebug.trace( String.format( \"\\n\\n *** trying to load schema: %1$s \\t\", matcher.group( 1 ) ) );\n\t\t\t\t\t\tresults.addAll( loadSQLQueries( res_prefix + \"-\" + matcher.group( 1 ), res_prefix, variables ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase IN_SQL:\n\t\t\t\tif (line.startsWith(\"-- QUERY END:\")) {\n\t\t\t\t\tstate = SQL_LOAD_STATE.INIT;\n\t\t\t\t\tsql_query = sql_query.trim();\n\t\t\t\t\tif (sql_query.endsWith(\";\")) {\n\t\t\t\t\t\tsql_query = sql_query.substring(0, sql_query.length()-1);\n\t\t\t\t\t}\n\t\t\t\t\tif (sql_query.endsWith(\"//\")) {\n\t\t\t\t\t\tsql_query = sql_query.substring(0, sql_query.length()-2);\n\t\t\t\t\t}\n\t\t\t\t\tresults.add(vs.substitute(sql_query, null));\n\t\t\t\t}\n                                if ((line.trim().startsWith(\"source\") || line.trim().startsWith(\"run\") || line.trim().startsWith(\"\\\\i\"))\n                                        && line.trim().contains(\"sql\")) {\n\n                                        Matcher matcher = Pattern.compile(res_prefix + \"-(.*).sql\").matcher(line);\n                                        if (matcher.find()) {\n                                            Debug.trace(String.format(\"\\n\\n *** trying to load schema: %1$s \\t\", matcher.group(1)));\n                                            results.addAll(loadSQLQueries(res_prefix + \"-\" + matcher.group(1), res_prefix, variables));\n                                        }\n                                        continue;\n                                }\n\t\t\t\tif (line.isEmpty() || line.trim().startsWith(\"--\")) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tsql_query += \" \" + line.trim();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbr.close();\n\t\treturn results;\n\t\t\t}\n\n\n\tprotected InputStream getResourcePath(String resource)\n\tthrows ResourceNotFoundException {\n\n\n\t\tFile f = new File( resource );\n\t\tInputStream is = null;\n\t\tDebug.trace(String.format( \"Getting resource: %1$s @ filename: %2$s\",resource, f.getAbsolutePath() ));\n\t\ttry {\n\t\t\tis = new FileInputStream( f );\n\t\t} catch ( FileNotFoundException ex ) {\n\t\t\tthrow new ResourceNotFoundException(\"could not find: \" + resource );\n\t\t}\n\t\treturn is;\n\t}\n\n\tprotected InputStream getResource(String resource)\n\tthrows ResourceNotFoundException {\n\t\treturn ResourceManager.getInstance().getInputStream(resource);\n\t}\n\n        private ArrayList<String> loadSchemaQueries(\n                String res_prefix,\n                Properties variables)\n                throws Exception {\n\n            ArrayList<String> queries = new ArrayList<String>();\n            queries.addAll(loadSQLQueries(res_prefix + \"-schema-7-1-schema\", res_prefix, variables));\n            queries.addAll(loadSQLQueries(res_prefix + \"-schema-7-1-sp\", res_prefix, variables));\n            queries.addAll(loadSQLQueries(res_prefix + \"-schema-7-1-props\", res_prefix, variables));\n\n//\t\t\tSystem.out.println( \"Socks5component variable: \" + variablesSource.getVariable(TigaseConfigConst.SOCKS5_COMP) );\n\n            return queries;\n        }\n\n\tpublic void validateDBConnection(TigaseInstallerDBHelper.MsgTarget msgTarget) {\n\t\tconnection_ok = false;\n\t\tString db_conn = TigaseConfigConst.props.getProperty(\"root-db-uri\");\n\t\tDebug.trace(\"validateDBConnection (root-db-uri): \" + db_conn);\n\t\tif (db_conn == null) {\n\t\t\tmsgTarget.addResultMessage().append(\"Missing DB connection URL\");\n\t\t\treturn;\n\t\t} else {\n\t\t\tselectDatabase(db_conn);\n\t\t\ttry {\n\t\t\t\tEnumeration<Driver> drivers = DriverManager.getDrivers();\n\t\t\t\twhile (drivers.hasMoreElements()) {\n\t\t\t\t\tDebug.trace(\"DriverManager (drivers): \" + drivers.nextElement().toString());\n\t\t\t\t}\n\t\t\t\tDebug.trace(\"DriverManager (drivers end):\");\n\t\t\t\tConnection conn = DriverManager.getConnection(db_conn);\n\t\t\t\tconn.close();\n\t\t\t\tconnection_ok = true;\n\t\t\t\tmsgTarget.addResultMessage().append(\"Connection OK\");\n\t\t\t\treturn;\n\t\t\t} catch (Exception e) {\n\t\t\t\t//e.printStackTrace();\n\t\t\t\tmsgTarget.addResultMessage().append(e.getMessage());\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void selectDatabase(String db_uri) {\n\t\tDebug.trace(\"selectDatabase (db_uri): \" + db_uri);\n\t\tschema_ver_query = TigaseConfigConst.JDBC_GETSCHEMAVER_QUERY;\n\t\tString driverClass = null;\n\t\tif (db_uri.startsWith(\"jdbc:postgresql\")) {\n\t\t\tdriverClass = TigaseConfigConst.PGSQL_DRIVER;\n\t\t\tSystem.setProperty(\"jdbc.drivers\", driverClass);\n\t\t\tres_prefix = \"postgresql\";\n\t\t}\n\t\tif (db_uri.startsWith(\"jdbc:sqlserver\") || db_uri.startsWith(\"jdbc:jtds:sqlserver\")) {\n\t\t\tdriverClass = TigaseConfigConst.SQLSERVER_DRIVER;\n\t\t\tSystem.setProperty(\"jdbc.drivers\", driverClass);\n\t\t\tres_prefix = \"sqlserver\";\n\t\t\tschema_ver_query = TigaseConfigConst.SQLSERVER_GETSCHEMAVER_QUERY;\n\t\t}\n\t\tif (db_uri.startsWith(\"jdbc:mysql\")) {\n\t\t\tdriverClass = TigaseConfigConst.MYSQL_DRIVER;\n\t\t\tSystem.setProperty(\"jdbc.drivers\", driverClass);\n\t\t\tres_prefix = \"mysql\";\n\t\t}\n\t\tif (db_uri.startsWith(\"jdbc:derby\")) {\n\t\t\tdriverClass = TigaseConfigConst.DERBY_DRIVER;\n\t\t\tSystem.setProperty(\"jdbc.drivers\", driverClass);\n\t\t\tres_prefix = \"derby\";\n\t\t\tschema_ver_query = TigaseConfigConst.DERBY_GETSCHEMAVER_QUERY;\n\t\t}\n\t\tDriver driver;\n\t\ttry {\n\n\t\t\tDebug.trace(\"selectDatabase (jdbc.drivers): \" + System.getProperty( \"jdbc.drivers\" ));\n\t\t\tDebug.trace(\"selectDatabase (res_prefix): \" + res_prefix);\n\t\t\tDebug.trace(\"selectDatabase (schema_ver_query): \" + schema_ver_query);\n\n\t\t\tdriver = (Driver) Class.forName(driverClass).newInstance();\n\t\t\tDebug.trace(\"selectDatabase (driver): \" + driver.toString());\n\t\t\tDebug.trace(\"selectDatabase (driver.acceptsURL): \" + driver.acceptsURL( db_uri));\n\n\t\t\tDriverManager.registerDriver(driver);\n\t\t} catch ( Exception ex ) {\n\t\t\tLogger.getLogger( TigaseInstallerDBHelper.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\t}\n\n\tpublic void validateDBExists(Properties variables, MsgTarget msgTarget) {\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\n\t\tdb_ok = false;\n\t\tString db_conn = TigaseConfigConst.props.getProperty(\"--user-db-uri\");\n\t\tDebug.trace(\"validateDBExists (--user-db-uri): \" + db_conn);\n\t\tif (db_conn == null) {\n\t\t\tmsgTarget.addResultMessage().append(\"Missing DB connection URL\");\n\t\t\treturn;\n\t\t} else {\n\t\t\tConnection conn = null;\n\t\t\ttry {\n\t\t\t\tconn = DriverManager.getConnection(db_conn);\n\t\t\t\tconn.close();\n\t\t\t\tdb_ok = true;\n\t\t\t\tmsgTarget.addResultMessage().append(\"Exists OK\");\n\t\t\t\treturn;\n\t\t\t} catch (Exception e) {\n\t\t\t\tResultMessage resulMessage = msgTarget.addResultMessage();\n\t\t\t\tresulMessage.append(\"Doesn't exist\");\n\t\t\t\tresulMessage.append(\", creating...\");\n\n\t\t\t\tdb_conn = TigaseConfigConst.props.getProperty(\"root-db-uri\");\n\t\t\t\ttry {\n                                    conn = DriverManager.getConnection(db_conn);\n                                    ArrayList<String> queries = loadSQLQueries(res_prefix + \"-installer-create-db\", res_prefix, variables);\n                                    queries.add(\"commit\");\n                                    for (String query : queries) {\n                                        Debug.trace(\"validateDBExists -- Executing query: \" + query);\n                                        if (!query.isEmpty()) {\n                                            Statement stmt = conn.createStatement();\n                                            // Some queries may fail and this is still fine\n                                            // the user or the database may already exist\n                                            try {\n                                                stmt.execute(query);\n                                                stmt.close();\n                                            } catch (Exception ex) {\n                                                Debug.trace(\"Query failed: \" + ex.getMessage());\n                                            }\n                                        }\n                                    }\n                                    conn.close();\n                                    resulMessage.append(\" OK\");\n                                    db_ok = true;\n\t\t\t\t} catch (Exception ex) {\n                                    resulMessage.append(ex.getMessage());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void validateDBConversion(Properties variables, TigaseInstallerDBHelper.MsgTarget msgTarget) {\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (schema_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Conversion not needed\");\n\t\t\treturn;\n\t\t}\n\t\tif (!schema_exists) {\n\t\t\tmsgTarget.addResultMessage().append(\"Something wrong, the schema still is not loaded...\");\n\t\t\treturn;\n\t\t}\n\t\tString db_conn = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\tDebug.trace(\"validateDBConversion (root-tigase-db-uri): \" + db_conn);\n\t\ttry {\n\t\t\t//conn.close();\n                        ResultMessage resultMessage = msgTarget.addResultMessage();\n                        resultMessage.append(\"Converting...\");\n\n                        Connection conn = DriverManager.getConnection(db_conn);\n                        Statement stmt = conn.createStatement();\n\n                        ArrayList<String> queries = null;\n\n                        if (schema_version == null) {\n                            queries = loadSQLQueries(res_prefix + \"-schema-upgrade-to-4\", res_prefix, variables);\n                        }\n\n                        if (\"4.0\".equals(schema_version)) {\n                            queries = loadSQLQueries(res_prefix + \"-schema-upgrade-to-5-1\", res_prefix, variables);\n                        }\n                        if (\"5.1\".equals(schema_version)) {\n                            queries = loadSQLQueries(res_prefix + \"-schema-upgrade-to-7-1\", res_prefix, variables);\n                        }\n                        for (String query : queries) {\n                            if (!query.isEmpty()) {\n                                Debug.trace(\"validateDBConversion :: Executing query: \" + query);\n                                stmt.execute(query);\n                            }\n                        }\n\n\t\t\tstmt.close();\n\t\t\tconn.close();\n\t\t\tschema_ok = true;\n\t\t\tresultMessage.append(\" completed OK\");\n\t\t} catch (Exception ex) {\n\t\t\tmsgTarget.addResultMessage().append(\"Can't upgrade schema: \" + ex.getMessage());\n\t\t\treturn;\n\t\t}\n\t}\n\n\tpublic void validateDBSchema(Properties variables, MsgTarget msgTarget) {\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\t\tschema_exists = false;\n\t\tschema_ok = false;\n\t\tConnection conn = null;\n\t\tString db_conn = TigaseConfigConst.props.getProperty(\"--user-db-uri\");\n\t\tDebug.trace(\"validateDBSchema (--user-db-uri): \" + db_conn);\n\t\tlong users = 0;\n\t\ttry {\n\t\t\tconn = DriverManager.getConnection(db_conn);\n\t\t\tStatement stmt = conn.createStatement();\n\n\t\t\tString query = TigaseConfigConst.JDBC_CHECKUSERTABLE_QUERY;\n\t\t\tResultSet rs = stmt.executeQuery(query);\n\t\t\tif (rs.next()) {\n\t\t\t\tusers = rs.getLong(1);\n\t\t\t\tschema_exists = true;\n\t\t\t\tDebug.trace(\"Schema exists, users: \" + users);\n\t\t\t}\n\n\t\t\tquery = schema_ver_query;\n\t\t\trs = stmt.executeQuery(query);\n\t\t\tif (rs.next()) {\n\t\t\t\tschema_version = rs.getString(1);\n\t\t\t\tif (\"5.1\".equals(schema_version)) {\n\t\t\t\t\tschema_ok = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tDebug.trace(\"Exception, posibly schema hasn't been loaded yet: \" + e);\n\t\t}\n\t\tif (schema_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Schema OK, accounts number: \" + users);\n\t\t\treturn;\n\t\t}\n\t\tif (!schema_exists) {\n\t\t\tDebug.trace(\"DB schema doesn't exists, creating one...\");\n\t\t\tdb_conn = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\t\tDebug.trace(\"validateDBSchema (root-tigase-db-uri): \" + db_conn);\n\t\t\ttry {\n                            //conn.close();\n                            conn = DriverManager.getConnection(db_conn);\n                            Statement stmt = conn.createStatement();\n                            ArrayList<String> queries = loadSchemaQueries(res_prefix, variables);\n\n                            for (String query : queries) {\n                                if (!query.isEmpty()) {\n                                    Debug.trace(\"validateDBSchema -- Executing query: \" + query);\n                                    stmt.execute(query);\n                                }\n                            }\n                            stmt.close();\n                            conn.close();\n                            schema_ok = true;\n                            msgTarget.addResultMessage().append(\"New schema loaded OK\");\n                            return;\n                    } catch (Exception ex) {\n                        msgTarget.addResultMessage().append(\"Can't load schema: \" + ex.getMessage());\n                        return;\n                    }\n\t\t} else {\n\t\t\tmsgTarget.addResultMessage().append(\"Old schema, accounts number: \" + users);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tpublic void postInstallation(Properties variables, TigaseInstallerDBHelper.MsgTarget msgTarget) {\n\n\t\t// part 1, check db preconditions\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (!schema_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database schema is invalid\");\n\t\t\treturn;\n\t\t}\n\n\t\t// part 2, acquire reqired fields and validate them\n                String db_conn = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\t\t\tDebug.trace(\"postInstallation (root-tigase-db-uri): \" + db_conn);\n                try {\n                    //conn.close();\n                    TigaseInstallerDBHelper.ResultMessage resultMessage = msgTarget.addResultMessage();\n                    resultMessage.append(\"Finalizing...\");\n\n                    Connection conn = DriverManager.getConnection(db_conn);\n                    Statement stmt = conn.createStatement();\n\n                    ArrayList<String> queries = loadSQLQueries(res_prefix + \"-installer-post\", res_prefix, variables);\n                    for (String query : queries) {\n                        if (!query.isEmpty()) {\n                            Debug.trace(\"postInstallation :: Executing query: \" + query);\n                            stmt.execute(query);\n                        }\n                    }\n\n                    stmt.close();\n                    conn.close();\n                    schema_ok = true;\n                    resultMessage.append(\" completed OK\");\n                } catch (Exception ex) {\n                    msgTarget.addResultMessage().append(\"Can't finalize: \" + ex.getMessage());\n                    return;\n                }\n\t}\n\n\tpublic void socks5SchemaLoad(Properties variables, TigaseInstallerDBHelper.MsgTarget msgTarget) {\n\n\t\tString socks5 = variablesSource.getVariable(TigaseConfigConst.SOCKS5_COMP);\n\t\tboolean installSocks5 = socks5.equals(\"on\") ? true : false ;\n\n\t\t// part 1, check db preconditions\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\t\tDebug.trace(\"socks5Component variable state: \" + socks5 + \" \" + installSocks5);\n\t\tif ( !installSocks5 ) {\n\t\t\tmsgTarget.addResultMessage().append(\"Socks5 component not selected, skipping schema load\");\n\t\t\treturn;\n\t\t}\n                String db_conn = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\t\t\tDebug.trace(\"socks5SchemaLoad (root-tigase-db-uri): \" + db_conn);\n                try {\n                    //conn.close();\n                    TigaseInstallerDBHelper.ResultMessage resultMessage = msgTarget.addResultMessage();\n                    resultMessage.append(\"Loading socks5 schema...\");\n\n                    Connection conn = DriverManager.getConnection(db_conn);\n\n\t\t\t\t\tDatabaseMetaData dbm = conn.getMetaData();\n\t\t\t\t\tResultSet tables = dbm.getTables(null, null, \"tig_socks5_users\", null);\n\t\t\t\t\tResultSet tables_derby = dbm.getTables(null, null, \"TIG_SOCKS5_USERS\", null);\n\t\t\t\t\tif (tables.next()) {\n\t\t\t\t\t\t// Table exists\n\t\t\t\t\t\tmsgTarget.addResultMessage().append(\"Socks5 schema exists, skipping schema load\");\n\t\t\t\t\t} else if (tables_derby.next()) {\n\t\t\t\t\t\t// Table exists\n\t\t\t\t\t\tmsgTarget.addResultMessage().append(\"Socks5 schema exists, skipping schema load\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Table does not exist\n\t\t\t\t\t\tStatement stmt = conn.createStatement();\n\n\t\t\t\t\t\tArrayList<String> queries = loadSQLQueries(res_prefix + \"-socks5-schema\", res_prefix, variables);\n\t\t\t\t\t\tfor (String query : queries) {\n\t\t\t\t\t\t\tif (!query.isEmpty()) {\n\t\t\t\t\t\t\t\tDebug.trace(\"socks5 schema :: Executing query: \" + query);\n\t\t\t\t\t\t\t\tstmt.execute(query);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresultMessage.append(\" completed OK\");\n\t\t\t\t\t\tstmt.close();\n\t\t\t\t\t}\n\n                    conn.close();\n                } catch (Exception ex) {\n                    msgTarget.addResultMessage().append(\"Can't load socks5 schema: \" + ex.getMessage());\n\t\t\t\t\tDebug.trace(\"Can't load socks5 schema: \" + ex.getMessage());\n                    return;\n                }\n\t}\n\n\tpublic void pubsubSchemaLoad(Properties variables, TigaseInstallerDBHelper.MsgTarget msgTarget) {\n\n\t\tString pubsub = variablesSource.getVariable(TigaseConfigConst.PUBSUB_COMP);\n\t\tDebug.trace(\"PubSub variable state: \" + pubsub);\n\t\tboolean installPubSub = (pubsub != null && pubsub.equals(\"on\")) ? true : false ;\n\n\t\t// part 1, check db preconditions\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\t\tDebug.trace(\"PubSub variable state: \" + pubsub + \" \" + installPubSub);\n\t\tif ( !installPubSub ) {\n\t\t\tmsgTarget.addResultMessage().append(\"PubSub component not selected, skipping schema load\");\n\t\t\treturn;\n\t\t}\n                String db_conn = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\t\t\tDebug.trace(\"PubSubSchemaLoad (root-tigase-db-uri): \" + db_conn);\n                try {\n                    //conn.close();\n                    TigaseInstallerDBHelper.ResultMessage resultMessage = msgTarget.addResultMessage();\n                    resultMessage.append(\"Loading PubSub schema...\");\n\n                    Connection conn = DriverManager.getConnection(db_conn);\n\n\t\t\t\t\tDatabaseMetaData dbm = conn.getMetaData();\n\t\t\t\t\tResultSet tables = dbm.getTables(null, null, \"tig_pubsub_nodes\", null);\n\t\t\t\t\tResultSet tables_derby = dbm.getTables(null, null, \"tig_pubsub_nodes\".toUpperCase(), null);\n\t\t\t\t\tif (tables.next()) {\n\t\t\t\t\t\t// Table exists\n\t\t\t\t\t\tmsgTarget.addResultMessage().append(\"PubSub schema exists, skipping schema load\");\n\t\t\t\t\t} else if (tables_derby.next()) {\n\t\t\t\t\t\t// Table exists\n\t\t\t\t\t\tmsgTarget.addResultMessage().append(\"PubSub schema exists, skipping schema load\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Table does not exist\n\t\t\t\t\t\tStatement stmt = conn.createStatement();\n\n\t\t\t\t\t\tArrayList<String> queries;\n\t\t\t\t\t\t\t\t\t\t\tqueries = loadSQLQueries(res_prefix + \"-pubsub-schema-3-2\", res_prefix, variables);\n//\t\t\t\t\t\tqueries.addAll( loadSQLQueries(res_prefix + \"-pubsub-schema-3-1\", res_prefix, variables) );\n\t\t\t\t\t\tfor (String query : queries) {\n\t\t\t\t\t\t\tif (!query.isEmpty()) {\n\t\t\t\t\t\t\t\tDebug.trace(\"pubsub schema :: Executing query: \" + query);\n\t\t\t\t\t\t\t\tstmt.execute(query);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresultMessage.append(\" completed OK\");\n\t\t\t\t\t\tstmt.close();\n\t\t\t\t\t}\n\n                    conn.close();\n                } catch (Exception ex) {\n                    msgTarget.addResultMessage().append(\"Can't load PubSub schema: \" + ex.getMessage());\n\t\t\t\t\tDebug.trace(\"Can't load PubSub schema: \" + ex.getMessage());\n                    return;\n                }\n\t}\n\n\tprotected void addXmppAdminAccount(Properties variables,\n\t\t\tMsgTarget msgTarget) {\n\n\n\t\t// part 1, check db preconditions\n\t\tif (!connection_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Connection not validated\");\n\t\t\treturn;\n\t\t}\n\t\tif (!db_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database not validated\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (!schema_ok) {\n\t\t\tmsgTarget.addResultMessage().append(\"Database schema is invalid\");\n\t\t\treturn;\n\t\t}\n\n\t\t// part 2, acquire reqired fields and validate them\n\t\tObject admins = variables.get(\"admins\");\n\t\tSet<BareJID> jids = new LinkedHashSet<BareJID>();\n\t\tif (admins != null) {\n\t\t\tString[] adminsStr = admins.toString().split(\",\");\n\t\t\tfor (String adminStr : adminsStr) {\n\t\t\t\tString jid = adminStr.trim();\n\t\t\t\tif (jid != null && !jid.equals(\"\")) {\n\t\t\t\t\tjids.add(BareJID.bareJIDInstanceNS(jid));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (jids.size() < 1) {\n\t\t\tmsgTarget.addResultMessage().append(\"Error: No admin users entered\");\n\t\t\treturn;\n\t\t}\n\n\t\tObject pwdObj = variables.get(\"adminsPwd\");\n\t\tif (pwdObj == null) {\n\t\t\tmsgTarget.addResultMessage().append(\"Error: No admin password enetered\");\n\t\t\treturn;\n\t\t}\n\t\tString pwd = pwdObj.toString();\n\n\t\tString className = TigaseConfigConst.props.getProperty(\"--auth-db\");\n\t\t// currently Tigase use \"tigase.db.jdbc.TigaseCustomAuth\" if no --auth-db was configured\n\t\t// if (className == null)\n\t\t//\tclassName = TigaseConfigConst.props.getProperty(\"--user-db\");\n\t\tString resource = TigaseConfigConst.props.getProperty(\"--auth-db-uri\");\n\t\tDebug.trace(\"addXmppAdminAccount (--auth-db-uri): \" + resource);\n\t\tif (resource == null)\n\t\t\tresource = TigaseConfigConst.props.getProperty(\"root-tigase-db-uri\");\n\t\t\tDebug.trace(\"addXmppAdminAccount (root-tigase-db-uri): \" + resource);\n\n\t\ttry {\n\t\t\tDebug.trace(\"RepositoryFactory.getAuthRepository(\" + className + \", \" + resource + \",  + null)\" );\n\t\t\tSystem.setProperty( RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, \"1\" );\n\t\t\tAuthRepository repo = RepositoryFactory.getAuthRepository(\n\t\t\t\t\tclassName, resource, null);\n\n\t\t\tfor (BareJID jid : jids) {\n\t\t\t\ttry {\n\t\t\t\t\trepo.addUser(jid, pwd);\n\t\t\t\t} catch (UserExistsException e) {\n\t\t\t\t\t// user is already there, we swallow the exception\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmsgTarget.addResultMessage().append(\"All users added\");\n\n\t\t} catch (DBInitException e) {\n\t\t\tmsgTarget.addResultMessage().append(\"Error initializing DB\");\n\t\t\tDebug.trace(\"DBInitException: \" + e);\n\t\t} catch (TigaseDBException e) {\n\t\t\tmsgTarget.addResultMessage().append(\"DB error: \" + e.getMessage());\n\t\t\tDebug.trace(\"TigaseDBException: \" + e);\n\t\t} catch (ClassNotFoundException e) {\n\t\t\tmsgTarget.addResultMessage().append(\"Error locating connector\");\n\t\t\tDebug.trace(\"ClassNotFoundException: \" + e);\n\t\t} catch (InstantiationException e) {\n\t\t\tmsgTarget.addResultMessage().append(\"Error initializing connector\");\n\t\t\tDebug.trace(\"InstantiationException: \" + e);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tmsgTarget.addResultMessage().append(\"Illegal access\");\n\t\t\tDebug.trace(\"IllegalAccessException: \" + e);\n\t\t}\n\t}\n\n\n\tenum Tasks implements TigaseDBTask {\n\t\tVALIDATE_CONNECTION(\"Checking connection to the database\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.validateDBConnection(msgTarget);\n\t\t\t}\n\t\t},\n\t\tVALIDATE_DB_EXISTS(\"Checking if the database exists\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.validateDBExists(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tVALIDATE_DB_SCHEMA(\"Checking the database schema\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.validateDBSchema(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tVALIDATE_DB_CONVERSION(\"Checking whether the database needs conversion\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.validateDBConversion(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tADD_ADMIN_XMPP_ACCOUNT(\"Adding XMPP admin accounts\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.addXmppAdminAccount(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tSOCKS5_COMPONENT(\"Loading socks5 component schema\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.socks5SchemaLoad(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tPUBSUB_COMPONENT(\"Loading PubSub component schema\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.pubsubSchemaLoad(variables, msgTarget);\n\t\t\t}\n\t\t},\n\t\tPOST_INSTALLATION(\"Post installation actions\") {\n\t\t\tpublic void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget) {\n\t\t\t\thelper.postInstallation(variables, msgTarget);\n\t\t\t}\n\t\t}\n\n\n//\t\t\t\tSystem.out.println( \"Socks5component variable: \" + variablesSource.getVariable(TigaseConfigConst.SOCKS5_COMP) );\n//\t\tDebug.trace( \"Socks5component variable: \" + variablesSource.getVariable(TigaseConfigConst.SOCKS5_COMP) );\n\n\t\t;\n\n\t\tprivate final String description;\n\n\t\tprivate Tasks(String description) {\n\t\t\tthis.description = description;\n\t\t}\n\n\t\tpublic String getDescription() {\n\t\t\treturn description;\n\t\t}\n\n\t\t// override to change order\n\t\tpublic static TigaseDBTask[] getTasksInOrder() {\n\t\t\treturn values();\n\t\t}\n\t}\n\n\n\tstatic interface TigaseDBTask {\n\t\tString getDescription();\n\t\tabstract void execute(TigaseInstallerDBHelper helper, Properties variables, MsgTarget msgTarget);\n\t}\n\n\tstatic interface MsgTarget {\n\t\tabstract ResultMessage addResultMessage();\n\t}\n\n\tstatic interface ResultMessage {\n\t\tvoid append(String msg);\n\t}\n\n}\n\n\nabstract class VariablesSource {\n\tabstract String getVariable(String key);\n\tabstract String getEncodedVariable(String key);\n}\n\nclass IzPackInstallDataVariablesSource extends VariablesSource {\n\tprivate final AutomatedInstallData idata;\n\n\tpublic IzPackInstallDataVariablesSource(AutomatedInstallData idata) {\n\t\tthis.idata = idata;\n\n\t}\n\n\t@Override\n\tString getVariable(String key) {\n\t\treturn idata.getVariable(key);\n\t}\n\n\t@Override\n\tString getEncodedVariable(String key) {\n\n\t\tString variable = idata.getVariable(key);\n\t\tString value = null;\n\t\ttry {\n\t\t\tvalue = URLEncoder.encode(variable, \"UTF-8\");\n\t\t} catch ( Exception ex ) {\n\t\t\tLogger.getLogger( TigaseInstallerDBHelper.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\t\treturn value;\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseInstallerDbHelperFunctionalTest.java",
    "content": "package com.izforge.izpack.panels;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport com.izforge.izpack.installer.ResourceNotFoundException;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.MsgTarget;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.ResultMessage;\nimport com.izforge.izpack.panels.TigaseInstallerDBHelper.TigaseDBTask;\n\npublic class TigaseInstallerDbHelperFunctionalTest {\n\n\tpublic static void main(String[] args) throws ClassNotFoundException {\n\t\t testPostgres();\n\t}\n\n\t// values\n\t// TigaseConfigConst.getProperty\n\t// root-db-uri jdbc:postgresql://localhost/postgres?user=postgres&password=1\n\t// root-tigase-db-uri jdbc:postgresql://localhost/tigasedb?user=postgres&password=1\n\t// --auth-db null \n\t// --user-db null\n\t// --auth-db-uri \n\t// --user-db-uri  jdbc:postgresql://localhost/tigasedb?user=tigase&password=tigase12\n\t//\n\t// variables:\n\t// admins: admin@mateusz-latop\n\t// adminsPwd: tigase\n\n\tprivate static void testPostgres() throws ClassNotFoundException {\n\n\t\tProperties variables = new Properties();\n\t\tvariables.put(\"admins\", \"admin@mateusz-laptop\");\n\t\tvariables.put(\"adminsPwd\", \"tigase\");\n\t\tvariables.put(\"dbName\", \"tigasedb\");\n\t\tvariables.put(\"dbUser\", \"tigase\");\n\t\tvariables.put(\"dbPass\", \"tigase12\");\n\t\t\n\t\tTigaseConfigConst.props.put(\"root-db-uri\", \"jdbc:postgresql://localhost/postgres?user=postgres&password=1\");\n\t\tTigaseConfigConst.props.put(\"root-tigase-db-uri\", \"jdbc:postgresql://localhost/tigasedb?user=postgres&password=1\");\n\t\tTigaseConfigConst.props.put(\"--user-db-uri\", \"jdbc:postgresql://localhost/tigasedb?user=tigase&password=tigase12\");\n\t\tTigaseConfigConst.props.put(\"--user-db\", \"pgsql\");\n\n\t\tfinal String databaseScriptsDir = \"/home/mateusz/projects/tigase-server/database\";\n\t\tfinal Map<String, String> resourceMappings = new HashMap<String, String>();\n\t\tresourceMappings.put(\"pgsql.create\", \"postgresql-create-db.sql\");\n\t\tresourceMappings.put(\"pgsql.schema\", \"postgresql-schema-4.sql\");\n\t\tresourceMappings.put(\"pgsql.sp\", \"postgresql-schema-4-sp.schema\");\n\t\tresourceMappings.put(\"pgsql.props\", \"postgresql-schema-4-props.sql\");\n\n\t\tTigaseInstallerDBHelper helper = new TigaseInstallerDBHelper() {\n\t\t\n\t\t\tprotected java.io.InputStream getResource(String resource) \n\t\t\tthrows ResourceNotFoundException {\n\t\t\t\tString realResource = resourceMappings.get(resource);\n\t\t\t\tFile resFile = new File(databaseScriptsDir, realResource);\n\t\t\t\ttry {\n\t\t\t\t\treturn new FileInputStream(resFile);\n\t\t\t\t} catch (FileNotFoundException e) {\n\t\t\t\t\tthrow new ResourceNotFoundException();\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t};\n\n\t\t\n\t\tfor (final TigaseDBTask task : TigaseInstallerDBHelper.Tasks\n\t\t\t\t.getTasksInOrder()) {\n\t\t\tMsgTarget msgTarget = new MsgTarget() {\n\t\t\t\tpublic ResultMessage addResultMessage() {\n\t\t\t\t\tSystem.out.println(\"Task: \" + task.getDescription() + \" \");\n\t\t\t\t\treturn new ResultMessage() {\n\t\t\t\t\t\tpublic void append(String msg) {\n\t\t\t\t\t\t\tSystem.out.print(msg);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttask.execute(helper, variables, msgTarget);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseJDKPathPanel.java",
    "content": "/*\n * $Id: JDKPathPanel.java 2163 2008-05-18 13:48:36Z jponge $\n * IzPack - Copyright 2001-2012 Julien Ponge, All Rights Reserved.\n * \n * http://izpack.org/\n * http://izpack.codehaus.org/\n * \n * Copyright 2004 Klaus Bartz\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *     http://www.apache.org/licenses/LICENSE-2.0\n *     \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.izforge.izpack.panels;\n\nimport java.io.BufferedReader;\n\nimport com.coi.tools.os.win.MSWinConstants;\nimport com.coi.tools.os.win.NativeLibException;\nimport com.izforge.izpack.installer.InstallData;\nimport com.izforge.izpack.installer.InstallerFrame;\nimport com.izforge.izpack.util.Debug;\nimport com.izforge.izpack.util.VariableSubstitutor;\nimport com.izforge.izpack.util.AbstractUIHandler;\nimport com.izforge.izpack.util.FileExecutor;\nimport com.izforge.izpack.util.OsVersion;\nimport com.izforge.izpack.util.os.RegistryDefaultHandler;\nimport com.izforge.izpack.util.os.RegistryHandler;\nimport com.izforge.izpack.gui.IzPanelLayout;\n\n\nimport javax.swing.*;\nimport javax.swing.event.HyperlinkEvent;\nimport javax.swing.event.HyperlinkListener;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.StringTokenizer;\n\n/**\n * Panel which asks for the JDK path.\n *\n * @author Klaus Bartz\n */\npublic class TigaseJDKPathPanel extends PathInputPanel implements HyperlinkListener\n{\n\n    private static final long serialVersionUID = 3257006553327810104L;\n\n    private static final String[] testFiles = new String[]{\"lib\" + File.separator + \"tools.jar\"};\n\n    private static final String JDK_ROOT_KEY = \"Software\\\\JavaSoft\\\\Java Development Kit\";\n\n    private static final String JDK_VALUE_NAME = \"JavaHome\";\n\n    private static final String OSX_JDK_HOME = \"/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home/\";\n\n    private static final int OK = 0;\n    private static final int BAD_VERSION = 1;\n    private static final int BAD_REAL_PATH = 2;\n    private static final int BAD_REG_PATH = 3;\n\n    private String detectedVersion;\n\n    private String minVersion = null;\n\n    private String maxVersion = null;\n\n    private String variableName;\n\n    private Set<String> badRegEntries = null;\n\n    private JEditorPane textArea = null;\n\n    /**\n     * The constructor.\n     *\n     * @param parent The parent window.\n     * @param idata  The installation data.\n     */\n    public TigaseJDKPathPanel(InstallerFrame parent, InstallData idata)\n    {\n        super(parent, TigaseInstallerCommon.init(idata));\n        setMustExist(true);\n        if (!OsVersion.IS_OSX)\n        {\n            setExistFiles(TigaseJDKPathPanel.testFiles);\n        }\n        setMinVersion(idata.getVariable(\"JDKPathPanel.minVersion\"));\n        setMaxVersion(idata.getVariable(\"JDKPathPanel.maxVersion\"));\n        setVariableName(\"JDKPath\");\n\n       \n    }\n    \n    public void hyperlinkUpdate(HyperlinkEvent e) {\n        try {\n            if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) \n                {\n                    String urls = e.getURL().toExternalForm();\n                    // if the link points to a chapter in the same page\n                    // don't open a browser\n                    if (urls.contains(\"HTMLInfoPanel.info#\")) \n                        {\n                            textArea.setPage(e.getURL());\n                        } else {\n                        if (com.izforge.izpack.util.OsVersion.IS_OSX) \n                            {\n                                Runtime.getRuntime().exec(\"open \" + urls);\n                            } else if (com.izforge.izpack.util.OsVersion.IS_UNIX) \n                            {\n                                String[] launchers = {\"htmlview QqzURL\", \"xdg-open QqzURL\"\n                                                      , \"gnome-open QqzURL\", \"kfmclient openURL QqzURL\"\n                                                      , \"call-browser QqzURL\", \"firefox QqzURL\"\n                                                      , \"opera QqzURL\", \"konqueror QqzURL\"\n                                                      , \"epiphany QqzURL\", \"mozilla QqzURL\", \"netscape QqzURL\"};                         \n                                //String launchers = \"/bin/sh -c \\\"htmlview QqzURL || xdg-open QqzURL || gnome-open QqzURL || kfmclien$\n                                for (String launcher : launchers) \n                                    {\n                                        \n                                        try \n                                            {\n                                                Runtime.getRuntime().exec(launcher.replaceAll(\"QqzURL\", urls));\n                                                System.out.println(\"OK\");\n                                                break;\n                                            } catch (Exception ignore) {\n                                            System.out.println(launcher + \" NOT OK\");\n                                        }\n                                    }\n                            } else \n                            {\n                                Runtime.getRuntime().exec(\"cmd /C start \" + urls);\n                            }\n                    }\n                }\n        } catch (Exception err) \n            {\n                // no action\n            }\n    }\n\n\n    /**\n     * Indicates wether the panel has been validated or not.\n     *\n     * @return Wether the panel has been validated or not.\n     */\n    public boolean isValidated()\n    {\n        boolean retval = false;\n        if (super.isValidated())\n        {\n            switch (verifyVersionEx())\n            {\n                case OK:\n                    idata.setVariable(getVariableName(), pathSelectionPanel.getPath());\n                    retval = true;\n                    break;\n                case BAD_REG_PATH:\n                    if (askQuestion(parent.langpack.getString(\"installer.warning\"), parent.langpack.getString(\"TigaseJDKPathPanel.nonValidPathInReg\"),\n                            AbstractUIHandler.CHOICES_YES_NO, AbstractUIHandler.ANSWER_NO) == AbstractUIHandler.ANSWER_YES)\n                    {\n                        idata.setVariable(getVariableName(), pathSelectionPanel.getPath());\n                        retval = true;\n                    }\n                    break;\n                case BAD_REAL_PATH:\n                    break;\n                case BAD_VERSION:\n                    String min = getMinVersion();\n                    String max = getMaxVersion();\n                    StringBuffer message = new StringBuffer();\n                    message.append(parent.langpack.getString(\"TigaseJDKPathPanel.badVersion1\")).append(\n                            getDetectedVersion()).append(\n                            parent.langpack.getString(\"TigaseJDKPathPanel.badVersion2\"));\n                    if (min != null && max != null)\n                    {\n                        message.append(min).append(\" - \").append(max);\n                    }\n                    else if (min != null)\n                    {\n                        message.append(\" >= \").append(min);\n                    }\n                    else if (max != null)\n                    {\n                        message.append(\" <= \").append(max);\n                    }\n\n                    message.append(parent.langpack.getString(\"TigaseJDKPathPanel.badVersion3\"));\n                    if (askQuestion(parent.langpack.getString(\"installer.warning\"), message.toString(),\n                            AbstractUIHandler.CHOICES_YES_NO, AbstractUIHandler.ANSWER_NO) == AbstractUIHandler.ANSWER_YES)\n                    {\n                        idata.setVariable(getVariableName(), pathSelectionPanel.getPath());\n                        retval = true;\n                    }\n                    break;\n                default:\n                    throw new RuntimeException(\"Internal error: unknown result of version verification.\");\n\n            }\n        }\n        return (retval);\n    }\n\n    /**\n     * Called when the panel becomes active.\n     */\n    public void panelActivate()\n    {\n        // Resolve the default for chosenPath\n        super.panelActivate();\n        String chosenPath;\n\n        String msg = parent.langpack.getString(\"TigaseJDKPathPanel.jdkDownload\");\n        if (msg != null && !msg.isEmpty()) \n            {\n                //msg = msg.replace(\"&lt;\", \"<\");\n                //msg = msg.replace(\"&gt;\", \">\");\n                VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());\n                \n                add(IzPanelLayout.createParagraphGap());\n                textArea = new JEditorPane(\"text/html; charset=utf-8\", vs.substitute(msg, null));\n                //textArea.setContentType(\"text/html; charset=utf-8\");\n                textArea.setCaretPosition(0);\n                textArea.setEditable(false);\n                textArea.addHyperlinkListener(this);\n                textArea.setBackground(getBackground());\n                JScrollPane scroller = new JScrollPane(textArea);\n                scroller.setAlignmentX(LEFT_ALIGNMENT);\n                add(scroller, NEXT_LINE);\n            }\n \n\n        // The variable will be exist if we enter this panel\n        // second time. We would maintain the previos\n        // selected path.\n        if (idata.getVariable(getVariableName()) != null)\n        {\n            chosenPath = idata.getVariable(getVariableName());\n        }\n        else\n        {\n            if (OsVersion.IS_OSX)\n            {\n\t\t\t\t\t\t\tProcess proc;\n\n\t\t\t\t\t\t\tString[] params = { \"/usr/libexec/java_home\" };\n\t\t\t\t\t\t\tString[] output = new String[ 2 ];\n\t\t\t\t\t\t\tFileExecutor fe = new FileExecutor();\n\t\t\t\t\t\t\tfe.executeCommand( params, output );\n\n\t\t\t\t\t\t\tDebug.trace(\"output[0]: \" + output[0]);\n\n\t\t\t\t\t\t\tif (output[0] != null && !output[0].trim().isEmpty()) {\n\t\t\t\t\t\t\t\tchosenPath = output[0].trim();\n\t\t\t\t\t\t\t} else if ( idata.getVariable(\"JAVA_HOME\") != null ) {\n\t\t\t\t\t\t\t\tchosenPath = (new File(idata.getVariable(\"JAVA_HOME\"))).getParent();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tchosenPath = OSX_JDK_HOME;\n\t\t\t\t\t\t\t}\n            }\n            else\n            {\n                // Try the JAVA_HOME as child dir of the jdk path\n                chosenPath = (new File(idata.getVariable(\"JAVA_HOME\"))).getParent();\n            }\n        }\n        // Set the path for method pathIsValid ...\n        pathSelectionPanel.setPath(chosenPath);\n\n        if (!pathIsValid() || !verifyVersion())\n        {\n            chosenPath = resolveInRegistry();\n            if (!pathIsValid() || !verifyVersion())\n            {\n                chosenPath = \"\";\n            }\n        }\n        // Set the default to the path selection panel.\n        pathSelectionPanel.setPath(chosenPath);\n        String var = idata.getVariable(\"TigaseJDKPathPanel.skipIfValid\");\n        // Should we skip this panel?\n        if (chosenPath.length() > 0 && var != null && \"yes\".equalsIgnoreCase(var))\n        {\n            idata.setVariable(getVariableName(), chosenPath);\n            parent.skipPanel();\n        }\n\n    }\n\n    /**\n     * Returns the path to the needed JDK if found in the registry. If there are more than one JDKs\n     * registered, that one with the highest allowd version will be returned. Works only on windows.\n     * On Unix an empty string returns.\n     *\n     * @return the path to the needed JDK if found in the windows registry\n     */\n    private String resolveInRegistry()\n    {\n        String retval = \"\";\n        int oldVal = 0;\n        RegistryHandler rh = null;\n        badRegEntries = new HashSet<String>();\n        try\n        {\n            // Get the default registry handler.\n            rh = RegistryDefaultHandler.getInstance();\n            if (rh == null)\n            // We are on a os which has no registry or the\n            // needed dll was not bound to this installation. In\n            // both cases we forget the try to get the JDK path from registry.\n            {\n                return (retval);\n            }\n            rh.verify(idata);\n            oldVal = rh.getRoot(); // Only for security...\n            rh.setRoot(MSWinConstants.HKEY_LOCAL_MACHINE);\n            String[] keys = rh.getSubkeys(JDK_ROOT_KEY);\n            if (keys == null || keys.length == 0)\n            {\n                return (retval);\n            }\n            Arrays.sort(keys);\n            int i = keys.length - 1;\n            String min = getMinVersion();\n            String max = getMaxVersion();\n            // We search for the highest allowd version, therefore retrograde\n            while (i > 0)\n            {\n                if (compareVersions(keys[i], max, false, 4, 4, \"__NO_NOT_IDENTIFIER_\"))\n                { // First allowd version found, now we have to test that the min value\n                    // also allows this version.\n                    if (compareVersions(keys[i], min, true, 4, 4, \"__NO_NOT_IDENTIFIER_\"))\n                    {\n                        String cv = JDK_ROOT_KEY + \"\\\\\" + keys[i];\n                        String path = rh.getValue(cv, JDK_VALUE_NAME).getStringData();\n                        // Use it only if the path is valid.\n                        // Set the path for method pathIsValid ...\n                        pathSelectionPanel.setPath(path);\n                        if (!pathIsValid())\n                        {\n                            badRegEntries.add(keys[i]);\n                        }\n                        else if (\"\".equals(retval))\n                        {\n                            retval = path;\n                        }\n                        pathSelectionPanel.setPath(retval);\n                    }\n                }\n                i--;\n            }\n        }\n        catch (Exception e)\n        { // Will only be happen if registry handler is good, but an\n            // exception at performing was thrown. This is an error...\n            e.printStackTrace();\n        }\n        finally\n        {\n            if (rh != null && oldVal != 0)\n            {\n                try\n                {\n                    rh.setRoot(MSWinConstants.HKEY_LOCAL_MACHINE);\n                }\n                catch (NativeLibException e)\n                {\n                    e.printStackTrace();\n                }\n            }\n        }\n        return (retval);\n    }\n\n    private int verifyVersionEx()\n    {\n        String min = getMinVersion();\n        String max = getMaxVersion();\n        int retval = OK;\n        // No min and max, version always ok.\n        if (min == null && max == null)\n        {\n            return (OK);\n        }\n\n        if (!pathIsValid())\n        {\n            return (BAD_REAL_PATH);\n        }\n        // No get the version ...\n        // We cannot look to the version of this vm because we should\n        // test the given JDK VM.\n        String[] params = {\n                pathSelectionPanel.getPath() + File.separator + \"bin\" + File.separator + \"java\",\n                \"-version\"};\n        String[] output = new String[2];\n        FileExecutor fe = new FileExecutor();\n        fe.executeCommand(params, output);\n        // \"My\" VM writes the version on stderr :-(\n        String vs = (output[0].length() > 0) ? output[0] : output[1];\n        if (min != null)\n        {\n            if (!compareVersions(vs, min, true, 4, 4, \"__NO_NOT_IDENTIFIER_\"))\n            {\n                retval = BAD_VERSION;\n            }\n        }\n        if (max != null)\n        {\n            if (!compareVersions(vs, max, false, 4, 4, \"__NO_NOT_IDENTIFIER_\"))\n            {\n                retval = BAD_VERSION;\n            }\n        }\n        if (retval == OK && badRegEntries != null && badRegEntries.size() > 0)\n        {   // Test for bad registry entry.\n            if (badRegEntries.contains(getDetectedVersion()))\n            {\n                retval = BAD_REG_PATH;\n            }\n        }\n        return (retval);\n\n    }\n\n    private boolean verifyVersion()\n    {\n        return (verifyVersionEx() <= 0);\n    }\n\n    private boolean compareVersions(String in, String template, boolean isMin,\n                                    int assumedPlace, int halfRange, String useNotIdentifier)\n    {\n        StringTokenizer st = new StringTokenizer(in, \" \\t\\n\\r\\f\\\"\");\n        int i;\n        int currentRange = 0;\n        String[] interestedEntries = new String[halfRange + halfRange];\n        for (i = 0; i < assumedPlace - halfRange; ++i)\n        {\n            if (st.hasMoreTokens())\n            {\n                st.nextToken(); // Forget this entries.\n            }\n        }\n\n        for (i = 0; i < halfRange + halfRange; ++i)\n        { // Put the interesting Strings into an intermediaer array.\n            if (st.hasMoreTokens())\n            {\n                interestedEntries[i] = st.nextToken();\n                currentRange++;\n            }\n        }\n\n        for (i = 0; i < currentRange; ++i)\n        {\n            if (useNotIdentifier != null && interestedEntries[i].indexOf(useNotIdentifier) > -1)\n            {\n                continue;\n            }\n            if (Character.getType(interestedEntries[i].charAt(0)) != Character.DECIMAL_DIGIT_NUMBER)\n            {\n                continue;\n            }\n            break;\n        }\n        if (i == currentRange)\n        {\n            detectedVersion = \"<not found>\";\n            return (false);\n        }\n        detectedVersion = interestedEntries[i];\n        StringTokenizer current = new StringTokenizer(interestedEntries[i], \"._-\");\n        StringTokenizer needed = new StringTokenizer(template, \"._-\");\n        while (needed.hasMoreTokens())\n        {\n            // Current can have no more tokens if needed has more\n            // and if a privious token was not accepted as good version.\n            // e.g. 1.4.2_02 needed, 1.4.2 current. The false return\n            // will be right here. Only if e.g. needed is 1.4.2_00 the\n            // return value will be false, but zero should not b e used\n            // at the last version part.\n            if (!current.hasMoreTokens())\n            {\n                return (false);\n            }\n            String cur = current.nextToken();\n            String nee = needed.nextToken();\n            int curVal = 0;\n            int neededVal = 0;\n            try\n            {\n                curVal = Integer.parseInt(cur);\n                neededVal = Integer.parseInt(nee);\n            }\n            catch (NumberFormatException nfe)\n            { // A number format exception will be raised if\n                // there is a non numeric part in the version,\n                // e.g. 1.5.0_beta. The verification runs only into\n                // this deep area of version number (fourth sub place)\n                // if all other are equal to the given limit. Then\n                // it is right to return false because e.g.\n                // the minimal needed version will be 1.5.0.2.\n                return (false);\n            }\n            if (curVal < neededVal)\n            {\n                if (isMin)\n                {\n                    return (false);\n                }\n                return (true);\n            }\n            if (Integer.parseInt(cur) > Integer.parseInt(nee))\n            {\n                if (isMin)\n                {\n                    return (true);\n                }\n                return (false);\n            }\n        }\n        return (true);\n    }\n\n    /**\n     * Returns the current detected version.\n     *\n     * @return the current detected version\n     */\n    public String getDetectedVersion()\n    {\n        return detectedVersion;\n    }\n\n    /**\n     * Returns the current used maximum version.\n     *\n     * @return the current used maximum version\n     */\n    public String getMaxVersion()\n    {\n        return maxVersion;\n    }\n\n    /**\n     * Returns the current used minimum version.\n     *\n     * @return the current used minimum version\n     */\n    public String getMinVersion()\n    {\n        return minVersion;\n    }\n\n    /**\n     * Sets the given value as current detected version.\n     *\n     * @param string version string to be used as detected version\n     */\n    protected void setDetectedVersion(String string)\n    {\n        detectedVersion = string;\n    }\n\n    /**\n     * Sets the given value as maximum for version control.\n     *\n     * @param string version string to be used as maximum\n     */\n    protected void setMaxVersion(String string)\n    {\n        if (string != null && string.length() > 0)\n        {\n            maxVersion = string;\n        }\n        else\n        {\n            maxVersion = \"99.0.0\";\n        }\n    }\n\n    /**\n     * Sets the given value as minimum for version control.\n     *\n     * @param string version string to be used as minimum\n     */\n    protected void setMinVersion(String string)\n    {\n        if (string != null && string.length() > 0)\n        {\n            minVersion = string;\n        }\n        else\n        {\n            minVersion = \"1.0.0\";\n        }\n    }\n\n    /**\n     * Returns the name of the variable which should be used for the path.\n     *\n     * @return the name of the variable which should be used for the path\n     */\n    public String getVariableName()\n    {\n        return variableName;\n    }\n\n    /**\n     * Sets the name for the variable which should be set with the path.\n     *\n     * @param string variable name to be used\n     */\n    public void setVariableName(String string)\n    {\n        variableName = string;\n    }\n\n    /*\n     * (non-Javadoc)\n     * \n     * @see com.izforge.izpack.installer.IzPanel#getSummaryBody()\n     */\n    public String getSummaryBody()\n    {\n        return (idata.getVariable(getVariableName()));\n    }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/java/TigaseJDKPathPanelConsoleHelper.java",
    "content": "package com.izforge.izpack.panels;\n\nimport com.izforge.izpack.installer.AutomatedInstallData;\n\npublic class TigaseJDKPathPanelConsoleHelper \nextends JDKPathPanelConsoleHelper {\n\n        public boolean runConsole(AutomatedInstallData installData) {\n                TigaseInstallerCommon.init(installData);\n                return super.runConsole(installData);\n        }\n        \n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/resources/packsLang.xml",
    "content": "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\" ?>\n\n <!-- The English langpack -->\n\n <langpack>\n </langpack>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/resources/panelsLangPack.xml",
    "content": "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\" ?>\n\n <!-- The English langpack -->\n\n <langpack>\n\t <str id=\"DerbyPathPanel.headline\" txt=\"Derby Database Path\"/>\n\t <str id=\"DerbyPathPanel.intro\" txt=\"The Derby database has been selected. It needs a directory to store data files.\"/>\n\t <str id=\"DerbyPathPanel.info\" txt=\"Select the Derby database path:\"/>\n\t <str id=\"TigaseConfigLoadPanel.info\" txt=\"Existing Tigase server configuration\"/>\n\t <str id=\"TigaseConfigSavePanel.info\" txt=\"New Tigase server configuration generated. Press 'Next' to save the configuration, 'Prev' to make changes. You can also edit settings here and press 'Next' to save them.\"/>\n\t <str id=\"TigaseDBCheckPanel.info\" txt=\"Checking database connection and the database schema.\"/>\n\n\t<str id=\"TigaseJDKPathPanel.extendedIntro\" txt=\"The installed application needs a JDK between version ${JDKPathPanel.minVersion} and ${JDKPathPanel.maxVersion}. A java runtime environment (JRE) will be not sufficient.\"/>\n\t<str id=\"TigaseJDKPathPanel.intro\" txt=\"The installed application needs a JDK. A java runtime environment (JRE) will be not sufficient.\"/>\n\t<str id=\"TigaseJDKPathPanel.info\" txt=\"Select the JDK path:\"/>\n\t<str id=\"TigaseJDKPathPanel.badVersion1\" txt=\"The chosen JDK has the wrong version (available: \"/>\n\t<str id=\"TigaseJDKPathPanel.badVersion2\" txt=\" required: \"/>\n\t<str id=\"TigaseJDKPathPanel.badVersion3\" txt=\") should this JDK be used anyway?\"/>\n\t<str id=\"TigaseJDKPathPanel.nonValidPathInReg\" txt=\"The Windows registry contains a non-valid path for this JDK. Should this JDK be used anyway?\"/>\n\t<str id=\"TigaseJDKPathPanel.jdkDownload\" txt=\"&lt;html&gt;&lt;p&gt;If you don't have JDK installed on your system please go to address: &lt;a href='http://java.sun.com/javase/downloads/'&gt;http://java.sun.com/javase/downloads&lt;/a&gt; and select JDK. Download it and install and proceed with the Tigase server installation.&lt;/p&gt;&lt;p&gt; You need at least ${JDKPathPanel.minVersion} version of Java JDK.&lt;/p&gt;&lt;/html&gt;\"/>\n\n\t<str id=\"TigaseJDKPathPanel.headline\" txt=\"JDK Path\"/>\n\t<str id=\"TigaseJDKPathPanel.summaryCaption\" txt=\"JDK Path\"/>\n\n </langpack>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/resources/target_windows.dir",
    "content": "c:\\Tigase"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/shortcutSpec.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n\n<shortcuts>\n\n <skipIfNotSupported/>\n\n <programGroup defaultName=\"Tigase-$APP_VER\" location=\"applications\"/>\n\n <shortcut\n\t\t name=\"Manually Start Tigase-$APP_VER Server\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"yes\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"$INSTALL_PATH\\Run.bat\"\n\t\t workingDirectory=\"$INSTALL_PATH\"\n\t\t commandLine=\"\"\n\t\t description=\"Manually run the Tigase server if it is not running as a system service.\"\n\t\t iconFile=\"$INSTALL_PATH\\Tigase.ico\"\n\t\t iconIndex=\"0\"\n\t\t initialState=\"noShow\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Install Tigase-$APP_VER Windows Service\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"yes\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"$INSTALL_PATH\\InstallTigaseService.bat\"\n\t\t workingDirectory=\"$INSTALL_PATH\"\n\t\t commandLine=\"\"\n\t\t description=\"Install Windows system service to start the Tigase server automatically.\"\n\t\t iconFile=\"$INSTALL_PATH\\Tigase.ico\"\n\t\t iconIndex=\"0\"\n\t\t initialState=\"noShow\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Uninstall Tigase-$APP_VER Windows Service\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"$INSTALL_PATH\\UninstallTigaseService.bat\"\n\t\t workingDirectory=\"$INSTALL_PATH\"\n\t\t commandLine=\"\"\n\t\t description=\"Uninstall Windows system service to stop the Tigase server from starting automatically.\"\n\t\t iconFile=\"\"\n\t\t iconIndex=\"0\"\n\t\t initialState=\"noShow\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER Online Documentation\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"http://www.tigase.org/en/content/configuration-4-0\"\n\t\t commandLine=\"\"\n\t\t description=\"This opens a WebBrowser to look into the Tigase-$APP_VER (HTML) administrator documentation\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER README\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"$INSTALL_PATH\\package.html\"\n\t\t commandLine=\"\"\n\t\t description=\"Tigase README file opens in a web browser.\">\n </shortcut>\n\n <shortcut\n\t\t name=\"Tigase-$APP_VER Uninstaller\"\n\t\t programGroup=\"yes\"\n\t\t desktop=\"no\"\n\t\t applications=\"no\"\n\t\t startMenu=\"no\"\n\t\t startup=\"no\"\n\t\t target=\"$INSTALL_PATH\\Uninstaller\\uninstaller.jar\"\n\t\t commandLine=\"\"\n\t\t iconFile=\"%SystemRoot%\\system32\\SHELL32.dll\"\n\t\t iconIndex=\"31\"\n\t\t description=\"This uninstalls Tigase-$APP_VER\">\n </shortcut>\n\n</shortcuts>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/izpack/userInputSpec.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n\n<!--\nTigase Jabber/XMPP Server\nCopyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, version 3 of the License.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program. Look for COPYING file in the top folder.\nIf not, see http://www.gnu.org/licenses/.\n\n\nIzPack insallation file for the Tigase server.\nBased on the IzPack sample installation file.\n\nThis is user input panels definition...\n\n$Rev: 1190 $\nLast modified by $Author: kobit $\n$Date: 2008-10-22 14:32:10 +0100 (Wed, 22 Oct 2008) $\n-->\n\n<userInput>\n\t<!-- Select what you want to do... -->\n\t<panel order=\"0\">\n\t\t<field type=\"title\" txt=\"Select what you want to do next:\"\n\t\t\t\t\t bold=\"true\" size=\"2\"/>\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"On this panel you can specify whether you want to install only or configure already installed server or to do both. If you are just installing a server on your machine it is a good idea to do both steps.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"check\" variable=\"serverInstall\">\n\t\t\t<description align=\"left\" txt=\"The wizards you want to execute\" />\n\t\t\t<spec txt=\"Installation of the Tigase Server\"\n\t\t\t\t\t\ttrue=\"on\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"serverConfig\">\n\t\t\t<spec txt=\"Configuration of the Tigase Server\"\n\t\t\t\t\t\ttrue=\"on\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"Please note!\"/>\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"While the Tigase server is quite stable and well tested application the installer itself is a new addition. Take precautions especially if you upgrade the server from earlier version. Backup old server files and the database.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"If you notice any problems please report them to address: artur.hefczyc@tigase.org\"/>\n\t</panel>\n\n\t<!-- Select installation directory in config-only mode -->\n\t<panel order=\"1\">\n\t\t<field type=\"title\" txt=\"Installation directory\"\n\t\t\t\t\t bold=\"true\" size=\"2\"/>\n\n\t\t<field type=\"search\" variable=\"searchTigaseHome\">\n\t\t\t<spec txt=\"Path to Tigase installation:\"\n\t\t\t\t\t\tcheckfilename=\"jars/tigase-server.jar\"\n\t\t\t\t\t\ttype=\"directory\" result=\"directory\">\n\t\t\t\t<choice value=\"$INSTALL_PATH\" set=\"true\"/>\n\t\t\t\t<choice value=\"$APPLICATIONS_DEFAULT_ROOT/Tigase-$APP_VER\"/>\n\t\t\t\t<choice value=\"C:\\Tigase\\Tigase-$APP_VER\" os=\"windows\" />\n\t\t\t\t<choice value=\"/opt/Tigase-$APP_VER\" os=\"unix\" />\n\t\t\t\t<choice value=\"/Applications/Tigase-$APP_VER\" os=\"Mac OS X\" />\n\t\t\t\t<choice value=\"/home/tigase/server\" os=\"unix\" />\n\t\t\t\t<choice value=\"/home/jabber/tigase\" os=\"unix\" />\n\t\t\t</spec>\n\t\t</field>\n\t</panel>\n\n\t<!-- Basic configuration -->\n\t<panel order=\"2\">\n\t\t<field type=\"title\" txt=\"Basic Tigase server configuration\"\n\t\t\t\t\t bold=\"true\" size=\"2\" />\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"On this panel you can specify basic configuration settings for the Tigase server.\"/>\n\t\t<field type=\"space\" />\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"Based on your selection here more configuration options might be presented later on. After the configuration is complete init.properties file will be created.\"/>\n\t\t<field type=\"space\" />\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"You can optionally restart the server at the end of the process if you like.\"/>\n\t\t<field type=\"divider\" />\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"combo\" variable=\"configType\">\n<!-- \t\t\t<description align=\"left\" id=\"description.configType\" -->\n<!-- \t\t\t\t\t\t\t\t\t txt=\"Stick to the default unless you are realy sure you want something else.\"/> -->\n\t\t\t<spec txt=\"Configuration type\">\n\t\t\t\t<choice txt=\"Default installation\"\n\t\t\t\t\t\t\t\tvalue=\"--gen-config-def\"  set=\"true\"/>\n\t\t\t\t<choice txt=\"Default plus extra components\"\n\t\t\t\t\t\t\t\tvalue=\"--gen-config-all\" />\n\t\t\t\t<choice txt=\"Session Manager only\"\n\t\t\t\t\t\t\t\tvalue=\"--gen-config-sm\" />\n\t\t\t\t<choice txt=\"Network connectivity only\"\n\t\t\t\t\t\t\t\tvalue=\"--gen-config-cs\" />\n\t\t\t</spec>\n\t\t</field>\n\n\t\t<field type=\"text\" align=\"left\" variable=\"virtualDomains\">\n<!-- \t\t\t<description align=\"left\" id=\"description.virtualDomains\" -->\n<!-- \t\t\t\t\t\t\t\t\t txt=\"You can enter multiple virtual domains separating them with a comma: im.$HOST_NAME,jabber.$HOST_NAME\"/> -->\n\t\t\t<spec txt=\"Your XMPP (Jabber) domains\" size=\"30\" set=\"$HOST_NAME\"/>\n\t\t</field>\n\n\t\t<field type=\"text\" align=\"right\" variable=\"admins\">\n<!-- \t\t\t<description align=\"left\" id=\"description.admins\" -->\n<!-- \t\t\t\t\t\t\t\t\t txt=\"Within domains configured above only: admin@im.$HOST_NAME,frank@jabber.$HOST_NAME\"/> -->\n\t\t\t<spec txt=\"Server administrators\" size=\"30\" set=\"admin@$HOST_NAME\"/>\n\t\t</field>\n\n\t\t<field type=\"text\" align=\"right\" variable=\"adminsPwd\">\n\t\t\t<spec txt=\"Admin password\" size=\"30\" set=\"tigase\"/>\n\t\t</field>\n\n\t\t<field type=\"combo\" variable=\"dbType\">\n\t\t\t<spec txt=\"Select database\">\n\t\t\t\t<choice txt=\"Derby (built-in database)\"\n\t\t\t\t\t\t\t\tvalue=\"Derby\" set=\"true\"/>\n\t\t\t\t<choice txt=\"MySQL\"\n\t\t\t\t\t\t\t\tvalue=\"MySQL\"/>\n\t\t\t\t<choice txt=\"PostgreSQL\"\n\t\t\t\t\t\t\t\tvalue=\"PostgreSQL\"/>\n\t\t\t\t<choice txt=\"SQLServer\"\n\t\t\t\t\t\t\t\tvalue=\"SQLServer\"/>\n\t\t\t\t<choice txt=\"Other...\"\n\t\t\t\t\t\t\t\tvalue=\"Other\"/>\n\t\t\t</spec>\n\t\t</field>\n\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\" />\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"check\" variable=\"advancedConfig\">\n\t\t\t<spec txt=\"Advanced configuration options\"\n\t\t\t\t\t\ttrue=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t</panel>\n\n\t<!-- Advanced configuration -->\n\t<panel order=\"3\">\n\t\t<field type=\"title\" txt=\"Advanced configuration options:\" bold=\"true\" size=\"2\"/>\n\t\t<field type=\"staticText\" align=\"left\"\n\t\t\t\t\t txt=\"This panel offer advanced configuration options. Please do not change them unless you know what you are doing.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"check\" variable=\"authDB\">\n\t\t\t<spec txt=\"Separate authentication database\"\n\t\t\t\t\t\ttrue=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\n\t\t<field type=\"check\" variable=\"mucComponent\">\n\t\t\t<description align=\"left\" txt=\"Select optional components to run\" />\n\t\t\t<spec txt=\"MUC\" true=\"on\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"PubSubComponent\">\n\t\t\t<spec txt=\"PubSub\" true=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"stunComponent\">\n\t\t\t<spec txt=\"STUN Component\" true=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"socks5Component\">\n\t\t\t<spec txt=\"Socks5 Component\" true=\"on\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"httpApiComponent\">\n\t\t\t<spec txt=\"HTTP API Component\" true=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"messageArchiveComponent\">\n\t\t\t<spec txt=\"Message Archive Component\" true=\"on\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\n\t\t<field type=\"space\"/>\n\n\n\t\t<field type=\"check\" variable=\"clusterMode\">\n\t\t\t<description align=\"left\" txt=\"Do you want your server to run in the cluster mode?\" />\n\t\t\t<spec txt=\"Cluster mode\" true=\"true\" false=\"false\"\tset=\"true\"/>\n\t\t</field>\n\n\t\t<field type=\"check\" variable=\"acsComponent\" condition=\"clusterMode\">\n\t\t\t<spec txt=\"Tigase Advanced Clustering Strategy (ACS) Component\" true=\"on\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"acsPubSubComponent\"  condition=\"{{clusterMode+acsComponent}}\">\n\t\t\t<spec txt=\"PubSub ACS\" true=\"acs\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"acsMUCComponent\"  condition=\"{{clusterMode+acsComponent}}\">\n\t\t\t<spec txt=\"MUC ACS\" true=\"acs\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\n\n\t<!--\t\t<field type=\"text\" align=\"left\" variable=\"clusterNodes\">\n\t\t\t<spec txt=\"Cluster nodes list\" size=\"30\" set=\"$HOST_NAME\"/>\n\t\t</field>-->\n\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"check\" variable=\"serverDebug\">\n\t\t\t<description align=\"left\" txt=\"Select components for debug logging\" />\n\t\t\t<spec txt=\"Base server\" true=\"server\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"pluginsDebug\">\n\t\t\t<spec txt=\"Plugins debug\" true=\"xmpp.impl\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"dbDebug\">\n\t\t\t<spec txt=\"Database debug\" true=\"db\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"clusterDebug\">\n\t\t\t<spec txt=\"Cluster debug\" true=\"cluster\" false=\"off\"\tset=\"false\"/>\n\t\t</field>\n\n\t</panel>\n\n\t<!-- ACS information -->\n\t<panel order=\"4\">\n\t\t<field type=\"title\" txt=\"Advanced Clustering Strategy information\" bold=\"true\" size=\"2\" />\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"This installation package contains a free trial version of the Tigase Advanced Clustering Strategy (“ACS”) software, which you as a licensee may use for the term of your agreement with Tigase.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"ACS is not open source software, it is Tigase’s proprietary software and constitutes the valuable intellectual property of Tigase.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"The free trial granted hereunder does not grant you the right to sublicense ACS to third parties, to copy ACS for third party use, or to use ACS in connection with production systems or for commercial purposes. ACS is provided free of charge for non-commercial testing and development purposes only. Any use of ACS other than for non-commercial testing and development purposes requires the purchase of a license from Tigase.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"If you activate the ACS software under this free trial, you should understand that it will send certain statistical information to Tigase's servers on a regular basis. If ACS cannot access our servers to send this statistical information, it will stop working. If this occurs, please contact your Tigase representative to resolve the issue and discuss upgrading to a full version of the ACS software. If ACS is installed but not activated, no statistical information will be sent to Tigase's servers.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"If you enjoy your free trial version of ACS, please contact your Tigase representative to obtain a commercial license for the full version of the ACS software. The full commercial version of ACS does not send statistical information to Tigase's servers.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\" txt=\"By activating this free trial version of ACS you agree and accept that certain statistical information of yours (such as DNS domain names, host names, number of online users, number of cluster nodes, etc.) which may be considered confidential and proprietary, will be sent to Tigase. You accept and confirm that such information, which may be considered confidential or proprietary, may be transferred to Tigase's servers. You hereby consent to such transfer and waive any rights to this information. You also hereby agree that you will not pursue any remedy at law as a result of the information transfer.\" />\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"text\" align=\"left\" size=\"1\" variable=\"acsName\">\n\t\t\t<description align=\"left\" txt=\"To confirm please enter your name or company name below\" />\n\t\t\t<spec txt=\"Name: \" id=\"\" size=\"15\" set=\"\"/>\n\t\t\t<validator class=\"com.izforge.izpack.util.NotEmptyValidator\" txt=\"Field is empty!\" />\n\t\t</field>\n\n\t</panel>\n\n\t<!-- MS SQL Server information -->\n\t<panel order=\"5\">\n\t\t<field type=\"title\" txt=\"MS SQL Server information\" bold=\"true\" size=\"2\" />\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\"\n\t\t\t\t\t txt=\"You have selected MS SQL Server as your database. While we provide you, for easy install, with open-source jTDS JDBC driver allowing to connect to MS SQL Server, we recommend using JDBC driver from Microsoft.\" />\n\t\t<field type=\"staticText\" align=\"left\" size=\"2\"\n\t\t\t\t\t txt=\"More information can be found on our website: http://www.tigase.org/content/prepare-ms-sql-server-database-tigase-server\" />\n\t\t<field type=\"space\"/>\n\n\t</panel>\n\n\t<!-- Plugins selection -->\n\t<panel order=\"6\">\n\t\t<field type=\"title\" txt=\"Plugins selection:\" bold=\"true\" size=\"2\"/>\n\t\t<field type=\"staticText\" align=\"left\" txt=\"Please selected/deselect plugins to be loaded by the server.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\nuvme:vcard-temp,http://jabber.org/protocol/commands,jabber:iq:private,urn:xmpp:ping,uvme:iq:games-list,uvme:jabber:iq:search\n\n\t\t<field type=\"check\" variable=\"nonSaslAuthPlugin\">\n\t\t\t<spec txt=\"Non-SASL Authentication\" true=\"jabber:iq:auth\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"saslAuthPlugin\">\n\t\t\t<spec txt=\"SASL Authentication\" true=\"urn:ietf:params:xml:ns:xmpp-sasl\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"resBindPlugin\">\n\t\t\t<spec txt=\"Resource Bind\" true=\"urn:ietf:params:xml:ns:xmpp-bind\" false=\"off\" set=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"sessionBindPlugin\">\n\t\t\t<spec txt=\"Session bind\" true=\"urn:ietf:params:xml:ns:xmpp-session\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"registerPlugin\">\n\t\t\t<spec txt=\"User registration\" true=\"jabber:iq:register\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"rosterPlugin\">\n\t\t\t<spec txt=\"Roster management\" true=\"jabber:iq:roster\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"presencePlugin\">\n\t\t\t<spec txt=\"Presence management\" true=\"presence\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"basicFilterPlugin\">\n\t\t\t<spec txt=\"Basic filter\" true=\"basic-filter\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"domainFilterPlugin\">\n\t\t\t<spec txt=\"Domain filter\" true=\"domain-filter\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"privacyPlugin\">\n\t\t\t<spec txt=\"Privacy lists\" true=\"jabber:iq:privacy\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"versionPlugin\">\n\t\t\t<spec txt=\"Software version\" true=\"jabber:iq:version\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"statsPlugin\">\n\t\t\t<spec txt=\"Server statistics\" true=\"http://jabber.org/protocol/stats\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"tlsPlugin\">\n\t\t\t<spec txt=\"TLS\" true=\"starttls\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"msgOfflinePlugin\">\n\t\t\t<spec txt=\"Offline message storage\" true=\"msgoffline\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"vcardPlugin\">\n\t\t\t<spec txt=\"vCard\" true=\"vcard-temp\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"commandsPlugin\">\n\t\t\t<spec txt=\"Ad-hoc commands\" true=\"http://jabber.org/protocol/commands\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"privatePlugin\">\n\t\t\t<spec txt=\"Private data storage\" true=\"jabber:iq:private\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"pingPlugin\">\n\t\t\t<spec txt=\"Ping\" true=\"urn:xmpp:ping\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"pepPlugin\">\n\t\t\t<spec txt=\"Personal eventing (PEP)\" true=\"urn:xmpp:ping\" false=\"off\"\tset=\"true\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"zlibPlugin\">\n\t\t\t<spec txt=\"Zlib stream compression (new, experimental)\" true=\"zlib\" false=\"off\" set=\"false\"/>\n\t\t</field>\n\t\t<field type=\"check\" variable=\"messageArchivePlugin\">\n\t\t\t<spec txt=\"Message archive plugin (xep 0136) required by archive component\" true=\"message-archive-xep-0136\" false=\"off\" set=\"true\"/>\n\t\t</field>\n\n\t</panel>\n\n\t<!-- Database configuration -->\n\t<panel order=\"7\">\n\t\t<field type=\"title\" txt=\"Database configuration:\" bold=\"true\" size=\"2\"/>\n\t\t<field type=\"staticText\" align=\"left\" txt=\"You have selected $dbType database. This database needs additional configuration parameters. Please enter all required information.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"staticText\" align=\"left\" txt=\"$dbType super user account will be used only to create and configure database for the Tigase server. It will not be used by the Tigase server later on.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbSuperuser\">\n\t\t\t<spec txt=\"Super user account name:\" size=\"20\" set=\"root\"/>\n\t\t</field>\n\t\t<field type=\"password\" align=\"left\" variable=\"dbSuperpass\">\n\t\t\t<spec>\n\t\t\t\t<pwd txt=\"Super user password:\" size=\"20\" set=\"\"/>\n\t\t\t\t<pwd txt=\"Retype password:\" size=\"20\" set=\"\"/>\n\t\t\t</spec>\n\t\t\t<validator class=\"com.izforge.izpack.util.PasswordEqualityValidator\"\n\t\t\t\t\t\t\t\t txt=\"Both passwords must match.\" />\n\t\t</field>\n\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"staticText\" align=\"left\" txt=\"$dbType database details. It will be created automatically if it does not exist.\"/>\n\n\t\t<field type=\"space\"/>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbUser\">\n\t\t\t<spec txt=\"Database account:\" size=\"20\" set=\"tigase\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbPass\">\n\t\t\t<spec txt=\"Account password:\" size=\"20\" set=\"tigase12\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbName\">\n\t\t\t<spec txt=\"Database name:\" size=\"20\" set=\"tigasedb\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbHost\">\n\t\t\t<spec txt=\"Database host or IP:\" size=\"20\" set=\"localhost\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbParams\">\n\t\t\t<spec txt=\"Additional database parameters:\" size=\"20\" set=\"\"/>\n\t\t</field>\n\n\t</panel>\n\n\t<!-- Authentication database configuration -->\n\t<panel order=\"8\">\n\t\t<field type=\"title\" txt=\"Authentication database configuration:\"\n\t\t\t\t\t bold=\"true\" size=\"2\"/>\n\t\t<field type=\"staticText\" align=\"left\" txt=\"You have selected a separate authentication database. You have to provide more details about this database.\"/>\n\t\t<field type=\"space\"/>\n\t\t<field type=\"divider\"/>\n\t\t<field type=\"space\"/>\n\n\t\t<field type=\"combo\" variable=\"dbAuthType\">\n\t\t\t<spec txt=\"Select database\">\n\t\t\t\t<choice txt=\"Derby\" value=\"derby\" set=\"true\"/>\n\t\t\t\t<choice txt=\"MySQL\" value=\"mysql\"/>\n\t\t\t\t<choice txt=\"PostgreSQL\" value=\"postgresql\"/>\n\t\t\t\t<choice txt=\"SQL Server\" value=\"jtds:sqlserver\"/>\n\t\t\t</spec>\n\t\t</field>\n\t\t<field type=\"combo\" variable=\"dbAuthHandle\">\n\t\t\t<spec txt=\"Select database\">\n\t\t\t\t<choice txt=\"Tigase Standard\" value=\"Standard\" set=\"true\"/>\n\t\t\t\t<choice txt=\"Tigase Auth\" value=\"tigase-auth\" set=\"true\"/>\n\t\t\t\t<choice txt=\"Tigase Custom\" value=\"tigase-custom\"/>\n\t\t\t\t<choice txt=\"Drupal\" value=\"drupal\"/>\n\t\t\t\t<choice txt=\"Libresource\" value=\"libresource\"/>\n\t\t\t\t<choice txt=\"Your custom\" value=\"Enter your class here\"/>\n\t\t\t</spec>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbAuthUser\">\n\t\t\t<spec txt=\"Database account:\" size=\"20\" set=\"tigase\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbAuthPass\">\n\t\t\t<spec txt=\"Account password:\" size=\"20\" set=\"tigase12\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbAuthName\">\n\t\t\t<spec txt=\"Database name:\" size=\"20\" set=\"tigasedb\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbAuthHost\">\n\t\t\t<spec txt=\"Database host or IP:\" size=\"20\" set=\"localhost\"/>\n\t\t</field>\n\t\t<field type=\"text\" align=\"left\" variable=\"dbAuthParams\">\n\t\t\t<spec txt=\"Additional database parameters:\" size=\"20\" set=\"\"/>\n\t\t</field>\n\n\t</panel>\n\n</userInput>\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/annotations/TODO.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.annotations;\n\nimport java.lang.annotation.ElementType; // NOPMD\nimport java.lang.annotation.Target; // NOPMD\nimport java.lang.annotation.Documented; // NOPMD\nimport java.lang.annotation.Retention; // NOPMD\nimport java.lang.annotation.RetentionPolicy; // NOPMD\n\n/**\n * <code>TODO</code> this is information for developers that there is still\n * something to do with annotated code. Additional parameters can provide\n * detailed information what exatcly is suposed to correct in code, how\n * important it is for project the time when it should be done and name of\n * developer to which correction is assigned.\n *\n * <code>TODO</code> annotation has a few properties which can be set to better\n * describe code to be changed like <code>note</code> - allows you to add some\n * description, <code>severity</code> - allows you to set severity level for\n * this code change, <code>timeLine</code> - allows you to set expected time\n * when code change should be ready to use and <code>assignedTo</code> - allows\n * you to set name of developer who should make the change to code. All this\n * properties has some default values so it is not necessary to set them all\n * every time you use <code>TODO</code> annotation.<br>\n * Below you can find a few samples how to use <code>TODO</code> annotation:\n * <p>Sample of use all annotation with all possible properties:</p>\n * <pre>  @TODO(\n *  severity=TODO.Severity.CRITICAL,\n *  note=\"This empty method which should calculate data checksum, needs implementation.\",\n *  timeLine=\"30/11/2004\",\n *  assignedTo=\"Artur Hefczyc\"\n * )\n * public long checksum(char[] buff) { return -1; }</pre>\n * <p>A few samples using selected set of <code>TODO</code> properties:</p>\n * <pre>  @TODO(\n *  severity=TODO.Severity.DOCUMENTATION,\n *  note=\"This method needs better inline documentation, I can't udnerstan how it works\",\n *  assignedTo=\"Artur Hefczyc\"\n * )\n * public String calculateWeather(byte[][][] buff) { ... }</pre>\n * <pre>  @TODO(note=\"SSL socket functionality not implemented yet.\")\n * protected void init() { ... }</pre>\n * <p>\n * Created: Wed Sep 29 18:58:21 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Retention(RetentionPolicy.SOURCE)\n@Documented\n@Target({ElementType.TYPE,\n      ElementType.METHOD,\n      ElementType.CONSTRUCTOR,\n      ElementType.ANNOTATION_TYPE})\npublic @interface TODO {\n\n  /**\n   * This enumeration defines importance levels for code change which is\n   * expected to be made for annotated element.\n   */\n  public enum Severity {\n    /**\n     * If change severity is set to <code>CRITICAL</code> it means that wihtout\n     * this change some progress is not possible. Probably it blocks some\n     * important functionality like <em>SSL</em> activation for server port.\n     */\n    CRITICAL,\n    /**\n     * <code>IMPORTANT</code> severity means that this code does not block\n     * implementation of any functionality but might be inefficient, insecure\n     * or contain some temporary solution.<br>\n     * <code>IMPORTANT</code> severity can be also assigned to code which needs\n     * some medium or major refactoring.\n     */\n    IMPORTANT,\n    /**\n     * <code>TRIVIAL</code> severity means that this code works correctly and\n     * is implemented according to design but there is still some minor\n     * improvement that can be done or just cleaning the code.<br>\n     * <code>TRIVIAL</code> severity can be assigned also to code which needs\n     * some minor refactoring.\n     */\n    TRIVIAL,\n    /**\n     * <code>DOCUMENTATION</code> severity refers to code which should be\n     * documented. It does not refer to API documentation. It refers to in-line\n     * documentation which should be added due to complicity of some code or\n     * unusual algorithm used.<br>\n     * Usually I try to avoid \"smart\" code but in certain cases it is required\n     * to use code which might be difficult to understand. In all such cases\n     * code should be detaily documented. This annotation can help to remind\n     * what parts of code needs more documentation.<br>\n     * This annotation should be also added by other developer who is not owner\n     * of some part of code but tried to read it and found it difficult to\n     * understand. In such case it is recommended that this developers should\n     * leave such annotation to bring attention to owner that some code needs\n     * better documentation.\n     */\n    DOCUMENTATION;\n  };\n\n  /**\n   * <code>severity</code> property allows you to set and retrieve severity of\n   * expected code change described by this <code>TODO</code> annotation.\n\t *\n\t * @return priority of code change\n   */\n  Severity severity() default Severity.IMPORTANT;\n  /**\n   * <code>note</code> property allows you to set and retrieve description\n   * text for expected code change.\n\t *\n\t * @return description text for code change\n   */\n  String note() default \"Functionality not fully implemented.\";\n  /**\n   * <code>timeLine</code> property allows you to set and retrieve expected\n   * time by when the change should be done to this code.\n\t *\n\t * @return due date of the change\n   */\n  String timeLine() default \"2004/12/31\";\n  /**\n   * <code>assignedTo</code> property allows you to assign developer for the code\n   * change described by this annotation.\n\t *\n\t * @return Name of the developer\n   */\n  String assignedTo() default \"Artur Hefczyc\";\n\n}// TODO\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/annotations/TigaseDeprecatedComponent.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n *\n * @author Wojtek\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE,\n      ElementType.METHOD,\n      ElementType.CONSTRUCTOR,\n      ElementType.ANNOTATION_TYPE})\npublic @interface TigaseDeprecatedComponent {\n\n\tString note() default \"This compnent/plugin hass been deprecated\";\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/apns/APNSDBFactory.java",
    "content": "/*\n * Tigase Jabber/XMPP Multi-User Chat Component\n * Copyright (C) 2008 \"Bartosz M. Małkowski\" <bartosz.malkowski@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.apns;\n\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.conf.ConfigurationException;\nimport tigase.db.RepositoryFactory;\n\n/**\n * @author bmalkow\n * \n */\npublic class APNSDBFactory {\n\n\tpublic static final String DB_CLASS_KEY = \"apns-token-db\";\n\n\tpublic static final String DB_URI_KEY = \"apns-token-db-uri\";\n\n\tprotected static final Logger log = Logger.getLogger(APNSDBFactory.class.getName());\n\n\tpublic static APNSDBProvider getAPNSDBManager(Map<String, Object> params) throws ConfigurationException {\n\t\ttry {\n\t\t\t\n\t\t\tString uri = (String) params.get(DB_URI_KEY);\n\t\t\tString cl = (String) params.get(DB_CLASS_KEY);\n\n\t\t\tif (uri == null && cl == null)\n\t\t\t\treturn null;\n\n\t\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\t\tlog.config(\"Using APNS Provider\"\n\t\t\t\t\t\t\t\t+ \"; params.size: \" + params.size()\n\t\t\t\t\t\t\t\t+ \"; uri: \" + uri\n\t\t\t\t\t\t\t\t+ \"; cl: \" + cl);\n\t\t\t\n\t\t\tClass<? extends APNSDBProvider> cls = null;\n\t\t\tif (cl != null) {\n\t\t\t\tif (cl.contains(\"mysql\")) {\n\t\t\t\t\tcls = MySqlAPNSProvider.class;\n\t\t\t\t} else{\n\t\t\t\t\tthrow new ConfigurationException(\"Not found implementation of mysql Provider for \" + uri);\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif (cls == null) {\n\t\t\t\tcls = RepositoryFactory.getRepoClass(APNSDBProvider.class, uri);\n\t\t\t}\n\t\t\tif (cls == null) {\n\t\t\t\tthrow new ConfigurationException(\"Not found implementation of Roster DB Provider for \" + uri);\n\t\t\t}\n\t\t\t\n\t\t\tAPNSDBProvider provider = cls.newInstance();\n\t\t\tprovider.initRepository(uri, null);\n\t\t\treturn provider;\t\t\n\t\t} catch (Exception e) {\n\t\t\tthrow new ConfigurationException(\"Cannot initialize Roster APNS Provider\", e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/apns/APNSDBProvider.java",
    "content": "/*\n * Tigase Jabber/XMPP Multi-User Chat Component\n * Copyright (C) 2008 \"Bartosz M. Małkowski\" <bartosz.malkowski@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.apns;\n\nimport java.util.Map;\n\nimport tigase.db.Repository;\nimport tigase.xmpp.BareJID;\n\n/**\n * @author bmalkow\n * \n */\npublic interface APNSDBProvider extends Repository {\n\n\tpublic void init(Map<String, Object> props);\n\t/**\n\t * Adds join event.\n\t * \n\t * @param room\n\t * @param date\n\t * @param senderJID\n\t * @param nickName\n\t */\n\t\n\tpublic void updateToken(BareJID bareJID, String $token);\n\t\n\tpublic void delToken(BareJID user);\n\t\n\tpublic Map<String, String> getAllTokens();\n\t\n\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/apns/APNSManager.java",
    "content": "package tigase.apns;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport com.notnoop.apns.APNS;\nimport com.notnoop.apns.ApnsService;\n\npublic class APNSManager {\n\t\n\tprivate static final Logger     log = Logger.getLogger(APNSManager.class.getName());\n\t\n\tprivate static final String File_Name = \"etc/init-apns.properties\";\n\t\n\tpublic static File devCert; \n\t\n\tprivate static String certPwd; \n\t\n\tprivate static Properties propts;\n\t\n\tprivate static int executor_size;\n\t\n\tstatic ScheduledThreadPoolExecutor schedule = new ScheduledThreadPoolExecutor(executor_size);\n\t\n\tprivate static Map<String, String> tokens = new ConcurrentHashMap<String, String>();\n\t\n\tprivate static Map<String, Integer> msg_counts = new ConcurrentHashMap<String, Integer>();\n\t\n\tprivate static int maxConnections;\n\t\n\tstatic {\n\t\ttry {\n\t\t\tpropts = new Properties();\n\t\t\tpropts.load(new FileInputStream(File_Name));\n\t\t\t\n\t\t\tdevCert = new File(\"etc/\" + propts.getProperty(\"cert_file\"));\n\t\t\t\n\t\t\tcertPwd = propts.getProperty(\"pwd\");\n\t\t\t\n\t\t\texecutor_size = Integer.valueOf(propts.getProperty(\"executor_size\", \"15\")); \n\t\t\t\n\t\t\tschedule = new ScheduledThreadPoolExecutor(executor_size);\n\t\t\t\n\t\t\tmaxConnections = Integer.valueOf(propts.getProperty(\"maxConnections\", \"15\"));\n\t\t\t\n\t\t} catch (Exception ex) {\n\t\t\tex.printStackTrace();\n\t\t}\n\t}\n\n\t\n\tprivate static ApnsService apnsService = APNS.newService().asPool(schedule, maxConnections).withCert(devCert.getAbsolutePath(), certPwd).withSandboxDestination().build();\n\n\tpublic static void pushMsg(String uid, String message){\n\t\t\n\t\tfinal String token = tokens.get(uid);\n\t\tif(token == null)\n\t\t\treturn;\n\t\t\n\t\tmsgCountAdd(uid);\n\t\t\n\t\tint count = msg_counts.get(uid);\n\t\t\n\t\tString push = APNS.newPayload().alertBody(message).badge(count).sound(\"newMsg.mp3\").build();\n\t\tapnsService.push(token, push);\n\t\t\n\t\t\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"#IOS push: uid:{0} token:{1} message:{2}\", new String[]{ uid, token, message});\n\t\t}\n\t}\n\n\tpublic static void addToken(String uid, String token) {\n\t\tif(token != null)\n\t\t\ttokens.put(uid, token);\n\t}\n\t\n\tpublic static void delToken(String uid) {\n\t\ttokens.remove(uid);\n\t}\n\t\n\tpublic static String getToken(String uid) {\n\t\treturn tokens.get(uid);\n\t}\n\t\n\tpublic static void initToken(Map<String, String> $tokens){\n\t\ttokens.putAll($tokens);\n\t}\n\t\n\tpublic static void msgCountAdd(String uid){\n\t\tif(msg_counts.get(uid) == null){\n\t\t\tmsg_counts.put(uid, 1);\n\t\t}else{\n\t\t\tint temp = msg_counts.get(uid);\n\t\t\tmsg_counts.put(uid, ++temp);\n\t\t}\n\t}\n\t\n\tpublic static void msgCountClear(String uid){\n\t\tmsg_counts.remove(uid);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/apns/MySqlAPNSProvider.java",
    "content": "/*\n * Tigase Jabber/XMPP Multi-User Chat Component\n * Copyright (C) 2008 \"Bartosz M. Małkowski\" <bartosz.malkowski@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.apns;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Types;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\nimport tigase.xmpp.BareJID;\n\n/**\n * @author bmalkow\n * \n */\n@Repository.Meta( supportedUris = { \"jdbc:mysql:.*\" } )\npublic class MySqlAPNSProvider implements APNSDBProvider {\n\t\n\t// add by cai \n\t\n\tprivate static final String DEF_TOKEN_TABLE = \"tig_users\";\n\t\n\tpublic static final String UPDATE_TOKEN_KEY = \"UPDATE_TOKEN_KEY\";\n\n\tpublic static final String GET_ALL_TOKENS_KEY = \"GET_ALL_TOKENS_KEY\";\n\t\n\t\n\tpublic static final String UPDATE_TOKEN_VAL = \"update \" + DEF_TOKEN_TABLE + \" set push_token = ? where user_id = ?\";\n\n\tpublic static final String GET_ALL_TOKENS_VAL = \"select user_id, push_token from \" + DEF_TOKEN_TABLE + \" where push_token is not null\";\n\n\tprivate Logger log = Logger.getLogger(this.getClass().getName());\n\n\tprotected DataRepository dataRepository;\n\t\n\t/**\n\t * @param dataRepository\n\t */\n\tpublic MySqlAPNSProvider() {\n\t}\n\t\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\ttry {\n\t\t\tdataRepository = RepositoryFactory.getDataRepository(null, resource_uri, params);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new DBInitException(\"Error during initialization of ext repository\", ex);\n\t\t}\n\t}\n\n\t/** {@inheritDoc} */\n\t@Override\n\tpublic void init(Map<String, Object> props) {\n\t\ttry {\n\t\t\tinternalInit();\n\t\t} catch (SQLException e) {\n\t\t\te.printStackTrace();\n\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\tlog.log(Level.WARNING, \"Initializing problem\", e);\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.INFO))\n\n\t\t\t\tinternalInit();\n\t\t\t} catch (SQLException e1) {\n\t\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't access youshixiu db\", e1);\n\t\t\t\tthrow new RuntimeException(e1);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void internalInit() throws SQLException {\n\t\tthis.dataRepository.initPreparedStatement(UPDATE_TOKEN_KEY, UPDATE_TOKEN_VAL);\n\t\tthis.dataRepository.initPreparedStatement(GET_ALL_TOKENS_KEY, GET_ALL_TOKENS_VAL);\n\t}\n\t\n\t@Override\n\tpublic void delToken(BareJID user) {\n\t\tPreparedStatement st = null;\n\t\ttry {\n\t\t\tst = this.dataRepository.getPreparedStatement(user, UPDATE_TOKEN_KEY);\n\t\t\tfinal int uid = Integer.valueOf(user.getLocalpart());\n\t\t\t\n\t\t\tsynchronized (st) {\n\t\t\t\tst.setNull(1, Types.VARCHAR);\n\t\t\t\tst.setString(2, user.toString());\n\t\t\t\tst.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't del token from \" + DEF_TOKEN_TABLE, e);\n\t\t\tthrow new RuntimeException(e);\n\t\t} finally {\n\t\t\tdataRepository.release(null, null);\n\t\t}\n\t\t\n\t}\n\n\t@Override\n\tpublic void updateToken(BareJID bareJID, String token) {\n\t\t\n\t\tif(token == null)\n\t\t\treturn;\n\t\t\n\t\tPreparedStatement st = null;\n\t\ttry {\n\t\t\tst = this.dataRepository.getPreparedStatement(bareJID, UPDATE_TOKEN_KEY);\n\t\t\t\n\t\t\tsynchronized (st) {\n\t\t\t\tst.setString(1, token);\n\t\t\t\tst.setString(2, bareJID.toString());\n\t\t\t\tst.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't update push_token from \" + DEF_TOKEN_TABLE, e);\n\t\t\tthrow new RuntimeException(e);\n\t\t} finally {\n\t\t\tdataRepository.release(null, null);\n\t\t}\n\t\t\n\t}\n\t\n\n\t@Override\n\tpublic Map<String, String> getAllTokens() {\n\t\tPreparedStatement st = null;\n\t\tResultSet rs = null;\n\t\t\n\t\ttry {\n\t\t\tMap<String, String> tokens = new ConcurrentHashMap<String, String>();\n\t\t\t\n\t\t\tst = this.dataRepository.getPreparedStatement(null, GET_ALL_TOKENS_KEY);\n\t\t\t\n\t\t\tsynchronized (st) {\n\t\t\t\trs = st.executeQuery();\n\t\t\t\twhile(rs.next()){\n\t\t\t\t\ttokens.put(rs.getString(\"user_id\").split(\"@\")[0], rs.getString(\"push_token\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn tokens;\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't get all tokens from \" + DEF_TOKEN_TABLE, e);\n\t\t\tthrow new RuntimeException(e);\n\t\t} finally {\n\t\t\tdataRepository.release(null, rs);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/AuthRepositoryAware.java",
    "content": "package tigase.auth;\n\nimport javax.security.auth.callback.CallbackHandler;\n\nimport tigase.db.AuthRepository;\n\n/**\n * Interface should be implemented by {@linkplain CallbackHandler} instance if\n * {@linkplain AuthRepository} from session should be injected.\n */\npublic interface AuthRepositoryAware extends Aware {\n\n\t/**\n\t * Sets {@linkplain AuthRepository}.\n\t * \n\t * @param repo\n\t *            {@linkplain AuthRepository}.\n\t */\n\tvoid setAuthRepository(AuthRepository repo);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/Aware.java",
    "content": "package tigase.auth;\n\npublic interface Aware {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/CallbackHandlerFactory.java",
    "content": "package tigase.auth;\n\nimport java.util.Map;\n\nimport javax.security.auth.callback.CallbackHandler;\n\nimport tigase.auth.impl.AuthRepoPlainCallbackHandler;\nimport tigase.auth.impl.ScramCallbackHandler;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Factory of {@linkplain CallbackHandler CallbackHandlers}.\n * \n */\npublic class CallbackHandlerFactory {\n\n\tprivate static final String CALLBACK_HANDLER_KEY = \"callbackhandler\";\n\n\tpublic CallbackHandler create(String mechanismName, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tMap<String, Object> settings) throws ClassNotFoundException, InstantiationException, IllegalAccessException {\n\t\tString handlerClassName = getHandlerClassname(mechanismName, session, repo, settings);\n\t\tif (handlerClassName == null)\n\t\t\thandlerClassName = AuthRepoPlainCallbackHandler.class.getName();\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tClass<CallbackHandler> handlerClass = (Class<CallbackHandler>) Class.forName(handlerClassName);\n\n\t\tCallbackHandler handler = handlerClass.newInstance();\n\n\t\tif (handler instanceof SessionAware) {\n\t\t\t((SessionAware) handler).setSession(session);\n\t\t}\n\n\t\tif (handler instanceof DomainAware) {\n\t\t\t((DomainAware) handler).setDomain(session.getDomain().getVhost().getDomain());\n\t\t}\n\n\t\tif (handler instanceof NonAuthUserRepositoryAware) {\n\t\t\t((NonAuthUserRepositoryAware) handler).setNonAuthUserRepository(repo);\n\t\t}\n\n\t\tif (handler instanceof AuthRepositoryAware) {\n\t\t\t((AuthRepositoryAware) handler).setAuthRepository(session.getAuthRepository());\n\t\t}\n\n        if (handler instanceof PluginSettingsAware) {\n            ((PluginSettingsAware) handler).setPluginSettings(settings);\n        }\n\n\t\treturn handler;\n\t}\n\n\tprivate String getHandlerClassname(String mechanismName, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\t\t\t\t\t\t\t   Map<String, Object> settings) {\n\t\tif (settings != null && settings.containsKey(CALLBACK_HANDLER_KEY + \"-\" + mechanismName)) {\n\t\t\treturn (String) settings.get(CALLBACK_HANDLER_KEY + \"-\" + mechanismName);\n\t\t} else if (settings != null && settings.containsKey(CALLBACK_HANDLER_KEY)) {\n\t\t\treturn (String) settings.get(CALLBACK_HANDLER_KEY);\n\t\t} else if (mechanismName.equals(\"SCRAM-SHA-1\")) {\n\t\t\treturn ScramCallbackHandler.class.getName();\n\t\t} else if (mechanismName.equals(\"SCRAM-SHA-1-PLUS\")) {\n\t\t\treturn ScramCallbackHandler.class.getName();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/DefaultMechanismSelector.java",
    "content": "package tigase.auth;\n\nimport tigase.auth.mechanisms.SaslEXTERNAL;\nimport tigase.auth.mechanisms.SaslSCRAMPlus;\nimport tigase.auth.mechanisms.TigaseSaslServerFactory;\nimport tigase.cert.CertificateUtil;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport javax.security.sasl.SaslServerFactory;\nimport java.security.cert.Certificate;\nimport java.security.cert.X509Certificate;\nimport java.util.*;\n\npublic class DefaultMechanismSelector implements MechanismSelector {\n\n\tprivate final Set<String> allowedMechanisms = new HashSet<String>();\n\n\tprotected Map<String, Object> settings;\n\n\t@Override\n\tpublic Collection<String> filterMechanisms(Enumeration<SaslServerFactory> serverFactories, XMPPResourceConnection session) {\n\t\tfinal Map<String, ?> props = new HashMap<String, Object>();\n\t\tfinal ArrayList<String> result = new ArrayList<String>();\n\t\twhile (serverFactories.hasMoreElements()) {\n\t\t\tSaslServerFactory ss = serverFactories.nextElement();\n\t\t\tString[] x = ss.getMechanismNames(props);\n\t\t\tfor (String name : x) {\n\t\t\t\tif (match(ss, name, session) && isAllowedForDomain(name, session.getDomain()))\n\t\t\t\t\tresult.add(name);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) {\n\t\tthis.settings = settings;\n\t\tString tmp;\n\n\t\ttmp = (String) settings.get(\"enabled-mechanisms\");\n\t\tif (tmp != null) {\n\t\t\tString[] a = tmp.split(\",\");\n\t\t\tif (a != null)\n\t\t\t\tallowedMechanisms.addAll(Arrays.asList(a));\n\t\t}\n\t}\n\n\tprotected boolean isAllowedForDomain(final String mechanismName, final VHostItem vhost) {\n\t\tfinal String[] saslAllowedMechanisms = vhost.getSaslAllowedMechanisms();\n\t\tif (saslAllowedMechanisms != null && saslAllowedMechanisms.length > 0) {\n\t\t\tfor (String allowed : saslAllowedMechanisms) {\n\t\t\t\tif (allowed.equals(mechanismName))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (!allowedMechanisms.isEmpty()) {\n\t\t\treturn allowedMechanisms.contains(mechanismName);\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate boolean isJIDInCertificate(final XMPPResourceConnection session) {\n\t\tCertificate cert = (Certificate) session.getSessionData(SaslEXTERNAL.PEER_CERTIFICATE_KEY);\n\t\tif (cert == null)\n\t\t\treturn false;\n\n\t\tfinal List<String> authJIDs = CertificateUtil.extractXmppAddrs((X509Certificate) cert);\n\t\treturn authJIDs != null && !authJIDs.isEmpty();\n\t}\n\n\tprotected boolean match(SaslServerFactory factory, String mechanismName, XMPPResourceConnection session) {\n\t\tif (session.isTlsRequired() && !session.isEncrypted())\n\t\t\treturn false;\n\t\tif (factory instanceof TigaseSaslServerFactory) {\n\t\t\tif (!session.getDomain().isAnonymousEnabled() && \"ANONYMOUS\".equals(mechanismName))\n\t\t\t\treturn false;\n\t\t\tif (\"EXTERNAL\".equals(mechanismName) && !isJIDInCertificate(session))\n\t\t\t\treturn false;\n\t\t\tif (SaslSCRAMPlus.NAME.equals(mechanismName) && !SaslSCRAMPlus.isAvailable(session))\n\t\t\t\treturn false;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/DomainAware.java",
    "content": "package tigase.auth;\n\nimport javax.security.auth.callback.CallbackHandler;\n\n/**\n * Interface should be implemented by {@linkplain CallbackHandler} instance if\n * domain name rom current XMPP Session should be injected.\n */\npublic interface DomainAware extends Aware {\n\n\t/**\n\t * Sets name of domain from XMPP Stream.\n\t * \n\t * @param domain\n\t *            domain name\n\t */\n\tvoid setDomain(String domain);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/MechanismSelector.java",
    "content": "/*\n * MechanismSelector.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.auth;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collection;\nimport java.util.Enumeration;\nimport java.util.Map;\n\nimport javax.security.sasl.SaslServerFactory;\n\n/**\n * Interface for implementing selectors of SASL mechanisms.\n *\n */\npublic interface MechanismSelector {\n\t/**\n\t * Method filters all available SASL mechanisms from\n\t * {@link SaslServerFactory factories} with current\n\t * {@link XMPPResourceConnection session} state.\n\t *\n\t * @param serverFactories\n\t *            {@link SaslServerFactory SaslServerFactory} enumeration.\n\t * @param session\n\t *            current session\n\t * @return collection of all SASL mechanisms available in given session (and\n\t *         current XMPP Stream).\n\t */\n\tCollection<String> filterMechanisms(Enumeration<SaslServerFactory> serverFactories,\n\t\t\tXMPPResourceConnection session);\n\n\t/**\n\t * Initialize selector.\n\t *\n\t * @param settings\n\t *            settings of {@link tigase.xmpp.impl.SaslAuth} plugin.\n\t */\n\tvoid init(Map<String, Object> settings);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/MechanismSelectorFactory.java",
    "content": "package tigase.auth;\n\nimport java.util.Map;\n\npublic class MechanismSelectorFactory {\n\n\tprivate static final String MECHANISM_SELECTOR_KEY = \"mechanism-selector\";\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic MechanismSelector create(Map<String, Object> settings) throws ClassNotFoundException, InstantiationException,\n\t\t\tIllegalAccessException {\n\t\tClass<? extends MechanismSelector> selectorClass;\n\t\tif (settings.containsKey(MECHANISM_SELECTOR_KEY)) {\n\t\t\tselectorClass = (Class<MechanismSelector>) Class.forName((String) settings.get(MECHANISM_SELECTOR_KEY));\n\t\t} else\n\t\t\tselectorClass = DefaultMechanismSelector.class;\n\n\t\tfinal MechanismSelector selector = selectorClass.newInstance();\n\t\tselector.init(settings);\n\n\t\treturn selector;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/NonAuthUserRepositoryAware.java",
    "content": "package tigase.auth;\n\nimport tigase.db.NonAuthUserRepository;\n\npublic interface NonAuthUserRepositoryAware extends Aware {\n\n\tvoid setNonAuthUserRepository(NonAuthUserRepository repo);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/PluginSettingsAware.java",
    "content": "package tigase.auth;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport java.util.Map;\n\n/**\n * Interface should be implemented by {@linkplain CallbackHandler} instance if\n * plugin settings should be injected.\n * @author Daniele Ricci\n */\npublic interface PluginSettingsAware {\n\n    public void setPluginSettings(Map<String, Object> settings);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/SessionAware.java",
    "content": "package tigase.auth;\n\nimport javax.security.auth.callback.CallbackHandler;\n\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Interface should be implemented by {@linkplain CallbackHandler} instance if\n * current XMPP Session should be injected.\n */\npublic interface SessionAware extends Aware {\n\n\t/**\n\t * Sets XMPP Session.\n\t * \n\t * @param session\n\t *            XMPP session.\n\t */\n\tvoid setSession(XMPPResourceConnection session);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/TigaseSaslProvider.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.auth;\n\nimport java.security.Provider;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.security.sasl.SaslServerFactory;\n\n/**\n * Describe class TigaseSaslProvider here.\n * \n * Created: Sun Nov 5 22:31:20 2006\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class TigaseSaslProvider extends Provider {\n\n\tpublic static final String FACTORY_KEY = \"factory\";\n\n\tprivate static final String INFO = \"This is tigase provider (provides Tigase server specific mechanisms)\";\n\n\tprivate static final Logger log = Logger.getLogger(TigaseSaslProvider.class.getName());\n\n\tprivate static final String MY_NAME = \"tigase.sasl\";\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate static final double VERSION = 1.0;\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic TigaseSaslProvider(Map<String, Object> settings) {\n\t\tsuper(MY_NAME, VERSION, INFO);\n\n\t\tClass<? extends SaslServerFactory> facClass;\n\t\tif (settings.containsKey(FACTORY_KEY)) {\n\t\t\ttry {\n\t\t\t\tfacClass = (Class<? extends SaslServerFactory>) Class.forName(settings.get(FACTORY_KEY).toString());\n\t\t\t} catch (ClassNotFoundException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Unknown factory class\", e);\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t} else\n\t\t\tfacClass = tigase.auth.mechanisms.TigaseSaslServerFactory.class;\n\n\t\ttry {\n\t\t\tSaslServerFactory tmp = facClass.newInstance();\n\t\t\tString[] mech = tmp.getMechanismNames(new HashMap<String, Object>());\n\t\t\tfor (String name : mech) {\n\t\t\t\tlog.config(\"Registering SASL mechanism '\" + name + \"' with factory \" + facClass.getName());\n\t\t\t\tputService(new Provider.Service(this, \"SaslServerFactory\", name, facClass.getName(), null, null));\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can't instantiate factory\", e);\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/XmppSaslException.java",
    "content": "package tigase.auth;\n\nimport javax.security.sasl.SaslException;\n\npublic class XmppSaslException extends SaslException {\n\n\tpublic static enum SaslError {\n\t\t/**\n\t\t * The receiving entity acknowledges that the authentication handshake\n\t\t * has been aborted by the initiating entity.\n\t\t */\n\t\taborted(\"aborted\"),\n\t\t/**\n\t\t * The account of the initiating entity has been temporarily disabled.\n\t\t */\n\t\taccount_disabled(\"account-disabled\"),\n\t\t/**\n\t\t * The authentication failed because the initiating entity provided\n\t\t * credentials that have expired.\n\t\t */\n\t\tcredentials_expired(\"credentials-expired\"),\n\t\t/**\n\t\t * The mechanism requested by the initiating entity cannot be used\n\t\t * unless the confidentiality and integrity of the underlying stream are\n\t\t * protected (typically via TLS).\n\t\t */\n\t\tencryption_required(\"encryption-required\"),\n\t\t/**\n\t\t * The data provided by the initiating entity could not be processed\n\t\t * because the base 64 encoding is incorrect.\n\t\t */\n\t\tincorrect_encoding(\"incorrect-encoding\"),\n\t\t/**\n\t\t * The authzid provided by the initiating entity is invalid, either\n\t\t * because it is incorrectly formatted or because the initiating entity\n\t\t * does not have permissions to authorize that ID.\n\t\t */\n\t\tinvalid_authzid(\"invalid-authzid\"),\n\t\t/**\n\t\t * The initiating entity did not specify a mechanism, or requested a\n\t\t * mechanism that is not supported by the receiving entity.\n\t\t */\n\t\tinvalid_mechanism(\"invalid-mechanism\"),\n\t\t/**\n\t\t * The request is malformed (e.g., the {@code <auth/>} element includes initial\n\t\t * response data but the mechanism does not allow that, or the data sent\n\t\t * violates the syntax for the specified SASL mechanism).\n\t\t */\n\t\tmalformed_request(\"malformed-request\"),\n\t\t/**\n\t\t * The mechanism requested by the initiating entity is weaker than\n\t\t * server policy permits for that initiating entity.\n\t\t */\n\t\tmechanism_too_weak(\"mechanism-too-weak\"),\n\t\t/**\n\t\t * The authentication failed because the initiating entity did not\n\t\t * provide proper credentials, or because some generic authentication\n\t\t * failure has occurred but the receiving entity does not wish to\n\t\t * disclose specific information about the cause of the failure.\n\t\t */\n\t\tnot_authorized(\"not-authorized\"),\n\t\t/**\n\t\t * The authentication failed because of a temporary error condition\n\t\t * within the receiving entity, and it is advisable for the initiating\n\t\t * entity to try again later.\n\t\t */\n\t\ttemporary_auth_failure(\"temporary-auth-failure\");\n\n\t\tprivate final String elementName;\n\n\t\tSaslError(String elementName) {\n\t\t\tthis.elementName = elementName;\n\t\t}\n\n\t\tpublic String getElementName() {\n\t\t\treturn elementName;\n\t\t}\n\n\t}\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate SaslError saslError;\n\n\t/**\n\t * \n\t * @param saslError\n\t */\n\tpublic XmppSaslException(SaslError saslError) {\n\t\tsuper();\n\t\tthis.saslError = saslError;\n\t}\n\n\t/**\n\t *\n\t * @param saslError\n\t * @param detail\n\t */\n\tpublic XmppSaslException(SaslError saslError, String detail) {\n\t\tsuper(detail);\n\t\tthis.saslError = saslError;\n\t}\n\n\t/**\n\t *\n\t * @return\n\t */\n\tpublic String getSaslErrorElementName() {\n\t\treturn saslError == null ? null : saslError.getElementName();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/ChannelBindingCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\n\nimport javax.security.auth.callback.Callback;\n\npublic class ChannelBindingCallback implements Callback, java.io.Serializable {\n\n\tprivate final String prompt;\n\tprivate final AbstractSaslSCRAM.BindType requestedBindType;\n\tprivate byte[] bindingData;\n\n\tpublic ChannelBindingCallback(String prompt, AbstractSaslSCRAM.BindType requestedBindType) {\n\t\tthis.prompt = prompt;\n\t\tthis.requestedBindType = requestedBindType;\n\t}\n\n\tpublic byte[] getBindingData() {\n\t\treturn bindingData;\n\t}\n\n\tpublic void setBindingData(byte[] bindingData) {\n\t\tthis.bindingData = bindingData;\n\t}\n\n\tpublic String getPrompt() {\n\t\treturn prompt;\n\t}\n\n\tpublic AbstractSaslSCRAM.BindType getRequestedBindType() {\n\t\treturn requestedBindType;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/PBKDIterationsCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport javax.security.auth.callback.Callback;\n\npublic class PBKDIterationsCallback implements Callback, java.io.Serializable {\n\n\tprivate static final long serialVersionUID = -4342673378785456908L;\n\n\tprivate int interations;\n\n\tprivate String prompt;\n\n\tpublic PBKDIterationsCallback(String prompt) {\n\t\tthis.prompt = prompt;\n\t}\n\n\t/**\n\t * @return the interations\n\t */\n\tpublic int getInterations() {\n\t\treturn interations;\n\t}\n\n\t/**\n\t * @param interations\n\t *            the interations to set\n\t */\n\tpublic void setInterations(int interations) {\n\t\tthis.interations = interations;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/SaltCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport javax.security.auth.callback.Callback;\n\npublic class SaltCallback implements Callback, java.io.Serializable {\n\n\tprivate static final long serialVersionUID = -4342673378785456908L;\n\n\tprivate String prompt;\n\n\tprivate byte[] salt;\n\n\tpublic SaltCallback(String prompt) {\n\t\tthis.prompt = prompt;\n\t}\n\n\t/**\n\t * @return the salt\n\t */\n\tpublic byte[] getSalt() {\n\t\treturn salt;\n\t}\n\n\t/**\n\t * @param salt\n\t *            the salt to set\n\t */\n\tpublic void setSalt(byte[] salt) {\n\t\tthis.salt = salt;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/SaltedPasswordCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport javax.security.auth.callback.Callback;\n\npublic class SaltedPasswordCallback implements Callback, java.io.Serializable {\n\n\tprivate static final long serialVersionUID = -4342673378785456908L;\n\n\tprivate String prompt;\n\n\tprivate byte[] saltedPassword;\n\n\tpublic SaltedPasswordCallback(String prompt) {\n\t\tthis.prompt = prompt;\n\t}\n\n\t/**\n\t * @return the salt\n\t */\n\tpublic byte[] getSaltedPassword() {\n\t\treturn saltedPassword;\n\t}\n\n\t/**\n\t * @param salt\n\t *            the salt to set\n\t */\n\tpublic void setSaltedPassword(byte[] salt) {\n\t\tthis.saltedPassword = salt;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/ValidateCertificateData.java",
    "content": "package tigase.auth.callbacks;\n\nimport javax.security.auth.callback.Callback;\n\nimport tigase.xmpp.BareJID;\n\npublic class ValidateCertificateData implements Callback {\n\n\tprivate boolean authorized;\n\n\tprivate String authorizedID;\n\n\tprivate BareJID defaultAuthzid;\n\n\tpublic ValidateCertificateData() {\n\t}\n\n\tpublic ValidateCertificateData(BareJID jid) {\n\t\tsetDefaultAuthzid(jid);\n\t}\n\n\tpublic String getAuthorizedID() {\n\t\treturn authorizedID;\n\t}\n\n\tpublic BareJID getDefaultAuthzid() {\n\t\treturn defaultAuthzid;\n\t}\n\n\tpublic boolean isAuthorized() {\n\t\treturn authorized;\n\t}\n\n\tpublic void setAuthorized(boolean authorized) {\n\t\tthis.authorized = authorized;\n\t}\n\n\tpublic void setAuthorizedID(String authorizedID) {\n\t\tthis.authorizedID = authorizedID;\n\t}\n\n\tpublic void setDefaultAuthzid(BareJID defaultAuthzid) {\n\t\tthis.defaultAuthzid = defaultAuthzid;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/VerifyPasswordCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport javax.security.auth.callback.Callback;\n\n/**\n * Class for validate password. Called by SASL mechanisms. If given password is\n * valid then {@linkplain VerifyPasswordCallback#setVerified(boolean)\n * setVerified(true)} must be called.\n */\npublic class VerifyPasswordCallback implements Callback {\n\n\tprivate final String password;\n\n\tprivate boolean verified = false;\n\n\tpublic VerifyPasswordCallback(final String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic boolean isVerified() {\n\t\treturn verified;\n\t}\n\n\tpublic void setVerified(boolean verified) {\n\t\tthis.verified = verified;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/callbacks/XMPPSessionCallback.java",
    "content": "package tigase.auth.callbacks;\n\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport javax.security.auth.callback.Callback;\n\npublic class XMPPSessionCallback implements Callback, java.io.Serializable {\n\n\tprivate final String prompt;\n\tprivate XMPPResourceConnection session;\n\n\tpublic XMPPSessionCallback(String prompt) {\n\t\tthis.prompt = prompt;\n\t}\n\n\tpublic String getPrompt() {\n\t\treturn prompt;\n\t}\n\n\tpublic XMPPResourceConnection getSession() {\n\t\treturn session;\n\t}\n\n\tpublic void setSession(XMPPResourceConnection session) {\n\t\tthis.session = session;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/impl/AuthRepoPlainCallbackHandler.java",
    "content": "/*\n * AuthRepoPlainCallbackHandler.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.auth.impl;\n\n//~--- JDK imports ------------------------------------------------------------\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.RealmCallback;\n\nimport tigase.auth.AuthRepositoryAware;\nimport tigase.auth.DomainAware;\nimport tigase.auth.callbacks.VerifyPasswordCallback;\nimport tigase.auth.mechanisms.AbstractSasl;\nimport tigase.db.AuthRepository;\nimport tigase.xmpp.BareJID;\n\n/**\n * This is implementation of {@linkplain CallbackHandler} to use with old\n * {@linkplain AuthRepository AuthRepositories}. Callback\n * {@linkplain VerifyPasswordCallback} uses method\n * {@linkplain AuthRepository#plainAuth(BareJID, String)} to password\n * verification.\n */\npublic class AuthRepoPlainCallbackHandler implements CallbackHandler, AuthRepositoryAware, DomainAware {\n\tprotected String domain;\n\n\tprotected BareJID jid = null;\n\tprotected Logger log = Logger.getLogger(this.getClass().getName());\n\tprotected AuthRepository repo;\n\n\t@Override\n\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t}\n\t\t\thandleCallback(callbacks[i]);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tprotected void handleAuthorizeCallback(AuthorizeCallback authCallback) {\n\t\tString authenId = authCallback.getAuthenticationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t}\n\n\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t}\n\t\tif (AbstractSasl.isAuthzIDIgnored() || authenId.equals(authorId)) {\n\t\t\tauthCallback.setAuthorized(true);\n\t\t}\n\t}\n\n\tprotected void handleCallback(Callback callback) throws UnsupportedCallbackException, IOException {\n\t\tif (callback instanceof RealmCallback) {\n\t\t\thandleRealmCallback((RealmCallback) callback);\n\t\t} else if (callback instanceof NameCallback) {\n\t\t\thandleNameCallback((NameCallback) callback);\n\t\t} else if (callback instanceof VerifyPasswordCallback) {\n\t\t\thandleVerifyPasswordCallback((VerifyPasswordCallback) callback);\n\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\thandleAuthorizeCallback((AuthorizeCallback) callback);\n\t\t} else {\n\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback\");\n\t\t}\n\n\t}\n\n\tprotected void handleNameCallback(NameCallback nc) throws IOException {\n\t\tString user_name = nc.getDefaultName();\n\t\tjid = BareJID.bareJIDInstanceNS(user_name, domain);\n\t\tnc.setName(jid.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t}\n\t}\n\n\tprotected void handleRealmCallback(RealmCallback rc) throws IOException {\n\t\tString realm = domain;\n\n\t\tif (realm != null) {\n\t\t\trc.setText(realm);\n\t\t} // end of if (realm == null)\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"RealmCallback: {0}\", realm);\n\t\t}\n\t}\n\n\tprotected void handleVerifyPasswordCallback(VerifyPasswordCallback pc) throws IOException {\n\t\tString passwd = pc.getPassword();\n\n\t\ttry {\n\t\t\tMap<String, Object> map = new HashMap<String, Object>();\n\n\t\t\tmap.put(AuthRepository.PROTOCOL_KEY, AuthRepository.PROTOCOL_VAL_NONSASL);\n\t\t\tmap.put(AuthRepository.USER_ID_KEY, jid);\n\t\t\tmap.put(AuthRepository.PASSWORD_KEY, passwd);\n\t\t\tmap.put(AuthRepository.REALM_KEY, jid.getDomain());\n\t\t\tmap.put(AuthRepository.SERVER_NAME_KEY, jid.getDomain());\n\t\t\tpc.setVerified(repo.otherAuth(map));\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"VerifyPasswordCallback: {0}\", \"******\");\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tpc.setVerified(false);\n\n\t\t\tthrow new IOException(\"Password verification problem.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setAuthRepository(AuthRepository repo) {\n\t\tthis.repo = repo;\n\t}\n\n\t@Override\n\tpublic void setDomain(String domain) {\n\t\tthis.domain = domain;\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/impl/CertBasedCallbackHandler.java",
    "content": "package tigase.auth.impl;\n\nimport java.io.IOException;\nimport java.security.cert.Certificate;\nimport java.security.cert.X509Certificate;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.UnsupportedCallbackException;\n\nimport tigase.auth.SessionAware;\nimport tigase.auth.callbacks.ValidateCertificateData;\nimport tigase.auth.mechanisms.SaslEXTERNAL;\nimport tigase.cert.CertificateUtil;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.XMPPResourceConnection;\n\npublic class CertBasedCallbackHandler implements CallbackHandler, SessionAware {\n\n\tprotected Logger log = Logger.getLogger(this.getClass().getName());\n\n\tprivate XMPPResourceConnection session;\n\n\t@Override\n\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\ttry {\n\t\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t\t}\n\n\t\t\t\tif (callbacks[i] instanceof ValidateCertificateData) {\n\t\t\t\t\tValidateCertificateData authCallback = ((ValidateCertificateData) callbacks[i]);\n\n\t\t\t\t\tfinal String domain = session.getDomain().getVhost().getDomain();\n\t\t\t\t\tfinal BareJID defaultAuthzid = authCallback.getDefaultAuthzid();\n\t\t\t\t\tif (defaultAuthzid != null && !defaultAuthzid.getDomain().equals(domain)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tCertificate cert = (Certificate) session.getSessionData(SaslEXTERNAL.PEER_CERTIFICATE_KEY);\n\t\t\t\t\tfinal String[] authJIDs = CertificateUtil.extractXmppAddrs((X509Certificate) cert).toArray(new String[] {});\n\n\t\t\t\t\tfor (String string : authJIDs) {\n\t\t\t\t\t\tif (defaultAuthzid != null) {\n\t\t\t\t\t\t\tif (string.equals(defaultAuthzid.toString())) {\n\t\t\t\t\t\t\t\tauthCallback.setAuthorized(true);\n\t\t\t\t\t\t\t\tauthCallback.setAuthorizedID(string);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (BareJID.bareJIDInstance(string).getDomain().equals(domain)) {\n\t\t\t\t\t\t\tauthCallback.setAuthorized(true);\n\t\t\t\t\t\t\tauthCallback.setAuthorizedID(string);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UnsupportedCallbackException(callbacks[i], \"Unrecognized Callback\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseStringprepException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setSession(XMPPResourceConnection session) {\n\t\tthis.session = session;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/impl/PlainSPCallbackHandler.java",
    "content": "/*\n * AuthRepoPlainCallbackHandler.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.auth.impl;\n\n//~--- JDK imports ------------------------------------------------------------\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.RealmCallback;\nimport javax.security.sasl.SaslException;\n\nimport tigase.auth.AuthRepositoryAware;\nimport tigase.auth.DomainAware;\nimport tigase.auth.callbacks.VerifyPasswordCallback;\nimport tigase.auth.mechanisms.AbstractSasl;\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\nimport tigase.db.AuthRepository;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\n\n/**\n * This is implementation of {@linkplain CallbackHandler} to use with old\n * {@linkplain AuthRepository AuthRepositories}. Callback\n * {@linkplain VerifyPasswordCallback} uses method\n * {@linkplain AuthRepository#plainAuth(BareJID, String)} to password\n * verification.\n */\npublic class PlainSPCallbackHandler implements CallbackHandler, AuthRepositoryAware, DomainAware {\n\tprotected String domain;\n\n\tprotected BareJID jid = null;\n\tprotected Logger log = Logger.getLogger(this.getClass().getName());\n\tprotected AuthRepository repo;\n\n\t@Override\n\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t}\n\t\t\thandleCallback(callbacks[i]);\n\t\t}\n\t}\n\n\tprotected void handleAuthorizeCallback(AuthorizeCallback authCallback) {\n\t\tString authenId = authCallback.getAuthenticationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t}\n\n\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t}\n\t\tif (AbstractSasl.isAuthzIDIgnored() || authenId.equals(authorId)) {\n\t\t\tauthCallback.setAuthorized(true);\n\t\t}\n\t}\n\n\tprotected void handleCallback(Callback callback) throws UnsupportedCallbackException, IOException {\n\t\tif (callback instanceof RealmCallback) {\n\t\t\thandleRealmCallback((RealmCallback) callback);\n\t\t} else if (callback instanceof NameCallback) {\n\t\t\thandleNameCallback((NameCallback) callback);\n\t\t} else if (callback instanceof VerifyPasswordCallback) {\n\t\t\thandleVerifyPasswordCallback((VerifyPasswordCallback) callback);\n\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\thandleAuthorizeCallback((AuthorizeCallback) callback);\n\t\t} else {\n\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback\");\n\t\t}\n\n\t}\n\n\tprotected void handleNameCallback(NameCallback nc) throws IOException {\n\t\tString user_name = nc.getDefaultName();\n\t\tjid = BareJID.bareJIDInstanceNS(user_name, domain);\n\t\tnc.setName(jid.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t}\n\t}\n\n\tprotected void handleRealmCallback(RealmCallback rc) throws IOException {\n\t\tString realm = domain;\n\n\t\tif (realm != null) {\n\t\t\trc.setText(realm);\n\t\t} // end of if (realm == null)\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"RealmCallback: {0}\", realm);\n\t\t}\n\t}\n\n\tprotected void handleVerifyPasswordCallback(VerifyPasswordCallback pc) throws IOException {\n\t\tfinal String password = pc.getPassword();\n\t\ttry {\n\t\t\tString pwd = repo.getPassword(jid);\n\t\t\tif (pwd == null)\n\t\t\t\tthrow new SaslException(\"User \" + jid + \" not found.\");\n\t\t\tbyte[] buffer = Base64.decode(pwd);\n\t\t\tbyte[] salt = new byte[20];\n\t\t\tbyte[] saltedPassword = new byte[20];\n\t\t\tSystem.arraycopy(buffer, 0, salt, 0, salt.length);\n\t\t\tSystem.arraycopy(buffer, salt.length, saltedPassword, 0, saltedPassword.length);\n\n\t\t\tbyte[] np = AbstractSaslSCRAM.hi(\"SHA1\", AbstractSaslSCRAM.normalize(password), salt, 4096);\n\n\t\t\tpc.setVerified(Arrays.equals(saltedPassword, np));\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"VerifyPasswordCallback: {0}\", \"******\");\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tpc.setVerified(false);\n\t\t\tthrow new IOException(\"Password verification problem.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setAuthRepository(AuthRepository repo) {\n\t\tthis.repo = repo;\n\t}\n\n\t@Override\n\tpublic void setDomain(String domain) {\n\t\tthis.domain = domain;\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/impl/ScramCallbackHandler.java",
    "content": "package tigase.auth.impl;\n\nimport tigase.auth.AuthRepositoryAware;\nimport tigase.auth.DomainAware;\nimport tigase.auth.SessionAware;\nimport tigase.auth.callbacks.*;\nimport tigase.auth.mechanisms.AbstractSasl;\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\nimport tigase.db.AuthRepository;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport java.io.IOException;\nimport java.security.MessageDigest;\nimport java.security.SecureRandom;\nimport java.security.cert.Certificate;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\npublic class ScramCallbackHandler implements CallbackHandler, AuthRepositoryAware, SessionAware, DomainAware {\n\n\tprivate final SecureRandom random = new SecureRandom();\n\tprivate final byte[] salt;\n\tprotected BareJID jid = null;\n\tprotected Logger log = Logger.getLogger(this.getClass().getName());\n\tprivate String domain;\n\tprivate int pbkd2Iterations = 4096;\n\tprivate AuthRepository repo;\n\tprivate XMPPResourceConnection session;\n\n\tpublic ScramCallbackHandler() {\n\t\tthis.salt = new byte[10];\n\t\trandom.nextBytes(salt);\n\t}\n\n\t@Override\n\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t}\n\t\t\thandleCallback(callbacks[i]);\n\t\t}\n\t}\n\n\tprotected void handleAuthorizeCallback(AuthorizeCallback authCallback) {\n\t\tString authenId = authCallback.getAuthenticationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t}\n\n\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t}\n\t\tif (AbstractSasl.isAuthzIDIgnored() || authenId.equals(authorId)) {\n\t\t\tauthCallback.setAuthorized(true);\n\t\t}\n\t}\n\n\tprotected void handleCallback(Callback callback) throws UnsupportedCallbackException, IOException {\n\t\tif (callback instanceof XMPPSessionCallback) {\n\t\t\t((XMPPSessionCallback) callback).setSession(session);\n\t\t} else if (callback instanceof ChannelBindingCallback) {\n\t\t\thandleChannelBindingCallback((ChannelBindingCallback) callback);\n\t\t} else if (callback instanceof PBKDIterationsCallback) {\n\t\t\thandlePBKDIterationsCallback((PBKDIterationsCallback) callback);\n\t\t} else if (callback instanceof SaltedPasswordCallback) {\n\t\t\thandleSaltedPasswordCallbackCallback((SaltedPasswordCallback) callback);\n\t\t} else if (callback instanceof NameCallback) {\n\t\t\thandleNameCallback((NameCallback) callback);\n\t\t} else if (callback instanceof SaltCallback) {\n\t\t\thandleSaltCallback((SaltCallback) callback);\n\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\thandleAuthorizeCallback((AuthorizeCallback) callback);\n\t\t} else {\n\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback \" + callback);\n\t\t}\n\t}\n\n\tprivate void handleChannelBindingCallback(ChannelBindingCallback callback) {\n\t\tif (callback.getRequestedBindType() == AbstractSaslSCRAM.BindType.tls_unique) {\n\t\t\tcallback.setBindingData((byte[]) session.getSessionData(AbstractSaslSCRAM.TLS_UNIQUE_ID_KEY));\n\t\t} else if (callback.getRequestedBindType() == AbstractSaslSCRAM.BindType.tls_server_end_point) {\n\t\t\ttry {\n\t\t\t\tCertificate cert = (Certificate) session.getSessionData(AbstractSaslSCRAM.LOCAL_CERTIFICATE_KEY);\n\t\t\t\tfinal String usealgo;\n\t\t\t\tfinal String algo = cert.getPublicKey().getAlgorithm();\n\t\t\t\tif (algo.equals(\"MD5\") || algo.equals(\"SHA-1\")) {\n\t\t\t\t\tusealgo = \"SHA-256\";\n\t\t\t\t} else {\n\t\t\t\t\tusealgo = algo;\n\t\t\t\t}\n\t\t\t\tfinal MessageDigest md = MessageDigest.getInstance(usealgo);\n\t\t\t\tfinal byte[] der = cert.getEncoded();\n\t\t\t\tmd.update(der);\n\t\t\t\tcallback.setBindingData(md.digest());\n\t\t\t} catch (Exception e) {\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.log(Level.FINEST, \"Channel binding {0}: {1} in session-id {2}\", new Object[]{callback.getRequestedBindType(), callback.getBindingData() == null ? \"null\" : Base64.encode(callback.getBindingData()), session});\n\t}\n\n\tprotected void handleNameCallback(NameCallback nc) throws IOException {\n\t\tString user_name = nc.getDefaultName();\n\t\tjid = BareJID.bareJIDInstanceNS(user_name, domain);\n\t\tnc.setName(jid.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t}\n\t}\n\n\tprotected void handlePBKDIterationsCallback(PBKDIterationsCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"PBKDIterationsCallback: {0}\", jid);\n\t\t}\n\t\tcallback.setInterations(pbkd2Iterations);\n\t}\n\n\tprotected void handleSaltCallback(SaltCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"SaltCallback: {0}\", jid);\n\t\t}\n\n\t\tcallback.setSalt(salt);\n\t}\n\n\tprotected void handleSaltedPasswordCallbackCallback(SaltedPasswordCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"PasswordCallback: {0}\", jid);\n\t\t}\n\n\t\ttry {\n\t\t\tString pwd = repo.getPassword(jid);\n\n\t\t\tif (pwd == null) {\n\t\t\t\tcallback.setSaltedPassword(new byte[]{});\n\t\t\t} else {\n\n\t\t\t\tbyte[] saltedPassword = AbstractSaslSCRAM.hi(\"SHA1\", AbstractSaslSCRAM.normalize(pwd), salt, pbkd2Iterations);\n\n\t\t\t\tcallback.setSaltedPassword(saltedPassword);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tcallback.setSaltedPassword(null);\n\t\t\tlog.log(Level.WARNING, \"Can't retrieve user password.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setAuthRepository(AuthRepository repo) {\n\t\tthis.repo = repo;\n\t}\n\n\t@Override\n\tpublic void setDomain(String domain) {\n\t\tthis.domain = domain;\n\t}\n\n\t@Override\n\tpublic void setSession(XMPPResourceConnection session) {\n\t\tthis.session = session;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/impl/ScramSPCallbackHandler.java",
    "content": "package tigase.auth.impl;\n\nimport tigase.auth.AuthRepositoryAware;\nimport tigase.auth.DomainAware;\nimport tigase.auth.SessionAware;\nimport tigase.auth.callbacks.*;\nimport tigase.auth.mechanisms.AbstractSasl;\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\nimport tigase.db.AuthRepository;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\nimport java.io.IOException;\nimport java.security.MessageDigest;\nimport java.security.cert.Certificate;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Handler for SCRAM with Salted Password.\n * <p>\n * Password should be encoded as:<br>\n * <p>\n * <pre>\n * base64(salt | saltedPassword)\n * </pre>\n * <p>\n * Where:<br>\n * <code>salt</code> - 20 bytes,<br>\n * <code>saltedPassword</code> - 20 bytes.\n */\npublic class ScramSPCallbackHandler implements CallbackHandler, AuthRepositoryAware, SessionAware, DomainAware {\n\n\tprotected BareJID jid = null;\n\tprotected Logger log = Logger.getLogger(this.getClass().getName());\n\tprivate String domain;\n\tprivate int pbkd2Iterations = 4096;\n\n\tprivate AuthRepository repo;\n\n\tprivate byte[] salt;\n\n\tprivate byte[] saltedPassword;\n\n\tprivate XMPPResourceConnection session;\n\n\tpublic ScramSPCallbackHandler() {\n\t}\n\n\t@Override\n\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t}\n\t\t\thandleCallback(callbacks[i]);\n\t\t}\n\t}\n\n\tprotected void handleAuthorizeCallback(AuthorizeCallback authCallback) {\n\t\tString authenId = authCallback.getAuthenticationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t}\n\n\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t}\n\t\tif (AbstractSasl.isAuthzIDIgnored() || authenId.equals(authorId)) {\n\t\t\tauthCallback.setAuthorized(true);\n\t\t}\n\t}\n\n\tprotected void handleCallback(Callback callback) throws UnsupportedCallbackException, IOException {\n\t\tif (callback instanceof XMPPSessionCallback) {\n\t\t\t((XMPPSessionCallback) callback).setSession(session);\n\t\t} else if (callback instanceof ChannelBindingCallback) {\n\t\t\thandleChannelBindingCallback((ChannelBindingCallback) callback);\n\t\t} else if (callback instanceof PBKDIterationsCallback) {\n\t\t\thandlePBKDIterationsCallback((PBKDIterationsCallback) callback);\n\t\t} else if (callback instanceof SaltedPasswordCallback) {\n\t\t\thandleSaltedPasswordCallback((SaltedPasswordCallback) callback);\n\t\t} else if (callback instanceof NameCallback) {\n\t\t\thandleNameCallback((NameCallback) callback);\n\t\t} else if (callback instanceof SaltCallback) {\n\t\t\thandleSaltCallback((SaltCallback) callback);\n\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\thandleAuthorizeCallback((AuthorizeCallback) callback);\n\t\t} else {\n\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback \" + callback);\n\t\t}\n\t}\n\n\tprivate void handleChannelBindingCallback(ChannelBindingCallback callback) {\n\t\tif (callback.getRequestedBindType() == AbstractSaslSCRAM.BindType.tls_unique) {\n\t\t\tcallback.setBindingData((byte[]) session.getSessionData(AbstractSaslSCRAM.TLS_UNIQUE_ID_KEY));\n\t\t} else if (callback.getRequestedBindType() == AbstractSaslSCRAM.BindType.tls_server_end_point) {\n\t\t\ttry {\n\t\t\t\tCertificate cert = (Certificate) session.getSessionData(AbstractSaslSCRAM.LOCAL_CERTIFICATE_KEY);\n\t\t\t\tfinal String usealgo;\n\t\t\t\tfinal String algo = cert.getPublicKey().getAlgorithm();\n\t\t\t\tif (algo.equals(\"MD5\") || algo.equals(\"SHA-1\")) {\n\t\t\t\t\tusealgo = \"SHA-256\";\n\t\t\t\t} else {\n\t\t\t\t\tusealgo = algo;\n\t\t\t\t}\n\t\t\t\tfinal MessageDigest md = MessageDigest.getInstance(usealgo);\n\t\t\t\tfinal byte[] der = cert.getEncoded();\n\t\t\t\tmd.update(der);\n\t\t\t\tcallback.setBindingData(md.digest());\n\t\t\t} catch (Exception e) {\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.log(Level.FINEST, \"Channel binding {0}: {1}\", new Object[]{callback.getRequestedBindType(), Base64.encode(callback.getBindingData())});\n\t}\n\n\tprotected void handleNameCallback(NameCallback nc) throws IOException {\n\t\tString user_name = nc.getDefaultName();\n\t\tjid = BareJID.bareJIDInstanceNS(user_name, domain);\n\t\tnc.setName(jid.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t}\n\t\ttry {\n\t\t\tString pwd = repo.getPassword(jid);\n\t\t\tif (pwd == null)\n\t\t\t\tthrow new SaslException(\"User \" + jid + \" not found.\");\n\t\t\tbyte[] buffer = Base64.decode(pwd);\n\t\t\tthis.salt = new byte[20];\n\t\t\tthis.saltedPassword = new byte[20];\n\t\t\tSystem.arraycopy(buffer, 0, salt, 0, salt.length);\n\t\t\tSystem.arraycopy(buffer, salt.length, saltedPassword, 0, saltedPassword.length);\n\t\t} catch (Exception e) {\n\t\t\tthis.salt = null;\n\t\t\tthis.saltedPassword = null;\n\t\t\tlog.log(Level.WARNING, \"Can't retrieve users salted password.\", e);\n\t\t}\n\t}\n\n\tprotected void handlePBKDIterationsCallback(PBKDIterationsCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"PBKDIterationsCallback: {0}\", jid);\n\t\t}\n\t\tcallback.setInterations(pbkd2Iterations);\n\t}\n\n\tprotected void handleSaltCallback(SaltCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"SaltCallback: {0}\", jid);\n\t\t}\n\n\t\tcallback.setSalt(salt);\n\t}\n\n\tprotected void handleSaltedPasswordCallback(SaltedPasswordCallback callback) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"SaltedPasswordCallback: {0}\", jid);\n\t\t}\n\n\t\tcallback.setSaltedPassword(saltedPassword);\n\t}\n\n\t@Override\n\tpublic void setAuthRepository(AuthRepository repo) {\n\t\tthis.repo = repo;\n\t}\n\n\t@Override\n\tpublic void setDomain(String domain) {\n\t\tthis.domain = domain;\n\t}\n\n\t@Override\n\tpublic void setSession(XMPPResourceConnection session) {\n\t\tthis.session = session;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/AbstractSasl.java",
    "content": "package tigase.auth.mechanisms;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Logger;\n\npublic abstract class AbstractSasl implements SaslServer {\n\n\tpublic static final String SASL_STRICT_MODE_KEY = \"sasl-strict\";\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\tprotected final CallbackHandler callbackHandler;\n\tprotected final Map<String, Object> negotiatedProperty = new HashMap<String, Object>();\n\tprotected final Map<? super String, ?> props;\n\tprotected String authorizedId = null;\n\tprotected boolean complete = false;\n\n\tprotected AbstractSasl(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tthis.props = props;\n\t\tthis.callbackHandler = callbackHandler;\n\t}\n\n\tpublic static boolean isAuthzIDIgnored() {\n\t\tString x = System.getProperty(SASL_STRICT_MODE_KEY, \"false\");\n\t\treturn !Boolean.parseBoolean(x);\n\t}\n\n\tprotected static final boolean isEmpty(Object x) {\n\t\treturn x == null || x.toString().length() == 0;\n\t}\n\n\t@Override\n\tpublic void dispose() throws SaslException {\n\t\tthis.authorizedId = null;\n\t}\n\n\t@Override\n\tpublic Object getNegotiatedProperty(String propName) {\n\t\tif (!isComplete())\n\t\t\tthrow new IllegalStateException(\"Server negotiation not complete\");\n\t\treturn negotiatedProperty.get(propName);\n\t}\n\n\tprotected void handleCallbacks(Callback... callbacks) throws SaslException {\n\t\ttry {\n\t\t\tcallbackHandler.handle(callbacks);\n\t\t} catch (IOException e) {\n\t\t\tthrow new SaslException(e.getMessage(), e);\n\t\t} catch (UnsupportedCallbackException e) {\n\t\t\tthrow new SaslException(\"Callback not supported by handler\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isComplete() {\n\t\treturn complete;\n\t}\n\n\tprotected String[] split(final byte[] byteArray, final String defaultValue) {\n\t\tif (byteArray == null)\n\t\t\treturn new String[]{};\n\t\tArrayList<String> result = new ArrayList<String>();\n\n\t\tint pi = 0;\n\t\tfor (int i = 0; i < byteArray.length; i++) {\n\t\t\tif (byteArray[i] == 0) {\n\t\t\t\tString item;\n\t\t\t\tif (pi == i) {\n\t\t\t\t\titem = defaultValue;\n\t\t\t\t\tpi = i + 1;\n\t\t\t\t} else {\n\t\t\t\t\titem = new String(byteArray, pi, i - pi);\n\t\t\t\t\tpi = i + 1;\n\t\t\t\t}\n\t\t\t\tresult.add(item);\n\t\t\t}\n\n\t\t}\n\t\tif (pi < byteArray.length) {\n\t\t\tString item = new String(byteArray, pi, byteArray.length - pi);\n\t\t\tresult.add(item);\n\t\t} else\n\t\t\tresult.add(defaultValue);\n\n\t\treturn result.toArray(new String[]{});\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/AbstractSaslSCRAM.java",
    "content": "package tigase.auth.mechanisms;\n\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.XmppSaslException.SaslError;\nimport tigase.auth.callbacks.ChannelBindingCallback;\nimport tigase.auth.callbacks.PBKDIterationsCallback;\nimport tigase.auth.callbacks.SaltCallback;\nimport tigase.auth.callbacks.SaltedPasswordCallback;\nimport tigase.util.Base64;\n\nimport javax.crypto.Mac;\nimport javax.crypto.SecretKey;\nimport javax.crypto.spec.SecretKeySpec;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\nimport java.io.ByteArrayOutputStream;\nimport java.nio.charset.Charset;\nimport java.security.InvalidKeyException;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.SecureRandom;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.logging.Level;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\npublic abstract class AbstractSaslSCRAM extends AbstractSasl {\n\n\tpublic static final String TLS_UNIQUE_ID_KEY = \"TLS_UNIQUE_ID_KEY\";\n\tpublic static final String LOCAL_CERTIFICATE_KEY = \"LOCAL_CERTIFICATE_KEY\";\n\tprotected final static byte[] DEFAULT_CLIENT_KEY = \"Client Key\".getBytes();\n\tprotected final static byte[] DEFAULT_SERVER_KEY = \"Server Key\".getBytes();\n\tprivate final static String ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\tprivate static final Charset CHARSET = Charset.forName(\"UTF-8\");\n\tprivate final static Pattern CLIENT_FIRST_MESSAGE = Pattern.compile(\"^(?<gs2Header>(?:y|n|p=(?<cbName>[a-zA-z0-9.-]+)),\"\n\t\t\t+ \"(?:a=(?<authzid>(?:[\\\\x21-\\\\x2B\\\\x2D-\\\\x7E]|=2C|=3D)+))?,)(?<clientFirstBare>(?<mext>m=[^\\\\000=]+,)\"\n\t\t\t+ \"?n=(?<username>(?:[\\\\x21-\\\\x2B\\\\x2D-\\\\x7E]|=2C|=3D)+),r=(?<nonce>[\\\\x21-\\\\x2B\\\\x2D-\\\\x7E]+)(?:,.*)?)$\");\n\tprivate final static Pattern CLIENT_LAST_MESSAGE = Pattern.compile(\"^(?<withoutProof>c=(?<cb>[a-zA-Z0-9/+=]+),\"\n\t\t\t+ \"(?:r=(?<nonce>[\\\\x21-\\\\x2B\\\\x2D-\\\\x7E]+))(?:,.*)?),p=(?<proof>[a-zA-Z0-9/+=]+)$\");\n\tprivate final String algorithm;\n\tprivate final byte[] clientKeyData;\n\tprivate final String mechanismName;\n\tprivate final byte[] serverKeyData;\n\tprivate final String serverNonce;\n\tprivate String cfmAuthzid;\n\tprivate String cfmBareMessage;\n\tprivate String cfmCbname;\n\tprivate String cfmGs2header;\n\tprivate String cfmUsername;\n\tprivate byte[] clientKey;\n\tprivate Random random = new SecureRandom();\n\tprivate byte[] saltedPassword;\n\tprivate String sfmMessage;\n\tprivate String sfmNonce;\n\tprivate Step step = Step.clientFirstMessage;\n\tprivate byte[] storedKey;\n\tprivate BindType requestedBindType;\n\tprivate byte[] bindingData = null;\n\n\tprotected AbstractSaslSCRAM(String mechanismName, String algorithm, byte[] clientKey, byte[] serverKey,\n\t\t\t\t\t\t\t\tMap<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(props, callbackHandler);\n\t\tthis.mechanismName = mechanismName;\n\t\tthis.algorithm = algorithm;\n\t\tthis.clientKeyData = clientKey;\n\t\tthis.serverKeyData = serverKey;\n\t\tserverNonce = randomString();\n\t}\n\n\tprotected AbstractSaslSCRAM(String mechanismName, String algorithm, byte[] clientKey, byte[] serverKey,\n\t\t\t\t\t\t\t\tMap<? super String, ?> props, CallbackHandler callbackHandler, String serverOnce) {\n\t\tsuper(props, callbackHandler);\n\t\tthis.mechanismName = mechanismName;\n\t\tthis.algorithm = algorithm;\n\t\tthis.clientKeyData = clientKey;\n\t\tthis.serverKeyData = serverKey;\n\t\tthis.serverNonce = serverOnce;\n\t}\n\n\tpublic static byte[] hi(String algorithm, byte[] password, final byte[] salt, final int iterations)\n\t\t\tthrows InvalidKeyException, NoSuchAlgorithmException {\n\t\tfinal SecretKeySpec k = new SecretKeySpec(password, \"Hmac\" + algorithm);\n\n\t\tbyte[] z = new byte[salt.length + 4];\n\t\tSystem.arraycopy(salt, 0, z, 0, salt.length);\n\t\tSystem.arraycopy(new byte[]{0, 0, 0, 1}, 0, z, salt.length, 4);\n\n\t\tbyte[] u = hmac(k, z);\n\t\tbyte[] result = new byte[u.length];\n\t\tSystem.arraycopy(u, 0, result, 0, result.length);\n\n\t\tint i = 1;\n\t\twhile (i < iterations) {\n\t\t\tu = hmac(k, u);\n\t\t\tfor (int j = 0; j < u.length; j++) {\n\t\t\t\tresult[j] ^= u[j];\n\t\t\t}\n\t\t\t++i;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprotected static byte[] hmac(final SecretKey key, byte[] data) throws NoSuchAlgorithmException, InvalidKeyException {\n\t\tMac mac = Mac.getInstance(key.getAlgorithm());\n\t\tmac.init(key);\n\t\treturn mac.doFinal(data);\n\t}\n\n\tpublic static byte[] normalize(String str) {\n\t\treturn str.getBytes(CHARSET);\n\t}\n\n\tprotected byte[] calculateC() {\n\t\ttry {\n\t\t\tfinal ByteArrayOutputStream result = new ByteArrayOutputStream();\n\n\t\t\tresult.write(this.cfmGs2header.getBytes());\n\n\t\t\tif (this.requestedBindType == BindType.tls_unique\n\t\t\t\t\t|| this.requestedBindType == BindType.tls_server_end_point) {\n\t\t\t\tresult.write(bindingData);\n\t\t\t}\n\t\t\treturn result.toByteArray();\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprotected abstract void checkRequestedBindType(BindType requestedBindType) throws SaslException;\n\n\tprivate BindType createBindType(final String cfmGs2header, final String cfmCbname) throws SaslException {\n\t\tfinal char t = cfmGs2header.charAt(0);\n\n\t\tif ('n' == t) return BindType.n;\n\t\telse if ('y' == t) return BindType.y;\n\t\telse if (\"tls-unique\".equals(cfmCbname)) return BindType.tls_unique;\n\t\telse if (\"tls-server-end-point\".equals(cfmCbname)) return BindType.tls_server_end_point;\n\t\telse throw new SaslException(\"Unsupported channel binding type\");\n\t}\n\n\t@Override\n\tpublic byte[] evaluateResponse(byte[] response) throws SaslException {\n\t\ttry {\n\t\t\tswitch (step) {\n\t\t\t\tcase clientFirstMessage:\n\t\t\t\t\treturn processClientFirstMessage(response);\n\t\t\t\tcase clientFinalMessage:\n\t\t\t\t\treturn processClientLastMessage(response);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new SaslException(getMechanismName() + \": Server at illegal state\");\n\t\t\t}\n\t\t} catch (SaslException e) {\n\t\t\tthrow e;\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new SaslException(\"SASL Failed\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getAuthorizationID() {\n\t\treturn authorizedId;\n\t}\n\n\t@Override\n\tpublic String getMechanismName() {\n\t\treturn mechanismName;\n\t}\n\n\tprotected byte[] h(byte[] data) throws NoSuchAlgorithmException {\n\t\tMessageDigest digest = MessageDigest.getInstance(algorithm);\n\t\treturn digest.digest(data);\n\t}\n\n\tprotected SecretKey key(final byte[] key) {\n\t\treturn new SecretKeySpec(key, \"Hmac\" + algorithm);\n\t}\n\n\tprotected byte[] processClientFirstMessage(byte[] data) throws SaslException, InvalidKeyException, NoSuchAlgorithmException {\n\t\tMatcher r = CLIENT_FIRST_MESSAGE.matcher(new String(data, CHARSET));\n\t\tif (!r.matches())\n\t\t\tthrow new SaslException(\"Bad challenge syntax\");\n\n\t\tthis.cfmGs2header = r.group(\"gs2Header\");\n\t\tthis.cfmCbname = r.group(\"cbName\");\n\t\tthis.requestedBindType = createBindType(this.cfmGs2header, this.cfmCbname);\n\t\tthis.cfmAuthzid = r.group(\"authzid\");\n\t\tthis.cfmBareMessage = r.group(\"clientFirstBare\");\n\t\tfinal String cfmMext = r.group(\"mext\");\n\t\tthis.cfmUsername = r.group(\"username\");\n\t\tfinal String cfmNonce = r.group(\"nonce\");\n\n\t\tif (this.cfmAuthzid == null)\n\t\t\tthis.cfmAuthzid = this.cfmUsername;\n\n\t\tcheckRequestedBindType(requestedBindType);\n\n\t\tfinal ChannelBindingCallback cc = new ChannelBindingCallback(\"Channel binding data\", this.requestedBindType);\n\t\tfinal NameCallback nc = new NameCallback(\"Authentication identity\", cfmUsername);\n\t\tfinal PBKDIterationsCallback ic = new PBKDIterationsCallback(\"PBKD2 iterations\");\n\t\tfinal SaltCallback sc = new SaltCallback(\"Salt\");\n\t\tfinal SaltedPasswordCallback pc = new SaltedPasswordCallback(\"Salted password\");\n\n\t\thandleCallbacks(nc, ic, sc, pc, cc);\n\n\t\tif (pc.getSaltedPassword() == null)\n\t\t\tthrow new SaslException(\"Unknown user\");\n\n\t\tvalidateBindingsData(requestedBindType, cc.getBindingData());\n\t\tthis.bindingData = cc.getBindingData();\n\n\n\t\tthis.sfmNonce = cfmNonce + serverNonce;\n\n\t\tthis.saltedPassword = pc.getSaltedPassword();\n\t\tthis.clientKey = hmac(key(saltedPassword), clientKeyData);\n\t\tthis.storedKey = h(clientKey);\n\n\t\tfinal StringBuilder serverStringMessage = new StringBuilder();\n\t\tserverStringMessage.append(\"r=\").append(sfmNonce).append(\",\");\n\t\tserverStringMessage.append(\"s=\").append(Base64.encode(sc.getSalt())).append(\",\");\n\t\tserverStringMessage.append(\"i=\").append(ic.getInterations());\n\n\t\tthis.sfmMessage = serverStringMessage.toString();\n\t\tstep = Step.clientFinalMessage;\n\t\treturn sfmMessage.getBytes();\n\t}\n\n\tprotected byte[] processClientLastMessage(byte[] data) throws SaslException, InvalidKeyException, NoSuchAlgorithmException {\n\t\tMatcher r = CLIENT_LAST_MESSAGE.matcher(new String(data, CHARSET));\n\t\tif (!r.matches())\n\t\t\tthrow new SaslException(\"Bad challenge syntax\");\n\n\t\tfinal String clmWithoutProof = r.group(\"withoutProof\");\n\t\tfinal byte[] clmCb = Base64.decode(r.group(\"cb\"));\n\t\tfinal String clmNonce = r.group(\"nonce\");\n\t\tfinal String clmProof = r.group(\"proof\");\n\n\t\tbyte[] calculatedCb = calculateC();\n\t\tif (!(new String(clmCb, CHARSET)).startsWith(cfmGs2header)) {\n\t\t\tthrow new XmppSaslException(SaslError.not_authorized, \"Invalid GS2 header\");\n\t\t} else if (!Arrays.equals(clmCb, calculatedCb)) {\n\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\tlog.log(Level.FINEST, \"Channel bindings does not match. expected: {0}; received: {1}\",\n\t\t\t\t\t\tnew Object[]{calculatedCb, clmCb});\n\t\t\tthrow new XmppSaslException(SaslError.not_authorized, \"Channel bindings does not match\");\n\t\t}\n\n\t\tif (!clmNonce.equals(sfmNonce)) {\n\t\t\tthrow new XmppSaslException(SaslError.not_authorized, \"Wrong nonce\");\n\t\t}\n\n\t\tfinal String authMessage = cfmBareMessage + \",\" + sfmMessage + \",\" + clmWithoutProof;\n\t\tbyte[] clientSignature = hmac(key(storedKey), authMessage.getBytes());\n\t\tbyte[] clientProof = xor(clientKey, clientSignature);\n\n\t\tbyte[] dcp = Base64.decode(clmProof);\n\t\tboolean proofMatch = Arrays.equals(clientProof, dcp);\n\n\t\tif (proofMatch == false) {\n\t\t\tthrow new XmppSaslException(SaslError.not_authorized, \"Password not verified\");\n\t\t}\n\n\t\tfinal AuthorizeCallback ac = new AuthorizeCallback(cfmUsername, cfmAuthzid);\n\t\thandleCallbacks(ac);\n\t\tif (ac.isAuthorized() == true) {\n\t\t\tauthorizedId = ac.getAuthorizedID();\n\t\t} else {\n\t\t\tthrow new XmppSaslException(SaslError.invalid_authzid, \"SCRAM: \" + cfmAuthzid + \" is not authorized to act as \"\n\t\t\t\t\t+ cfmAuthzid);\n\t\t}\n\n\t\tbyte[] serverKey = hmac(key(saltedPassword), serverKeyData);\n\t\tbyte[] serverSignature = hmac(key(serverKey), authMessage.getBytes());\n\n\t\tfinal StringBuilder serverStringMessage = new StringBuilder();\n\t\tserverStringMessage.append(\"v=\").append(Base64.encode(serverSignature));\n\t\tstep = Step.finished;\n\t\tcomplete = true;\n\t\treturn serverStringMessage.toString().getBytes();\n\t}\n\n\tprivate String randomString() {\n\t\tfinal int length = 20;\n\t\tfinal int x = ALPHABET.length();\n\t\tchar[] buffer = new char[length];\n\t\tfor (int i = 0; i < length; i++) {\n\t\t\tint r = random.nextInt(x);\n\t\t\tbuffer[i] = ALPHABET.charAt(r);\n\t\t}\n\t\treturn new String(buffer);\n\t}\n\n\t@Override\n\tpublic byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n\tprotected void validateBindingsData(BindType requestedBindType, byte[] bindingData) throws SaslException {\n\t\tif (requestedBindType == BindType.tls_server_end_point && bindingData == null) {\n\t\t\tthrow new RuntimeException(\"Binding data not found!\");\n\t\t} else if (requestedBindType == BindType.tls_unique && bindingData == null) {\n\t\t\tthrow new RuntimeException(\"Binding data not found!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n\tprotected byte[] xor(final byte[] a, final byte[] b) {\n\t\tfinal int l = a.length;\n\t\tbyte[] r = new byte[l];\n\t\tfor (int i = 0; i < l; i++) {\n\t\t\tr[i] = (byte) (a[i] ^ b[i]);\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic enum BindType {\n\t\t/**\n\t\t * Client doesn't support channel binding.\n\t\t */\n\t\tn,\n\t\t/**\n\t\t * Client does support channel binding but thinks the server does not.\n\t\t */\n\t\ty,\n\t\t/**\n\t\t * Client requires channel binding: <code>tls-unique</code>.\n\t\t */\n\t\ttls_unique,\n\t\t/**\n\t\t * Client requires channel binding: <code>tls-server-end-point</code>.\n\t\t */\n\t\ttls_server_end_point\n\t}\n\n\tprivate enum Step {\n\t\tclientFinalMessage,\n\t\tclientFirstMessage,\n\t\tfinished;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/SaslANONYMOUS.java",
    "content": "package tigase.auth.mechanisms;\n\nimport java.util.Map;\nimport java.util.UUID;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.sasl.SaslException;\n\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.XmppSaslException.SaslError;\n\n/**\n * SASL-ANONYMOUS mechanism.\n * <br>\n * Called {@linkplain Callback callbacks} in order:\n * <ul>\n * <li>{@link NameCallback}</li>\n * </ul>\n */\npublic class SaslANONYMOUS extends AbstractSasl {\n\n\tpublic static final String IS_ANONYMOUS_PROPERTY = \"IS_ANONYMOUS\";\n\n\tprivate static final String MECHANISM = \"ANONYMOUS\";\n\n\tSaslANONYMOUS(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(props, callbackHandler);\n\t\tnegotiatedProperty.put(IS_ANONYMOUS_PROPERTY, Boolean.TRUE);\n\t}\n\n\t@Override\n\tpublic byte[] evaluateResponse(byte[] response) throws SaslException {\n\t\tNameCallback nc = new NameCallback(\"ANONYMOUS identity\", UUID.randomUUID().toString());\n\t\thandleCallbacks(nc);\n\n\t\tthis.authorizedId = nc.getName() != null ? nc.getName() : nc.getDefaultName();\n\n\t\tif (this.authorizedId == null) {\n\t\t\tthrow new XmppSaslException(SaslError.temporary_auth_failure);\n\t\t}\n\n\t\tcomplete = true;\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getAuthorizationID() {\n\t\treturn authorizedId;\n\t}\n\n\t@Override\n\tpublic String getMechanismName() {\n\t\treturn MECHANISM;\n\t}\n\n\t@Override\n\tpublic byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/SaslEXTERNAL.java",
    "content": "package tigase.auth.mechanisms;\n\nimport java.util.Map;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.sasl.SaslException;\n\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.XmppSaslException.SaslError;\nimport tigase.auth.callbacks.ValidateCertificateData;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xmpp.BareJID;\n\npublic class SaslEXTERNAL extends AbstractSasl {\n\n\tprivate static final String MECHANISM = \"EXTERNAL\";\n\n\tpublic static final String PEER_CERTIFICATE_KEY = \"PEER_CERTIFICATE_ENTRY_KEY\";\n\n\tSaslEXTERNAL(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(props, callbackHandler);\n\t}\n\n\t@Override\n\tpublic byte[] evaluateResponse(byte[] response) throws SaslException {\n\t\tBareJID jid;\n\t\ttry {\n\t\t\tif (response != null && response.length > 0) {\n\t\t\t\tjid = BareJID.bareJIDInstance(new String(response));\n\t\t\t} else {\n\t\t\t\tjid = null;\n\t\t\t}\n\t\t} catch (TigaseStringprepException e) {\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request);\n\t\t}\n\n\t\tfinal ValidateCertificateData ac = new ValidateCertificateData(jid);\n\t\thandleCallbacks(ac);\n\n\t\tif (ac.isAuthorized() == true) {\n\t\t\tauthorizedId = ac.getAuthorizedID();\n\t\t} else {\n\t\t\tthrow new XmppSaslException(SaslError.invalid_authzid);\n\t\t}\n\n\t\tcomplete = true;\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getAuthorizationID() {\n\t\treturn authorizedId;\n\t}\n\n\t@Override\n\tpublic String getMechanismName() {\n\t\treturn MECHANISM;\n\t}\n\n\t@Override\n\tpublic byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/SaslPLAIN.java",
    "content": "package tigase.auth.mechanisms;\n\nimport java.util.Map;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\n\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.XmppSaslException.SaslError;\nimport tigase.auth.callbacks.VerifyPasswordCallback;\n\n/**\n * SASL-PLAIN mechanism.\n * <br>\n * Called {@linkplain Callback callbacks} in order:\n * <ul>\n * <li>{@link NameCallback}</li>\n * <li>{@link VerifyPasswordCallback}</li>\n * <li>{@link AuthorizeCallback}</li>\n * </ul>\n */\npublic class SaslPLAIN extends AbstractSasl {\n\n\tprivate static final String MECHANISM = \"PLAIN\";\n\n\tSaslPLAIN(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(props, callbackHandler);\n\t}\n\n\t@Override\n\tpublic byte[] evaluateResponse(byte[] response) throws SaslException {\n\n\t\tString[] data = split(response, \"\");\n\n\t\tif (data.length != 3)\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request, \"Invalid number of message parts\");\n\n\t\tfinal String authzid = data[0];\n\t\tfinal String authcid = data[1];\n\t\tfinal String passwd = data[2];\n\n\t\tif (authcid.length() < 1)\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request, \"Authentication identity string is empty\");\n\n\t\tif (authcid.length() > 255)\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request, \"Authentication identity string is too long\");\n\n\t\tif (!isEmpty(authzid) && authzid.length() > 255)\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request, \"Authorization identity string is too long\");\n\n\t\tif (passwd.length() > 255)\n\t\t\tthrow new XmppSaslException(SaslError.malformed_request, \"Password string is too long\");\n\n\t\tfinal NameCallback nc = new NameCallback(\"Authentication identity\", authcid);\n\t\tfinal VerifyPasswordCallback vpc = new VerifyPasswordCallback(passwd);\n\n\t\thandleCallbacks(nc, vpc);\n\n\t\tif (vpc.isVerified() == false) {\n\t\t\tthrow new XmppSaslException(SaslError.not_authorized, \"Password not verified\");\n\t\t}\n\n\t\tfinal String authorizationJID = isEmpty(authzid) ? nc.getName() : authzid;\n\n\t\tfinal AuthorizeCallback ac = new AuthorizeCallback(nc.getName(), authorizationJID);\n\t\thandleCallbacks(ac);\n\n\t\tif (ac.isAuthorized() == true) {\n\t\t\tauthorizedId = ac.getAuthorizedID();\n\t\t} else {\n\t\t\tthrow new XmppSaslException(SaslError.invalid_authzid, \"PLAIN: \" + authcid + \" is not authorized to act as \"\n\t\t\t\t\t+ authorizationJID);\n\t\t}\n\n\t\tcomplete = true;\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getAuthorizationID() {\n\t\treturn authorizedId;\n\t}\n\n\t@Override\n\tpublic String getMechanismName() {\n\t\treturn MECHANISM;\n\t}\n\n\t@Override\n\tpublic byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/SaslSCRAM.java",
    "content": "package tigase.auth.mechanisms;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.sasl.SaslException;\nimport java.util.Map;\n\npublic class SaslSCRAM extends AbstractSaslSCRAM {\n\n\tpublic final static String NAME = \"SCRAM-SHA-1\";\n\tprotected final static String ALGO = \"SHA1\";\n\n\tpublic SaslSCRAM(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(NAME, ALGO, DEFAULT_CLIENT_KEY, DEFAULT_SERVER_KEY, props, callbackHandler);\n\t}\n\n\tSaslSCRAM(Map<? super String, ?> props, CallbackHandler callbackHandler, String once) {\n\t\tsuper(NAME, ALGO, DEFAULT_CLIENT_KEY, DEFAULT_SERVER_KEY, props, callbackHandler, once);\n\t}\n\n\t@Override\n\tprotected void checkRequestedBindType(BindType requestedBindType) throws SaslException {\n\t\tswitch (requestedBindType) {\n\t\t\tcase n:\n\t\t\t\tbreak;\n\t\t\tcase y:\n\t\t\t\tthrow new SaslException(\"Server supports PLUS. Please use 'p'\");\n\t\t\tcase tls_server_end_point:\n\t\t\tcase tls_unique:\n\t\t\t\tthrow new SaslException(\"Invalid request for \"+NAME);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/SaslSCRAMPlus.java",
    "content": "package tigase.auth.mechanisms;\n\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.sasl.SaslException;\nimport java.util.Map;\n\npublic class SaslSCRAMPlus extends AbstractSaslSCRAM {\n\n\tpublic final static String NAME = \"SCRAM-SHA-1-PLUS\";\n\tprotected final static String ALGO = \"SHA1\";\n\n\tpublic SaslSCRAMPlus(Map<? super String, ?> props, CallbackHandler callbackHandler) {\n\t\tsuper(NAME, ALGO, DEFAULT_CLIENT_KEY, DEFAULT_SERVER_KEY, props, callbackHandler);\n\t}\n\n\tSaslSCRAMPlus(Map<? super String, ?> props, CallbackHandler callbackHandler, String once) {\n\t\tsuper(NAME, ALGO, DEFAULT_CLIENT_KEY, DEFAULT_SERVER_KEY, props, callbackHandler, once);\n\t}\n\n\tpublic static boolean isAvailable(XMPPResourceConnection session) {\n\t\treturn session.getSessionData(AbstractSaslSCRAM.TLS_UNIQUE_ID_KEY) != null\n\t\t\t\t|| session.getSessionData(AbstractSaslSCRAM.LOCAL_CERTIFICATE_KEY) != null;\n\t}\n\n\t@Override\n\tprotected void checkRequestedBindType(BindType requestedBindType) throws SaslException {\n\t\tswitch (requestedBindType) {\n\t\t\tcase n:\n\t\t\t\tthrow new SaslException(\"Invalid request for \" + NAME);\n\t\t\tcase y:\n\t\t\t\tthrow new SaslException(\"Server supports PLUS. Please use 'p'\");\n\t\t\tcase tls_server_end_point:\n\t\t\tcase tls_unique:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/auth/mechanisms/TigaseSaslServerFactory.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.auth.mechanisms;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\nimport javax.security.sasl.SaslServerFactory;\nimport java.util.Map;\n\npublic class TigaseSaslServerFactory implements SaslServerFactory {\n\n\tpublic static final String ANONYMOUS_MECHANISM_ALLOWED = \"anonymous-mechanism-allowed\";\n\n\tpublic TigaseSaslServerFactory() {\n\t}\n\n\t@Override\n\tpublic SaslServer createSaslServer(final String mechanism, final String protocol, final String serverName,\n\t\t\t\t\t\t\t\t\t   final Map<String, ?> props, final CallbackHandler callbackHandler) throws SaslException {\n\t\tswitch (mechanism) {\n\t\t\tcase SaslSCRAM.NAME:\n\t\t\t\treturn new SaslSCRAM(props, callbackHandler);\n\t\t\tcase SaslSCRAMPlus.NAME:\n\t\t\t\treturn new SaslSCRAMPlus(props, callbackHandler);\n\t\t\tcase \"PLAIN\":\n\t\t\t\treturn new SaslPLAIN(props, callbackHandler);\n\t\t\tcase \"ANONYMOUS\":\n\t\t\t\treturn new SaslANONYMOUS(props, callbackHandler);\n\t\t\tcase \"EXTERNAL\":\n\t\t\t\treturn new SaslEXTERNAL(props, callbackHandler);\n\t\t\tdefault:\n\t\t\t\tthrow new SaslException(\"Mechanism not supported yet.\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[] getMechanismNames(Map<String, ?> props) {\n\t\treturn new String[]{\n\t\t\t\tSaslSCRAMPlus.NAME,\n\t\t\t\tSaslSCRAM.NAME,\n\t\t\t\t\"PLAIN\",\n\t\t\t\t\"EXTERNAL\",\n\t\t\t\t\"ANONYMOUS\",\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/AmpComponentClustered.java",
    "content": "/*\n * AmpComponentClustered.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.cluster;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.cluster.api.ClusterCommandException;\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.cluster.api.CommandListener;\nimport tigase.cluster.api.CommandListenerAbstract;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\nimport tigase.server.amp.AmpComponent;\nimport static tigase.server.amp.AmpFeatureIfc.FROM_CONN_ID;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\n/**\n *\n * @author andrzej\n */\npublic class AmpComponentClustered extends AmpComponent implements ClusteredComponentIfc {\n\n\tprivate static final Logger log = Logger.getLogger(AmpComponentClustered.class.getCanonicalName());\n\t\n\tprivate ClusterControllerIfc controller = null;\n\tprivate Set<CommandListener> commandListeners = new CopyOnWriteArraySet<CommandListener>();\n\t\n\tpublic AmpComponentClustered() {\n\t\tcommandListeners.add(new PacketForwardCommand(\"packet-forward\"));\n\t}\n\t\n\tprotected void forwardPacket(Packet packet) {\n\t\tList<JID> toNodes = new ArrayList<JID>();\n\t\tfor (JID jid : getNodesConnected()) {\n\t\t\t// jid of local node should not be part of getNodesConnected but let's keep this check for now\n\t\t\tif (jid.equals(getComponentId()))\n\t\t\t\tcontinue;\n\t\t\ttoNodes.add(jid);\n\t\t}\n\t\tif (!toNodes.isEmpty())\n\t\t\tcontroller.sendToNodes(\"packet-forward\", null, packet.getElement(), getComponentId(), null, toNodes.toArray(new JID[toNodes.size()]));\n\t}\n\t\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (packet.getPacketFrom() == null || getComponentId().getDomain().equals(packet.getPacketFrom().getDomain())) {\n\t\t\tif (packet.getElemName() == Message.ELEM_NAME && packet.getElement().getChild(\"broadcast\", \"http://tigase.org/protocol/broadcast\") != null\n\t\t\t\t\t&& packet.getAttributeStaticStr(FROM_CONN_ID) == null) {\n\t\t\t\tforwardPacket(packet.copyElementOnly());\n\t\t\t}\n\t\t}\n\t\tsuper.processPacket(packet); //To change body of generated methods, choose Tools | Templates.\n\t}\n\t\n\t@Override\n\tpublic void setClusterController(ClusterControllerIfc cl_controller) {\n\t\tsuper.setClusterController(cl_controller);\n\t\tif (controller != null) {\n\t\t\tfor (CommandListener listener : commandListeners) {\n\t\t\t\tcontroller.removeCommandListener(listener);\n\t\t\t}\n\t\t}\n\t\tcontroller = cl_controller;\n\t\tif (controller != null) {\n\t\t\tfor (CommandListener listener : commandListeners) {\n\t\t\t\tcontroller.setCommandListener(listener);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected class PacketForwardCommand extends CommandListenerAbstract {\n\n\t\tpublic PacketForwardCommand(String name) {\n\t\t\tsuper(name, Priority.HIGH);\n\t\t}\n\n\t\t@Override\n\t\tpublic void executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String, String> data, Queue<Element> packets) throws ClusterCommandException {\n\t\t\tElement packetEl = null;\n\t\t\twhile ((packetEl = packets.poll()) != null) {\n\t\t\t\ttry {\n\t\t\t\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\t\t\t\tpacket.setPacketFrom(fromNode);\n\t\t\t\t\tpacket.setPacketTo(getComponentId());\n\t\t\t\t\tAmpComponentClustered.this.addPacket(packet);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"exception converting element to packet after forwarding from other node\", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/BoshConnectionClustered.java",
    "content": "/*\n * BoshConnectionClustered.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\n\nimport tigase.server.bosh.BoshConnectionManager;\nimport tigase.server.ServiceChecker;\nimport tigase.server.xmppclient.SeeOtherHostIfc;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n *\n * @author andrzej\n */\npublic class BoshConnectionClustered\n\t\t\t\textends BoshConnectionManager\n\t\t\t\timplements ClusteredComponentIfc {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(BoshConnectionClustered.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\t\n\t@Override\n\tprotected void onNodeConnected(JID jid) {\n\t\tsuper.onNodeConnected(jid);\n\t\t\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\t}\t\n\n\t@Override\n\tpublic void onNodeDisconnected(JID jid) {\n\t\tsuper.onNodeDisconnected(jid);\n\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\n\t\tfinal String hostname = jid.getDomain();\n\n\t\tdoForAllServices(new ServiceChecker<XMPPIOService<Object>>() {\n\t\t\t@Override\n\t\t\tpublic void check(XMPPIOService<Object> service) {\n\t\t\t\tJID dataReceiver = service.getDataReceiver();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Checking service for dataReceiver: {0}\", dataReceiver);\n\t\t\t\t}\n\t\t\t\tif ((dataReceiver != null) && dataReceiver.getDomain().equals(hostname)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Stopping service because corresponding cluster node stopped.\");\n\t\t\t\t\t}\n\t\t\t\t\tservice.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn super.getDiscoDescription() + \" clustered\";\n\t}\n\n\t@Override\n\tpublic SeeOtherHostIfc getSeeOtherHostInstance(String see_other_host_class) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Configuring see_other_host clustered strategy for: \" +\n\t\t\t\t\tsee_other_host_class);\n\t\t}\n\t\tif (see_other_host_class == null) {\n\t\t\tsee_other_host_class = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL_CLUSTER;\n\t\t}\n\t\tsee_other_host_strategy = super.getSeeOtherHostInstance(see_other_host_class);\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\n\t\treturn see_other_host_strategy;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClientConnectionClustered.java",
    "content": "/*\n * ClientConnectionClustered.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\n\nimport tigase.server.ServiceChecker;\nimport tigase.server.xmppclient.ClientConnectionManager;\nimport tigase.server.xmppclient.SeeOtherHostIfc;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Describe class ClientConnectionClustered here.\n *\n *\n * Created: Sat Jun 21 22:23:18 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ClientConnectionClustered\n\t\t\t\textends ClientConnectionManager\n\t\t\t\timplements ClusteredComponentIfc {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ClientConnectionClustered.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate SeeOtherHostIfc see_other_host_strategy = null;\n\t@SuppressWarnings(\"serial\")\n\tprivate List<BareJID>   connectedNodes          = new CopyOnWriteArrayList<BareJID>() {\n\t\t{\n\t\t\tadd(getDefHostName());\n\t\t}\n\t};\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void onNodeConnected(JID jid) {\n\t\tsuper.onNodeConnected(jid);\n\t\t\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\t}\t\n\t\n\t@Override\n\tpublic void onNodeDisconnected(JID jid) {\n\t\tsuper.onNodeDisconnected(jid);\n\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\n\t\tfinal String hostname = jid.getDomain();\n\n\t\tdoForAllServices(new ServiceChecker<XMPPIOService<Object>>() {\n\t\t\t@Override\n\t\t\tpublic void check(XMPPIOService<Object> service) {\n\t\t\t\tJID dataReceiver = service.getDataReceiver();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Checking service for dataReceiver: {0}\", dataReceiver);\n\t\t\t\t}\n\t\t\t\tif ((dataReceiver != null) && dataReceiver.getDomain().equals(hostname)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Stopping service because corresponding cluster node stopped.\");\n\t\t\t\t\t}\n\t\t\t\t\tservice.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn super.getDiscoDescription() + \" clustered\";\n\t}\n\n\t@Override\n\tpublic SeeOtherHostIfc getSeeOtherHostInstance(String see_other_host_class) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Configuring see_other_host clustered strategy for: \" +\n\t\t\t\t\tsee_other_host_class);\n\t\t}\n\t\tif (see_other_host_class == null) {\n\t\t\tsee_other_host_class = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL_CLUSTER;\n\t\t}\n\t\tsee_other_host_strategy = super.getSeeOtherHostInstance(see_other_host_class);\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(getNodesConnectedWithLocal());\n\t\t}\n\n\t\treturn see_other_host_strategy;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClusterConnection.java",
    "content": "/*\n * ClusterConnection.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n *\n * @author andrzej\n */\npublic class ClusterConnection {\n\t\n\tprivate final String addr;\n\tprivate final CopyOnWriteArrayList<XMPPIOService<Object>> conns = new CopyOnWriteArrayList<>();\n\t\n\tpublic ClusterConnection(String addr) {\n\t\tthis.addr = addr;\n\t}\n\t\n\tpublic void addConn(XMPPIOService<Object> conn) {\n\t\tconns.add(conn);\n\t}\n\t\n\tpublic void removeConn(XMPPIOService<Object> conn) {\n\t\tconns.remove(conn);\n\t}\n\t\n\tpublic int size() {\n\t\treturn conns.size();\n\t}\n\t\n\tpublic List<XMPPIOService<Object>> getConnections() {\n\t\treturn conns;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn addr + conns;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClusterConnectionManager.java",
    "content": "/*\n * ClusterConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.*;\nimport tigase.cluster.repo.ClConConfigRepository;\nimport tigase.cluster.repo.ClusterRepoConstants;\nimport tigase.cluster.repo.ClusterRepoItem;\nimport tigase.conf.ConfigurationException;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.db.comp.RepositoryChangeListenerIfc;\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.net.ConnectionType;\nimport tigase.net.SocketType;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.ServiceChecker;\nimport tigase.stats.StatisticsList;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.Algorithms;\nimport tigase.util.TigaseStringprepException;\nimport tigase.util.TimeUtils;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\n\nimport javax.script.Bindings;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.net.SocketException;\nimport java.net.UnknownHostException;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.zip.Deflater;\n\n/**\n * Class ClusterConnectionManager\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ClusterConnectionManager\n\t\t\t\textends ConnectionManager<XMPPIOService<Object>>\n\t\t\t\timplements ClusteredComponentIfc, RepositoryChangeListenerIfc<ClusterRepoItem>, ClusterConnectionHandler {\n\t/** Field description */\n\tpublic static final String CLCON_REPO_CLASS_PROP_KEY = \"repository-class\";\n\n\t/** Field description */\n\tpublic static final String CLCON_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.cluster.repo.ClConSQLRepository\";\n\n\t/** Field description */\n\tpublic static final String CLCON_REPO_CLASS_PROPERTY = \"--cl-conn-repo-class\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_CONNECTIONS_PER_NODE_PAR =\n\t\t\t\"--cluster-connections-per-node\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY =\n\t\t\t\"cluster-connections-per-node\";\n\n\t/** Field description */\n\tpublic static final int CLUSTER_CONNECTIONS_PER_NODE_VAL = 5;\n\n\t/** Field description */\n\tpublic static final String CLUSTER_CONNECTIONS_SELECTOR_KEY = \"connection-selector\";\n\t/** Field description */\n\tpublic static final String DEF_CLUSTER_CONNECTIONS_SELECTOR_VAL = ClusterConnectionSelector.class.getCanonicalName();\n\t\n\t/** Field description */\n\tpublic static final String CLUSTER_CONTR_ID_PROP_KEY = \"cluster-controller-id\";\n\n\t/** Field description */\n\tpublic static final String COMPRESS_STREAM_PROP_KEY = \"compress-stream\";\n\n\t/** Field description */\n\tpublic static final String CONNECT_ALL_PAR = \"--cluster-connect-all\";\n\n\t/** Field description */\n\tpublic static final String CONNECT_ALL_PROP_KEY = \"connect-all\";\n\n\tpublic static final String NON_CLUSTER_TRAFFIC_ALLOWED_PROP_KEY = \"non-cluster-traffic-allowed\";\n\tpublic static final boolean NON_CLUSTER_TRAFFIC_ALLOWED_PROP_VAL = true;\n\n\t/**\n\t * Default value for the system property for configuration protection\n\t * from system overload and DOS attack.\n\t */\n\tpublic static int ELEMENTS_NUMBER_LIMIT_CLUSTER_PROP_VAL = 100 * 1000;\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_KEY = \"identity-type\";\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_VAL = \"generic\";\n\n\t/** Field description */\n\tpublic static final String PORT_ROUTING_TABLE_PROP_KEY = \"routing-table\";\n\n\t/** Field description */\n\tpublic static final String RETURN_SERVICE_DISCO_KEY = \"service-disco\";\n\n\t/** Field description */\n\tpublic static final String SECRET_PROP_KEY = \"secret\";\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"tigase:cluster\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ClusterConnectionManager.class\n\t\t\t.getName());\n\n\t/** Field description */\n\tpublic static final boolean RETURN_SERVICE_DISCO_VAL = true;\n\n\t/** Field description */\n\tpublic static final boolean CONNECT_ALL_PROP_VAL = false;\n\n\t/** Field description */\n\tpublic static final boolean COMPRESS_STREAM_PROP_VAL = false;\n\tprivate static final String SERVICE_CONNECTED_TASK_FUTURE =\n\t\t\t\"service-connected-task-future\";\n\n\tpublic final static String REPO_ITEM_EVENT_NAME = \"repo-item-modified\";\n\tpublic final static String EVENTBUS_REPO_ITEM_EVENT_XMLNS = \"tigase:system:cluster-update\";\n\tprivate EventBus eventBus = null;\n\n\tpublic final static String EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_KEY = \"eventbus-repository-notifications\";\n\tpublic final static boolean EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_VALUE = false;\n\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprivate ClusterControllerIfc clusterController = null;\n\n\tpublic static enum REPO_ITEM_UPDATE_TYPE {\n\t\tADDED,\n\t\tUPDATED,\n\t\tREMOVED\n\t}\n\n\n\t// private String cluster_controller_id = null;\n\tprivate IOServiceStatisticsGetter                                ioStatsGetter =\n\t\t\tnew IOServiceStatisticsGetter();\n\tprivate String                                                   identity_type =\n\t\t\tIDENTITY_TYPE_VAL;\n\tprivate Map<String, ClusterConnection> connectionsPool =\n\t\t\tnew ConcurrentSkipListMap<>();\n\tprivate boolean                              connect_all = CONNECT_ALL_PROP_VAL;\n\tprivate boolean                              compress_stream = COMPRESS_STREAM_PROP_VAL;\n\tprivate long[]                               lastDay               = new long[24];\n\tprivate int                                  lastDayIdx            = 0;\n\tprivate long[]                               lastHour              = new long[60];\n\tprivate int                                  lastHourIdx           = 0;\n\tprivate int                                  nodesNo               = 0;\n\tprivate int                                  per_node_conns =\n\t\t\tCLUSTER_CONNECTIONS_PER_NODE_VAL;\n\tprivate ComponentRepository<ClusterRepoItem> repo                  = null;\n\tprivate long                                 servConnectedTimeouts = 0;\n\tprivate long                                 totalNodeDisconnects  = 0;\n\n\t// private long packetsSent = 0;\n\t// private long packetsReceived = 0;\n\tprivate ClusterConnectionSelectorIfc connectionSelector = null;\n\tprivate CommandListener sendPacket = new SendPacket(ClusterControllerIfc\n\t\t\t.DELIVER_CLUSTER_PACKET_CMD);\n\tprivate boolean nonClusterTrafficAllowed = true;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\n\t\t// If this is a cluster packet let's try to do a bit more smart hashing\n\t\t// based on the stanza from/to addresses\n\t\tif (packet.getElemName() == ClusterElement.CLUSTER_EL_NAME) {\n\n\t\t\t// TODO: Look for a simpler, more efficient algorithm to distribute\n\t\t\t// cluster packets among different threads.\n\t\t\t// This looks like an overkill to me, however I don't see any better way\n\t\t\tClusterElement clel = new ClusterElement(packet.getElement());\n\n\t\t\t// If there is no XMPP stanzas with an address inside the cluster packet,\n\t\t\t// we can try Map data and User ID inside it if it exists.\n\t\t\tString userId = clel.getMethodParam(\"userId\");\n\n\t\t\tif (userId != null) {\n\t\t\t\treturn userId.hashCode();\n\t\t\t}\n\n\t\t\tQueue<Element> children = clel.getDataPackets();\n\n\t\t\tif ((children != null) && (children.size() > 0)) {\n\t\t\t\tElement child     = children.peek();\n\t\t\t\tString  stanzaAdd = child.getAttributeStaticStr(Packet.TO_ATT);\n\n\t\t\t\tif (stanzaAdd != null) {\n\t\t\t\t\treturn stanzaAdd.hashCode();\n\t\t\t\t} else {\n\n\t\t\t\t\t// This might be user's initial presence. In such a case we take\n\t\t\t\t\t// stanzaFrom instead\n\t\t\t\t\tstanzaAdd = child.getAttributeStaticStr(Packet.FROM_ATT);\n\t\t\t\t\tif (stanzaAdd != null) {\n\t\t\t\t\t\treturn stanzaAdd.hashCode();\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// This may happen for some cluster packets, like:\n\t\t\t\t\t\t// resp-sync-online-sm-cmd and this is correct\n\t\t\t\t\t\tlog.log(Level.FINE, \"No stanzaTo or from for cluster packet: {0}\", packet);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// There is a separate connection to each cluster node, ideally we want to\n\t\t// process packets in a separate thread for each connection, so let's try\n\t\t// to get the hash code by the destination node address\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().hashCode();\n\t\t}\n\n\t\treturn packet.getTo().hashCode();\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(\"clusterCM\", this);\n\t\tbinds.put(ComponentRepository.COMP_REPO_BIND, repo);\n\t}\n\n\t@Override\n\tpublic void itemAdded(ClusterRepoItem repoItem) {\n\t\tlog.log(Level.INFO, \"Loaded repoItem: {0}\", repoItem.toString());\n\n\t\tString host = repoItem.getHostname();\n\n\t\tboolean isCorrect = false;\n\t\ttry {\n\t\t\tInetAddress addr = InetAddress.getByName( host );\n\n\t\t\t// we ignore any local addresses\n\t\t\tisCorrect = !addr.isAnyLocalAddress() && !addr.isLoopbackAddress()\n\t\t\t\t\t\t\t\t\t&& !( NetworkInterface.getByInetAddress( addr ) != null );\n\t\t\tif ( !isCorrect && log.isLoggable( Level.CONFIG ) ){\n\t\t\t\tlog.log( Level.CONFIG, \"ClusterRepoItem of local machine, skipping connection attempt: {0}\", repoItem );\n\t\t\t}\n\t\t} catch ( UnknownHostException | SocketException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Incorrect ClusterRepoItem, skipping connection attempt: \" + repoItem, ex );\n\t\t}\n\n\t\tif (isCorrect) {\n\t\t\tfor (int i = 0; i < per_node_conns; ++i) {\n\t\t\t\tlog.log(Level.CONFIG, \"Trying to connect to cluster node: {0}\", host);\n\n\t\t\t\tMap<String, Object> port_props = new LinkedHashMap<String, Object>(12);\n\n\t\t\t\tport_props.put(SECRET_PROP_KEY, repoItem.getPassword());\n\t\t\t\tport_props.put(PORT_LOCAL_HOST_PROP_KEY, getDefHostName());\n\t\t\t\tport_props.put(PORT_TYPE_PROP_KEY, ConnectionType.connect);\n\t\t\t\tport_props.put(PORT_SOCKET_PROP_KEY, SocketType.plain);\n\t\t\t\tport_props.put(PORT_REMOTE_HOST_PROP_KEY, host);\n\t\t\t\tport_props.put(PORT_IFC_PROP_KEY, new String[] { host });\n\t\t\t\tport_props.put(MAX_RECONNECTS_PROP_KEY, 99999999);\n\t\t\t\tport_props.put(PORT_KEY, repoItem.getPortNo());\n\t\t\t\taddWaitingTask(port_props);\n\t\t\t}\n\n\t\t\tsendEvent( REPO_ITEM_UPDATE_TYPE.ADDED, repoItem.getHostname(), repoItem.getSecondaryHostname() );\n\t\t\t// reconnectService(port_props, connectionDelay);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemRemoved(ClusterRepoItem item) {\n\t\tsendEvent( REPO_ITEM_UPDATE_TYPE.REMOVED, item.getHostname(), item.getSecondaryHostname() );\n\t}\n\n\t@Override\n\tpublic void itemUpdated(ClusterRepoItem item) {\n\t\tsendEvent( REPO_ITEM_UPDATE_TYPE.UPDATED, item.getHostname(), item.getSecondaryHostname() );\n\t}\n\n\t@Override\n\tpublic void nodeConnected(String node) {\n\t\tsuper.nodeConnected(node);\n\t}\n\n\t@Override\n\tpublic void nodeDisconnected(String node) {\n\t\tsuper.nodeDisconnected(node);\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\n\t\t// TODO: The number of threads should be equal or greater to number of\n\t\t// cluster nodes.\n\t\t// This should work well as far as nodesNo is initialized before this\n\t\t// method is called which is true only during program startup time.\n\t\t// In case of reconfiguration or new node joining this might not be\n\t\t// the case. Low priority issue though.\n\t\treturn Math.max(Runtime.getRuntime().availableProcessors(), nodesNo) * 8;\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\n\t\t// TODO: The number of threads should be equal or greater to number of\n\t\t// cluster nodes.\n\t\t// This should work well as far as nodesNo is initialized before this\n\t\t// method is called which is true only during program startup time.\n\t\t// In case of reconfiguration or new node joining this might not be\n\t\t// the case. Low priority issue though.\n\t\treturn Math.max(Runtime.getRuntime().availableProcessors(), nodesNo) * 8;\n\t}\n\n\t@Override\n\tpublic void processOutPacket(Packet packet) {\n\t\tif (packet.getElemName() == ClusterElement.CLUSTER_EL_NAME) {\n\t\t\tclusterController.handleClusterPacket(packet.getElement());\n\t\t} else {\n\n\t\t\t// This should, actually, not happen. Let's log it here\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Unexpected packet on cluster connection: {0}\", packet);\n\t\t\t}\n\t\t\tsuper.processOutPacket(packet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\t\t}\n\t\tif ((packet.getStanzaTo() != null) && packet.getStanzaTo().equals(getComponentId())) {\n\t\t\ttry {\n\t\t\t\taddOutPacket(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t\t\t\t\t\"Not implemented\", true));\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Packet processing exception: {0}\", e);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (packet.getElemName() == ClusterElement.CLUSTER_EL_NAME || packet.getElemName() == \"route\") {\n\t\t\twritePacketToSocket(packet);\n\t\t} else {\n\n\t\t\tif (nonClusterTrafficAllowed) {\n\t\t\t\twritePacketToSocket(packet.packRouted());\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Unexpected packet for the cluster connetcion: {0}\", packet);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(XMPPIOService<Object> serv) {\n\t\tPacket p = null;\n\n\t\twhile ((p = serv.getReceivedPackets().poll()) != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing socket data: {0}\", p);\n\t\t\t}\n\t\t\tif (p.getElemName().equals(\"handshake\")) {\n\t\t\t\tprocessHandshake(p, serv);\n\t\t\t} else {\n\t\t\t\tif (p.getAttributeStaticStr(new String[] { Iq.ELEM_NAME, \"ping\" }, \"xmlns\") == \"urn:xmpp:ping\" \n\t\t\t\t\t\t&& getDefHostName().getDomain().equals(p.getStanzaTo().getDomain()) \n\t\t\t\t\t\t&& p.getStanzaFrom().getDomain().equals(serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY))) {\n\t\t\t\t\t// received PING between cluster nodes to confirm connectivity\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, received XMPP ping\", serv);\n\t\t\t\t\t}\n\t\t\t\t\tserv.getSessionData().put(\"lastConnectivityCheck\", System.currentTimeMillis());\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\t\n\n\t\t\t\t// ++packetsReceived;\n\t\t\t\tPacket result = p;\n\n\t\t\t\tif (p.isRouted()) {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = p.unpackRouted();\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Packet stringprep addressing problem, dropping packet: {0}\", p);\n\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (p.isRouted())\n\t\t\t\taddOutPacket(result);\n\t\t\t}\n\t\t}        // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\t// readd packet - this may be good as we would retry to send packet \n\t\t// which delivery failed due to IO error\n\t\taddPacket(packet);\n\t\treturn true;\n\t}\t\n\t\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\n\t\t// TODO: handle this somehow\n\t}\n\n\t@Override\n\tpublic void serviceStarted(XMPPIOService<Object> serv) {\n\t\ttry {\n\t\t\trepo.reload();\n\t\t} catch ( TigaseDBException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Items reloading failed\", ex );\n\t\t}\n\t\tServiceConnectedTimerTask task = new ServiceConnectedTimerTask(serv);\n\n\t\tserv.getSessionData().put(SERVICE_CONNECTED_TASK_FUTURE, task);\n\t\taddTimerTask(task, 10, TimeUnit.SECONDS);\n\t\tsuper.serviceStarted(serv);\n\t\tlog.log(Level.INFO, \"cluster connection opened: {0}, type: {1}, id={2}\",\n\t\t\t\tnew Object[] { serv.getRemoteAddress(),\n\t\t\t\tserv.connectionType().toString(), serv.getUniqueId() });\n\t\tif (compress_stream) {\n\t\t\tlog.log(Level.INFO, \"Starting stream compression for: {0}\", serv.getUniqueId());\n\t\t\tserv.startZLib(Deflater.BEST_COMPRESSION);\n\t\t}\n\t\tswitch (serv.connectionType()) {\n\t\tcase connect :\n\n\t\t\t// Send init xmpp stream here\n\t\t\tString remote_host = (String) serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY);\n\n\t\t\tserv.getSessionData().put(XMPPIOService.HOSTNAME_KEY, getDefHostName().toString());\n\t\t\tserv.getSessionData().put(PORT_ROUTING_TABLE_PROP_KEY, new String[] { remote_host,\n\t\t\t\t\t\".*@\" + remote_host, \".*\\\\.\" + remote_host });\n\n\t\t\tString data = \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\" +\n\t\t\t\t\t\" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" +\n\t\t\t\t\tgetDefHostName() + \"'\" + \" to='\" + remote_host + \"'\" + \">\";\n\n\t\t\tlog.log(Level.INFO, \"cid: {0}, sending: {1}\", new Object[] { (String) serv\n\t\t\t\t\t.getSessionData().get(\"cid\"),\n\t\t\t\t\tdata });\n\t\t\tserv.xmppStreamOpen(data);\n\n\t\t\tbreak;\n\n\t\tdefault :\n\n\t\t\t// Do nothing, more data should come soon...\n\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService<Object> service) {\n\t\tboolean result = super.serviceStopped(service);\n\n\t\t// Make sure it runs just once for each disconnect\n\t\tif (result) {\n\t\t\tMap<String, Object> sessionData = service.getSessionData();\n\t\t\tString[] routings = (String[]) sessionData.get( PORT_ROUTING_TABLE_PROP_KEY );\n\t\t\tString addr = (String) sessionData.get( PORT_REMOTE_HOST_PROP_KEY );\n\t\t\tClusterConnection conns = connectionsPool.get( addr );\n\n\t\t\tif (conns == null) {\n\t\t\t\tconns = new ClusterConnection(addr);\n\t\t\t\tconnectionsPool.put(addr, conns);\n\t\t\t}\n\n\t\t\tint size = conns.size();\n\n\t\t\tconns.removeConn( service );\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"serviceStopped: result={0} / size={1} / connPool={2} / serv={3} / conns={4} / type={5}\",\n\t\t\t\t\t\t\t\t new Object[] { result, size, connectionsPool, service, conns, service.connectionType() } );\n\t\t\t}\n\n\t\t\tif (size != 0 && conns.size() == 0) {\n\t\t\t\tif ( routings != null ){\n\t\t\t\t\tupdateRoutings( routings, false );\n\t\t\t\t}\n\n\t\t\t\t// removeRouting(serv.getRemoteHost());\n\t\t\t\tlog.log(Level.INFO, \"Disonnected from: {0}\", addr);\n\t\t\t\tupdateServiceDiscoveryItem(addr, addr, XMLNS + \" disconnected\", true);\n\t\t\t\tclusterController.nodeDisconnected(addr);\n\t\t\t}\n\n\t\t\tConnectionType type = service.connectionType();\n\n\t\t\tif (type == ConnectionType.connect) {\n\t\t\t\taddWaitingTask(sessionData);\n\t\t\t}    // end of if (type == ConnectionType.connect)\n\t\t\t++totalNodeDisconnects;\n\n\t\t\tint hour = TimeUtils.getHourNow();\n\n\t\t\tif (lastDayIdx != hour) {\n\t\t\t\tlastDayIdx    = hour;\n\t\t\t\tlastDay[hour] = 0;\n\t\t\t\tArrays.fill(lastHour, 0);\n\t\t\t}\n\t\t\t++lastDay[hour];\n\n\t\t\tint minute = TimeUtils.getMinuteNow();\n\n\t\t\t++lastHour[minute];\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(XMPPIOService<Object> service) {}\n\n\t@Override\n\tpublic void updateConnectionDetails(Map<String, Object> port_props) {\n\t\tString          host = (String) port_props.get(PORT_REMOTE_HOST_PROP_KEY);\n\t\tClusterRepoItem item = repo.getItem(host);\n\n\t\tif (item != null) {\n\t\t\tport_props.put(SECRET_PROP_KEY, item.getPassword());\n\t\t\tport_props.put(PORT_KEY, item.getPortNo());\n\t\t} else {\n\t\t\tport_props.put(MAX_RECONNECTS_PROP_KEY, 0);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"ClusterRepoItem: {0}, port_props: {1}\", new Object[] { item,\n\t\t\t\t\tport_props });\n\t\t}\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(XMPPIOService<Object> serv) {\n\t\tlog.info(\"Stream closed.\");\n\t}\n\n\t@Override\n\tpublic String xmppStreamOpened(XMPPIOService<Object> service, Map<String,\n\t\t\tString> attribs) {\n\t\tlog.log(Level.INFO, \"Stream opened: {0}, service: {1}\", new Object[] {attribs, service});\n\t\tswitch (service.connectionType()) {\n\t\tcase connect : {\n\t\t\tString id = attribs.get(\"id\");\n\n\t\t\tservice.getSessionData().put(XMPPIOService.SESSION_ID_KEY, id);\n\n\t\t\tClusterRepoItem item   = repo.getItem(getDefHostName().getDomain());\n\t\t\tString          secret = item.getPassword();\n\n\t\t\ttry {\n\t\t\t\tString digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calculating digest: id={0}, secret={1}, digest={2}, item={3}\",\n\t\t\t\t\t\t\tnew Object[] { id, secret, digest, item });\n\t\t\t\t}\n\n\t\t\t\treturn \"<handshake>\" + digest + \"</handshake>\";\n\t\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can not generate digest for pass phrase.\", e);\n\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tcase accept : {\n\t\t\tString remote_host = attribs.get(\"from\");\n\n\t\t\tservice.getSessionData().put(XMPPIOService.HOSTNAME_KEY, getDefHostName().toString());\n\t\t\tservice.getSessionData().put(PORT_REMOTE_HOST_PROP_KEY, remote_host);\n\t\t\tservice.getSessionData().put(PORT_ROUTING_TABLE_PROP_KEY, new String[] {\n\t\t\t\t\tremote_host,\n\t\t\t\t\t\".*@\" + remote_host, \".*\\\\.\" + remote_host });\n\n\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\tservice.getSessionData().put(XMPPIOService.SESSION_ID_KEY, id);\n\t\t\tupdateConnectionDetails(service.getSessionData());\n\n\t\t\treturn \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\" +\n\t\t\t\t\t\" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" +\n\t\t\t\t\tgetDefHostName() + \"'\" + \" to='\" + remote_host + \"'\" + \" id='\" + id + \"'\" + \">\";\n\t\t}\n\n\t\tdefault :\n\n\t\t\t// Do nothing, more data should come soon...\n\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs       = new LinkedHashMap<String, Object>(50);\n\t\tString              repo_class = (String) params.get(CLCON_REPO_CLASS_PROPERTY);\n\t\tString\t\t\t\trepo_uri   = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\n\t\tif (repo_class != null) {\n\t\t\tdefs.put(CLCON_REPO_CLASS_PROP_KEY, repo_class);\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tClass<?> cls;\n\t\t\tif (repo_class == null) {\n\t\t\t\tcls = RepositoryFactory.getRepoClass(ClConConfigRepository.class, repo_uri);\n\t\t\t} else {\n\t\t\t\tcls = ModulesManagerImpl.getInstance().forName(repo_class);\n\t\t\t}\n\t\t\tComponentRepository<ClusterRepoItem> repoTmp =\n\t\t\t\t\t(ComponentRepository<ClusterRepoItem>) cls.newInstance();\n\n\t\t\trepoTmp.getDefaults(defs, params);\n\t\t\tif (repo == null) {\n\t\t\t\trepo = repoTmp;\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not instantiate items repository for class: \" +\n\t\t\t\t\trepo_class, e);\n\t\t}\n\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tprops.putAll(defs);\n\t\tprops.put(RETURN_SERVICE_DISCO_KEY, RETURN_SERVICE_DISCO_VAL);\n\t\tprops.put(IDENTITY_TYPE_KEY, IDENTITY_TYPE_VAL);\n\t\tif ((params.get(CONNECT_ALL_PAR) == null) ||!((String) params.get(CONNECT_ALL_PAR))\n\t\t\t\t.equals(\"true\")) {\n\t\t\tprops.put(CONNECT_ALL_PROP_KEY, false);\n\t\t} else {\n\t\t\tprops.put(CONNECT_ALL_PROP_KEY, true);\n\t\t}\n\t\tif (params.get(CLUSTER_NODES) != null) {\n\t\t\tString[] cl_nodes = ((String) params.get(CLUSTER_NODES)).split(\",\");\n\n\t\t\tfor (int i = 0; i < cl_nodes.length; i++) {\n\t\t\t\tcl_nodes[i] = BareJID.parseJID(cl_nodes[i])[1];\n\t\t\t}\n\t\t\tnodesNo = cl_nodes.length;\n\t\t\tprops.put(CLUSTER_NODES_PROP_KEY, cl_nodes);\n\t\t} else {\n\t\t\tprops.put(CLUSTER_NODES_PROP_KEY, new String[] { getDefHostName().getDomain() });\n\t\t}\n\t\tprops.put(CLUSTER_CONTR_ID_PROP_KEY, DEF_CLUST_CONTR_NAME + \"@\" + getDefHostName());\n\t\tprops.put(COMPRESS_STREAM_PROP_KEY, COMPRESS_STREAM_PROP_VAL);\n\t\tprops.put(NON_CLUSTER_TRAFFIC_ALLOWED_PROP_KEY, NON_CLUSTER_TRAFFIC_ALLOWED_PROP_VAL);\n\n\t\tString conns     = (String) params.get(CLUSTER_CONNECTIONS_PER_NODE_PAR);\n\t\tint    conns_int = Runtime.getRuntime().availableProcessors();\n\n\t\tif (conns != null) {\n\t\t\ttry {\n\t\t\t\tconns_int = Integer.parseInt(conns);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\tconns_int = CLUSTER_CONNECTIONS_PER_NODE_VAL;\n\t\t\t}\n\t\t}\n\t\tprops.put(CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY, conns_int);\n\t\tprops.put(ELEMENTS_NUMBER_LIMIT_PROP_KEY, ELEMENTS_NUMBER_LIMIT_CLUSTER_PROP_VAL);\n\n\t\tprops.put(WATCHDOG_PING_TYPE_KEY, WATCHDOG_PING_TYPE.XMPP);\n\t\tprops.put(WATCHDOG_DELAY, 30 * SECOND);\n\t\tprops.put(WATCHDOG_TIMEOUT, -1 * SECOND);\n\t\t\n\t\tprops.put(CLUSTER_CONNECTIONS_SELECTOR_KEY, DEF_CLUSTER_CONNECTIONS_SELECTOR_VAL);\n\n\t\tprops.put(EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_KEY, EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_VALUE);\n\t\t\n\t\tif (getDefHostName().toString().equalsIgnoreCase( \"localhost\") ) {\n\t\t\tTigaseRuntime.getTigaseRuntime().shutdownTigase( new String [] {\n\t\t\t\t\"\",\n\t\t\t\t\"  ---------------------------------------------\",\n\t\t\t\t\"  ERROR! Tigase is running in Clustered Mode yet the hostname\",\n\t\t\t\t\"  of the machine was resolved to *localhost* which will cause\",\n\t\t\t\t\"  malfunctioning of Tigase in clustered environment!\",\n\t\t\t\t\"  \",\n\t\t\t\t\"  To prevent further issues with the clustering Tigase will be shutdown.\",\n\t\t\t\t\"  \",\n\t\t\t\t\"  Please make sure that FQDN hostname of the machine is set correctly\",\n\t\t\t\t\"  and restart the server.\",\n\t\t\t\t\"  ---------------------------------------------\",\n\t\t\t\t\"\",\n\t\t\t\t\"\",\n\t\t\t} );\n\t\t}\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn identity_type;\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Cluster connection manager\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getName(), \"Total disconnects\", totalNodeDisconnects, Level.FINE);\n\t\tlist.add(getName(), \"Service connected time-outs\", servConnectedTimeouts, Level.FINE);\n\t\tlist.add(getName(), \"Last day disconnects\", Arrays.toString(lastDay), Level.FINE);\n\t\tlist.add(getName(), \"Last hour disconnects\", Arrays.toString(lastHour), Level.FINE);\n\t\tioStatsGetter.reset();\n\t\tdoForAllServices(ioStatsGetter);\n\t\tlist.add(getName(), \"Average compression ratio\", ioStatsGetter\n\t\t\t\t.getAverageCompressionRatio(), Level.FINE);\n\t\tlist.add(getName(), \"Average decompression ratio\", ioStatsGetter\n\t\t\t\t.getAverageDecompressionRatio(), Level.FINE);\n\t\tlist.add(getName(), \"Waiting to send\", ioStatsGetter.getWaitingToSend(), Level.FINE);\n\n\t\tif ((!list.checkLevel(Level.FINEST)) && getNodesConnected().size() > 0) {\n\t\t\t// in FINEST level every component will provide this data\n\t\t\tlist.add(getName(), \"Known cluster nodes\", getNodesConnected().size(), Level.INFO);\n\t\t}\n\n\t\t// list.add(getName(), StatisticType.MSG_RECEIVED_OK.getDescription(),\n\t\t// packetsReceived,\n\t\t// Level.FINE);\n\t\t// list.add(getName(), StatisticType.MSG_SENT_OK.getDescription(),\n\t\t// packetsSent,\n\t\t// Level.FINE);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setClusterController(ClusterControllerIfc cl_controller) {\n\t\tsuper.setClusterController(cl_controller);\n\t\tclusterController = cl_controller;\n\t\tclusterController.removeCommandListener(sendPacket);\n\t\tclusterController.setCommandListener(sendPacket);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.get(IDENTITY_TYPE_KEY) != null) {\n\t\t\tidentity_type = (String) props.get(IDENTITY_TYPE_KEY);\n\t\t}\n\t\tif (props.get(COMPRESS_STREAM_PROP_KEY) != null) {\n\t\t\tcompress_stream = (Boolean) props.get(COMPRESS_STREAM_PROP_KEY);\n\t\t}\n\t\tif (props.get(CONNECT_ALL_PROP_KEY) != null) {\n\t\t\tconnect_all = (Boolean) props.get(CONNECT_ALL_PROP_KEY);\n\t\t}\n\n\t\tif (props.get(NON_CLUSTER_TRAFFIC_ALLOWED_PROP_KEY) != null) {\n\t\t\tnonClusterTrafficAllowed = (Boolean)props.get(NON_CLUSTER_TRAFFIC_ALLOWED_PROP_KEY);\n\t\t}\n\n\t\t// cluster_controller_id = (String) props.get(CLUSTER_CONTR_ID_PROP_KEY);\n\t\tif (props.get(CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY) != null) {\n\t\t\tper_node_conns = (Integer) props.get(CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY);\n\t\t}\n\n\t\tif (props.containsKey(CLUSTER_CONNECTIONS_SELECTOR_KEY)) {\n\t\t\tString selectorClsName = (String) props.get(CLUSTER_CONNECTIONS_SELECTOR_KEY);\n\t\t\ttry {\n\t\t\t\tClusterConnectionSelectorIfc tmp_selector = (ClusterConnectionSelectorIfc) ModulesManagerImpl.getInstance().forName(selectorClsName).newInstance();\n\t\t\t\ttmp_selector.setClusterConnectionHandler(this);\n\t\t\t\ttmp_selector.setProperties(props);\n\t\t\t\tconnectionSelector = tmp_selector;\n\t\t\t} catch (InstantiationException|ClassNotFoundException|IllegalAccessException ex) {\n\t\t\t\tlog.log(Level.SEVERE, \"Coulnd not create instance of cluster connection selector of class \" + selectorClsName, ex);\n\t\t\t}\n\t\t}\n\t\t\n\t\tconnectionDelay = 5 * SECOND;\n\t\tif ((props.size() == 1) || isInitializationComplete()) {\n\t\t\tsuper.setProperties(props);\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\n\t\tString repo_class = (String) props.get(CLCON_REPO_CLASS_PROP_KEY);\n\n\t\ttry {\n\t\t\tString repo_uri = (String) props.get(ClusterRepoConstants.REPO_URI_PROP_KEY);\n\t\t\tClass<ClConConfigRepository> cls;\n\t\t\tif (repo_class == null) {\n\t\t\t\tcls = RepositoryFactory.getRepoClass(ClConConfigRepository.class, repo_uri);\n\t\t\t} else {\n\t\t\t\tcls = (Class<ClConConfigRepository>) ModulesManagerImpl.getInstance().forName(repo_class);\n\t\t\t}\n\t\t\tComponentRepository<ClusterRepoItem> repo_tmp = cls.newInstance();\n\n\t\t\trepo_tmp.addRepoChangeListener(this);\n\t\t\trepo_tmp.setProperties(props);\n\t\t\trepo_tmp.initRepository(repo_uri, new HashMap<String,String>());\n\t\t\tComponentRepository<ClusterRepoItem> old_repo = repo;\n\t\t\trepo = repo_tmp;\n\t\t\tif (old_repo != null) {\n\t\t\t\told_repo.destroy();\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not create items repository instance for class: \" +\n\t\t\t\t\trepo_class, e);\n\t\t}\n\t\tif (props.get(ELEMENTS_NUMBER_LIMIT_PROP_KEY) != null) {\n\t\t\telements_number_limit = (Integer) props.get(ELEMENTS_NUMBER_LIMIT_PROP_KEY);\n\t\t}\n\n\t\tif (props.get(EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_KEY) != null) {\n\t\t\tboolean eventbus_enabled = (Boolean) props.get(EVENTBUS_REPOSITORY_NOTIFICATIONS_ENABLED_KEY);\n\t\t\tif (eventbus_enabled) {\n\t\t\t\teventBus = EventBusFactory.getInstance();\n\t\t\t}\n\t\t}\n\n\n\n\t\tsuper.setProperties(props);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\tprivate void sendEvent( REPO_ITEM_UPDATE_TYPE action, String hostname, String secondary ) {\n\n\t\t// either RepositoryItem was wrong or EventBus is not enabled - skiping broadcasting the event;\n\t\tif ( eventBus == null || hostname == null ){\n\t\t\treturn;\n\t\t}\n\n\t\tElement event = new Element( REPO_ITEM_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { EVENTBUS_REPO_ITEM_EVENT_XMLNS } );\n\t\tevent.setAttribute( \"local\", \"true\" );\n\t\tElement repoItem = new Element( \"repo-item\" );\n\t\t{\n\t\t\trepoItem.setAttribute( \"action\", action.name() );\n\t\t\trepoItem.addAttribute( \"hostname\", hostname );\n\t\t\trepoItem.addAttribute( \"secondary\", ( null != secondary ? secondary : \"\" ) );\n\t\t}\n\t\tevent.addChild( repoItem );\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Sending event: \" + event );\n\t\t}\n\n\t\teventBus.fire( event );\n\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tprotected void serviceConnected(XMPPIOService<Object> serv) {\n\t\tString[] routings = (String[]) serv.getSessionData().get(PORT_ROUTING_TABLE_PROP_KEY);\n\t\tString   addr     = (String) serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY);\n\n\t\tClusterConnection conns = connectionsPool.get(addr);\n\n\t\tif (conns == null) {\n\t\t\tconns = new ClusterConnection(addr);\n\t\t\tconnectionsPool.put(addr, conns);\n\t\t}\n\n\t\tint size = conns.size();\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"New service connected: size = {0} / connectionsPool={1} / serv={2} / conns={3}\",\n\t\t\t\t\t\t\t new Object[] { size, connectionsPool, serv, conns } );\n\t\t}\n\n\t\t// setting userJid to hostname of remote cluster node\n\t\tserv.setUserJid((String) serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY));\n\t\t\n\t\tconns.addConn(serv );\n\t\tif ( size == 0 && conns.size() > 0 ){\n\t\t\tupdateRoutings(routings, true);\n\t\t\tlog.log(Level.INFO, \"Connected to: {0}\", addr);\n\t\t\tupdateServiceDiscoveryItem(addr, addr, XMLNS + \" connected\", true);\n\t\t\tclusterController.nodeConnected(addr);\n\t\t}\n\n\t\tServiceConnectedTimerTask task = (ServiceConnectedTimerTask) serv.getSessionData()\n\t\t\t\t.get(SERVICE_CONNECTED_TASK_FUTURE);\n\n\t\tif (task == null) {\n\t\t\tlog.log(Level.WARNING, \"Missing service connected timer task: {0}\", serv);\n\t\t} else {\n\t\t\ttask.cancel();\n\t\t}\n\t}\n\n\t@Override\n\tprotected boolean writePacketToSocket(Packet p) {\n\n\t\t// ++packetsSent;\n\t\tString ip = p.getTo().getDomain();\n\t\tClusterConnection conns = connectionsPool.get(ip);\n\n\t\tXMPPIOService<Object> serv = connectionSelector.selectConnection(p, conns);\n\t\tif (serv != null) {\n\t\t\treturn super.writePacketToSocket(serv, p);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"No cluster connection to send a packet: {0}\", p);\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\tClusterRepoItem item = repo.getItem(getDefHostName().getDomain());\n\n\t\treturn new int[] { item.getPortNo() };\n\t}\n\n\t@Override\n\tprotected String getDefTrafficThrottling() {\n\t\treturn \"xmpp:25m:0:disc,bin:20000m:0:disc\";\n\t}\n\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 3 * MINUTE;\n\t}\n\n\t@Override\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def * 10;\n\t}\n\n\t@Override\n\tprotected Map<String, Object> getParamsForPort(int port) {\n\t\tMap<String, Object> defs = new LinkedHashMap<String, Object>(10);\n\n\t\tdefs.put(PORT_TYPE_PROP_KEY, ConnectionType.accept);\n\t\tdefs.put(PORT_SOCKET_PROP_KEY, SocketType.plain);\n\t\tdefs.put(PORT_IFC_PROP_KEY, PORT_IFC_PROP_VAL);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tprotected XMPPIOService<Object> getXMPPIOServiceInstance() {\n\t\treturn new XMPPIOService<>();\n\t}\n\n\t@Override\n\tprotected boolean isHighThroughput() {\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void processHandshake(Packet p, XMPPIOService<Object> serv) {\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Processing handshake: packet={0} / service={1} / sessionData={2}\",\n\t\t\t\t\t\t\t new Object[] { p, serv, serv.getSessionData() } );\n\t\t}\n\n\t\tString serv_addr = (String) serv.getSessionData().get( PORT_REMOTE_HOST_PROP_KEY );\n\t\ttry {\n\t\t\tInetAddress addr = InetAddress.getByName( serv_addr );\n\n\t\t\t// we ignore any local addresses\n\t\t\tif ( ( addr.isAnyLocalAddress() || addr.isLoopbackAddress() )\n\t\t\t\t\t || NetworkInterface.getByInetAddress( addr ) != null ){\n\t\t\t\tlog.log( Level.WARNING, \"Cluster handshake received from this instance, terminating: {0}\", serv_addr );\n\t\t\t\tserv.stop();\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch ( Exception ex ) {\n\t\t\tlog.log( Level.WARNING, \"Cluster handshake received from this instance, terminating: \" + serv_addr, ex );\n\t\t\tserv.stop();\n\t\t}\n\n\n\t\tswitch (serv.connectionType()) {\n\t\tcase connect : {\n\t\t\tString data = p.getElemCData();\n\n\t\t\tif (data == null) {\n\t\t\t\tserviceConnected(serv);\n\t\t\t} else {\n\t\t\t\tlog.log(Level.WARNING, \"Incorrect packet received: {0}\", p);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase accept : {\n\t\t\tString digest = p.getElemCData();\n\t\t\tString id     = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\t\t\tString secret = (String) serv.getSessionData().get(SECRET_PROP_KEY);\n\n\t\t\ttry {\n\t\t\t\tString loc_digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Calculating digest: secret={0}, digest={1}, loc_digest={2}, sessionData={3}\",\n\t\t\t\t\t\t\tnew Object[] { secret,\n\t\t\t\t\t\t\tdigest, loc_digest, serv.getSessionData() });\n\t\t\t\t}\n\t\t\t\tif ((digest != null) && digest.equals(loc_digest)) {\n\t\t\t\t\tPacket resp = Packet.packetInstance(new Element(\"handshake\"), null, null);\n\n\t\t\t\t\twritePacketToSocket(serv, resp);\n\t\t\t\t\tserviceConnected(serv);\n\t\t\t\t} else {\n\t\t\t\t\tif (secret == null) {\n\t\t\t\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t \"Remote hostname not found in local configuration or time difference between cluster nodes is too big. Connection not accepted: {0}\", serv );\n\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t \"Remote hostname not found in local configuration or time difference between cluster nodes is too big. Connection not accepted! Remote host: {0}, sessionData: {1}, repoItem: {2}, service: {3}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { serv_addr, serv.getSessionData(), repo.getItem( serv_addr ), serv } );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Handshaking password doesn''t match, disconnecting: {0}\", serv);\n\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t\t \"Handshaking password doesn''t match, disconnecting! Remote host: {0}, sessionData: {1}, repoItem: {2}, service: {3}\", new Object[] { serv_addr, serv.getSessionData(), repo.getItem( serv_addr ), serv } );\n\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t}\n\t\t\t\t\tserv.stop();\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Handshaking error.\", e);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault :\n\n\t\t\t// Do nothing, more data should come soon...\n\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\t}\n\n\tprivate void updateRoutings(String[] routings, boolean add) {\n\t\tif (add) {\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\taddRegexRouting(route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can not add regex routing ''{0}'' : {1}\",\n\t\t\t\t\t\t\tnew Object[] { route,\n\t\t\t\t\t\t\te });\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\tremoveRegexRouting(route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can not remove regex routing ''{0}'' : {1}\",\n\t\t\t\t\t\t\tnew Object[] { route,\n\t\t\t\t\t\t\te });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class IOServiceStatisticsGetter\n\t\t\t\t\timplements ServiceChecker<XMPPIOService<Object>> {\n\t\tprivate int            clIOQueue          = 0;\n\t\tprivate float          compressionRatio   = 0f;\n\t\tprivate int            counter            = 0;\n\t\tprivate float          decompressionRatio = 0f;\n\t\tprivate StatisticsList list               = new StatisticsList(Level.ALL);\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void check(XMPPIOService<Object> service) {\n\t\t\tservice.getStatistics(list, true);\n\t\t\tcompressionRatio   += list.getValue(\"zlibio\", \"Average compression rate\", -1f);\n\t\t\tdecompressionRatio += list.getValue(\"zlibio\", \"Average decompression rate\", -1f);\n\t\t\t++counter;\n\t\t\tclIOQueue += service.waitingToSendSize();\n\t\t}\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t */\n\t\tpublic void reset() {\n\n\t\t\t// Statistics are reset on the low socket level instead. This way we do\n\t\t\t// not loose\n\t\t\t// any stats in case of the disconnection.\n\t\t\t// bytesReceived = 0;\n\t\t\t// bytesSent = 0;\n\t\t\tclIOQueue          = 0;\n\t\t\tcounter            = 0;\n\t\t\tcompressionRatio   = 0f;\n\t\t\tdecompressionRatio = 0f;\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t *\n\t\t *\n\t\t * @return a value of <code>float</code>\n\t\t */\n\t\tpublic float getAverageCompressionRatio() {\n\t\t\treturn compressionRatio / counter;\n\t\t}\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t *\n\t\t *\n\t\t * @return a value of <code>float</code>\n\t\t */\n\t\tpublic float getAverageDecompressionRatio() {\n\t\t\treturn decompressionRatio / counter;\n\t\t}\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t *\n\t\t *\n\t\t * @return a value of <code>int</code>\n\t\t */\n\t\tpublic int getWaitingToSend() {\n\t\t\treturn clIOQueue;\n\t\t}\n\t}\n\n\n\tprivate class SendPacket\n\t\t\t\t\textends CommandListenerAbstract {\n\t\tprivate SendPacket(String name) {\n\t\t\tsuper(name, null);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String,\n\t\t\t\tString> data, Queue<Element> packets)\n\t\t\t\tthrows ClusterCommandException {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Called fromNode: {0}, visitedNodes: {1}, data: {2}, packets: {3}\",\n\t\t\t\t\t\tnew Object[] { fromNode,\n\t\t\t\t\t\tvisitedNodes, data, packets });\n\t\t\t}\n\t\t\tfor (Element element : packets) {\n\t\t\t\ttry {\n\t\t\t\t\taddPacketNB(Packet.packetInstance(element));\n\n\t\t\t\t\t// writePacketToSocket();\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Stringprep exception for packet: {0}\", element);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tprivate class ServiceConnectedTimerTask\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\tprivate XMPPIOService<Object> serv = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate ServiceConnectedTimerTask(XMPPIOService<Object> serv) {\n\t\t\tthis.serv = serv;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\t++servConnectedTimeouts;\n\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\"ServiceConnectedTimer timeout expired, closing connection: {0}\", serv);\n\t\t\tserv.forceStop();\n\t\t}\n\t}\n\t\n\tprotected class Watchdog extends ConnectionManager.Watchdog {\n\n\t\t@Override\n\t\tprotected long getDurationSinceLastTransfer(final XMPPIOService service) {\n\t\t\tLong lastTransfer = (Long) service.getSessionData().get(\"lastConnectivityCheck\");\n\t\t\tif (lastTransfer == null) {\n\t\t\t\tservice.getSessionData().put(\"lastConnectivityCheck\", System.currentTimeMillis() - watchdogTimeout);\n\t\t\t\treturn watchdogTimeout;\n\t\t\t}\n\t\t\treturn System.currentTimeMillis() - lastTransfer;\n\t\t}\n\t\t\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClusterConnectionSelector.java",
    "content": "/*\n * ClusterConnectionSelector.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster;\n\nimport java.util.List;\nimport java.util.Map;\nimport tigase.cluster.api.ClusterConnectionHandler;\nimport tigase.cluster.api.ClusterConnectionSelectorIfc;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n * Advanced implementation of ClusterConnectionSelectorIfc which separates packets\n * with priority CLUSTER or higher from other packets in cluster connections\n * by using separate connections for them\n * \n * @author andrzej\n */\npublic class ClusterConnectionSelector implements ClusterConnectionSelectorIfc {\n\n\tprotected static final String CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY = \"cluster-sys-connections-per-node\";\n\t\n\tprivate int allConns = ClusterConnectionManager.CLUSTER_CONNECTIONS_PER_NODE_VAL;\n\tprivate int sysConns = 2;\n\tprivate ClusterConnectionHandler handler;\n\t\n\t@Override\n\tpublic XMPPIOService<Object> selectConnection(Packet p, ClusterConnection conn) {\n\t\tif (conn == null)\n\t\t\treturn null;\n\t\t\n\t\tint code  = Math.abs(handler.hashCodeForPacket(p));\n\t\tList<XMPPIOService<Object>> conns = conn.getConnections();\n\t\tif (conns.size() > 0) {\n\t\t\tif (conns.size() > sysConns) {\n\t\t\t\tif (p.getPriority() != null && p.getPriority().ordinal() <= Priority.CLUSTER.ordinal()) {\n\t\t\t\t\treturn conns.get(code % sysConns);\n\t\t\t\t} else {\n\t\t\t\t\treturn conns.get(sysConns + (code % (conns.size() - sysConns)));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn conns.get(code % conns.size());\n\t\t\t}\n\t\t}\n\t\treturn null;\t\t\n\t}\n\t\n\t@Override\n\tpublic void setClusterConnectionHandler(ClusterConnectionHandler handler) {\n\t\tthis.handler = handler;\n\t}\n\t\n\t@Override\n\tpublic void setProperties(Map<String,Object> props) {\n\t\tif (props.containsKey(CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY)) {\n\t\t\tsysConns = (Integer) props.get(CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY);\n\t\t}\n\t\tif (props.containsKey(ClusterConnectionManager.CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY)) {\n\t\t\tallConns = (Integer) props.get(ClusterConnectionManager.CLUSTER_CONNECTIONS_PER_NODE_PROP_KEY);\n\t\t}\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClusterConnectionSelectorOld.java",
    "content": "/*\n * ClusterConnectionSelectorOld.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster;\n\nimport java.util.List;\nimport java.util.Map;\nimport tigase.cluster.api.ClusterConnectionHandler;\nimport tigase.cluster.api.ClusterConnectionSelectorIfc;\nimport tigase.server.Packet;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n * ClusterConnectionSelectorOld class implements old cluster connection selection\n * algoritm which before was part of ClusterConnectionManager class.\n * \n * @author andrzej\n */\npublic class ClusterConnectionSelectorOld implements ClusterConnectionSelectorIfc {\n\n\tprivate ClusterConnectionHandler handler;\n\t\n\t@Override\n\tpublic XMPPIOService<Object> selectConnection(Packet p, ClusterConnection conn) {\n\t\tif (conn == null)\n\t\t\treturn null;\n\t\t\n\t\tint code  = Math.abs(handler.hashCodeForPacket(p));\n\t\tList<XMPPIOService<Object>> conns = conn.getConnections();\n\t\tif (conns.size() > 0) {\n\t\t\treturn conns.get(code % conns.size());\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void setClusterConnectionHandler(ClusterConnectionHandler handler) {\n\t\tthis.handler = handler;\n\t}\n\t\n\t@Override\n\tpublic void setProperties(Map<String,Object> props) {\n\t\t\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/ClusterController.java",
    "content": "/*\n * ClusterController.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.cluster.api.ClusterCommandException;\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusterElement;\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.cluster.api.CommandListener;\nimport tigase.conf.Configurable;\nimport tigase.conf.ConfigurationException;\nimport tigase.server.AbstractComponentRegistrator;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\nimport tigase.server.ServerComponent;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Describe class ClusterController here.\n *\n *\n * Created: Mon Jun 9 20:03:28 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ClusterController\n\t\t\t\textends AbstractComponentRegistrator<ClusteredComponentIfc>\n\t\t\t\timplements Configurable, ClusterControllerIfc {\n\t/** Field description */\n\tpublic static final String MY_DOMAIN_NAME_PROP_KEY = \"domain-name\";\n\n\t/** Field description */\n\tpublic static final String  MY_DOMAIN_NAME_PROP_VAL = \"localhost\";\n\tprivate static final Logger log = Logger.getLogger(ClusterController.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate ConcurrentSkipListMap<String, CommandListener> commandListeners =\n\t\t\tnew ConcurrentSkipListMap<String, CommandListener>();\n\tprivate AtomicLong currId = new AtomicLong(1L);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void componentAdded(ClusteredComponentIfc component) {\n\t\t// we are not passing wrapper to ClusterConnectionManager as we need to\n\t\t// check later if it's command is added\n\t\tif (component instanceof ClusterConnectionManager) {\n\t\t\tcomponent.setClusterController(this);\n\t\t} else {\n\t\t\tWrapper wrapper = new Wrapper(this, component);\n\t\t\tcomponent.setClusterController(wrapper);\n\t\t}\n\t\tupdateServiceDiscoveryItem(getName(), component.getName(), \"Component: \" + component\n\t\t\t\t.getName(), true);\n\t}\n\n\t@Override\n\tpublic void componentRemoved(ClusteredComponentIfc component) {}\n\n\t@Override\n\tpublic void handleClusterPacket(Element packet) {\n\t\tClusterElement  clel    = new ClusterElement(packet);\n\t\tCommandListener cmdList = commandListeners.get(clel.getMethodName());\n\n\t\tif (cmdList != null) {\n\t\t\tclel.addVisitedNode(JID.jidInstanceNS(packet.getAttributeStaticStr(Packet.TO_ATT)));\n\n\t\t\tMap<String, String> data         = clel.getAllMethodParams();\n\t\t\tSet<JID>            visitedNodes = clel.getVisitedNodes();\n\t\t\tQueue<Element>      packets      = clel.getDataPackets();\n\n\t\t\ttry {\n\t\t\t\tcmdList.executeCommand(clel.getFirstNode(), visitedNodes, data, packets);\n\n\t\t\t\t// TODO Send result back (possibly)\n\t\t\t} catch (ClusterCommandException ex) {\n\n\t\t\t\t// TODO Send error back\n\t\t\t\tex.printStackTrace();\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Missing CommandListener for cluster method: {0}\", clel\n\t\t\t\t\t.getMethodName());\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void nodeConnected(String node) {\n\t\tsuper.nodeConnected(node);\n\t\tfor (ClusteredComponentIfc comp : components.values()) {\n\t\t\tcomp.nodeConnected(node);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void nodeDisconnected(String node) {\n\t\tsuper.nodeDisconnected(node);\n\t\tfor (ClusteredComponentIfc comp : components.values()) {\n\t\t\tcomp.nodeDisconnected(node);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet, final Queue<Packet> results) {}\n\n\t@Override\n\tpublic void removeCommandListener(CommandListener listener) {\n\t\tremoveCommandListener(listener.getName(), listener);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Map<String, String> data,\n\t\t\tQueue<Element> packets, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t// this command should not be prefixed as we passed original instance instead of \n\t\t// wrapper to ClusterConnectionManager\n\t\tCommandListener packetSender = commandListeners.get(DELIVER_CLUSTER_PACKET_CMD);\n\n\t\tif (packetSender == null) {\n\t\t\tlog.log(Level.SEVERE, \"Misconfiguration or packaging error, can not send a \" +\n\t\t\t\t\t\"cluster packet! No CommandListener for \" + DELIVER_CLUSTER_PACKET_CMD);\n\n\t\t\treturn;\n\t\t}\n\n\t\tQueue<Element> results = new ArrayDeque<Element>();\n\n\t\t// retrive listener for command and it's priority to if available\n\t\tCommandListener listener = commandListeners.get(command);\n\t\tPriority priority = listener != null ? listener.getPriority() : null;\n\t\t\n\t\t// TODO: Maybe more optimal would be creating the object once and then clone\n\t\t// it? However, the 'to' parameter must be double-checked whether all\n\t\t// internal states are set properly for each different to parameter\n\t\tfor (JID to : toNodes) {\n\t\t\tClusterElement clel = ClusterElement.createClusterMethodCall(fromNode, to,\n\t\t\t\t\tStanzaType.set, command, data);\n\n\t\t\t// set priority to ClusterElement so it will get proper priority for processing\n\t\t\tif (priority != null)\n\t\t\t\tclel.setPriority(priority);\n\t\t\tclel.addVisitedNodes(visitedNodes);\n\t\t\tclel.addDataPackets(packets);\n\n\t\t\tElement result = clel.getClusterElement(nextId());\n\n\t\t\tresults.offer(result);\n\t\t}\n\t\ttry {\n\t\t\tpacketSender.executeCommand(null, null, null, results);\n\t\t} catch (ClusterCommandException ex) {\n\n\t\t\t// TODO Auto-generated catch block\n\t\t\tex.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Queue<Element> packets, JID fromNode,\n\t\t\tSet<JID> visitedNodes, JID... toNodes) {\n\t\tsendToNodes(command, null, packets, fromNode, visitedNodes, toNodes);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Map<String, String> data, JID fromNode,\n\t\t\tSet<JID> visitedNodes, JID... toNodes) {\n\t\tsendToNodes(command, data, (Queue<Element>) null, fromNode, visitedNodes, toNodes);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Map<String, String> data, JID fromNode,\n\t\t\tJID... toNodes) {\n\t\tsendToNodes(command, data, (Queue<Element>) null, fromNode, null, toNodes);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, JID fromNode, JID... toNodes) {\n\t\tsendToNodes(command, null, (Queue<Element>) null, fromNode, null, toNodes);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Element packet, JID fromNode,\n\t\t\tSet<JID> visitedNodes, JID... toNodes) {\n\t\tsendToNodes(command, null, packet, fromNode, visitedNodes, toNodes);\n\t}\n\n\t@Override\n\tpublic void sendToNodes(String command, Map<String, String> data, Element packet,\n\t\t\tJID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\tQueue<Element> packets = new ArrayDeque<Element>();\n\n\t\tpackets.offer(packet);\n\t\tsendToNodes(command, data, packets, fromNode, visitedNodes, toNodes);\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"load\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Cluster controller\";\n\t}\n\n\t@Override\n\tpublic boolean isCorrectType(ServerComponent component) {\n\t\treturn (component instanceof ClusteredComponentIfc) && !(component instanceof ClusterControllerIfc);\n\t}\n\n\t@Override\n\tpublic void setCommandListener(CommandListener listener) {\n\t\tsetCommandListener(listener.getName(), listener);\n\t}\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) throws ConfigurationException {\n\t\tsuper.setProperties(properties);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate String nextId() {\n\t\treturn \"cl-\" + currId.incrementAndGet();\n\t}\n\t\n\tprivate void removeCommandListener(String name, CommandListener listener) {\n\t\tcommandListeners.remove(name, listener);\n\t}\n\t\n\tprivate void setCommandListener(String name, CommandListener listener) {\n\t\tcommandListeners.put(name, listener);\n\t}\n\t\n\tprivate class Wrapper implements ClusterControllerIfc {\n\n\t\tprivate final ClusterController controller;\n\t\tprivate final ClusteredComponentIfc component;\n\t\tprivate final String name;\n\t\t\n\t\tpublic Wrapper(ClusterController controller, ClusteredComponentIfc component) {\n\t\t\tthis.controller = controller;\n\t\t\tthis.component = component;\n\t\t\tname = component.getName();\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void handleClusterPacket(Element packet) {\n\t\t\tcontroller.handleClusterPacket(packet);\n\t\t}\n\n\t\t@Override\n\t\tpublic void nodeConnected(String addr) {\n\t\t\tthrow new UnsupportedOperationException(\"This method should not be called.\"); \n\t\t}\n\n\t\t@Override\n\t\tpublic void nodeDisconnected(String addr) {\n\t\t\tthrow new UnsupportedOperationException(\"This method should not be called.\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void removeCommandListener(CommandListener listener) {\n\t\t\tString name = this.name + \"-\" + listener.getName();\n\t\t\tcontroller.removeCommandListener(name, listener);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Map<String, String> data, Queue<Element> packets, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, data, packets, fromNode, visitedNodes, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Queue<Element> packets, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, packets, fromNode, visitedNodes, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Map<String, String> data, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, data, fromNode, visitedNodes, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Map<String, String> data, JID fromNode, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, data, fromNode, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, JID fromNode, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, fromNode, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Element packet, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, packet, fromNode, visitedNodes, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void sendToNodes(String command, Map<String, String> data, Element packet, JID fromNode, Set<JID> visitedNodes, JID... toNodes) {\n\t\t\tcommand = name + \"-\" + command;\n\t\t\tcontroller.sendToNodes(command, data, packet, fromNode, visitedNodes, toNodes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setCommandListener(CommandListener listener) {\n\t\t\tString name = this.name + \"-\" + listener.getName();\n\t\t\tcontroller.setCommandListener(name, listener);\n\t\t}\n\t\t\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/10/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/MonitorClustered.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.monitor.MonitorComponent;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jul 4, 2010 7:18:46 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated Use {@link tigase.monitor.MonitorComponent} instead.\n */\n@Deprecated\npublic class MonitorClustered extends MonitorComponent {\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/SessionManagerClustered.java",
    "content": "/*\n * SessionManagerClustered.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\nimport tigase.cluster.strategy.ClusteringStrategyIfc;\nimport tigase.conf.ConfigurationException;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.ComponentInfo;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.XMPPServer;\nimport tigase.server.xmppsession.SessionManager;\nimport tigase.stats.StatisticsList;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\n\nimport javax.script.Bindings;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class SessionManagerClusteredOld\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class SessionManagerClustered\n\t\t\t\textends SessionManager\n\t\t\t\timplements ClusteredComponentIfc, SessionManagerClusteredIfc {\n\t/** Field description */\n\tpublic static final String CLUSTER_STRATEGY_VAR = \"clusterStrategy\";\n\n\t/** Field description */\n\tpublic static final String MY_DOMAIN_NAME_PROP_KEY = \"domain-name\";\n\n\t/** Field description */\n\tpublic static final String STRATEGY_CLASS_PROP_KEY = \"sm-cluster-strategy-class\";\n\n\t/** Field description */\n\tpublic static final String STRATEGY_CLASS_PROP_VAL =\n\t\t\t\"tigase.cluster.strategy.DefaultClusteringStrategy\";\n\n\t/** Field description */\n\tpublic static final String STRATEGY_CLASS_PROPERTY = \"--sm-cluster-strategy-class\";\n\n\t/** Field description */\n\tpublic static final int SYNC_MAX_BATCH_SIZE = 1000;\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(SessionManagerClustered.class\n\t\t\t.getName());\n\n\tprivate enum STATUS {CONNECETED, DISCONNECTED};\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate ClusterControllerIfc  clusterController = null;\n\tprivate ComponentInfo         cmpInfo           = null;\n\tprivate JID                   my_address        = null;\n\tprivate JID                   my_hostname       = null;\n\tprivate int                   nodesNo           = 0;\n\tprivate ClusteringStrategyIfc strategy          = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean containsJid(BareJID jid) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for jid: {0}\", jid);\n\t\t}\n\n\t\treturn super.containsJid(jid) || strategy.containsJid(jid);\n\t}\n\n\t@Override\n\tpublic boolean fastAddOutPacket(Packet packet) {\n\t\treturn super.fastAddOutPacket(packet);\n\t}\n\n\t@Override\n\tpublic void handleLocalPacket(Packet packet, XMPPResourceConnection conn) {\n\t\tif (strategy != null) {\n\t\t\tstrategy.handleLocalPacket(packet, conn);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleLogin(BareJID userId, XMPPResourceConnection conn) {\n\t\tsuper.handleLogin(userId, conn);\n\t\tstrategy.handleLocalUserLogin(userId, conn);\n\t}\n\n\t@Override\n\tpublic void handleLogout(BareJID userId, XMPPResourceConnection conn) {\n\t\t// Exception here should not normally happen, but if it does, then\n\t\t// consequences might be severe, let's catch it then\n\t\ttry {\n\t\t\tif (conn.isAuthorized() && conn.isResourceSet()) {\n\t\t\t\tstrategy.handleLocalUserLogout(userId, conn);\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t}\n\t\tsuper.handleLogout(userId, conn); //To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t@Override\n\tpublic void handleResourceBind(XMPPResourceConnection conn) {\n\t\tsuper.handleResourceBind(conn);\n\t\tstrategy.handleLocalResourceBind(conn);\n\t}\n\t\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(CLUSTER_STRATEGY_VAR, strategy);\n\t}\n\n\t@Override\n\tpublic void onNodeConnected(JID jid) {\n\t\tsuper.onNodeConnected(jid);\n\n\t\tif (!getComponentId().equals(jid)) {\n\t\t\tstrategy.nodeConnected(jid);\n\t\t\t\n\t\t\tsendAdminNotification( jid.getDomain(), STATUS.CONNECETED );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onNodeDisconnected(JID jid) {\n\t\tsuper.onNodeDisconnected(jid);\n\n\t\tif (!getComponentId().equals(jid)) {\n\t\t\tstrategy.nodeDisconnected(jid);\n\n\t\t\t// Not sure what to do here, there might be still packets\n\t\t\t// from the cluster node waiting....\n\t\t\t// delTrusted(jid);\n\t\t\t\n\t\t\tsendAdminNotification(jid.toString(), STATUS.DISCONNECTED);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Math.max(nodesNo, super.processingInThreads());\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn Math.max(nodesNo, super.processingOutThreads());\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br>\n\t * \n\t * This is a standard component method for processing packets. The method\n\t * takes care of cases where the packet cannot be processed locally, in such a\n\t * case it is forwarded to another node.\n\t *\n\t * @param packet to be processed\n\t */\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Received packet: {0}\", packet);\n\t\t}\n\n\t\tif (packet.isCommand() && processCommand(packet)) {\n\t\t\tpacket.processedBy(\"SessionManager\");\n\n\t\t} else {\n\t\t\tXMPPResourceConnection conn = getXMPPResourceConnection(packet);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Ressource connection found: {0}\", conn);\n\t\t\t}\n\n\t\t\tboolean clusterOK = strategy.processPacket(packet, conn);\n\n\t\t\tif (conn == null) {\n\t\t\t\tif (isBrokenPacket(packet) || processAdminsOrDomains(packet)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Ignoring/dropping packet: {0}\", packet);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Process is as packet to offline user only if there are no other\n\t\t\t\t\t// nodes for the packet to be processed.\n\t\t\t\t\tif (!clusterOK) {\n\n\t\t\t\t\t\t// Process packet for offline user\n\t\t\t\t\t\tprocessPacket(packet, (XMPPResourceConnection) null);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tprocessPacket(packet, conn);\n\n\t\t\t\t// smTm = System.currentTimeMillis() - startTime;\n\t\t\t}\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet, XMPPResourceConnection conn) {\n\t\tsuper.processPacket(packet, conn);\n\t}\n\n\t@Override\n\tpublic void processPresenceUpdate(XMPPSession session, Element packet) {\n\t\tsuper.processPresenceUpdate(session, packet);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic ComponentInfo getComponentInfo() {\n\t\tcmpInfo = super.getComponentInfo();\n\t\tcmpInfo.getComponentData().put(\"ClusteringStrategy\", (strategy != null)\n\t\t\t\t? strategy.getClass()\n\t\t\t\t: null);\n\n\t\treturn cmpInfo;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * If the installation knows about user's JID, that he is connected to the\n\t * system, then this method returns all user's connection IDs. As an\n\t * optimization we can forward packets to all user's connections directly from\n\t * a single node.\n\t *\n\t * @param jid\n\t *          a user's JID for whom we query information.\n\t *\n\t * @return a list of all user's connection IDs.\n\t */\n\t@Override\n\tpublic JID[] getConnectionIdsForJid(BareJID jid) {\n\t\tJID[] ids = super.getConnectionIdsForJid(jid);\n\n\t\tif (ids == null) {\n\t\t\tids = strategy.getConnectionIdsForJid(jid);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for jid: {0}, results: {1}\", new Object[] { jid,\n\t\t\t\t\tArrays.toString(ids) });\n\t\t}\n\n\t\treturn ids;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props          = super.getDefaults(params);\n\t\tString              strategy_class = (String) params.get(STRATEGY_CLASS_PROPERTY);\n\n\t\tif (strategy_class == null) {\n\t\t\tstrategy_class = STRATEGY_CLASS_PROP_VAL;\n\t\t}\n\t\tprops.put(STRATEGY_CLASS_PROP_KEY, strategy_class);\n\t\ttry {\n\t\t\tClusteringStrategyIfc strat_tmp = (ClusteringStrategyIfc) ModulesManagerImpl.getInstance().forName(\n\t\t\t\t\tstrategy_class).newInstance();\n\t\t\tMap<String, Object> strat_defs = strat_tmp.getDefaults(params);\n\n\t\t\tif (strat_defs != null) {\n\t\t\t\tprops.putAll(strat_defs);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not instantiate clustering strategy for class: \" +\n\t\t\t\t\tstrategy_class, e);\n\t\t}\n\n\t\tString[] local_domains = DNSResolverFactory.getInstance().getDefaultHosts();\n\n\t\tif (params.get(GEN_VIRT_HOSTS) != null) {\n\t\t\tlocal_domains = ((String) params.get(GEN_VIRT_HOSTS)).split(\",\");\n\t\t}\n\n\t\t// defs.put(LOCAL_DOMAINS_PROP_KEY, LOCAL_DOMAINS_PROP_VAL);\n\t\tprops.put(MY_DOMAIN_NAME_PROP_KEY, local_domains[0]);\n\t\tif (params.get(CLUSTER_NODES) != null) {\n\t\t\tString[] cl_nodes = ((String) params.get(CLUSTER_NODES)).split(\",\");\n\n\t\t\tnodesNo = cl_nodes.length;\n\t\t}\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"disco description from SM Clustered\");\n\t\t}\n\n\t\tString result;\n\n\t\tresult = super.getDiscoDescription();\n\t\tresult += \" clustered, \";\n\t\tresult += strategy;\n\n\t\treturn result;\n\n\t}\n\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tstrategy.getStatistics(list);\n\n\t}\n\n\t/**\n\t * Returns active clustering strategy object.\n\t *\n\t * @return active clustering strategy object.\n\t */\n\tpublic ClusteringStrategyIfc getStrategy() {\n\t\treturn strategy;\n\t}\n\n\t@Override\n\tpublic XMPPResourceConnection getXMPPResourceConnection(Packet p) {\n\t\treturn super.getXMPPResourceConnection(p);\n\t}\n\n\t@Override\n\tpublic ConcurrentHashMap<JID, XMPPResourceConnection> getXMPPResourceConnections() {\n\t\treturn connectionsByFrom;\n\t}\n\n\t@Override\n\tpublic ConcurrentHashMap<BareJID, XMPPSession> getXMPPSessions() {\n\t\treturn sessionsByNodeId;\n\t}\n\n\t@Override\n\tpublic boolean hasCompleteJidsInfo() {\n\t\treturn strategy.hasCompleteJidsInfo();\n\t}\n\n\t@Override\n\tpublic boolean hasXMPPResourceConnectionForConnectionJid(JID connJid) {\n\t\treturn this.connectionsByFrom.containsKey(connJid);\n\t}\n\t\n\t@Override\n\tpublic void setClusterController(ClusterControllerIfc cl_controller) {\n\t\tsuper.setClusterController(cl_controller);\n\t\tclusterController = cl_controller;\n\t\tif (strategy != null) {\n\t\t\tstrategy.setClusterController(clusterController);\n\t\t}\n\n//  clusterController.removeCommandListener(USER_CONNECTED_CMD, userConnected);\n//  clusterController.removeCommandListener(USER_DISCONNECTED_CMD, userDisconnected);\n//  clusterController.removeCommandListener(USER_PRESENCE_CMD, userPresence);\n//  clusterController.removeCommandListener(REQUEST_SYNCONLINE_CMD, requestSyncOnline);\n//  clusterController.removeCommandListener(RESPOND_SYNCONLINE_CMD, respondSyncOnline);\n//  clusterController.setCommandListener(USER_CONNECTED_CMD, userConnected);\n//  clusterController.setCommandListener(USER_DISCONNECTED_CMD, userDisconnected);\n//  clusterController.setCommandListener(USER_PRESENCE_CMD, userPresence);\n//  clusterController.setCommandListener(REQUEST_SYNCONLINE_CMD, requestSyncOnline);\n//  clusterController.setCommandListener(RESPOND_SYNCONLINE_CMD, respondSyncOnline);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.get(STRATEGY_CLASS_PROP_KEY) != null) {\n\t\t\tString strategy_class = (String) props.get(STRATEGY_CLASS_PROP_KEY);\n\n\t\t\ttry {\n\t\t\t\t// we should not replace instance of ClusteringStrategyIfc if it\n\t\t\t\t// is not required as instance may contain data!!\n\t\t\t\tClusteringStrategyIfc strategy_tmp = strategy;\n\t\t\t\tif (strategy == null || !strategy_class.equals(strategy.getClass().getCanonicalName())) {\n\t\t\t\t\tClass<?> cls = ModulesManagerImpl.getInstance().forName(strategy_class);\n\t\t\t\t\tstrategy_tmp = (ClusteringStrategyIfc) cls.newInstance();\n\t\t\t\t}\n\t\t\t\tstrategy_tmp.setSessionManagerHandler(this);\n\t\t\t\tstrategy_tmp.setProperties(props);\n\n\t\t\t\t// strategy_tmp.init(getName());\n\t\t\t\tstrategy = strategy_tmp;\n\t\t\t\tstrategy.setSessionManagerHandler(this);\n\t\t\t\tlog.log(Level.CONFIG, \"Loaded SM strategy: {0}\", strategy_class);\n\n\t\t\t\tif (clusterController != null) {\n\t\t\t\t\tstrategy.setClusterController(clusterController);\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (!XMPPServer.isOSGi()) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Cannot instance clustering strategy class: \" +\n\t\t\t\t\t\t\tstrategy_class, e);\n\t\t\t\t}\n\t\t\t\tthrow new ConfigurationException(\"Can not instantiate clustering strategy for class: \" +\n\t\t\t\t\tstrategy_class);\t\t\n\t\t\t}\n\t\t}\n\t\tsuper.setProperties(props);\n\t\tupdateServiceEntity();\n\t\ttry {\n\t\t\tif (props.get(MY_DOMAIN_NAME_PROP_KEY) != null) {\n\t\t\t\tmy_hostname = JID.jidInstance((String) props.get(MY_DOMAIN_NAME_PROP_KEY));\n\t\t\t\tmy_address = JID.jidInstance(getName(), (String) props.get(\n\t\t\t\t\t\tMY_DOMAIN_NAME_PROP_KEY), null);\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Creating component source address failed stringprep processing: {0}@{1}\",\n\t\t\t\t\tnew Object[] { getName(),\n\t\t\t\t\tmy_hostname });\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method intercept user's disconnect event. On user disconnect the method\n\t * takes a list of cluster nodes from the strategy and sends a notification to\n\t * all those nodes about the event.\n\t *\n\t * @see SessionManager#closeSession\n\t *\n\t * @param conn {@link XMPPResourceConnection} to be closed\n\t * @param closeOnly whether to perform additional processing before closing\n\t */\n\t@Override\n\tprotected void closeSession(XMPPResourceConnection conn, boolean closeOnly) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for conn: {0}, closeOnly: {1}\", new Object[] { conn,\n\t\t\t\t\tcloseOnly });\n\t\t}\n\n\t\t// Exception here should not normally happen, but if it does, then\n\t\t// consequences might be severe, let's catch it then\n\t\ttry {\n\t\t\tif (conn.isAuthorized() && conn.isResourceSet()) {\n\t\t\t\tBareJID userId = conn.getBareJID();\n\n\t\t\t\tstrategy.handleLocalUserLogout(userId, conn);\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t}\n\n\t\t// Exception here should not normally happen, but if it does, then\n\t\t// consequences might be severe, let's catch it then\n\t\ttry {\n\t\t\tsuper.closeSession(conn, closeOnly);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void xmppStreamMoved(XMPPResourceConnection conn, JID oldConnId, JID newConnId) {\n\t\ttry {\n\t\t\tstrategy.handleLocalUserChangedConnId(conn.getBareJID(), conn, oldConnId, newConnId);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t}\n\t\tsuper.xmppStreamMoved(conn, oldConnId, newConnId);\n\t}\n\n\tprivate void sendAdminNotification(String node, STATUS stat) {\n\t\tString message = \"Cluster \";\n\t\tString subject = null;\n\n\t\tif (node != null) {\n\t\t\tmessage += \"node \" + node + \" \";\n\t\t}\n\n\t\tswitch ( stat ) {\n\t\t\tcase CONNECETED:\n\t\t\t\tmessage += \"connected to \";\n//\t\t\t\tsubject = \"New cluster node connected\";\n\t\t\t\tbreak;\n\t\t\tcase DISCONNECTED:\n\t\t\t\tmessage += \"disconnected from \";\n//\t\t\t\tsubject = \"Cluster node disconnected\";\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tmessage += getDefHostName() + \" (\" + new Date() + \")\";\n\n\t\tPacket p_msg = Message.getMessage(my_address, my_hostname, StanzaType.chat,\n\t\t\t\tmessage, subject, \"cluster_status_update\", newPacketId(null));\n\n\t\tsendToAdmins(p_msg);\n\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/VirtualComponent.java",
    "content": "/*\n * VirtualComponent.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\nimport tigase.server.ComponentInfo;\nimport tigase.server.DisableDisco;\nimport tigase.server.Packet;\nimport tigase.server.ServerComponent;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.conf.Configurable;\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\nimport tigase.disco.XMPPService;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostListener;\nimport tigase.vhosts.VHostManagerIfc;\nimport tigase.xml.Element;\n\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * The purpose of this component implementation is to forward packets to a\n * target real component implementation in the cluster installation. Let's say\n * you have a cluster installation with full Tigase server installed on each\n * node and you also want to use a component which doesn't have clustered\n * implementation yet. In such case you deploy the component on one of the\n * cluster nodes and put the virtual component on all other nodes. With proper\n * configuration they pretend to be the component returning a correct service\n * disco information and forward all packets for this component to a cluster\n * node with real component running.\n *\n * This is a very lightweight implementation which doesn't use much resources\n * either memory or CPU.\n *\n * It can work well for any kind of a component: MUC, PubSub, transport either\n * native Tigase components or third-party components connected via XEP-0114 -\n * external protocol component.\n *\n * Basic configuration parameters are actually the same as for a real component.\n * You set a real component name as a name for the virtual component and a\n * vritual component class name to load. Let's say we want to deploy MUC\n * component this way. The MUC component is visible as\n * <code>muc.domain.our</code> in our installation. Thus the name of the\n * component is: <code>muc</code>:\n *\n * <pre>\n * --comp-name-1=muc\n * --comp-class-1=tigase.cluster.VirtualComponent\n * </pre>\n *\n * This is pretty much all you need to load a virtual component. A few other\n * options are needed to point to correct destination addresses for forwarded\n * packets and to set correct service discovery parameters:\n *\n * <pre>\n * muc/redirect-to=muc@cluster-node-with-real-muc.domain.our\n * muc/disco-name=Multi User Chat\n * muc/disco-node=\n * muc/disco-type=text\n * muc/disco-category=conference\n * muc/disco-features=http://jabber.org/protocol/muc\n * muc/fixed-domain=example.com\n * </pre>\n *\n * Above options set all possible parameters to setup virtual MUC component.\n * Created: Dec 13, 2008 7:44:35 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class VirtualComponent\n\t\t\t\timplements ServerComponent, XMPPService, Configurable, DisableDisco,\n\t\t\t\t\t\tVHostListener {\n\t/**\n\t * Parameter to set service discovery item category name for the virtual\n\t * component. Please refer to service discovery documentation for a correct\n\t * category or check what is returned by your real component instance.\n\t */\n\tpublic static final String DISCO_CATEGORY_PROP_KEY = \"disco-category\";\n\n\t/** Field description */\n\tpublic static final String DISCO_CATEGORY_PROP_VAL = \"conference\";\n\n\t/**\n\t * Comma separated list of features for the service discovery item represented\n\t * by this virtual component. Please check with the real component to obtain a\n\t * correct list of features.\n\t */\n\tpublic static final String DISCO_FEATURES_PROP_KEY = \"disco-features\";\n\n\t/** Field description */\n\tpublic static final String DISCO_FEATURES_PROP_VAL = \"http://jabber.org/protocol/muc\";\n\n\t/**\n\t * Parameter to set service discovery item name for the virtual component\n\t * instance. You should refer to service discovery documentation for a proper\n\t * name for your component.\n\t */\n\tpublic static final String DISCO_NAME_PROP_KEY = \"disco-name\";\n\n\t/** Field description */\n\tpublic static final String DISCO_NAME_PROP_VAL = \"Multi User Chat\";\n\n\t/**\n\t * Parameter to set service discovery node name. In most cases you should\n\t * leave it empty unless you really know what you are doing.\n\t */\n\tpublic static final String DISCO_NODE_PROP_KEY = \"disco-node\";\n\n\t/** Field description */\n\tpublic static final String DISCO_NODE_PROP_VAL = \"\";\n\n\t/**\n\t * Parameter to set service discovery item type for the virtual component. You\n\t * should refer to a service discovery documentation for a correct type for\n\t * your component. Or, alternatively you can have a look what returns your\n\t * real component.\n\t */\n\tpublic static final String DISCO_TYPE_PROP_KEY = \"disco-type\";\n\n\t/** A default value for service discovery item type, which is 'text' */\n\tpublic static final String DISCO_TYPE_PROP_VAL = \"text\";\n\n\t/**\n\t * If set, then it is used as the component domain name part. This domains is\n\t * displayed on the service discovery information, instead of virtual host based on\n\t * the user's query.\n\t */\n\tpublic static final String FIXED_DOMAIN_PROP_KEY = \"fixed-domain\";\n\n\t/**\n\t * Virtual component parameter setting packet redirect destination address.\n\t */\n\tpublic static final String REDIRECT_TO_PROP_KEY = \"redirect-to\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.cluster.VirtualComponent\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprotected VHostManagerIfc vHostManager  = null;\n\tprivate JID               componentId   = null;\n\tprivate String            discoCategory = null;\n\tprivate String[]          discoFeatures = null;\n\tprivate String            discoName     = null;\n\tprivate String            discoNode     = null;\n\tprivate String            discoType     = null;\n\tprivate String            fixedDomain   = null;\n\tprivate String            name          = null;\n\tprivate JID               redirectTo    = null;\n\tprivate ServiceEntity     serviceEntity = null;\n\tprivate ComponentInfo     cmpInfo\t\t\t\t= null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean handlesLocalDomains() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean handlesNameSubdomains() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean handlesNonLocalDomains() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void initializationCompleted() {}\n\n\t@Override\n\tpublic void processPacket(Packet packet, Queue<Packet> results) {\n\t\tif (redirectTo != null) {\n\t\t\tpacket.setPacketTo(redirectTo);\n\t\t\tresults.add(packet);\n\t\t} else {\n\t\t\tlog.log(Level.INFO, \"No redirectTo address, dropping packet: {0}\", packet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void release() {}\n\n\t@Override\n\tpublic JID getComponentId() {\n\t\treturn componentId;\n\t}\n\n\t@Override\n\tpublic ComponentInfo getComponentInfo() {\n\t\tif ( cmpInfo == null ){\n\t\t\tcmpInfo = new ComponentInfo( getName(), this.getClass() );\n\t\t}\n\t\treturn cmpInfo;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = new LinkedHashMap<String, Object>();\n\n\t\tdefs.put(REDIRECT_TO_PROP_KEY, \"\");\n\t\tif (params.get(CLUSTER_NODES) != null) {\n\t\t\tString[] cl_nodes = ((String) params.get(CLUSTER_NODES)).split(\",\");\n\n\t\t\tfor (String node : cl_nodes) {\n\t\t\t\tif (!node.equals(DNSResolverFactory.getInstance().getDefaultHost())) {\n\t\t\t\t\tdefs.put(REDIRECT_TO_PROP_KEY, BareJID.toString(getName(), node));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdefs.put(DISCO_NAME_PROP_KEY, DISCO_NAME_PROP_VAL);\n\t\tdefs.put(DISCO_NODE_PROP_KEY, DISCO_NODE_PROP_VAL);\n\t\tdefs.put(DISCO_TYPE_PROP_KEY, DISCO_TYPE_PROP_VAL);\n\t\tdefs.put(DISCO_CATEGORY_PROP_KEY, DISCO_CATEGORY_PROP_VAL);\n\t\tdefs.put(DISCO_FEATURES_PROP_KEY, DISCO_FEATURES_PROP_VAL);\n\t\tdefs.put(FIXED_DOMAIN_PROP_KEY, null);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\t\tString domain = jid.toString();\n\n\t\tif (fixedDomain != null) {\n\t\t\tdomain = fixedDomain;\n\t\t}\n\n\t\tElement result = serviceEntity.getDiscoItem(null, getName() + \".\" + domain);\n\n\t\treturn Arrays.asList(result);\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic boolean isInitializationComplete() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tthis.name        = name;\n\t\tthis.componentId = JID.jidInstanceNS(name, DNSResolverFactory.getInstance().getDefaultHost(), null);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tfixedDomain = (String) properties.get(FIXED_DOMAIN_PROP_KEY);\n\t\tif (fixedDomain != null) {\n\t\t\tthis.componentId = JID.jidInstanceNS(null, name + \".\" + fixedDomain, null);\n\t\t}\n\n\t\tString redirect = (String) properties.get(REDIRECT_TO_PROP_KEY);\n\n\t\tif (redirect != null) {\n\t\t\tif (redirect.isEmpty()) {\n\t\t\t\tredirectTo = null;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tredirectTo = JID.jidInstance(redirect);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tredirectTo = null;\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"stringprep processing failed for given redirect address: {0}\", redirect);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (properties.get(DISCO_NAME_PROP_KEY) != null) {\n\t\t\tdiscoName = (String) properties.get(DISCO_NAME_PROP_KEY);\n\t\t}\n\t\tif (properties.get(DISCO_NODE_PROP_KEY) != null) {\n\t\t\tdiscoNode = (String) properties.get(DISCO_NODE_PROP_KEY);\n\t\t\tif (discoNode.isEmpty()) {\n\t\t\t\tdiscoNode = null;\n\t\t\t}\n\t\t}\n\t\tif (properties.get(DISCO_CATEGORY_PROP_KEY) != null) {\n\t\t\tdiscoCategory = (String) properties.get(DISCO_CATEGORY_PROP_KEY);\n\t\t}\n\t\tif (properties.get(DISCO_TYPE_PROP_KEY) != null) {\n\t\t\tdiscoType = (String) properties.get(DISCO_TYPE_PROP_KEY);\n\t\t}\n\t\tif (properties.get(DISCO_TYPE_PROP_KEY) != null) {\n\t\t\tdiscoFeatures = ((String) properties.get(DISCO_TYPE_PROP_KEY)).split(\",\");\n\t\t}\n\t\tif ((discoName != null) && (discoCategory != null) && (discoType != null) &&\n\t\t\t\t(discoFeatures != null)) {\n\t\t\tserviceEntity = new ServiceEntity(getName(), null, discoName);\n\t\t\tserviceEntity.addIdentities(new ServiceIdentity(discoCategory, discoType,\n\t\t\t\t\tdiscoName));\n\t\t\tfor (String feature : discoFeatures) {\n\t\t\t\tserviceEntity.addFeatures(feature);\n\t\t\t}\n\t\t}\n\t\tcmpInfo = new ComponentInfo( getName(), this.getClass() );\n\t}\n\n\t@Override\n\tpublic void setVHostManager(VHostManagerIfc manager) {\n\t\tthis.vHostManager = manager;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/WebSocketClientConnectionClustered.java",
    "content": "/*\n * WebSocketClientConnectionClustered.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\n\nimport tigase.server.ServiceChecker;\nimport tigase.server.websocket.WebSocketClientConnectionManager;\nimport tigase.server.xmppclient.SeeOtherHostIfc;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Describe class WebSocketClientConnectionClustered here.\n *\n *\n * Created: Sat Jun 21 22:23:18 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class WebSocketClientConnectionClustered\n\t\t\t\textends WebSocketClientConnectionManager\n\t\t\t\timplements ClusteredComponentIfc {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\n\t\t\tWebSocketClientConnectionClustered.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate SeeOtherHostIfc see_other_host_strategy = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void onNodeConnected(JID jid) {\n\t\tsuper.onNodeConnected(jid);\n\t\t\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onNodeDisconnected(JID jid) {\n\t\tsuper.onNodeDisconnected(jid);\n\n\t\tList<JID> connectedNodes = getNodesConnectedWithLocal();\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(connectedNodes);\n\t\t}\n\t\t\n\t\t// }\n\t\tfinal String hostname = jid.getDomain();\n\n\t\tdoForAllServices(new ServiceChecker<XMPPIOService<Object>>() {\n\t\t\t@Override\n\t\t\tpublic void check(XMPPIOService<Object> service) {\n\t\t\t\tJID dataReceiver = service.getDataReceiver();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Checking service for dataReceiver: {0}\", dataReceiver);\n\t\t\t\t}\n\t\t\t\tif ((dataReceiver != null) && dataReceiver.getDomain().equals(hostname)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Stopping service because corresponding cluster node stopped.\");\n\t\t\t\t\t}\n\t\t\t\t\tservice.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn super.getDiscoDescription() + \" clustered\";\n\t}\n\n\t@Override\n\tpublic SeeOtherHostIfc getSeeOtherHostInstance(String see_other_host_class) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Configuring see_other_host clustered strategy for: \" +\n\t\t\t\t\tsee_other_host_class);\n\t\t}\n\t\tif (see_other_host_class == null) {\n\t\t\tsee_other_host_class = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL_CLUSTER;\n\t\t}\n\t\tsee_other_host_strategy = super.getSeeOtherHostInstance(see_other_host_class);\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setNodes(getNodesConnectedWithLocal());\n\t\t}\n\n\t\treturn see_other_host_strategy;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusterCommandException.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.cluster.api;\n\n/**\n * @author Artur Hefczyc\n * Created Mar 16, 2011\n */\npublic class ClusterCommandException extends Exception {\n\n\t/**\n\t * \n\t */\n\tprivate static final long serialVersionUID = 1L;\n\n\t/**\n\t * \n\t */\n\tpublic ClusterCommandException() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * @param arg0\n\t */\n\tpublic ClusterCommandException(String arg0) {\n\t\tsuper(arg0);\n\t}\n\n\t/**\n\t * @param arg0\n\t */\n\tpublic ClusterCommandException(Throwable arg0) {\n\t\tsuper(arg0);\n\t}\n\n\t/**\n\t * @param arg0\n\t * @param arg1\n\t */\n\tpublic ClusterCommandException(String arg0, Throwable arg1) {\n\t\tsuper(arg0, arg1);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusterConnectionHandler.java",
    "content": "/*\n * ClusterConnectionHandler.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster.api;\n\nimport tigase.server.Packet;\n\n/**\n * ClusterConnectionHandler interface used by ClusterConnectionSelectorIfc\n * implementations to separate implementation from ClusterConnectionManager\n * \n * @author andrzej\n */\npublic interface ClusterConnectionHandler {\n\n\t/**\n\t * Generates hashCode for particular packet used to spread processing between\n\t * thread or connections\n\t * \n\t * @param packet\n\t * @return \n\t */\n\tint hashCodeForPacket(Packet packet);\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusterConnectionSelectorIfc.java",
    "content": "/*\n * ClusterConnectionSelectorIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster.api;\n\nimport java.util.Map;\nimport tigase.cluster.ClusterConnection;\nimport tigase.server.Packet;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n * Interface ClusterConnectionSelectorIfc is base interface for classes responsible\n * for selecting connection which should be used to send packet between cluster nodes\n * \n * @author andrzej\n */\npublic interface ClusterConnectionSelectorIfc {\n\t\n\t/**\n\t * Method returns XMPPIOService instances which should be used to\n\t * send packet between cluster nodes\n\t * \n\t * @param packet\n\t * @param conn\n\t * @return \n\t */\n\tXMPPIOService<Object> selectConnection(Packet packet, ClusterConnection conn);\n\t\n\tvoid setClusterConnectionHandler(ClusterConnectionHandler handler);\n\n\tvoid setProperties(Map<String,Object> props);\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusterControllerIfc.java",
    "content": "/*\n * ClusterControllerIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\n\n/**\n * @author Artur Hefczyc Created Mar 16, 2011\n */\npublic interface ClusterControllerIfc {\n\t/** Field description */\n\tpublic static final String DELIVER_CLUSTER_PACKET_CMD = \"deliver-cluster-packet-cmd\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet which should be handled\n\t */\n\tvoid handleClusterPacket(Element packet);\n\n\t/**\n\t * Method is called on cluster node connection event. This is a\n\t * notification to the component that a new cluster node has connected.\n\t *\n\t * @param addr\n\t *          is a hostname of a cluster node generating the event.\n\t */\n\tvoid nodeConnected(String addr);\n\n\t/**\n\t * Method is called on cluster node disconnection event. This is a\n\t * notification to the component that there was network connection lost to one\n\t * of the cluster nodes.\n\t *\n\t * @param addr\n\t *          is a hostname of a cluster node generating the event.\n\n\t */\n\tvoid nodeDisconnected(String addr);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param listener CommandListener object\n\t */\n\tvoid removeCommandListener(CommandListener listener);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param data additional data to be included in the packet\n\t * @param packets collection of elements to be send to desired nodes\n\t * @param fromNode address of the source node\n\t * @param visitedNodes list of all already visited nodes\n\t * @param toNodes list of nodes to which packet should be sent\n\t */\n\tvoid sendToNodes(String command, Map<String, String> data, Queue<Element> packets,\n\t\t\tJID fromNode, Set<JID> visitedNodes, JID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param packets collection of elements to be send to desired nodes\n\t * @param fromNode address of the source node\n\t * @param visitedNodes list of all already visited nodes\n\t * @param toNodes list of nodes to which packet should be sent\n\t *\n\t */\n\tvoid sendToNodes(String command, Queue<Element> packets, JID fromNode,\n\t\t\tSet<JID> visitedNodes, JID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param data additional data to be included in the packet\n\t * @param fromNode address of the source node\n\t * @param visitedNodes list of all already visited nodes\n\t * @param toNodes list of nodes to which packet should be sent\n\t *\n\t */\n\tvoid sendToNodes(String command, Map<String, String> data, JID fromNode,\n\t\t\tSet<JID> visitedNodes, JID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param data additional data to be included in the packet\n\t * @param fromNode address of the source node\n\t * @param toNodes list of nodes to which packet should be sent\n\t */\n\tvoid sendToNodes(String command, Map<String, String> data, JID fromNode,\n\t\t\tJID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param fromNode address of the source node\n\t * @param toNodes list of nodes to which packet should be sent\n\t */\n\tvoid sendToNodes(String command, JID fromNode, JID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param packet collection of elements to be send to desired nodes\n\t * @param fromNode address of the source node\n\t * @param visitedNodes list of all already visited nodes\n\t * @param toNodes list of nodes to which packet should be sent\n\t */\n\tvoid sendToNodes(String command, Element packet, JID fromNode, Set<JID> visitedNodes,\n\t\t\tJID... toNodes);\n\n\t/**\n\t * Method which sends command to desired nodes\n\t *\n\t * @param command ID string of the command\n\t * @param data additional data to be included in the packet\n\t * @param packet element to be send to desired nodes\n\t * @param fromNode address of the source node\n\t * @param visitedNodes list of all already visited nodes\n\t * @param toNodes list of nodes to which packet should be sent\n\t */\n\tvoid sendToNodes(String command, Map<String, String> data, Element packet,\n\t\t\tJID fromNode, Set<JID> visitedNodes, JID... toNodes);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param listener CommandListener object\n\t */\n\tvoid setCommandListener(CommandListener listener);\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusterElement.java",
    "content": "/*\n * ClusterElement.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport tigase.server.Priority;\n\n/**\n * Class ClusterElement is a utility class for handling tigase cluster specific\n * packets. The cluster packet has the following form:\n *\n * {@code\n * <cluster xmlns=\"tigase:cluster\" from=\"source\" to=\"dest\" type=\"set\">\n *   <data>\n *     <message xmlns=\"jabber:client\" from=\"source-u\" to=\"dest-x\" type=\"chat\">\n *       <body>Hello world!</body>\n *     </message>\n *   </data>\n *   <control>\n *     <first-node>node1 JID address</first-node>\n *     <visited-nodes>\n *       <node-id>node1 JID address</node-id>\n *       <node-id>node2 JID address</node-id>\n *     </visited-nodes>\n *     <method-call name=\"method name\">\n *       <par name=\"param1 name\">value</par>\n *       <par name=\"param2 name\">value</par>\n *       <results>\n *         <val name=\"val1 name\">value</var>\n *         <val name=\"val2 name\">value</var>\n *       </results>\n *     </method-call>\n *   </control>\n * </cluster>\n * }\n *\n * If none of nodes could process the packet it goes back to the first node as\n * this node is the most likely to process the packet correctly.\n *\n *\n * Created: Fri May 2 09:40:40 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ClusterElement {\n\t/** Field description */\n\tpublic static final String CLUSTER_CONTROL_EL_NAME = \"control\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_DATA_EL_NAME = \"data\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_EL_NAME = \"cluster\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_METHOD_EL_NAME = \"method-call\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_METHOD_PAR_EL_NAME = \"par\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_METHOD_RESULTS_EL_NAME = \"results\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_METHOD_RESULTS_VAL_EL_NAME = \"val\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_NAME_ATTR = \"name\";\n\n\t/** Field description */\n\tpublic static final String FIRST_NODE_EL_NAME = \"first-node\";\n\n\t/** Field description */\n\tpublic static final String NODE_ID_EL_NAME = \"node-id\";\n\n\t/** Field description */\n\tpublic static final String VISITED_NODES_EL_NAME = \"visited-nodes\";\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"tigase:cluster\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.cluster.ClusterElement\");\n\n\t/** Field description */\n\tpublic static final String[] VISITED_NODES_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_CONTROL_EL_NAME, VISITED_NODES_EL_NAME };\n\n\t// public static final String PACKET_FROM_ATTR_NAME = \"packet-from\";\n\n\t/** Field description */\n\tpublic static final String[] FIRST_NODE_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_CONTROL_EL_NAME, FIRST_NODE_EL_NAME };\n\n\t/** Field description */\n\tpublic static final String[] CLUSTER_METHOD_RESULTS_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_CONTROL_EL_NAME, CLUSTER_METHOD_EL_NAME,\n\t\t\t\t\tCLUSTER_METHOD_RESULTS_EL_NAME };\n\n\t/** Field description */\n\tpublic static final String[] CLUSTER_METHOD_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_CONTROL_EL_NAME, CLUSTER_METHOD_EL_NAME };\n\n\t/** Field description */\n\tpublic static final String[] CLUSTER_DATA_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_DATA_EL_NAME };\n\n\t/** Field description */\n\tpublic static final String[] CLUSTER_CONTROL_PATH = { CLUSTER_EL_NAME,\n\t\t\t\t\tCLUSTER_CONTROL_EL_NAME };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Element elem                       = null;\n\tprivate JID first_node                     = null;\n\tprivate String method_name                 = null;\n\tprivate Map<String, String> method_params  = null;\n\tprivate Map<String, String> method_results = null;\n\tprivate Queue<Element> packets             = null;\n\tprivate Priority priority\t\t\t\t   = null;\n\tprivate Set<JID> visited_nodes             = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>ClusterElement</code> instance.\n\t *\n\t *\n\t * @param elem\n\t */\n\tpublic ClusterElement(Element elem) {\n\t\tthis.elem = elem;\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Parsing cluster element: \" + elem.toString());\n\t\t}\n\n\t\tList<Element> children = elem.getChildrenStaticStr(CLUSTER_DATA_PATH);\n\n\t\tif ((children != null) && (children.size() > 0)) {\n\t\t\tpackets = new ArrayDeque<Element>(children);\n\t\t}\n\n\t\tString fNode = elem.getCDataStaticStr(FIRST_NODE_PATH);\n\n\t\tif (fNode != null) {\n\t\t\tfirst_node = JID.jidInstanceNS(fNode);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"First node found: \" + first_node);\n\t\t}\n\t\tvisited_nodes = new LinkedHashSet<JID>();\n\n\t\tList<Element> nodes = elem.getChildrenStaticStr(VISITED_NODES_PATH);\n\n\t\tif (nodes != null) {\n\t\t\tint cnt = 0;\n\n\t\t\tfor (Element node : nodes) {\n\t\t\t\tvisited_nodes.add(JID.jidInstanceNS(node.getCData()));\n\t\t\t\t++cnt;\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Found and added visited nodes: \" + cnt);\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"No visited nodes found\");\n\t\t\t}\n\t\t}\n\n\t\tString priorityStr = elem.getAttributeStaticStr(Packet.PRIORITY_ATT);\n\t\tif (priorityStr != null) {\n\t\t\tpriority = Priority.valueOf(priorityStr);\n\t\t}\n\t\t\n\t\tElement method_call = elem.findChildStaticStr(CLUSTER_METHOD_PATH);\n\n\t\tif (method_call != null) {\n\t\t\tparseMethodCall(method_call);\n\t\t}\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param from\n\t * @param to\n\t * @param type\n\t * @param packet\n\t */\n\tpublic ClusterElement(JID from, JID to, StanzaType type, Packet packet) {\n\t\tif (packet != null) {\n\t\t\tpackets       = new ArrayDeque<Element>();\n\t\t\tvisited_nodes = new LinkedHashSet<JID>();\n\t\t\telem          = createClusterElement(from, to, type, packet.getFrom().toString());\n\t\t\tif (packet.getElement().getXMLNS() == null) {\n\t\t\t\tpacket.getElement().setXMLNS(\"jabber:client\");\n\t\t\t}\n\t\t\taddDataPacket(packet);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t * @param to\n\t * @param type\n\t *\n\t * \n\t */\n\tpublic static Element clusterElement(JID from, JID to, StanzaType type) {\n\t\tElement cluster_el = new Element(CLUSTER_EL_NAME, new String[] { \"from\", \"to\",\n\t\t\t\t\t\t\"type\" }, new String[] { from.toString(), to.toString(), type.toString() });\n\n\t\tcluster_el.setXMLNS(XMLNS);\n\t\tcluster_el.addChild(new Element(CLUSTER_CONTROL_EL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Element[] { new Element(VISITED_NODES_EL_NAME) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull, null));\n\n\t\treturn cluster_el;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t * @param to\n\t * @param type\n\t * @param packet_from\n\t *\n\t * \n\t */\n\tpublic static Element createClusterElement(JID from, JID to, StanzaType type,\n\t\t\t\t\tString packet_from) {\n\t\tElement cluster_el = clusterElement(from, to, type);\n\n\t\tcluster_el.addChild(new Element(CLUSTER_DATA_EL_NAME));\n\n\t\t// new String[] {PACKET_FROM_ATTR_NAME}, new String[] {packet_from}));\n\t\treturn cluster_el;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t * @param to\n\t * @param type\n\t * @param method_name\n\t * @param params\n\t *\n\t * \n\t */\n\tpublic static ClusterElement createClusterMethodCall(JID from, JID to, StanzaType type,\n\t\t\t\t\tString method_name, Map<String, String> params) {\n\t\tElement cluster_el  = clusterElement(from, to, type);\n\t\tElement method_call = new Element(CLUSTER_METHOD_EL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { CLUSTER_NAME_ATTR },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { method_name });\n\n\t\tif (params != null) {\n\t\t\tfor (Map.Entry<String, String> entry : params.entrySet()) {\n\t\t\t\tmethod_call.addChild(new Element(CLUSTER_METHOD_PAR_EL_NAME, entry.getValue(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { CLUSTER_NAME_ATTR },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { entry.getKey() }));\n\t\t\t}\n\t\t}\n\t\tcluster_el.findChildStaticStr(CLUSTER_CONTROL_PATH).addChild(method_call);\n\n\t\tClusterElement result_cl = new ClusterElement(cluster_el);\n\n\t\tresult_cl.addVisitedNode(from);\n\n\t\treturn result_cl;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clel\n\t * @param cluster_nodes\n\t * @param comp_id\n\t *\n\t * \n\t */\n\tpublic static ClusterElement createForNextNode(ClusterElement clel,\n\t\t\t\t\tList<JID> cluster_nodes, JID comp_id) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Calculating a next node from nodes: \" + ((cluster_nodes != null)\n\t\t\t\t\t\t\t? cluster_nodes.toString()\n\t\t\t\t\t\t\t: \"null\"));\n\t\t}\n\t\tif ((cluster_nodes != null) && (cluster_nodes.size() > 0)) {\n\t\t\tJID next_node = null;\n\n\t\t\tfor (JID cluster_node : cluster_nodes) {\n\t\t\t\tif (!clel.isVisitedNode(cluster_node) &&!cluster_node.equals(comp_id)) {\n\t\t\t\t\tnext_node = cluster_node;\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Found next cluster node: \" + next_node);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (next_node != null) {\n\t\t\t\tClusterElement result = clel.nextClusterNode(next_node);\n\n\t\t\t\tresult.addVisitedNode(comp_id);\n\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void addDataPacket(Packet packet) {\n\t\taddDataPacket(packet.getElement());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void addDataPacket(Element packet) {\n\t\tif (packets == null) {\n\t\t\tpackets = new ArrayDeque<Element>();\n\t\t}\n\t\tpackets.offer(packet);\n\t\tif (elem.findChildStaticStr(CLUSTER_DATA_PATH) == null) {\n\t\t\telem.addChild(new Element(CLUSTER_DATA_EL_NAME));\n\t\t}\n\t\telem.findChildStaticStr(CLUSTER_DATA_PATH).addChild(packet);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packets\n\t */\n\tpublic void addDataPackets(Queue<Element> packets) {\n\t\tif (packets != null) {\n\t\t\tfor (Element elem : packets) {\n\t\t\t\taddDataPacket(elem);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t * @param val\n\t */\n\tpublic void addMethodResult(String key, String val) {\n\t\tElement res = elem.findChildStaticStr(CLUSTER_METHOD_RESULTS_PATH);\n\n\t\tif (res == null) {\n\t\t\tres = new Element(CLUSTER_METHOD_RESULTS_EL_NAME);\n\t\t\telem.findChildStaticStr(CLUSTER_METHOD_PATH).addChild(res);\n\t\t}\n\t\tres.addChild(new Element(CLUSTER_METHOD_RESULTS_VAL_EL_NAME, val,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { CLUSTER_NAME_ATTR }, new String[] { key }));\n\t\tif (method_results == null) {\n\t\t\tmethod_results = new LinkedHashMap<String, String>();\n\t\t}\n\t\tmethod_results.put(key, val);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node_id\n\t */\n\tpublic void addVisitedNode(JID node_id) {\n\t\tif (visited_nodes.size() == 0) {\n\t\t\tfirst_node = node_id;\n\t\t\telem.findChildStaticStr(CLUSTER_CONTROL_PATH).addChild(\n\t\t\t\t\tnew Element(FIRST_NODE_EL_NAME, node_id.toString()));\n\t\t}\n\t\tif (visited_nodes.add(node_id)) {\n\t\t\telem.findChildStaticStr(VISITED_NODES_PATH).addChild(new Element(NODE_ID_EL_NAME,\n\t\t\t\t\t\t\tnode_id.toString()));\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param nodes\n\t */\n\tpublic void addVisitedNodes(Set<JID> nodes) {\n\t\tif (nodes != null) {\n\t\t\tfor (JID node : nodes) {\n\t\t\t\taddVisitedNode(node);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t * @param type\n\t * @param results\n\t *\n\t * \n\t */\n\tpublic ClusterElement createMethodResponse(JID from, StanzaType type,\n\t\t\t\t\tMap<String, String> results) {\n\t\treturn createMethodResponse(from, null, type, results);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t * @param to\n\t * @param type\n\t * @param results\n\t *\n\t * \n\t */\n\tpublic ClusterElement createMethodResponse(JID from, JID to, StanzaType type,\n\t\t\t\t\tMap<String, String> results) {\n\t\tElement result_el = elem.clone();\n\n\t\tresult_el.setAttribute(\"from\", from.toString());\n\t\tresult_el.setAttribute(\"to\", ((to != null)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? to.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: first_node.toString()));\n\t\tresult_el.setAttribute(\"type\", type.name());\n\n\t\tElement res = new Element(CLUSTER_METHOD_RESULTS_EL_NAME);\n\n\t\tresult_el.findChildStaticStr(CLUSTER_METHOD_PATH).addChild(res);\n\n\t\tClusterElement result_cl = new ClusterElement(result_el);\n\n\t\tif (results != null) {\n\t\t\tfor (Map.Entry<String, String> entry : results.entrySet()) {\n\t\t\t\tresult_cl.addMethodResult(entry.getKey(), entry.getValue());\n\t\t\t}\n\t\t}\n\n\t\treturn result_cl;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Map<String, String> getAllMethodParams() {\n\t\treturn method_params;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Map<String, String> getAllMethodResults() {\n\t\treturn method_results;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param id\n\t * \n\t */\n\tpublic Element getClusterElement(String id) {\n\t\telem.setAttribute(\"id\", id);\n\n\t\treturn elem;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Queue<Element> getDataPackets() {\n\t\treturn packets;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic JID getFirstNode() {\n\t\treturn first_node;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getMethodName() {\n\t\treturn method_name;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param par_name\n\t *\n\t * \n\t */\n\tpublic String getMethodParam(String par_name) {\n\t\treturn (method_params == null)\n\t\t\t\t\t ? null\n\t\t\t\t\t : method_params.get(par_name);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param par_name\n\t * @param def\n\t *\n\t * \n\t */\n\tpublic long getMethodParam(String par_name, long def) {\n\t\tString val_str = getMethodParam(par_name);\n\n\t\tif (val_str == null) {\n\t\t\treturn def;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\treturn Long.parseLong(val_str);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\treturn def;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param val_name\n\t *\n\t * \n\t */\n\tpublic String getMethodResultVal(String val_name) {\n\t\treturn (method_results == null)\n\t\t\t\t\t ? null\n\t\t\t\t\t : method_results.get(val_name);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param val_name\n\t * @param def\n\t *\n\t * \n\t */\n\tpublic long getMethodResultVal(String val_name, long def) {\n\t\tString val_str = getMethodResultVal(val_name);\n\n\t\tif (val_str == null) {\n\t\t\treturn def;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\treturn Long.parseLong(val_str);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\treturn def;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic Priority getPriority() {\n\t\treturn priority;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Set<JID> getVisitedNodes() {\n\t\treturn visited_nodes;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node_id\n\t *\n\t * \n\t */\n\tpublic boolean isVisitedNode(JID node_id) {\n\t\treturn visited_nodes.contains(node_id);\n\t}\n\n\tpublic void setPriority(Priority priority) {\n\t\tthis.priority = priority;\n\t\tthis.elem.setAttribute(Packet.PRIORITY_ATT, priority.name());\n\t}\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node_id\n\t *\n\t * \n\t */\n\tpublic ClusterElement nextClusterNode(JID node_id) {\n\t\tElement next_el = elem.clone();\n\t\tString from     = elem.getAttributeStaticStr(Packet.TO_ATT);\n\n\t\tnext_el.setAttribute(\"from\", from);\n\t\tnext_el.setAttribute(\"to\", node_id.toString());\n\n\t\t// next_el.setAttribute(\"type\", StanzaType.set.toString());\n\t\tClusterElement next_cl = new ClusterElement(next_el);\n\n\t\treturn next_cl;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param method_call\n\t */\n\tprotected void parseMethodCall(Element method_call) {\n\t\tmethod_name = method_call.getAttributeStaticStr(CLUSTER_NAME_ATTR);\n\t\tif (method_name != null) {\n\t\t\tmethod_name = method_name.intern();\n\t\t}\n\t\tmethod_params = new LinkedHashMap<String, String>();\n\n\t\tList<Element> children = method_call.getChildren();\n\n\t\tif (children != null) {\n\t\t\tfor (Element child : children) {\n\t\t\t\tif (child.getName() == CLUSTER_METHOD_PAR_EL_NAME) {\n\t\t\t\t\tString par_name = child.getAttributeStaticStr(CLUSTER_NAME_ATTR);\n\n\t\t\t\t\tmethod_params.put(par_name, child.getCData());\n\t\t\t\t}\n\t\t\t\tif (child.getName() == CLUSTER_METHOD_RESULTS_EL_NAME) {\n\t\t\t\t\tif (method_results == null) {\n\t\t\t\t\t\tmethod_results = new LinkedHashMap<String, String>();\n\t\t\t\t\t}\n\n\t\t\t\t\tList<Element> res_children = child.getChildren();\n\n\t\t\t\t\tif (res_children != null) {\n\t\t\t\t\t\tfor (Element res_child : res_children) {\n\t\t\t\t\t\t\tif (res_child.getName() == CLUSTER_METHOD_RESULTS_VAL_EL_NAME) {\n\t\t\t\t\t\t\t\tString val_name = res_child.getAttributeStaticStr(CLUSTER_NAME_ATTR);\n\n\t\t\t\t\t\t\t\tmethod_results.put(val_name, res_child.getCData());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/ClusteredComponentIfc.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.cluster.api;\n\nimport tigase.server.ServerComponent;\n\n/**\n * Describe interface ClusteredComponent here.\n *\n *\n * Created: Mon Jun  9 20:00:46 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ClusteredComponentIfc extends ServerComponent {\n\t\n\t/**\n\t * Set's the configures the cluster controller object for cluster\n\t * communication and API.\n\t *\n\t * @param cl_controller cluster controller object used for cluster\n\t *                      communication\n\t */\n\tvoid setClusterController(ClusterControllerIfc cl_controller);\n\n\t/**\n\t * Method is called on cluster node connection event. This is a\n\t * notification to the component that a new cluster node has connected.\n\t *\n\t * @param node\n\t *          is a hostname of a cluster node generating the event.\n\t */\n\tvoid nodeConnected(String node);\n\n\t/**\n\t * Method is called on cluster node disconnection event. This is a\n\t * notification to the component that there was network connection lost to one\n\t * of the cluster nodes.\n\t *\n\t * @param node\n\t *          is a hostname of a cluster node generating the event.\n\t */\n\tvoid nodeDisconnected(String node);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/CommandListener.java",
    "content": "/*\n * CommandListener.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport tigase.server.Priority;\n\n/**\n * @author Artur Hefczyc Created Mar 16, 2011\n */\npublic interface CommandListener\n\t\t\t\textends Comparable<CommandListener> {\n\t/**\n\t * Method is responsible for executing commands from other nodes and\n\t * appropriate processing\n\t *\n\t * @param fromNode     address of the node from which command was received\n\t * @param visitedNodes collection of already visited nodes\n\t * @param data         additional data associated with the command in addition\n\t *                     to the main {@link Element}\n\t * @param packets      collection of {@link Element} commands to be executed\n\t *\n\t * @throws ClusterCommandException execution exception\n\t */\n\tvoid executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String, String> data,\n\t\t\tQueue<Element> packets)\n\t\t\t\t\tthrows ClusterCommandException;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method allows retrieval name of the particular command\n\t *\n\t * @return a value of <code>String</code> name of the command\n\t */\n\tString getName();\n\n\t/**\n\t * Method returns priority of particular command which should be used \n\t * to assign proper priority for processing of this command\n\t * \n\t * @return \n\t */\n\tPriority getPriority();\n\t\n\t/**\n\t * Method allows retrieval possible statistics for particular command\n\t *\n\t * @param list collection to which statistics should be appended\n\t */\n\tvoid getStatistics(StatisticsList list);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method allows setting name of the command\n\t *\n\t * @param name to be used\n\t */\n\tvoid setName(String name);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/CommandListenerAbstract.java",
    "content": "/*\n * CommandListenerAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport static tigase.cluster.strategy.ClusteringStrategyIfc.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport tigase.server.Priority;\n\n/**\n *\n * @author kobit\n */\npublic abstract class CommandListenerAbstract\n\t\t\t\timplements CommandListener {\n\tprivate static long syncInTraffic  = 0;\n\tprivate static long syncOutTraffic = 0;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String commandName;\n\tprivate Priority priority;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param name\n\t */\n\tpublic CommandListenerAbstract(String name, Priority priority) {\n\t\tsetName(name);\n\t\tsetPriority(priority);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int compareTo(CommandListener cl) {\n\t\treturn commandName.compareTo(cl.getName());\n\t}\n\n\t@Override\n\tpublic boolean equals(Object cl) {\n\t\treturn ((cl != null) && (cl instanceof CommandListener) && commandName.equals(\n\t\t\t\t((CommandListener) cl).getName()));\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tint hash = 265;\n\n\t\thash = hash + ((this.commandName != null)\n\t\t\t\t? this.commandName.hashCode()\n\t\t\t\t: 0);\n\n\t\treturn hash;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic synchronized void incSyncInTraffic() {\n\t\t++syncInTraffic;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic synchronized void incSyncOutTraffic() {\n\t\t++syncOutTraffic;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn commandName;\n\t}\n\n\t@Override\n\tpublic Priority getPriority() {\n\t\treturn priority;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic static long getSyncInTraffic() {\n\t\treturn syncInTraffic;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic static long getSyncOutTraffic() {\n\t\treturn syncOutTraffic;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic final void setName(String name) {\n\t\tcommandName = name;\n\t}\n\n\tpublic void setPriority(Priority priority) {\n\t\tthis.priority = priority;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/api/SessionManagerClusteredIfc.java",
    "content": "/*\n * SessionManagerClusteredIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.List;\nimport tigase.server.Packet;\nimport tigase.server.xmppsession.SessionManagerHandler;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n *\n * @author kobit\n */\npublic interface SessionManagerClusteredIfc\n\t\t\t\textends SessionManagerHandler {\n\t/** Field description */\n\tpublic static final String SESSION_FOUND_KEY = \"user-session-found-key\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tboolean fastAddOutPacket(Packet packet);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param el_packet\n\t * @param conn\n\t */\n\tvoid processPacket(Packet el_packet, XMPPResourceConnection conn);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session is a <code>XMPPSession</code>\n\t * @param element is a <code>Element</code>\n\t */\n\tvoid processPresenceUpdate(XMPPSession session, Element element);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param el_packet\n\t *\n\t *\n\t *\n\t * @return a value of <code>XMPPResourceConnection</code>\n\t */\n\tXMPPResourceConnection getXMPPResourceConnection(Packet el_packet);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code ConcurrentHashMap<JID,XMPPResourceConnection>}\n\t */\n\tConcurrentHashMap<JID, XMPPResourceConnection> getXMPPResourceConnections();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code ConcurrentHashMap<BareJID,XMPPSession>}\n\t */\n\tConcurrentHashMap<BareJID, XMPPSession> getXMPPSessions();\n\t\n\t/**\n\t * Method to check if there is XMPPResourceConnection instance for \n\t * connection JID.\n\t * \n\t * @param connJid\n\t * @return true - if there is XMPPResourceConnection for connection JID\n\t */\n\tboolean hasXMPPResourceConnectionForConnectionJid(JID connJid);\n\n\tJID getComponentId();\n\n\tList<JID> getNodesConnected();\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClConConfigRepository.java",
    "content": "/*\n * ClConConfigRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.repo;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.DBInitException;\nimport tigase.db.comp.ConfigRepository;\n\nimport tigase.sys.ShutdownHook;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.DNSResolverFactory;\n\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class description\n *\n *\n * @version        5.2.0, 13/03/09\n * @author         <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class ClConConfigRepository\n\t\textends ConfigRepository<ClusterRepoItem>\n\t\timplements ShutdownHook {\n\n\tprivate static final Logger log = Logger.getLogger(ClConConfigRepository.class.getName());\n\n\t/** Field description */\n\tpublic static final String AUTORELOAD_INTERVAL_PROP_KEY = \"repo-autoreload-interval\";\n\tpublic static final String AUTO_REMOVE_OBSOLETE_ITEMS_PROP_KEY = \"repo-auto-remove-obsolete-items\";\n\n\t/** Field description */\n\tpublic static final long AUTORELOAD_INTERVAL_PROP_VAL = 15;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprotected long autoreload_interval = AUTORELOAD_INTERVAL_PROP_VAL;\n\tprotected boolean auto_remove_obsolete_items = true;\n\tprotected long lastReloadTime = 0;\n\tprotected long lastReloadTimeFactor = 10;\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getDefaultPropetyItems() {\n\t\treturn ClConRepoDefaults.getDefaultPropetyItems();\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Cluster repository clean-up\";\n\t}\n\n\t@Override\n\tpublic String getPropertyKey() {\n\t\treturn ClConRepoDefaults.getPropertyKey();\n\t}\n\n\t@Override\n\tpublic String getConfigKey() {\n\t\treturn ClConRepoDefaults.getConfigKey();\n\t}\n\n\t@Override\n\tpublic ClusterRepoItem getItemInstance() {\n\t\treturn ClConRepoDefaults.getItemInstance();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do\n\t}\n\t\n\t@Override\n\tpublic void reload() {\n\t\tsuper.reload();\n\n\t\tString          host = DNSResolverFactory.getInstance().getDefaultHost();\n\t\tClusterRepoItem item = getItem(host);\n\t\ttry {\n\t\t\titem = ( item != null ) ? (ClusterRepoItem)(item.clone()) : null;\n\t\t} catch ( CloneNotSupportedException ex ) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.SEVERE, \"Clonning of ClusterRepoItem has failed\", ex );\n\t\t\t}\n\t\t}\n\n\t\tif (item == null) {\n\t\t\titem = getItemInstance();\n\t\t\titem.setHostname(host);\n\t\t}\n\t\titem.setSecondaryHostname( DNSResolverFactory.getInstance().getSecondaryHost() );\n\t\titem.setLastUpdate(System.currentTimeMillis());\n\t\titem.setCpuUsage(TigaseRuntime.getTigaseRuntime().getCPUUsage());\n\t\titem.setMemUsage(TigaseRuntime.getTigaseRuntime().getHeapMemUsage());\n\t\tstoreItem(item);\n\n\n\t\tif (auto_remove_obsolete_items) {\n\t\t\tIterator<ClusterRepoItem> iterator = iterator();\n\t\t\twhile(iterator.hasNext()) {\n\t\t\t\tClusterRepoItem next = iterator.next();\n\t\t\t\tif ( ( next.getLastUpdate() > 0 ) && System.currentTimeMillis() - next.getLastUpdate() > 5000 * autoreload_interval ){\n\t\t\t\t\tremoveItem( next.getHostname() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic void itemLoaded(ClusterRepoItem item) {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Item loaded: {0}\", item );\n\t\t}\n\t\tif (System.currentTimeMillis() - item.getLastUpdate() <= 5000 * autoreload_interval && clusterRecordValid(item)) {\n\t\t\taddItem(item);\n\t\t} else {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t \"Removing stale item: {0}; current time: {1}, last update: {2} ({3}), diff: {4}, autoreload {5}\",\n\t\t\t\t\t\t\t\t new Object[] { item, System.currentTimeMillis(), item.getLastUpdate(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Date( item.getLastUpdate() ), System.currentTimeMillis() - item.getLastUpdate(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t5000 * autoreload_interval } );\n\t\t\t}\n\t\t\tif ( auto_remove_obsolete_items ){\n\t\t\t\tremoveItem( item.getHostname() );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean itemChanged(ClusterRepoItem oldItem, ClusterRepoItem newItem) {\n\t\treturn !oldItem.getPassword().equals( newItem.getPassword() )\n\t\t\t\t\t || ( oldItem.getPortNo() != newItem.getPortNo() )\n\t\t\t\t\t || !Objects.equals( oldItem.getSecondaryHostname(), newItem.getSecondaryHostname() );\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tsuper.getDefaults(defs, params);\n\t\tdefs.put(AUTORELOAD_INTERVAL_PROP_KEY, AUTORELOAD_INTERVAL_PROP_VAL);\n\t\tdefs.put(AUTO_REMOVE_OBSOLETE_ITEMS_PROP_KEY, true);\n\n\t\tString[] items_arr = (String[]) defs.get(getConfigKey());\n\n\t\tfor (String it : items_arr) {\n\t\t\tClusterRepoItem item = getItemInstance();\n\n\t\t\titem.initFromPropertyString(it);\n\t\t\taddItem(item);\n\t\t}\n\t\tif (getItem(DNSResolverFactory.getInstance().getDefaultHost()) == null) {\n\t\t\tClusterRepoItem item = getItemInstance();\n\n\t\t\titem.initFromPropertyString(DNSResolverFactory.getInstance().getDefaultHost());\n\t\t\taddItem(item);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) {\n\t\tsuper.setProperties(props);\n\t\tautoreload_interval = (Long) props.get(AUTORELOAD_INTERVAL_PROP_KEY);\n\t\tauto_remove_obsolete_items = (boolean) props.get(AUTO_REMOVE_OBSOLETE_ITEMS_PROP_KEY);\n\n\t\tsetAutoloadTimer(autoreload_interval);\n\t\tTigaseRuntime.getTigaseRuntime().addShutdownHook(this);\n\t}\n\n\t@Override\n\tpublic String shutdown() {\n\t\tString host = DNSResolverFactory.getInstance().getDefaultHost();\n\t\tremoveItem( host );\n\t\treturn \"== \" + \"Removing cluster_nodes item: \" + host + \"\\n\";\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic void storeItem(ClusterRepoItem item) {}\n\n\tprivate boolean clusterRecordValid( ClusterRepoItem item ) {\n\n\t\t// we ignore faulty addresses\n\t\tboolean isCorrect = !item.getHostname().equalsIgnoreCase( \"localhost\" );\n\n\t\tif ( !isCorrect && log.isLoggable( Level.FINE ) ){\n\t\t\tlog.log( Level.FINE, \"Incorrect entry in cluster table, skipping: {0}\", item );\n\t\t}\n\t\treturn isCorrect;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClConDirRepository.java",
    "content": "/*\n * ClConDirRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.repo;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.DBInitException;\nimport tigase.db.Repository;\n\n/**\n *\n * @author kobit\n */\n@Repository.Meta( supportedUris = { \"file://.*\" } )\npublic class ClConDirRepository\n\t\t\t\textends ClConConfigRepository\n\t\t\t\timplements ClusterRepoConstants {\n\t/** Field description */\n\tpublic static final String REPO_FILE_EXTENSION = \".rep\";\n\n\t/** Field description */\n\tpublic static final String REPO_URI_DB_DEF_VAL = \"etc/\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ClConDirRepository.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate File      repo_dir  = new File(REPO_URI_DB_DEF_VAL);\n\tprivate DirFilter dirFilter = new DirFilter();\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do here\n\t\tsuper.destroy();\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tsuper.getDefaults(defs, params);\n\t\tdefs.put(REPO_URI_PROP_KEY, REPO_URI_DB_DEF_VAL);\n\t}\n\n\t@Override\n\tpublic void initRepository(String conn_str, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do here\n\t\tsuper.initRepository(conn_str, params);\n\t}\n\t\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tsuper.setProperties(properties);\n\t\trepo_dir = new File((String) properties.get(REPO_URI_PROP_KEY));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void storeItem(ClusterRepoItem item) {\n\t\ttry {\n\t\t\tFile           file = new File(repo_dir, item.getHostname() + REPO_FILE_EXTENSION);\n\t\t\tBufferedWriter bw   = new BufferedWriter(new FileWriter(file, false));\n\n\t\t\tbw.write(item.toPropertyString());\n\t\t\tbw.newLine();\n\t\t\tbw.close();\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void reload() {\n\t\tsuper.reload();\n\t\ttry {\n\t\t\tFile[] files = repo_dir.listFiles(dirFilter);\n\n\t\t\tfor (File file : files) {\n\t\t\t\tBufferedReader br   = new BufferedReader(new FileReader(file));\n\t\t\t\tString         data = br.readLine();\n\n\t\t\t\tbr.close();\n\n\t\t\t\tClusterRepoItem item = getItemInstance();\n\n\t\t\t\titem.initFromPropertyString(data);\n\t\t\t\titemLoaded(item);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class DirFilter\n\t\t\t\t\timplements FileFilter {\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * @param file\n\t\t *\n\t\t * \n\t\t */\n\t\t@Override\n\t\tpublic boolean accept(File file) {\n\t\t\treturn file.isFile() && file.getName().endsWith(REPO_FILE_EXTENSION);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/11\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClConRepoDefaults.java",
    "content": "/*\n * ClConRepoDefaults.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.repo;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.DNSResolverFactory;\n\n/**\n * Class description\n *\n *\n * @version        5.2.0, 13/03/09\n * @author         <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic abstract class ClConRepoDefaults {\n\tprivate static final BareJID clcon_user = BareJID.bareJIDInstanceNS(\"cl-conn-manager\");\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tstatic String[] getDefaultPropetyItems() {\n\t\treturn new String[] { DNSResolverFactory.getInstance().getDefaultHost()};\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tstatic String getPropertyKey() {\n\t\treturn \"--cluster-nodes\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tstatic String getConfigKey() {\n\t\treturn \"cluster-nodes\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tstatic ClusterRepoItem getItemInstance() {\n\t\treturn new ClusterRepoItem();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static BareJID getRepoUser() {\n\t\treturn clcon_user;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClConSQLRepository.java",
    "content": "/*\n * ClConSQLRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.repo;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Timestamp;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class description\n *\n *\n * @version        5.2.0, 13/03/09\n * @author         <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\n@Repository.Meta( supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class ClConSQLRepository\n\t\t\t\textends ClConConfigRepository\n\t\t\t\timplements ClusterRepoConstants {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ClConSQLRepository.class.getName());\n\t//J-\n\t/* @formatter:off */\n\tprivate static final String GET_ITEM_QUERY =\n\t\t\t\t\t\"select \"\n\t\t\t\t\t+ HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ SECONDARY_HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ PASSWORD_COLUMN + \", \"\n\t\t\t\t\t+ LASTUPDATE_COLUMN + \", \"\n\t\t\t\t\t+ PORT_COLUMN + \", \"\n\t\t\t\t\t+ CPU_USAGE_COLUMN + \", \"\n\t\t\t\t\t+ MEM_USAGE_COLUMN\n\t\t\t\t\t+ \" from \" + TABLE_NAME + \" where \" + HOSTNAME_COLUMN + \" = ?\";\n\tprivate static final String GET_ALL_ITEMS_QUERY =\n\t\t\t\t\t\"select \"\n\t\t\t\t\t+ HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ SECONDARY_HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ PASSWORD_COLUMN + \", \"\n\t\t\t\t\t+ LASTUPDATE_COLUMN + \", \"\n\t\t\t\t\t+ PORT_COLUMN + \", \"\n\t\t\t\t\t+ CPU_USAGE_COLUMN + \", \"\n\t\t\t\t\t+ MEM_USAGE_COLUMN\n\t\t\t\t\t+ \" from \" + TABLE_NAME;\n\tprivate static final String DELETE_ITEM_QUERY =\n\t\t\t\t\t\"delete from \" + TABLE_NAME + \" where (\" + HOSTNAME_COLUMN + \" = ?)\";\n\tprivate static final String CREATE_TABLE_QUERY_MYSQL =\n\t\t\t\t\t\"create table \" + TABLE_NAME + \" (\"\n\t\t\t\t\t+ \"  \" + HOSTNAME_COLUMN + \" varchar(255) not null,\"\n\t\t\t\t\t+ \"  \" + SECONDARY_HOSTNAME_COLUMN + \" varchar(255),\"\n\t\t\t\t\t+ \"  \" + PASSWORD_COLUMN + \" varchar(255) not null,\"\n\t\t\t\t\t+ \"  \" + LASTUPDATE_COLUMN\n\t\t\t\t\t+ \" TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\"\n\t\t\t\t\t+ \"  \" + PORT_COLUMN + \" int,\"\n\t\t\t\t\t+ \"  \" + CPU_USAGE_COLUMN + \" double precision unsigned not null,\"\n\t\t\t\t\t+ \"  \" + MEM_USAGE_COLUMN + \" double precision unsigned not null,\"\n\t\t\t\t\t+ \"  primary key(\" + HOSTNAME_COLUMN + \"))\"\n\t\t\t\t\t+ \" ENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC\";\n\tprivate static final String CREATE_TABLE_QUERY =\n\t\t\t\t\t\"create table \" + TABLE_NAME + \" (\"\n\t\t\t\t\t+ \"  \" + HOSTNAME_COLUMN + \" varchar(512) not null,\"\n\t\t\t\t\t+ \"  \" + SECONDARY_HOSTNAME_COLUMN + \" varchar(512),\"\n\t\t\t\t\t+ \"  \" + PASSWORD_COLUMN + \" varchar(255) not null,\"\n\t\t\t\t\t+ \"  \" + LASTUPDATE_COLUMN\n\t\t\t\t\t+ \" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\"\n\t\t\t\t\t+ \"  \" + PORT_COLUMN + \" int,\"\n\t\t\t\t\t+ \"  \" + CPU_USAGE_COLUMN + \" double precision not null,\"\n\t\t\t\t\t+ \"  \" + MEM_USAGE_COLUMN + \" double precision not null,\"\n\t\t\t\t\t+ \"  primary key(\" + HOSTNAME_COLUMN + \"))\";\n\tprivate static final String CREATE_TABLE_QUERY_SQLSERVER =\n\t\t\t\t\t\"create table [dbo].[\" + TABLE_NAME + \"] (\"\n\t\t\t\t\t+ \"  \" + HOSTNAME_COLUMN + \" nvarchar(512) not null,\"\n\t\t\t\t\t+ \"  \" + SECONDARY_HOSTNAME_COLUMN + \" nvarchar(512),\"\n\t\t\t\t\t+ \"  \" + PASSWORD_COLUMN + \" nvarchar(255) not null,\"\n\t\t\t\t\t+ \"  \" + LASTUPDATE_COLUMN\n\t\t\t\t\t+ \" [datetime] NULL,\"\n\t\t\t\t\t+ \"  \" + PORT_COLUMN + \" int,\"\n\t\t\t\t\t+ \"  \" + CPU_USAGE_COLUMN + \" double precision not null,\"\n\t\t\t\t\t+ \"  \" + MEM_USAGE_COLUMN + \" double precision not null,\"\n\t\t\t\t\t+ \" CONSTRAINT [PK_\" + TABLE_NAME + \"] PRIMARY KEY CLUSTERED ( [\" + HOSTNAME_COLUMN + \"] ASC ) ON [PRIMARY], \"\n\t\t\t\t\t+ \" CONSTRAINT [IX_\" + TABLE_NAME + \"_\" + HOSTNAME_COLUMN + \"] UNIQUE NONCLUSTERED ( [\" + HOSTNAME_COLUMN + \"] ASC ) ON [PRIMARY] \"\n\t\t\t\t\t+ \") ON [PRIMARY]\"\n\t\t\t\t\t+ \"ALTER TABLE [dbo].[\" + TABLE_NAME + \"] ADD  CONSTRAINT \"\n\t\t\t\t\t+ \"[DF_\" + TABLE_NAME + \"_\" + LASTUPDATE_COLUMN + \"]  DEFAULT (getdate()) FOR [\" + LASTUPDATE_COLUMN + \"] \";\n\tprivate static final String INSERT_ITEM_QUERY =\n\t\t\t\t\t\"insert into \" + TABLE_NAME + \" (\"\n\t\t\t\t\t+ HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ SECONDARY_HOSTNAME_COLUMN + \", \"\n\t\t\t\t\t+ PASSWORD_COLUMN + \", \"\n\t\t\t\t\t+ LASTUPDATE_COLUMN + \", \"\n\t\t\t\t\t+ PORT_COLUMN + \", \"\n\t\t\t\t\t+ CPU_USAGE_COLUMN + \", \"\n\t\t\t\t\t+ MEM_USAGE_COLUMN\n\t\t\t\t\t+ \") \"\n\t\t\t\t\t+ \" (select ?, ?, ?, ?, ?, ?, ? from \" + TABLE_NAME\n\t\t\t\t\t+ \" WHERE \" + HOSTNAME_COLUMN + \"=? HAVING count(*)=0)\";\n\tprivate static final String UPDATE_ITEM_QUERY =\n\t\t\t\t\t\"update \" + TABLE_NAME + \" set \"\n\t\t\t\t\t+ HOSTNAME_COLUMN + \"= ?, \"\n\t\t\t\t\t+ SECONDARY_HOSTNAME_COLUMN + \"= ?, \"\n\t\t\t\t\t+ PASSWORD_COLUMN + \"= ?, \"\n\t\t\t\t\t+ LASTUPDATE_COLUMN + \" = ?,\"\n\t\t\t\t\t+ PORT_COLUMN + \"= ?, \"\n\t\t\t\t\t+ CPU_USAGE_COLUMN + \"= ?, \"\n\t\t\t\t\t+ MEM_USAGE_COLUMN + \"= ? \"\n\t\t\t\t\t+ \" where \" + HOSTNAME_COLUMN + \"= ?\"\t;\n\t/* @formatter:on */\n\t//J+\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\n\t@Override\n\tpublic void destroy() {\n\t\t// This implementation of ClConConfigRepository is using shared connection\n\t\t// pool to database which is cached by RepositoryFactory and maybe be used\n\t\t// in other places, so we can not destroy it.\n\t\tsuper.destroy();\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tsuper.getDefaults(defs, params);\n\n\t\tString repo_uri = RepositoryFactory.DERBY_REPO_URL_PROP_VAL;\n\n\t\tif (params.get(RepositoryFactory.GEN_USER_DB_URI) != null) {\n\t\t\trepo_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t}\n\t\tdefs.put(REPO_URI_PROP_KEY, repo_uri);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String conn_str, Map<String, String> params)\n\t\t\t\t\tthrows DBInitException {\n\t\tsuper.initRepository(conn_str, params);\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, params);\n\t\t\tcheckDB();\n\n\t\t\t// data_repo.initPreparedStatement(CHECK_TABLE_QUERY, CHECK_TABLE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_ITEM_QUERY, GET_ITEM_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_ALL_ITEMS_QUERY, GET_ALL_ITEMS_QUERY);\n\t\t\tdata_repo.initPreparedStatement(INSERT_ITEM_QUERY, INSERT_ITEM_QUERY);\n\t\t\tdata_repo.initPreparedStatement(UPDATE_ITEM_QUERY, UPDATE_ITEM_QUERY);\n\t\t\tdata_repo.initPreparedStatement(DELETE_ITEM_QUERY, DELETE_ITEM_QUERY);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem initializing database: \", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeItem( String key ) {\n\t\tsuper.removeItem( key );\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Removing item form database: {0}\", key );\n\t\t}\n\t\ttry {\n\t\t\tPreparedStatement removeItem = data_repo.getPreparedStatement( null, DELETE_ITEM_QUERY );\n\t\t\tsynchronized ( removeItem ) {\n\t\t\t\tremoveItem.setString( 1, key );\n\t\t\t\tremoveItem.executeUpdate();\n\t\t\t}\n\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem removing elements from DB: \", e);\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void storeItem(ClusterRepoItem item) {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Storing item to repository: {0}\", item );\n\t\t}\n\t\ttry {\n\t\t\tPreparedStatement updateItemSt = data_repo.getPreparedStatement(null,\tUPDATE_ITEM_QUERY);\n\t\t\tPreparedStatement insertItemSt = data_repo.getPreparedStatement(null, INSERT_ITEM_QUERY);\n\n\t\t\t// relatively most DB compliant UPSERT\n\t\t\tDate date = new Date();\n\n\t\t\tsynchronized (updateItemSt) {\n\t\t\t\tupdateItemSt.setString(1, item.getHostname());\n\t\t\t\tupdateItemSt.setString(2, item.getSecondaryHostname());\n\t\t\t\tupdateItemSt.setString(3, item.getPassword());\n\t\t\t\tupdateItemSt.setTimestamp(4, new Timestamp(date.getTime()));\n\t\t\t\tupdateItemSt.setInt(5, item.getPortNo());\n\t\t\t\tupdateItemSt.setFloat(6, item.getCpuUsage());\n\t\t\t\tupdateItemSt.setFloat(7, item.getMemUsage());\n\t\t\t\tupdateItemSt.setString(8, item.getHostname());\n\t\t\t\tupdateItemSt.executeUpdate();\n\t\t\t}\n\n\t\t\tsynchronized (insertItemSt) {\n\t\t\t\tinsertItemSt.setString(1, item.getHostname());\n\t\t\t\tinsertItemSt.setString(2, item.getSecondaryHostname());\n\t\t\t\tinsertItemSt.setString(3, item.getPassword());\n\t\t\t\tinsertItemSt.setTimestamp(4, new Timestamp(date.getTime()));\n\t\t\t\tinsertItemSt.setInt(5, item.getPortNo());\n\t\t\t\tinsertItemSt.setFloat(6, item.getCpuUsage());\n\t\t\t\tinsertItemSt.setFloat(7, item.getMemUsage());\n\t\t\t\tinsertItemSt.setString(8, item.getHostname());\n\t\t\t\tinsertItemSt.executeUpdate();\n\t\t\t}\n\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void reload() {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Reloading items\" );\n\t\t}\n\n\t\tif ( ( System.currentTimeMillis() - lastReloadTime ) <= ( autoreload_interval * lastReloadTimeFactor ) ){\n\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\tlog.log( Level.FINE, \"Last reload performed in {0}, skipping: \", ( System.currentTimeMillis() - lastReloadTime ) );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlastReloadTime = System.currentTimeMillis();\n\n\t\tsuper.reload();\n\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement getAllItemsSt = data_repo.getPreparedStatement(null,\n\t\t\t\t\tGET_ALL_ITEMS_QUERY);\n\t\t\t\n\t\t\tsynchronized (getAllItemsSt) {\n\t\t\t\ttry {\n\t\t\t\t\trs = getAllItemsSt.executeQuery();\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tClusterRepoItem item = getItemInstance();\n\n\t\t\t\t\t\titem.setHostname(rs.getString(HOSTNAME_COLUMN));\n\t\t\t\t\t\titem.setSecondaryHostname(rs.getString(SECONDARY_HOSTNAME_COLUMN));\n\t\t\t\t\t\titem.setPassword(rs.getString(PASSWORD_COLUMN));\n\t\t\t\t\t\titem.setLastUpdate(rs.getTimestamp(LASTUPDATE_COLUMN).getTime());\n\t\t\t\t\t\titem.setPort(rs.getInt(PORT_COLUMN));\n\t\t\t\t\t\titem.setCpuUsage(rs.getFloat(CPU_USAGE_COLUMN));\n\t\t\t\t\t\titem.setMemUsage(rs.getFloat(MEM_USAGE_COLUMN));\n\t\t\t\t\t\titemLoaded(item);\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tsuper.setProperties(properties);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void store() {\n\n\t\t// Do nothing everything is written on demand to DB\n\t}\n\n\t/**\n\t * Performs database check, creates missing schema if necessary\n\t *\n\t * @throws SQLException\n\t */\n\tprivate void checkDB() throws SQLException {\n\t\tStatement st = null;\n\n\t\tDataRepository.dbTypes databaseType = data_repo.getDatabaseType();\n\t\tString createTableQuery;\n\n\t\tswitch ( databaseType ) {\n\t\t\tcase mysql:\n\t\t\t\tcreateTableQuery = CREATE_TABLE_QUERY_MYSQL;\n\t\t\t\tbreak;\n\t\t\tcase jtds:\n\t\t\tcase sqlserver:\n\t\t\t\tcreateTableQuery = CREATE_TABLE_QUERY_SQLSERVER;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcreateTableQuery = CREATE_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tStatement stmt = null;\n\t\t\n\t\ttry {\n\t\t\tif (!data_repo.checkTable(TABLE_NAME)) {\n\t\t\t\tlog.info(\"DB for external component is not OK, creating missing tables...\");\n\n\t\t\t\tst = data_repo.createStatement(null);\n\t\t\t\tst.executeUpdate(createTableQuery);\n\t\t\t\tlog.info(\"DB for external component created OK\");\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstmt = data_repo.createStatement(null);\n\t\t\t\tstmt.executeQuery(\"select \" + SECONDARY_HOSTNAME_COLUMN + \" from \" + TABLE_NAME + \" where \" + HOSTNAME_COLUMN + \" IS NOT NULL\");\n\t\t\t} catch (SQLException ex) {\n\t\t\t\t// if this happens then we have issue with old database schema and missing body columns in MSGS_TABLE\n\t\t\t\tString alterTable = null;\n\t\t\t\tswitch (data_repo.getDatabaseType()) {\n\t\t\t\t\tcase derby:\n\t\t\t\t\tcase mysql:\n\t\t\t\t\tcase postgresql:\n\t\t\t\t\t\talterTable = \"alter table \" + TABLE_NAME + \" add \" + SECONDARY_HOSTNAME_COLUMN + \" varchar(512)\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase jtds:\n\t\t\t\t\tcase sqlserver:\n\t\t\t\t\t\talterTable = \"alter table \" + TABLE_NAME + \" add \" + SECONDARY_HOSTNAME_COLUMN + \" nvarchar(512)\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tstmt.execute(alterTable);\n\t\t\t\t} catch (SQLException ex1) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"could not alter table \" + TABLE_NAME + \" to add missing column by SQL:\\n\" + alterTable, ex1);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t} finally {\n\t\t\tdata_repo.release(st, null);\n\t\t\tst = null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClusterRepoConstants.java",
    "content": "/*\n * ClusterRepoConstants.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.cluster.repo;\n\npublic interface ClusterRepoConstants {\n\tpublic static final String CPU_USAGE_COLUMN = \"cpu_usage\";\n\n\tpublic static final String HOSTNAME_COLUMN = \"hostname\";\n\n\tpublic static final String SECONDARY_HOSTNAME_COLUMN = \"secondary\";\n\n\tpublic static final String LASTUPDATE_COLUMN = \"last_update\";\n\n\tpublic static final String MEM_USAGE_COLUMN = \"mem_usage\";\n\n\tpublic static final String PASSWORD_COLUMN = \"password\";\n\n\tpublic static final String PORT_COLUMN = \"port\";\n\n\tpublic static final String REPO_URI_PROP_KEY = \"repo-uri\";\n\n\tpublic static final String TABLE_NAME = \"cluster_nodes\";\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/repo/ClusterRepoItem.java",
    "content": "/*\n * ClusterRepoItem.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster.repo;\n\nimport tigase.db.comp.RepositoryItemAbstract;\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.Algorithms;\nimport tigase.xml.Element;\n\nimport java.text.DateFormat;\nimport java.text.ParseException;\nimport java.util.Date;\nimport java.util.UUID;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\npublic class ClusterRepoItem\n\t\textends RepositoryItemAbstract\n\t\timplements Cloneable {\n\n\tpublic static final String CPU_USAGE_ATTR = \"cpu\";\n\n\tpublic static final String CPU_USAGE_LABEL = \"CPU usage\";\n\n\tpublic static final String HOSTNAME_ATTR = \"host\";\n\n\tpublic static final String SECONDARY_HOSTNAME_ATTR = \"secondary\";\n\n\tpublic static final String HOSTNAME_LABEL = \"Hostname\";\n\n\tpublic static final String SECONDARY_HOSTNAME_LABEL = \"SecondaryHostname\";\n\n\tpublic static final String LAST_UPDATE_ATTR = \"updated\";\n\n\tpublic static final String LAST_UPDATE_LABEL = \"Last update\";\n\n\tpublic static final String MEM_USAGE_ATTR = \"mem\";\n\n\tpublic static final String MEM_USAGE_LABEL = \"Memory usage\";\n\n\tpublic static final String PASSWORD_ATTR = \"passwd\";\n\n\tpublic static final String PASSWORD_LABEL = \"Password\";\n\n\tpublic static final String PASSWORD_PROP_VAL = \"someSecret\";\n\n\tpublic static final String PORT_NO_ATTR = \"port\";\n\n\tpublic static final String PORT_NO_LABEL = \"Port number\";\n\n\tpublic static final int PORT_NO_PROP_VAL = 5277;\n\n\tpublic static final String REPO_ITEM_ELEM_NAME = \"item\";\n\n\tprivate static final Logger log = Logger.getLogger( ClusterRepoItem.class.getName() );\n\n\tprivate float cpuUsage = 0f;\n\tprivate String hostname = null;\n\tprivate String secondaryHostname = null;\n\tprivate long lastUpdate = 0l;\n\tprivate float memUsage = 0f;\n\tprivate String password = Algorithms.sha256( UUID.randomUUID().toString() );\n\tprivate int portNo = PORT_NO_PROP_VAL;\n\n\t//~--- methods --------------------------------------------------------------\n\t@Override\n\tpublic void addCommandFields( Packet packet ) {\n\t\tCommand.addFieldValue( packet, HOSTNAME_LABEL, ( ( hostname != null )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? hostname\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : \"\" ) );\n\t\tCommand.addFieldValue( packet, SECONDARY_HOSTNAME_LABEL, ( ( secondaryHostname != null )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? secondaryHostname\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : \"\" ) );\n\t\tCommand.addFieldValue( packet, PASSWORD_LABEL, ( ( password != null )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? password\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : \"\" ) );\n\t\tCommand.addFieldValue( packet, PORT_NO_LABEL, ( ( portNo > 0 )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? \"\" + portNo\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"\" ) );\n\t\tCommand.addFieldValue( packet, LAST_UPDATE_LABEL, \"\" + new Date( lastUpdate ) );\n\t\tCommand.addFieldValue( packet, CPU_USAGE_LABEL, \"\" + cpuUsage );\n\t\tCommand.addFieldValue( packet, MEM_USAGE_LABEL, \"\" + memUsage );\n\t\tsuper.addCommandFields( packet );\n\t}\n\n\t@Override\n\tpublic void initFromCommand( Packet packet ) {\n\t\tsuper.initFromCommand( packet );\n\t\thostname = Command.getFieldValue( packet, HOSTNAME_LABEL );\n\t\tsecondaryHostname = Command.getFieldValue( packet, SECONDARY_HOSTNAME_LABEL );\n\t\tpassword = Command.getFieldValue( packet, PASSWORD_LABEL );\n\n\t\tString tmp = Command.getFieldValue( packet, LAST_UPDATE_LABEL );\n\n\t\tif ( ( tmp != null ) && !tmp.isEmpty() ){\n\t\t\ttry {\n\t\t\t\tlastUpdate = DateFormat.getInstance().parse( tmp ).getTime();\n\t\t\t} catch ( ParseException ex ) {\n\t\t\t\tlastUpdate = System.currentTimeMillis();\n\t\t\t}\n\t\t}\n\t\ttmp = Command.getFieldValue( packet, PORT_NO_LABEL );\n\t\tif ( ( tmp != null ) && !tmp.isEmpty() ){\n\t\t\tportNo = parsePortNo( tmp );\n\t\t}\n\t\ttmp = Command.getFieldValue( packet, CPU_USAGE_LABEL );\n\t\tif ( ( tmp != null ) && !tmp.isEmpty() ){\n\t\t\tcpuUsage = Float.parseFloat( tmp );\n\t\t}\n\t\ttmp = Command.getFieldValue( packet, MEM_USAGE_LABEL );\n\t\tif ( ( tmp != null ) && !tmp.isEmpty() ){\n\t\t\tmemUsage = Float.parseFloat( tmp );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initFromElement( Element elem ) {\n\t\tif ( elem.getName() != REPO_ITEM_ELEM_NAME ){\n\t\t\tthrow new IllegalArgumentException( \"Incorrect element name, expected: \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ REPO_ITEM_ELEM_NAME );\n\t\t}\n\t\tsuper.initFromElement( elem );\n\t\thostname = elem.getAttributeStaticStr( HOSTNAME_ATTR );\n\t\tsecondaryHostname = elem.getAttributeStaticStr( SECONDARY_HOSTNAME_ATTR );\n\t\tpassword = elem.getAttributeStaticStr( PASSWORD_ATTR );\n\t\tportNo = parsePortNo( elem.getAttributeStaticStr( PORT_NO_ATTR ) );\n\t\tlastUpdate = Long.parseLong( elem.getAttributeStaticStr( LAST_UPDATE_ATTR ) );\n\t\tcpuUsage = Float.parseFloat( elem.getAttributeStaticStr( CPU_USAGE_ATTR ) );\n\t\tmemUsage = Float.parseFloat( elem.getAttributeStaticStr( MEM_USAGE_ATTR ) );\n\t}\n\n\t@Override\n\tpublic void initFromPropertyString( String propString ) {\n\t\tString[] props = propString.split( \":\" );\n\n\t\tif ( props.length > 0 ){\n\t\t\thostname = BareJID.parseJID( props[0] )[1];\n\t\t}\n\t\tif ( ( props.length > 1 ) && !props[1].trim().isEmpty() ){\n\t\t\tpassword = props[1];\n\t\t}\n\t\tif ( props.length > 2 ){\n\t\t\tportNo = parsePortNo( props[2] );\n\t\t}\n\t\tif ( props.length > 3 ){\n\t\t\tlastUpdate = Long.parseLong( props[3] );\n\t\t}\n\t\tif ( props.length > 4 ){\n\t\t\tcpuUsage = Float.parseFloat( props[4] );\n\t\t}\n\t\tif ( props.length > 5 ){\n\t\t\tmemUsage = Float.parseFloat( props[5] );\n\t\t}\n\t\tif ( props.length > 6 ){\n\t\t\tsecondaryHostname = BareJID.parseJID( props[6] )[1];\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element toElement() {\n\t\tElement elem = super.toElement();\n\n\t\telem.addAttribute( HOSTNAME_ATTR, hostname );\n\t\telem.addAttribute( SECONDARY_HOSTNAME_ATTR, secondaryHostname );\n\t\telem.addAttribute( PASSWORD_ATTR, password );\n\t\telem.addAttribute( PORT_NO_ATTR, \"\" + portNo );\n\t\telem.addAttribute( LAST_UPDATE_ATTR, \"\" + lastUpdate );\n\t\telem.addAttribute( CPU_USAGE_ATTR, \"\" + cpuUsage );\n\t\telem.addAttribute( MEM_USAGE_ATTR, \"\" + memUsage );\n\n\t\treturn elem;\n\t}\n\n\t@Override\n\tpublic String toPropertyString() {\n\t\treturn hostname + \":\" + password + \":\" + portNo + \":\" + lastUpdate + \":\" + cpuUsage\n\t\t\t\t\t + \":\" + memUsage + \":\" + secondaryHostname;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn toPropertyString();\n\t}\n\n\tpublic float getCpuUsage() {\n\t\treturn cpuUsage;\n\t}\n\n\t@Override\n\tpublic String getElemName() {\n\t\treturn REPO_ITEM_ELEM_NAME;\n\t}\n\n\tpublic String getHostname() {\n\t\treturn hostname;\n\t}\n\n\t@Override\n\tpublic String getKey() {\n\t\treturn hostname;\n\t}\n\n\tpublic long getLastUpdate() {\n\t\treturn lastUpdate;\n\t}\n\n\tpublic float getMemUsage() {\n\t\treturn memUsage;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic String getSecondaryHostname() {\n\t\treturn secondaryHostname;\n\t}\n\n\tpublic int getPortNo() {\n\t\treturn portNo;\n\t}\n\n\t@Override\n\tprotected Object clone() throws CloneNotSupportedException {\n\t\treturn super.clone();\n\t}\n\n\tprotected void setCpuUsage( float cpuUsage ) {\n\t\tthis.cpuUsage = cpuUsage;\n\t}\n\n\tprotected void setHostname( String hostname ) {\n\t\tthis.hostname = hostname;\n\t}\n\n\tprotected void setLastUpdate( long update ) {\n\t\tthis.lastUpdate = update;\n\t}\n\n\tprotected void setMemUsage( float memUsage ) {\n\t\tthis.memUsage = memUsage;\n\t}\n\n\tprotected void setPassword( String password ) {\n\t\tthis.password = password;\n\t}\n\n\tprotected void setSecondaryHostname( String secondaryHostname ) {\n\t\tthis.secondaryHostname = secondaryHostname;\n\t}\n\n\tprotected void setPort( int port ) {\n\t\tthis.portNo = port;\n\t}\n\n\tprivate int parsePortNo( String input ) {\n\t\tint result;\n\n\t\ttry {\n\t\t\tresult = Integer.parseInt( input );\n\t\t} catch ( Exception e ) {\n\t\t\tresult = 5277;\n\t\t\tlog.log( Level.WARNING, \"Incorrect port number, can't parse: {0}\", input );\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/ClusteringStrategyIfc.java",
    "content": "/*\n * ClusteringStrategyIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.sys.OnlineJidsReporter;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Created: May 2, 2009 4:36:03 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n *\n * @param <E>\n */\npublic interface ClusteringStrategyIfc<E extends ConnectionRecordIfc>\n\t\t\t\textends OnlineJidsReporter {\n\t\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param conn \n\t */\n\tpublic void handleLocalPresenceSet(XMPPResourceConnection conn);\n\t\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param conn \n\t */\n\tpublic void handleLocalResourceBind(XMPPResourceConnection conn);\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param conn\n\t */\n\tpublic void handleLocalUserLogin(BareJID userId, XMPPResourceConnection conn);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param conn\n\t */\n\tpublic void handleLocalUserLogout(BareJID userId, XMPPResourceConnection conn);\n\n\tpublic void handleLocalUserChangedConnId(BareJID userId, XMPPResourceConnection conn, JID oldConnId, JID newConnId);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getInfo();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param conn\n\t */\n\tvoid handleLocalPacket(Packet packet, XMPPResourceConnection conn);\n\n\t/**\n\t * This is a handler method which is called when a new node connects to the\n\t * cluster.\n\t *\n\t * @param node\n\t *          is a cluster node id.\n\t */\n\tvoid nodeConnected(JID node);\n\n\t/**\n\t * This is a handler method which is called when a node disconnects from the\n\t * cluster.\n\t *\n\t * @param node\n\t *          is a cluster node id.\n\t */\n\tvoid nodeDisconnected(JID node);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param conn\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tboolean processPacket(Packet packet, XMPPResourceConnection conn);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * The method returns all cluster nodes currently connected to the cluster node.\n\t *\n\t * @return List of all cluster nodes currently connected to the cluster node.\n\t */\n\tList<JID> getNodesConnected();\n\n\t/**\n\t * Returns a ConnectionRecord object associated with this user's full JID if\n\t * it exists in the cache or null if it does not. All parts of the user's JID\n\t * are checked and ConnectionRecord is returned only if there is a match for\n\t * all parts.\n\t *\n\t * @param jid\n\t *          is an instance of the user's full JID.\n\t * @return ConnectionRecord instance associated with given user's JID or null\n\t *         if there is no ConnectionRecord in the cache.\n\t */\n\tE getConnectionRecord(JID jid);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>E</code>\n\t */\n\tE getConnectionRecordInstance();\n\n\t/**\n\t * Returns a set with all ConnectionRecords found in the cache for a given\n\t * user ID, that is BareJID. In other words all user's resources/connectionIDs\n\t * found in the cache associated with user's account.\n\t *\n\t * @param bareJID\n\t *          is an instance of the user's BareJID, that is account ID.\n\t * @return a Set instance with all ConnectionRecords found for a given\n\t *         BareJID. Note, the result may be null or it maybe an empty Set or\n\t *         non-empty set.\n\t */\n\tSet<E> getConnectionRecords(BareJID bareJID);\n\n\t/**\n\t * This method is used for configuration purpose. Following the convention\n\t * used in the Tigase project this method is supposed to provide configuration\n\t * defaults. All parameters which exist in configuration file overwrite\n\t * corresponding default parameters. If some parameters are missing in\n\t * configuration file defaults are used then.\n\t *\n\t * A compiled set of parameters is then passed to <code>setProperties</code>\n\t * method.\n\t *\n\t * @param params\n\t *          a <code>Map</code> with properties loaded from init.properties\n\t *          file which should be used for generating defaults.\n\t * @return a <code>Map</code> with all the class default configuration\n\t *         parameters.\n\t */\n\tMap<String, Object> getDefaults(Map<String, Object> params);\n\n\t/**\n\t * <strong>Note! This is not for a common use method.</strong> This is for\n\t * debugging and diagnostic purposes only and maybe removed or changed at any\n\t * time in the future. It returns a content of an internal cache from the\n\t * strategy. Regardless of the cache data organization inside the strategy, it\n\t * is returned here in a common format. It may be a copy or a direct reference\n\t * to internal data. Therefore this is unmodifiable instance of the cache.\n\t * Generating results of this structure may be a costly operation, therefore\n\t * it must not be called frequently.\n\t *\n\t * @return an Object with content of an internal cache data.\n\t */\n\t@Deprecated\n\tObject getInternalCacheData();\n\n\t/**\n\t * Add the strategy statistics to the List.\n\t *\n\t * @param list\n\t */\n\tvoid getStatistics(StatisticsList list);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param clComp\n\t */\n\tvoid setClusterController(ClusterControllerIfc clComp);\n\n\t/**\n\t * Method used to pass configuration parameters to the class. Parameters are\n\t * stored in <code>Map</code> which contains compiles set of defaults\n\t * overwritten by parameters loaded from configuration file.\n\t *\n\t * If he implementation took a good care of providing defaults for all\n\t * parameters no parameter should be missing.\n\t *\n\t * @param props\n\t *          a <code>Map</code> with all configuration parameters for the\n\t *          class.\n\t */\n\tvoid setProperties(Map<String, Object> props);\n\n\t/**\n\t * The method allows to obtain SessionManagerHandler object by the strategy.\n\t * The object is mainly used to access local VHosts configuration and check\n\t * the ID of the local session manager.\n\t *\n\t * @param sm\n\t *          is an instance of the SessionManagerHandler class.\n\t */\n\tvoid setSessionManagerHandler(SessionManagerClusteredIfc sm);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/ConnectionRecord.java",
    "content": "/*\n * ConnectionRecord.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n/**\n * @author Artur Hefczyc Created Mar 15, 2011\n */\npublic class ConnectionRecord\n\t\t\t\timplements ConnectionRecordIfc, Comparable<ConnectionRecord> {\n\tprivate static final String CONNECTION_ID_ELEMENT = \"connection-id\";\n\tprivate static final String JID_ELEMENT           = \"user-jid\";\n\tprivate static final String NODE_ELEMENT          = \"node-jid\";\n\tprivate static final String SESSION_ID_ELEMENT    = \"session-id\";\n\tprivate static final String TOP_ELEMENT           = \"conn-rec\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JID    connectionId;\n\tprivate JID    node;\n\tprivate String sessionId;\n\tprivate JID    userJid;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic ConnectionRecord() {\n\t\tsuper();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int compareTo(ConnectionRecord rec) {\n\t\treturn connectionId.compareTo(rec.connectionId);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object rec) {\n\t\tboolean result = false;\n\n\t\tif (rec instanceof ConnectionRecord) {\n\t\t\tresult = connectionId.equals(((ConnectionRecord) rec).connectionId);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn connectionId.hashCode();\n\t}\n\n\t@Override\n\tpublic Element toElement() {\n\t\tElement result = new Element(TOP_ELEMENT);\n\n\t\tresult.addChild(new Element(NODE_ELEMENT, node.toString()));\n\t\tresult.addChild(new Element(JID_ELEMENT, userJid.toString()));\n\t\tresult.addChild(new Element(CONNECTION_ID_ELEMENT, connectionId.toString()));\n\t\tresult.addChild(new Element(SESSION_ID_ELEMENT, sessionId));\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tsb.append(\"ConnectionRecord=[\");\n\t\tsb.append(\"node: \").append(node);\n\t\tsb.append(\", userJid: \").append(userJid);\n\t\tsb.append(\", connectionId: \").append(connectionId);\n\t\tsb.append(\", sessionId: \").append(sessionId);\n\t\tsb.append(\"]\");\n\n\t\treturn sb.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic JID getConnectionId() {\n\t\treturn connectionId;\n\t}\n\n\t@Override\n\tpublic JID getNode() {\n\t\treturn node;\n\t}\n\n\t@Override\n\tpublic String getSessionId() {\n\t\treturn sessionId;\n\t}\n\n\t@Override\n\tpublic JID getUserJid() {\n\t\treturn userJid;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tpublic void setConnectionId(JID connectionId) {\n\t\tthis.connectionId = connectionId;\n\t}\n\n\t@Override\n\tpublic void setElement(Element elem) {\n\t\tthis.node         = JID.jidInstanceNS(elem.getChild(NODE_ELEMENT).getCData());\n\t\tthis.userJid      = JID.jidInstanceNS(elem.getChild(JID_ELEMENT).getCData());\n\t\tthis.connectionId = JID.jidInstanceNS(elem.getChild(CONNECTION_ID_ELEMENT)\n\t\t\t\t.getCData());\n\t\tthis.sessionId = elem.getChild(SESSION_ID_ELEMENT).getCData();\n\t}\n\n\t@Override\n\tpublic void setRecordFields(JID node, JID userJid, String sessionId, JID connectionId) {\n\t\tthis.node         = node;\n\t\tthis.userJid      = userJid;\n\t\tthis.connectionId = connectionId;\n\t\tthis.sessionId    = sessionId;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/ConnectionRecordIfc.java",
    "content": "/*\n * ConnectionRecordIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n/**\n *\n * @author kobit\n */\npublic interface ConnectionRecordIfc {\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Element</code>\n\t */\n\tElement toElement();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tJID getConnectionId();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tJID getNode();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tString getSessionId();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tJID getUserJid();\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param elem\n\t */\n\tvoid setElement(Element elem);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node\n\t * @param userJid\n\t * @param sessionId\n\t * @param connectionId\n\t */\n\tvoid setRecordFields(JID node, JID userJid, String sessionId, JID connectionId);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/01\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/DefaultClusteringStrategy.java",
    "content": "/*\n * DefaultClusteringStrategy.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterCommandException;\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.CommandListener;\nimport tigase.cluster.api.CommandListenerAbstract;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\nimport tigase.cluster.strategy.cmd.PacketForwardCmd;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Presence;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\nimport static tigase.cluster.api.SessionManagerClusteredIfc.SESSION_FOUND_KEY;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Random;\nimport java.util.Set;\nimport tigase.server.Priority;\n\n/**\n * Created: May 13, 2009 9:53:44 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n *\n * @param <E>\n */\npublic class DefaultClusteringStrategy<E extends ConnectionRecordIfc>\n\t\t\t\textends DefaultClusteringStrategyAbstract<E> {\n\t/** Field description */\n\tpublic static final String CONNECTION_ID = \"connectionId\";\n\n\t/** Field description */\n\tpublic static final String RESOURCE = \"resource\";\n\n\t/** Field description */\n\tpublic static final String SM_ID = \"smId\";\n\n\t/** Field description */\n\tpublic static final String USER_ID = \"userId\";\n\n\t/** Field description */\n\tpublic static final String  XMPP_SESSION_ID      = \"xmppSessionId\";\n\tprivate static final String AUTH_TIME            = \"auth-time\";\n\tprivate static final String INITIAL_PRESENCE_KEY = \"cluster-initial-presence\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(DefaultClusteringStrategy.class\n\t\t\t.getName());\n\tprivate static final String PRESENCE_TYPE_INITIAL = \"initial\";\n\tprivate static final String PRESENCE_TYPE_KEY     = \"presence-type\";\n\tprivate static final String PRESENCE_TYPE_UPDATE  = \"update\";\n\tprivate static final String USER_CONNECTED_CMD    = \"user-connected-sm-cmd\";\n\tprivate static final String USER_PRESENCE_CMD     = \"user-presence-sm-cmd\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// Simple random generator, we do not need a strong randomization here.\n\t// Just enough to ensure better traffic distribution\n\tprivate Random rand = new Random();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic DefaultClusteringStrategy() {\n\t\tsuper();\n\t\taddCommandListener(new UserPresenceCommand(USER_PRESENCE_CMD));\n\t\taddCommandListener(new UserConnectedCommand(USER_CONNECTED_CMD));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void nodeConnected(JID node) {\n\t}\n\n\t@Override\n\tpublic void nodeDisconnected(JID node) {\n\t}\n\n\t@Override\n\tpublic void handleLocalPacket(Packet packet, XMPPResourceConnection conn) {\n\t\tif (packet.getElemName() == Presence.ELEM_NAME) {\n\t\t\ttry {\n\t\t\t\tif ((packet.getStanzaFrom() != null) &&!conn.isUserId(packet.getStanzaFrom()\n\t\t\t\t\t\t.getBareJID())) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tboolean             initPresence = conn.getSessionData(INITIAL_PRESENCE_KEY) ==\n\t\t\t\t\t\tnull;\n\t\t\t\tMap<String, String> params = prepareConnectionParams(conn);\n\n\t\t\t\tif (initPresence) {\n\t\t\t\t\tconn.putSessionData(INITIAL_PRESENCE_KEY, INITIAL_PRESENCE_KEY);\n\t\t\t\t\tparams.put(PRESENCE_TYPE_KEY, PRESENCE_TYPE_INITIAL);\n\t\t\t\t} else {\n\t\t\t\t\tparams.put(PRESENCE_TYPE_KEY, PRESENCE_TYPE_UPDATE);\n\t\t\t\t}\n\n\t\t\t\tElement   presence = packet.getElement();    // conn.getPresence();\n\t\t\t\tList<JID> cl_nodes = getNodesForPacketForward(sm.getComponentId(), null, Packet\n\t\t\t\t\t\t.packetInstance(presence));\n\n\t\t\t\tif ((cl_nodes != null) && (cl_nodes.size() > 0)) {\n\n\t\t\t\t\t// ++clusterSyncOutTraffic;\n\t\t\t\t\tcluster.sendToNodes(USER_PRESENCE_CMD, params, presence, sm.getComponentId(),\n\t\t\t\t\t\t\tnull, cl_nodes.toArray(new JID[cl_nodes.size()]));\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem with broadcast user presence for: \" + conn, e);\n\t\t\t}\n\t\t}\n\t\tsuper.handleLocalPacket(packet, conn);\n\t}\n\n\t@Override\n\tpublic void handleLocalResourceBind(XMPPResourceConnection conn) {\n\t\ttry {\n\t\t\tMap<String, String> params = prepareConnectionParams(conn);\n\t\t\tList<JID> cl_nodes = getNodesConnected();\n\n\t\t\t// ++clusterSyncOutTraffic;\n\t\t\tcluster.sendToNodes(USER_CONNECTED_CMD, params, sm.getComponentId(), cl_nodes\n\t\t\t\t\t.toArray(new JID[cl_nodes.size()]));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem with broadcast user presence for: \" + conn, e);\n\t\t}\n\t}\t\n\t\n\t@Override\n\tpublic void handleLocalUserLogout(BareJID userId, XMPPResourceConnection conn) {\n\t\ttry {\n\t\t\tif (!conn.isAuthorized()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tElement presence = conn.getPresence();\n\n\t\t\tif (presence == null) {\n\t\t\t\tpresence = new Element(Presence.ELEM_NAME);\n\t\t\t\tpresence.setXMLNS(Presence.CLIENT_XMLNS);\n\t\t\t} else {\n\t\t\t\tpresence = presence.clone();\n\t\t\t}\n\t\t\tpresence.setAttribute(\"from\", conn.getJID().toString());\n\t\t\tpresence.setAttribute(\"type\", StanzaType.unavailable.name());\n\n\t\t\tMap<String, String> params   = prepareConnectionParams(conn);\n\t\t\tList<JID>           cl_nodes = getNodesConnected();\n\n\t\t\tif ((cl_nodes != null) && (cl_nodes.size() > 0)) {\n\n\t\t\t\t// ++clusterSyncOutTraffic;\n\t\t\t\tcluster.sendToNodes(USER_PRESENCE_CMD, params, presence, sm.getComponentId(),\n\t\t\t\t\t\tnull, cl_nodes.toArray(new JID[cl_nodes.size()]));\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem with broadcast user presence for: \" + conn, e);\n\t\t}\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic List<JID> getNodesForPacketForward(JID fromNode, Set<JID> visitedNodes,\n\t\t\tPacket packet) {\n\t\tif (visitedNodes != null) {\n\t\t\tList<JID> result = selectNodes(fromNode, visitedNodes);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Visited nodes not null: {0}, selecting new node: {1}, for packet: {2}\",\n\t\t\t\t\t\tnew Object[] { visitedNodes,\n\t\t\t\t\t\tresult, packet });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t// Presence status change set by the user have a special treatment:\n\t\tif ((packet.getElemName() == \"presence\") && (packet.getType() != StanzaType.error) &&\n\t\t\t\t(packet.getStanzaFrom() != null) && (packet.getStanzaTo() == null)) {\n\t\t\tList<JID> result = getNodesConnected();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Presence packet found: {0}, selecting all nodes: {1}\",\n\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\tresult });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t\tif (isSuitableForForward(packet)) {\n\t\t\tList<JID> result = selectNodes(fromNode, visitedNodes);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Visited nodes null, selecting new node: {0}, for packet: {1}\",\n\t\t\t\t\t\tnew Object[] { result,\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet not suitable for forwarding: {0}\", new Object[] {\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * A utility method used to prepare a Map of data with user session data\n\t * before it can be sent over to another cluster node. This is supposed to\n\t * contain all the user's session essential information which directly\n\t * identify user's resource and network connection. This information allows to\n\t * detect two different user's connection made for the same resource. This may\n\t * happen if both connections are established to different nodes.\n\t *\n\t * @param conn\n\t *          is user's XMPPResourceConnection for which Map structure is\n\t *          prepare.\n\t *\n\t * @return a Map structure with all user's connection essential data.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t */\n\tprotected Map<String, String> prepareConnectionParams(XMPPResourceConnection conn)\n\t\t\t\t\tthrows NotAuthorizedException, NoConnectionIdException {\n\t\tMap<String, String> params = new LinkedHashMap<String, String>();\n\n\t\tparams.put(USER_ID, conn.getBareJID().toString());\n\t\tparams.put(RESOURCE, conn.getResource());\n\t\tparams.put(CONNECTION_ID, conn.getConnectionId().toString());\n\t\tparams.put(XMPP_SESSION_ID, conn.getSessionId());\n\t\tparams.put(AUTH_TIME, \"\" + conn.getAuthTime());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for conn: {0}, result: \", new Object[] { conn,\n\t\t\t\t\tparams });\n\t\t}\n\n\t\treturn params;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method takes the data received from other cluster node and creates a\n\t * ConnectionRecord with all essential connection information. This might be\n\t * used later to identify user's XMPPResourceConnection or use the clustering\n\t * strategy API.\n\t *\n\t * @param node\n\t * @param data\n\t * @return\n\t */\n\tprotected ConnectionRecordIfc getConnectionRecord(JID node, Map<String, String> data) {\n\t\tBareJID             userId       = BareJID.bareJIDInstanceNS(data.get(USER_ID));\n\t\tString              resource     = data.get(RESOURCE);\n\t\tJID                 jid          = JID.jidInstanceNS(userId, resource);\n\t\tString              sessionId    = data.get(XMPP_SESSION_ID);\n\t\tJID                 connectionId = JID.jidInstanceNS(data.get(CONNECTION_ID));\n\t\tConnectionRecordIfc rec = this\n\t\t\t\t.getConnectionRecordInstance();    // new ConnectionRecord(node, jid, sessionId, connectionId);\n\n\t\trec.setRecordFields(node, jid, sessionId, connectionId);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"ConnectionRecord created: {0}\", new Object[] { rec });\n\t\t}\n\n\t\treturn rec;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * @param fromNode\n\t * @param visitedNodes\n\t *\n\t */\n\tprivate List<JID> selectNodes(JID fromNode, Set<JID> visitedNodes) {\n\t\tList<JID> result = null;\n\t\tList<JID> cl_nodes_list = getNodesConnected();\n\t\tint       size   = cl_nodes_list.size();\n\n\t\tif (size == 0) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No connected cluster nodes found, returning null\");\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tint idx = rand.nextInt(size);\n\n\t\tif ((visitedNodes == null) || (visitedNodes.size() == 0)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No visited nodes yet, trying random idx: \" + idx);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tresult = Collections.singletonList(cl_nodes_list.get(idx));\n\t\t\t} catch (IndexOutOfBoundsException ioobe) {\n\n\t\t\t\t// This may happen if the node disconnected in the meantime....\n\t\t\t\ttry {\n\t\t\t\t\tresult = Collections.singletonList(cl_nodes_list.get(0));\n\t\t\t\t} catch (IndexOutOfBoundsException ioobe2) {\n\n\t\t\t\t\t// Yes, this may happen too if there were only 2 nodes before\n\t\t\t\t\t// disconnect....\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"IndexOutOfBoundsException twice! Should not happen very often, returning null\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (JID jid : cl_nodes_list) {\n\t\t\t\tif (!visitedNodes.contains(jid)) {\n\t\t\t\t\tresult = Collections.singletonList(jid);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If all nodes visited already. We have to either send it back to the\n\t\t\t// first node\n\t\t\t// or if this is the first node return null\n\t\t\tif ((result == null) &&!sm.getComponentId().equals(fromNode)) {\n\t\t\t\tresult = Collections.singletonList(fromNode);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"All nodes visited, sending it back to the first node: \" + result);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"List of result nodes: \" + result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class UserConnectedCommand\n\t\t\t\t\textends CommandListenerAbstract {\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param name\n\t\t */\n\t\tpublic UserConnectedCommand(String name) {\n\t\t\tsuper(name, Priority.CLUSTER);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String,\n\t\t\t\tString> data, Queue<Element> packets)\n\t\t\t\tthrows ClusterCommandException {\n\n\t\t\t// ++clusterSyncInTraffic;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Called fromNode: {0}, visitedNodes: {1}, data: {2}, packets: {3}\",\n\t\t\t\t\t\tnew Object[] { fromNode,\n\t\t\t\t\t\tvisitedNodes, data, packets });\n\t\t\t}\n\n\t\t\t// Queue<Packet> results = new ArrayDeque<Packet>(10);\n\t\t\tConnectionRecordIfc rec = getConnectionRecord(fromNode, data);\n\n\t\t\t// strategy.usersConnected(results, rec);\n\t\t\t// addOutPackets(results);\n\t\t\t// There is one more thing....\n\t\t\t// If the new connection is for the same resource we have here then the\n\t\t\t// old connection must be destroyed.\n\t\t\tXMPPSession session = sm.getXMPPSessions().get(rec.getUserJid().getBareJID());\n\n\t\t\tif (session != null) {\n\t\t\t\tXMPPResourceConnection conn = session.getResourceForResource(rec.getUserJid()\n\t\t\t\t\t\t.getResource());\n\n\t\t\t\tif (conn != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\t\"Duplicate resource connection, logingout the older connection: \" + rec);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPacket cmd = Command.CLOSE.getPacket(sm.getComponentId(), conn\n\t\t\t\t\t\t\t\t.getConnectionId(), StanzaType.set, conn.nextStanzaId());\n\t\t\t\t\t\tElement err_el = new Element(\"conflict\");\n\n\t\t\t\t\t\terr_el.setXMLNS(\"urn:ietf:params:xml:ns:xmpp-streams\");\n\t\t\t\t\t\tcmd.getElement().getChild(\"command\").addChild(err_el);\n\t\t\t\t\t\tsm.fastAddOutPacket(cmd);\n\t\t\t\t\t} catch (Exception ex) {\n\n\t\t\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\t\t\tex.printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"User connected jid: \" + rec.getUserJid() + \", fromNode: \" + fromNode);\n\t\t\t}\n\t\t}\n\t}\n\n\n\tprivate class UserPresenceCommand\n\t\t\t\t\textends CommandListenerAbstract {\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param name\n\t\t */\n\t\tpublic UserPresenceCommand(String name) {\n\t\t\tsuper(name, Priority.CLUSTER);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String,\n\t\t\t\tString> data, Queue<Element> packets)\n\t\t\t\tthrows ClusterCommandException {\n\n\t\t\t// ++clusterSyncInTraffic;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Called fromNode: {0}, visitedNodes: {1}, data: {2}, packets: {3}\",\n\t\t\t\t\t\tnew Object[] { fromNode,\n\t\t\t\t\t\tvisitedNodes, data, packets });\n\t\t\t}\n\n\t\t\tConnectionRecordIfc rec  = getConnectionRecord(fromNode, data);\n\t\t\tXMPPSession         session = sm.getXMPPSessions().get(rec.getUserJid()\n\t\t\t\t\t.getBareJID());\n\t\t\tElement             elem = packets.poll();\n\n\t\t\t// Notify strategy about presence update\n//    strategy.presenceUpdate(elem, rec);\n\t\t\t// Update all user's resources with the new presence\n\t\t\tif (session != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"User's {0} XMPPSession found: {1}\", new Object[] { rec\n\t\t\t\t\t\t\t.getUserJid().getBareJID(),\n\t\t\t\t\t\t\tsession });\n\t\t\t\t}\n\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveResources()) {\n\t\t\t\t\tElement conn_presence = conn.getPresence();\n\n\t\t\t\t\tif (conn.isAuthorized() && conn.isResourceSet() && (conn_presence != null)) {\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Send user's presence from remote connection to local connection\n\t\t\t\t\t\t\tPacket presence = Packet.packetInstance(elem);\n\n\t\t\t\t\t\t\tpresence.setPacketTo(conn.getConnectionId());\n\t\t\t\t\t\t\tsm.fastAddOutPacket(presence);\n\n\t\t\t\t\t\t\t// Send user's presence from local connection to remote connection\n\t\t\t\t\t\t\t// but only if this was an initial presence\n\t\t\t\t\t\t\tif ((data != null) && PRESENCE_TYPE_INITIAL.equals(data.get(\n\t\t\t\t\t\t\t\t\tPRESENCE_TYPE_KEY))) {\n\t\t\t\t\t\t\t\tpresence = Packet.packetInstance(conn_presence);\n\t\t\t\t\t\t\t\tpresence.setPacketTo(rec.getConnectionId());\n\t\t\t\t\t\t\t\tsm.fastAddOutPacket(presence);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (Exception ex) {\n\n\t\t\t\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\t\t\t\tex.printStackTrace();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsm.processPresenceUpdate(session, elem);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"No user session for presence update: {0}, visitedNodes: {1}, data: {2}, packets: {3}\",\n\t\t\t\t\t\t\tnew Object[] { fromNode,\n\t\t\t\t\t\t\tvisitedNodes, data, packets });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"User presence jid: \" + rec.getUserJid() + \", fromNode: \" + fromNode);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/DefaultClusteringStrategyAbstract.java",
    "content": "/*\n * DefaultClusteringStrategyAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.CommandListener;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\nimport tigase.cluster.strategy.cmd.PacketForwardCmd;\nimport tigase.server.Iq;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.cluster.api.SessionManagerClusteredIfc.SESSION_FOUND_KEY;\n\n/**\n * Created: May 13, 2009 9:53:44 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n *\n * @param <E>\n */\npublic abstract class DefaultClusteringStrategyAbstract<E extends ConnectionRecordIfc>\n\t\t\t\timplements ClusteringStrategyIfc<E> {\n\tprivate static final String ERROR_FORWARDING_KEY = \"error-forwarding\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\n\t\t\tDefaultClusteringStrategyAbstract.class.getName());\n\tprivate static final String PACKET_FORWARD_CMD = \"packet-forward-sm-cmd\";\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected ClusterControllerIfc cluster = null;\n\n\t// private ClusteringMetadataIfc<E> metadata = null;\n\n\t/** Field description */\n\tprotected SessionManagerClusteredIfc sm = null;\n\n\tprivate JID ampJID = null;\n\n\t/** Field description */\n\tprivate Set<CommandListener>        commands =\n\t\t\tnew CopyOnWriteArraySet<CommandListener>();\n\tprivate ErrorForwarding             errorForwarding = ErrorForwarding.drop;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate static enum ErrorForwarding { forward, drop }\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic DefaultClusteringStrategyAbstract() {\n\t\tsuper();\n\t\taddCommandListener(new PacketForwardCmd(PACKET_FORWARD_CMD, this));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cmd\n\t */\n\tpublic final void addCommandListener(CommandListener cmd) {\n\t\tcommands.add(cmd);\n\t}\n\n\t@Override\n\tpublic boolean containsJid(BareJID jid) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean containsJidLocally(BareJID jid) {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic boolean containsJidLocally(JID jid) {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void handleLocalPacket(Packet packet, XMPPResourceConnection conn) {}\n\n\t@Override\n\tpublic void handleLocalPresenceSet(XMPPResourceConnection conn) {\n\t\t// Do nothing\n\t}\n\n\t@Override\n\tpublic void handleLocalResourceBind(XMPPResourceConnection conn) {\n\t\t// Do nothing\n\t}\n\t\n\t@Override\n\tpublic void handleLocalUserLogin(BareJID userId, XMPPResourceConnection conn) {\n\n\t\t// Do nothing\n\t}\n\n\t@Override\n\tpublic void handleLocalUserLogout(BareJID userId, XMPPResourceConnection conn) {\n\n\t\t// Do nothing\n\t}\n\n\t@Override\n\tpublic void handleLocalUserChangedConnId(BareJID userId, XMPPResourceConnection conn, JID oldConnId, JID newConnId) {\n\t\t// Do nothing\n\t}\n\n\t@Override\n\tpublic boolean processPacket(Packet packet, XMPPResourceConnection conn) {\n\t\tList<JID> toNodes = getNodesForPacketForward(sm.getComponentId(), null, packet);\n\t\tboolean   result  = (toNodes != null) && (toNodes.size() > 0);\n\n\t\tif (result) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Forwarding packet {0} to nodes: {1}\", new Object[] {\n\t\t\t\t\t\tpacket,\n\t\t\t\t\t\ttoNodes });\n\t\t\t}\n\n\t\t\tMap<String, String> data = null;\n\n\t\t\tif (conn != null || packet.getPacketFrom() != null) {\n\t\t\t\tdata = new LinkedHashMap<String, String>();\n\t\t\t\tif (conn != null)\n\t\t\t\t\tdata.put(SESSION_FOUND_KEY, sm.getComponentId().toString());\n\t\t\t\tif (packet.getPacketFrom() != null)\n\t\t\t\t\tdata.put(PacketForwardCmd.PACKET_FROM_KEY, packet.getPacketFrom().toString());\n\t\t\t}\n\t\t\tcluster.sendToNodes(PACKET_FORWARD_CMD, data, packet.getElement(), sm\n\t\t\t\t\t.getComponentId(), null, toNodes.toArray(new JID[toNodes.size()]));\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No cluster nodes found for packet forward: {0}\",\n\t\t\t\t\t\tnew Object[] { packet });\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method attempts to send the packet to the next cluster node. Returns true\n\t * on successful attempt and false on failure. The true result does not mean\n\t * that the packet has been delivered though. Only that it was sent. The send\n\t * attempt may fail if there is no more cluster nodes to send the packet or if\n\t * the clustering strategy logic decided that the packet does not have to be\n\t * sent.\n\t *\n\t *\n\t * @param fromNode\n\t * @param data\n\t * @param packet\n\t *          to be sent to a next cluster node\n\t * @param visitedNodes\n\t *          a list of nodes already visited by the packet.\n\t * @return true if the packet was sent to next cluster node and false\n\t *         otherwise.\n\t */\n\tpublic boolean sendToNextNode(JID fromNode, Set<JID> visitedNodes, Map<String,\n\t\t\tString> data, Packet packet) {\n\t\tboolean   result    = false;\n\t\tList<JID> nextNodes = getNodesForPacketForward(fromNode, visitedNodes, packet);\n\n\t\tif ((nextNodes != null) && (nextNodes.size() > 0)) {\n\t\t\tcluster.sendToNodes(PACKET_FORWARD_CMD, data, packet.getElement(), fromNode,\n\t\t\t\t\tvisitedNodes, nextNodes.toArray(new JID[nextNodes.size()]));\n\t\t\tresult = true;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for packet: {0}, visitedNodes: {1}, result: {2}\",\n\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\tvisitedNodes, result });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getInfo();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic List<JID> getNodesConnected() {\n\t\treturn sm.getNodesConnected();\n\t}\n\n\t@Override\n\tpublic JID[] getConnectionIdsForJid(BareJID jid) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic E getConnectionRecord(JID jid) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic E getConnectionRecordInstance() {\n\t\treturn (E) (new ConnectionRecord());\n\t}\n\n\t@Override\n\tpublic Set<E> getConnectionRecords(BareJID bareJID) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = new HashMap<String, Object>();\n\n\t\tprops.put(ERROR_FORWARDING_KEY, ErrorForwarding.drop.name());\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getInfo() {\n\t\treturn \"basic strategy\";\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic Object getInternalCacheData() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param fromNode\n\t * @param visitedNodes\n\t * @param packet\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<JID>}\n\t */\n\tpublic List<JID> getNodesForPacketForward(JID fromNode, Set<JID> visitedNodes,\n\t\t\tPacket packet) {\n\n\t\t// If visited nodes is not null then we return null as this strategy never\n\t\t// sends packets in ring, the first node decides where to send a packet\n\t\tif (visitedNodes != null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tList<JID> nodes = null;\n\n//  JID jidLookup = packet.getStanzaTo();\n//\n//  // Presence status change set by the user have a special treatment:\n//  if (presenceStatusUpdate(packet)) {\n//    jidLookup = packet.getStanzaFrom();\n//  }\n\t\tif (isSuitableForForward(packet)) {\n\n\t\t\t// nodes = metadata.getNodesForJid(jidLookup);\n\t\t\tnodes = getNodesConnected();\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Selected nodes: {0}, for packet: {1}\", new Object[] {\n\t\t\t\t\t\tnodes,\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet not suitable for forwarding: {0}\", new Object[] {\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tfor (CommandListener cmd : commands) {\n\t\t\tcmd.getStatistics(list);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasCompleteJidsInfo() {\n\t\treturn false;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setClusterController(ClusterControllerIfc clComp) {\n\t\tcluster = clComp;\n\t\tfor (CommandListener cmd : commands) {\n\t\t\tcluster.removeCommandListener(cmd);\n\t\t\tcluster.setCommandListener(cmd);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) {\n\n\t\t// This code is bad as some commands are added in other methods and in\n\t\t// constructors - this code would break those commands!\n//\t\t// we need to remember that this method can be called more than once\n//\t\t// and we need to clean list of commands if we are adding any command here\n//\t\tCommandListener[] oldCmds = commands.toArray(new CommandListener[commands.size()]);\n//\n//\t\tfor (CommandListener oldCmd : oldCmds) {\n//\t\t\tif (PACKET_FORWARD_CMD.equals(oldCmd.getName())) {\n//\t\t\t\tcommands.remove(oldCmd);\n//\t\t\t}\n//\t\t}\n//\t\taddCommandListener(new PacketForwardCmd(PACKET_FORWARD_CMD, sm, this));\n\t\tif (props.containsKey(ERROR_FORWARDING_KEY)) {\n\t\t\terrorForwarding = ErrorForwarding.valueOf((String) props.get(ERROR_FORWARDING_KEY));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setSessionManagerHandler(SessionManagerClusteredIfc sm) {\n\t\tthis.sm = sm;\n\t\tthis.ampJID = JID.jidInstanceNS(\"amp\", sm.getComponentId().getDomain());\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean isSuitableForForward(Packet packet) {\n\t\tswitch (errorForwarding) {\n\t\tcase forward :\n\t\t\tbreak;\n\n\t\tdefault :\n\n\t\t\t// Do not forward any error packets by default\n\t\t\tif (packet.getType() == StanzaType.error) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\t// Artur: Moved it to the front of the method for performance reasons.\n\t\t// TODO: make sure it does not affect logic.\n\t\t// Andrzej: this blocks sending responses from other components if \n\t\t// packet was processed on other node that node of user session, ie.\n\t\t// when new PubSub clustered component is used\n//\t\tif ((packet.getPacketFrom() != null) &&!sm.getComponentId().equals(packet\n//\t\t\t\t.getPacketFrom())) {\n//\t\t\treturn false;\n//\t\t}\n\t\t// Andrzej: Added in place of condition which was checked above as due to\n\t\t// lack of this condition messages sent from client with \"from\" attribute\n\t\t// set are duplicated\t\n\t\tif (packet.getPacketFrom() != null && sm.hasXMPPResourceConnectionForConnectionJid(packet.getPacketFrom())) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// This is for packet forwarding logic.\n\t\t// Some packets are for certain not forwarded like packets without to\n\t\t// attribute set.\n\t\tif ((packet.getStanzaTo() == null) || sm.isLocalDomain(packet.getStanzaTo()\n\t\t\t\t.toString(), false) || sm.getComponentId().getBareJID().equals((packet\n\t\t\t\t.getStanzaTo().getBareJID()))) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Also packets sent from the server to user are not being forwarded like\n\t\t// service discovery perhaps?\n\t\tif ((packet.getStanzaFrom() == null) || sm.isLocalDomain(packet.getStanzaFrom()\n\t\t\t\t.toString(), false) || sm.getComponentId().getBareJID().equals((packet\n\t\t\t\t.getStanzaFrom().getBareJID()))) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the packet is to some external domain, it is not forwarded to other\n\t\t// nodes either. It is also not forwarded if it is addressed to some\n\t\t// component.\n\t\tif (!sm.isLocalDomain(packet.getStanzaTo().getDomain(), false)) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// server needs to respond on Iq stanzas sent to bare jid, but there is\n\t\t// no need to forward it to cluster node with users session\n\t\tif (packet.getElemName() == Iq.ELEM_NAME && packet.getStanzaTo() != null \n\t\t\t\t&& packet.getStanzaTo().getResource() == null)\n\t\t\treturn false;\n\n\t\tif (packet.getElemName() == Message.ELEM_NAME && packet.getType() != StanzaType.error && ampJID.equals(packet.getPacketFrom())) {\n\t\t\tElement amp = packet.getElement().getChild(\"amp\", \"http://jabber.org/protocol/amp\");\n\t\t\tif (amp != null && amp.getAttributeStaticStr(\"status\") == null)\n\t\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\t\n\tpublic SessionManagerClusteredIfc getSM() {\n\t\treturn this.sm;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/SMNonCachingAllNodes.java",
    "content": "/*\n * SMNonCachingAllNodes.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.cluster.strategy;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.xmppsession.SessionManagerHandler;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collections;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.Set;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\n\n/**\n * Created: May 13, 2009 9:53:44 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class SMNonCachingAllNodes\n\t\t\t\timplements ClusteringStrategyIfc<ConnectionRecord> {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(SMNonCachingAllNodes.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate SessionManagerClusteredIfc     sm            = null;\n\n\t// Simple random generator, we do not need a strong randomization here.\n\t// Just enough to ensure better traffic distribution\n\tprivate Random rand = new Random();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean containsJid(BareJID jid) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void nodeConnected(JID jid) {\n\t}\n\n\t@Override\n\tpublic void nodeDisconnected(JID jid) {\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic List<JID> getNodesConnected() {\n\t\treturn sm.getNodesConnected();\n\t}\n\n\t@Override\n\tpublic JID[] getConnectionIdsForJid(BareJID jid) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Set<ConnectionRecord> getConnectionRecords(BareJID bareJID) {\n\t\treturn null;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic Object getInternalCacheData() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic List<JID> getNodesForJid(JID jid) {\n\t\treturn getNodesConnected();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param fromNode\n\t * @param visitedNodes\n\t * @param packet\n\t *\n\t * \n\t */\n\tpublic List<JID> getNodesForPacketForward(JID fromNode, Set<JID> visitedNodes,\n\t\t\tPacket packet) {\n\n\t\t// If the packet visited other nodes already it means it went through other\n\t\t// checking\n\t\t// like isSuitableForForward, etc... so there is no need for doing it again\n\t\tif (visitedNodes != null) {\n\t\t\tList<JID> result = selectNodes(fromNode, visitedNodes);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Visited nodes not null: {0}, selecting new node: {1}, for packet: {2}\",\n\t\t\t\t\t\tnew Object[] { visitedNodes,\n\t\t\t\t\t\tresult, packet });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t// Presence status change set by the user have a special treatment:\n\t\tif ((packet.getElemName() == \"presence\") && (packet.getType() != StanzaType.error) &&\n\t\t\t\t(packet.getStanzaFrom() != null) && (packet.getStanzaTo() == null)) {\n\t\t\tList<JID> result = getNodesConnected();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Presence packet found: {0}, selecting all nodes: {1}\",\n\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\tresult });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t\tif (isSuitableForForward(packet)) {\n\t\t\tList<JID> result = selectNodes(fromNode, visitedNodes);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Visited nodes null, selecting new node: {0}, for packet: {1}\",\n\t\t\t\t\t\tnew Object[] { result,\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet not suitable for forwarding: {0}\", new Object[] {\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see tigase.cluster.strategy.ClusteringStrategyIfc#getNodesForUserConnect()\n\t */\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic List<JID> getNodesForUserConnect(JID jid) {\n\t\treturn getNodesConnected();\n\t}\n\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see\n\t * tigase.cluster.strategy.ClusteringStrategyIfc#getNodesForUserDisconnect()\n\t */\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic List<JID> getNodesForUserDisconnect(JID jid) {\n\t\treturn getNodesConnected();\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t}\n\n\t@Override\n\tpublic boolean hasCompleteJidsInfo() {\n\t\treturn false;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sm\n\t */\n\t@Override\n\tpublic void setSessionManagerHandler(SessionManagerClusteredIfc sm) {\n\t\tthis.sm = sm;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t */\n\tprotected boolean isSuitableForForward(Packet packet) {\n\n\t\t// Do not forward any error packets for now.\n\t\tif (packet.getType() == StanzaType.error) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Artur: Moved it to the front of the method for performance reasons.\n\t\t// TODO: make sure it does not affect logic.\n\t\tif ((packet.getPacketFrom() != null) &&!sm.getComponentId().equals(packet\n\t\t\t\t.getPacketFrom())) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// This is for packet forwarding logic.\n\t\t// Some packets are for certain not forwarded like packets without to\n\t\t// attribute set.\n\t\tif ((packet.getStanzaTo() == null) || sm.isLocalDomain(packet.getStanzaTo()\n\t\t\t\t.toString(), false) || sm.getComponentId().equals((packet.getStanzaTo()\n\t\t\t\t.getBareJID()))) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Also packets sent from the server to user are not being forwarded like\n\t\t// service discovery perhaps?\n\t\tif ((packet.getStanzaFrom() == null) || sm.isLocalDomain(packet.getStanzaFrom()\n\t\t\t\t.toString(), false) || sm.getComponentId().equals((packet.getStanzaFrom()\n\t\t\t\t.getBareJID()))) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the packet is to some external domain, it is not forwarded to other\n\t\t// nodes either. It is also not forwarded if it is addressed to some\n\t\t// component.\n\t\tif (!sm.isLocalDomain(packet.getStanzaTo().getDomain(), false)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * @param fromNode\n\t * @param visitedNodes\n\t * \n\t */\n\tprivate List<JID> selectNodes(JID fromNode, Set<JID> visitedNodes) {\n\t\tList<JID> result = null;\n\t\tList<JID> cl_nodes_list = getNodesConnected();\n\t\tint       size   = cl_nodes_list.size();\n\n\t\tif (size == 0) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No connected cluster nodes found, returning null\");\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tint idx = rand.nextInt(size);\n\n\t\tif ((visitedNodes == null) || (visitedNodes.size() == 0)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No visited nodes yet, trying random idx: \" + idx);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tresult = Collections.singletonList(cl_nodes_list.get(idx));\n\t\t\t} catch (IndexOutOfBoundsException ioobe) {\n\n\t\t\t\t// This may happen if the node disconnected in the meantime....\n\t\t\t\ttry {\n\t\t\t\t\tresult = Collections.singletonList(cl_nodes_list.get(0));\n\t\t\t\t} catch (IndexOutOfBoundsException ioobe2) {\n\n\t\t\t\t\t// Yes, this may happen too if there were only 2 nodes before\n\t\t\t\t\t// disconnect....\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"IndexOutOfBoundsException twice! Should not happen very often, returning null\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (JID jid : cl_nodes_list) {\n\t\t\t\tif (!visitedNodes.contains(jid)) {\n\t\t\t\t\tresult = Collections.singletonList(jid);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If all nodes visited already. We have to either send it back to the\n\t\t\t// first node\n\t\t\t// or if this is the first node return null\n\t\t\tif ((result == null) &&!sm.getComponentId().equals(fromNode)) {\n\t\t\t\tresult = Collections.singletonList(fromNode);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"All nodes visited, sending it back to the first node: \" + result);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"List of result nodes: \" + result);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/cluster/strategy/cmd/PacketForwardCmd.java",
    "content": "/*\n * PacketForwardCmd.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.strategy.cmd;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterCommandException;\nimport tigase.cluster.api.CommandListenerAbstract;\nimport tigase.cluster.api.SessionManagerClusteredIfc;\nimport tigase.cluster.SessionManagerClustered;\nimport tigase.cluster.strategy.DefaultClusteringStrategyAbstract;\n\nimport tigase.server.Packet;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport tigase.server.Priority;\n\n/**\n * Class description\n *\n *\n * @version        5.2.0, 13/06/22\n * @author         <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class PacketForwardCmd\n\t\t\t\textends CommandListenerAbstract {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(PacketForwardCmd.class.getName());\n\n\tpublic static final String PACKET_FROM_KEY = \"packet-from\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DefaultClusteringStrategyAbstract strategy;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t *\n\t * @param name\n\t * @param strategy\n\t */\n\tpublic PacketForwardCmd(String name, DefaultClusteringStrategyAbstract strategy) {\n\t\tsuper(name, Priority.HIGH);\n\t\tthis.strategy = strategy;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void executeCommand(JID fromNode, Set<JID> visitedNodes, Map<String,\n\t\t\tString> data, Queue<Element> packets)\n\t\t\t\t\tthrows ClusterCommandException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\"Called fromNode: {0}, visitedNodes: {1}, data: {2}, packets: {3}\",\n\t\t\t\t\tnew Object[] { fromNode,\n\t\t\t\t\tvisitedNodes, data, packets });\n\t\t}\n\t\tif ((packets != null) && (packets.size() > 0)) {\n\t\t\tSessionManagerClusteredIfc sm = getSM();\n\t\t\tfor (Element elem : packets) {\n\t\t\t\ttry {\n\t\t\t\t\tPacket                 el_packet = Packet.packetInstance(elem);\n\t\t\t\t\tString packetFromStr  = data.get(PACKET_FROM_KEY);\n\t\t\t\t\tif (packetFromStr != null)\n\t\t\t\t\t\tel_packet.setPacketFrom(JID.jidInstanceNS(packetFromStr));\n\t\t\t\t\tXMPPResourceConnection conn      = sm.getXMPPResourceConnection(el_packet);\n\t\t\t\t\tMap<String, String>    locdata   = null;\n\n\t\t\t\t\tif (conn != null) {\n\t\t\t\t\t\tlocdata = new LinkedHashMap<String, String>();\n\t\t\t\t\t\tif (data != null) {\n\t\t\t\t\t\t\tlocdata.putAll(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata.put(SessionManagerClusteredIfc.SESSION_FOUND_KEY, sm.getComponentId()\n\t\t\t\t\t\t\t\t.toString());\n\t\t\t\t\t}\n\n\t\t\t\t\t// The commented if below causes the packet to stop being forwarded\n\t\t\t\t\t// if it reached a host on which there is a user session to handle\n\t\t\t\t\t// it.\n\t\t\t\t\t// This is incorrect though, as there might be multiple users'\n\t\t\t\t\t// connections\n\t\t\t\t\t// to different nodes and each node should receive the packet.\n\t\t\t\t\t// if (conn != null || !sendToNextNode(fromNode, visitedNodes, data,\n\t\t\t\t\t// Packet.packetInstance(elem))) {\n\t\t\t\t\t// Instead, always send the packet to next node:\n\t\t\t\t\tboolean isSent;\n\n\t\t\t\t\tisSent = strategy.sendToNextNode(fromNode, visitedNodes, data, Packet\n\t\t\t\t\t\t\t.packetInstance(elem));\n\n\t\t\t\t\t// If there is a user session for the packet, process it\n\t\t\t\t\tif (conn != null) {\n\n\t\t\t\t\t\t// Hold on! If this is the first node (fromNode) it means the\n\t\t\t\t\t\t// packet was already processed here....\n\t\t\t\t\t\tif (!sm.getComponentId().equals(fromNode)) {\n\t\t\t\t\t\t\tsm.processPacket(el_packet, conn);\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Ignore the packet, it has been processed already\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// No user session, but if this is the first node the packet has\n\t\t\t\t\t\t// returned, so maybe this is a packet for offline storage?\n\t\t\t\t\t\tif (sm.getComponentId().equals(fromNode)) {\n\n\t\t\t\t\t\t\t// However it could have been processed on another node already\n\t\t\t\t\t\t\tif ((data == null) || (data.get(SessionManagerClustered\n\t\t\t\t\t\t\t\t\t.SESSION_FOUND_KEY) == null)) {\n\t\t\t\t\t\t\t\tsm.processPacket(el_packet, conn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.warning(\"Addressing problem, stringprep failed for packet: \" + elem);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.finest(\"Empty packets list in the forward command\");\n\t\t}\n\t}\n\t\n\tprivate SessionManagerClusteredIfc getSM() {\n\t\treturn strategy.getSM();\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/AbstractComponent.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.modules.Module;\nimport tigase.component.modules.ModuleProvider;\nimport tigase.component.modules.ModulesManager;\nimport tigase.component.modules.impl.AdHocCommandModule.ScriptCommandProcessor;\nimport tigase.component.responses.AsyncCallback;\nimport tigase.component.responses.ResponseManager;\nimport tigase.conf.ConfigurationException;\nimport tigase.disco.XMPPService;\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.disteventbus.EventHandler;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.DisableDisco;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Base class for implement XMPP Component.\n *\n * @author bmalkow\n *\n * @param <CTX>\n *            {@link Context} of component Should be extended.\n */\npublic abstract class AbstractComponent<CTX extends Context> extends AbstractMessageReceiver implements XMPPService,\nDisableDisco {\n\n\tprotected static final String COMPONENT = \"component\";\n\n\t/**\n\t * Context of component.\n\t */\n\tprotected final CTX context;\n\n\tprotected final ScriptCommandProcessor defaultScriptCommandProcessor = new ScriptCommandProcessor() {\n\n\t\t@Override\n\t\tpublic List<Element> getScriptItems(String node, JID jid, JID from) {\n\t\t\treturn AbstractComponent.this.getScriptItems(node, jid, from);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean processScriptCommand(Packet pc, Queue<Packet> results) {\n\t\t\treturn AbstractComponent.this.processScriptCommand(pc, results);\n\t\t}\n\t};\n\n\tprivate EventBus eventBus = new EventBus() {\n\n\t\tprivate final EventBus eventBus = EventBusFactory.getInstance();\n\n\t\t@Override\n\t\tpublic void addHandler(String name, String xmlns, EventHandler handler) {\n\t\t\teventBus.addHandler(name, xmlns, handler);\n\t\t}\n\n\t\t@Override\n\t\tpublic void fire(Element event) {\n\t\t\tevent.setAttribute(\"eventSource\", getComponentId().toString());\n\t\t\tevent.setAttribute(\"eventTimestamp\", Long.toString(System.currentTimeMillis()));\n\n\t\t\teventBus.fire(event);\n\t\t}\n\n\t\t@Override\n\t\tpublic void removeHandler(String name, String xmlns, EventHandler handler) {\n\t\t\teventBus.removeHandler(name, xmlns, handler);\n\t\t}\n\t};\n\n\t/** Logger */\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\t/** Modules manager */\n\tprotected final ModulesManager modulesManager;\n\n\tprivate ResponseManager responseManager;\n\n\tprotected PacketWriter writer = new PacketWriter() {\n\t\t@Override\n\t\tpublic void write(Collection<Packet> elements) {\n\t\t\tif (elements != null) {\n\t\t\t\tfor (Packet element : elements) {\n\t\t\t\t\tif (element != null) {\n\t\t\t\t\t\twrite(element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void write(Packet packet) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Sent: \" + packet.getElement());\n\t\t\t}\n\t\t\taddOutPacket(packet);\n\t\t}\n\n\t\t@Override\n\t\tpublic void write(Packet packet, AsyncCallback callback) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Sent: \" + packet.getElement());\n\t\t\t}\n\t\t\taddOutPacket(packet, callback);\n\t\t}\n\n\t};\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic AbstractComponent() {\n\t\tthis(null);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic AbstractComponent(Context context) {\n\t\tif (context == null) {\n\t\t\tthis.context = createContext();\n\t\t} else {\n\t\t\tthis.context = (CTX) context;\n\t\t}\n\n\t\tthis.modulesManager = new ModulesManager(this.context);\n\n\t\tthis.responseManager = new ResponseManager(this.context);\n\t}\n\n\tprotected void addOutPacket(Packet packet, AsyncCallback asyncCallback) {\n\t\tresponseManager.registerResponseHandler(packet, ResponseManager.DEFAULT_TIMEOUT, asyncCallback);\n\t\taddOutPacket(packet);\n\t}\n\n\t/**\n\t * Creates {@link Context} particular for component implementation. Called\n\t * once.\n\t *\n\t * @return context instance.\n\t */\n\tprotected abstract CTX createContext();\n\n\t/**\n\t * Creates instance of module.\n\t *\n\t * @param moduleClass\n\t *            class of module\n\t * @return instance of module.\n\t */\n\tprotected Module createModuleInstance(Class<Module> moduleClass) throws InstantiationException, IllegalAccessException,\n\tIllegalArgumentException, InvocationTargetException {\n\t\tlog.finer(\"Create instance of: \" + moduleClass.getName());\n\t\tfor (Constructor<?> x : moduleClass.getConstructors()) {\n\t\t\tObject[] args = new Object[x.getParameterTypes().length];\n\t\t\tboolean ok = true;\n\n\t\t\tfor (int i = 0; i < x.getParameterTypes().length; i++) {\n\t\t\t\tfinal Class<?> type = x.getParameterTypes()[i];\n\n\t\t\t\tObject value;\n\t\t\t\tif (type.isAssignableFrom(Context.class)) {\n\t\t\t\t\tvalue = context;\n\t\t\t\t} else if (type.isAssignableFrom(ScriptCommandProcessor.class)) {\n\t\t\t\t\tvalue = defaultScriptCommandProcessor;\n\t\t\t\t} else {\n\t\t\t\t\tvalue = null;\n\t\t\t\t}\n\n\t\t\t\tok = ok && value != null;\n\n\t\t\t\targs[i] = value;\n\t\t\t}\n\n\t\t\tif (ok) {\n\t\t\t\tlog.finest(\"Use constructor \" + x);\n\t\t\t\treturn (Module) x.newInstance(args);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic synchronized void everyMinute() {\n\t\tsuper.everyMinute();\n\t\tresponseManager.checkTimeouts();\n\t}\n\n\t/**\n\t * Returns version of component. Used for Service Discovery purposes.\n\t *\n\t * @return version of component.\n\t */\n\tpublic abstract String getComponentVersion();\n\n\t/**\n\t * Returns {@link Context} of component.\n\t *\n\t * @return\n\t */\n\tprotected CTX getContext() {\n\t\treturn context;\n\t}\n\n\t/**\n\t * Returns default map of components. Keys in map are used as component\n\t * identifiers.<br>\n\t *\n\t * This map may be modified by <code>init.properties</code>:<br>\n\t * <code>&lt;component_name&gt;/modules/&lt;module_name&gt;[S]=&lt;module_class&gt;</code>\n\t *\n\t *\n\t * @return map of default modules.\n\t */\n\tprotected abstract Map<String, Class<? extends Module>> getDefaultModulesList();\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tfinal Map<String, Object> props = super.getDefaults(params);\n\n\t\tMap<String, Class<? extends Module>> modules = getDefaultModulesList();\n\t\tif (modules != null)\n\t\t\tfor (Entry<String, Class<? extends Module>> m : modules.entrySet()) {\n\t\t\t\tprops.put(\"modules/\" + m.getKey(), m.getValue().getName());\n\t\t\t}\n\n\t\treturn props;\n\t}\n\n\tEventBus getEventBus() {\n\t\treturn eventBus;\n\t}\n\n\t/**\n\t * Returns {@link ModuleProvider}. It allows to retrieve instance of module\n\t * by given ID.\n\t *\n\t * @return {@link ModuleProvider}.\n\t */\n\tpublic ModuleProvider getModuleProvider() {\n\t\treturn modulesManager;\n\t}\n\n\tpublic ResponseManager getResponseManager() {\n\t\treturn responseManager;\n\t}\n\n\t/**\n\t * Returns {@link PacketWriter}.\n\t *\n\t * @return {@link PacketWriter}.\n\t */\n\tpublic PacketWriter getWriter() {\n\t\treturn writer;\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds); // To change body of generated methods,\n\n\t\t// choose Tools | Templates.\n\t\tbinds.put(COMPONENT, this);\n\t}\n\n\t/**\n\t * Initialising component modules.\n\t *\n\t * @param props\n\t *            component properties.\n\t */\n\tprotected void initModules(Map<String, Object> props) throws InstantiationException, IllegalAccessException,\n\tIllegalArgumentException, InvocationTargetException {\n\t\tfor (Entry<String, Object> e : props.entrySet()) {\n\t\t\ttry {\n\t\t\t\tif (e.getKey().startsWith(\"modules/\")) {\n\t\t\t\t\tfinal String id = e.getKey().substring(8);\n\t\t\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\t\t\tfinal Class<Module> moduleClass = (Class<Module>) Class.forName(e.getValue().toString());\n\t\t\t\t\tModule module = createModuleInstance(moduleClass);\n\t\t\t\t\tregisterModule(id, module);\n\t\t\t\t}\n\t\t\t} catch (ClassNotFoundException ex) {\n\t\t\t\tlog.warning(\"Cannot find Module class \" + e.getValue().toString() + \".\");\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Is this component discoverable by disco#items for domain by non admin\n\t * users.\n\t *\n\t * @return <code>true</code> - if yes\n\t */\n\tpublic abstract boolean isDiscoNonAdmin();\n\n\t/**\n\t * Checks if module with given identifier is registered already.\n\t *\n\t * @param id\n\t *            module identifier.\n\t * @return <code>true</code> if module is registered. Otherwise\n\t *         <code>false</code>.\n\t */\n\tpublic boolean isRegistered(final String id) {\n\t\treturn this.modulesManager.isRegistered(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Received: \" + packet.getElement());\n\t\t}\n\t\ttry {\n\t\t\tRunnable responseHandler = responseManager.getResponseHandler(packet);\n\n\t\t\tboolean handled;\n\t\t\tif (responseHandler != null) {\n\t\t\t\thandled = true;\n\t\t\t\tresponseHandler.run();\n\t\t\t} else {\n\t\t\t\thandled = this.modulesManager.process(packet);\n\t\t\t}\n\n\t\t\tif (!handled) {\n\t\t\t\tfinal String t = packet.getElement().getAttributeStaticStr(Packet.TYPE_ATT);\n\t\t\t\tfinal StanzaType type = (t == null) ? null : StanzaType.valueof(t);\n\n\t\t\t\tif (type != StanzaType.error) {\n\t\t\t\t\tthrow new ComponentException(Authorization.FEATURE_NOT_IMPLEMENTED);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(packet.getElemName() + \" stanza with type='error' ignored\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseStringprepException e) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, e.getMessage() + \" when processing \" + packet.toString());\n\t\t\t}\n\t\t\tsendException(packet, new ComponentException(Authorization.JID_MALFORMED));\n\t\t} catch (ComponentException e) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, e.getMessageWithPosition() + \" when processing \" + packet.toString());\n\t\t\t}\n\t\t\tsendException(packet, e);\n\t\t} catch (Exception e) {\n\t\t\tif (log.isLoggable(Level.SEVERE)) {\n\t\t\t\tlog.log(Level.SEVERE, e.getMessage() + \" when processing \" + packet.toString(), e);\n\t\t\t}\n\t\t\tsendException(packet, new ComponentException(Authorization.INTERNAL_SERVER_ERROR));\n\t\t}\n\t}\n\n\t/**\n\t * Registers module. If there is module registered with given ID, it will be\n\t * unregistered.\n\t *\n\t * @param id\n\t *            identifier of module.\n\t * @param module\n\t *            module instance.\n\t * @return currently registered module instance.\n\t */\n\tpublic <M extends Module> M registerModule(final String id, final M module) {\n\t\tif (this.modulesManager.isRegistered(id)) {\n\t\t\tthis.modulesManager.unregister(id);\n\t\t}\n\t\tM r = this.modulesManager.register(id, module);\n\t\treturn r;\n\t}\n\n\t/**\n\t * Converts {@link ComponentException} to XMPP error stanza and sends it to\n\t * sender of packet.\n\t *\n\t *\n\t * @param packet\n\t *            packet what caused exception.\n\t * @param e\n\t *            exception.\n\t */\n\tprotected void sendException(final Packet packet, final ComponentException e) {\n\t\ttry {\n\t\t\tfinal String t = packet.getElement().getAttributeStaticStr(Packet.TYPE_ATT);\n\n\t\t\tif ((t != null) && (t == \"error\")) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.finer(packet.getElemName() + \" stanza already with type='error' ignored\");\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPacket result = e.makeElement(packet, true);\n\t\t\tElement el = result.getElement();\n\n\t\t\tel.setAttribute(\"from\", BareJID.bareJIDInstance(el.getAttributeStaticStr(Packet.FROM_ATT)).toString());\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Sending back: \" + result.toString());\n\t\t\t}\n\t\t\tcontext.getWriter().write(result);\n\t\t} catch (Exception e1) {\n\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem during generate error response\", e1);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\ttry {\n\t\t\tinitModules(props);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't initialize modules!\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updateServiceEntity() {\n\t\tsuper.updateServiceEntity();\n\t\tthis.updateServiceDiscoveryItem(getName(), null, getDiscoDescription(), !isDiscoNonAdmin());\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/AbstractContext.java",
    "content": "package tigase.component;\n\nimport tigase.component.modules.ModuleProvider;\nimport tigase.disteventbus.EventBus;\nimport tigase.xmpp.JID;\n\n/**\n * Abstract basic implementation of {@linkplain Context} as delegator of\n * {@linkplain AbstractComponent}.\n * \n * @author bmalkow\n * \n */\npublic abstract class AbstractContext implements Context {\n\n\tprivate final AbstractComponent<?> component;\n\n\tpublic AbstractContext(AbstractComponent<?> component) {\n\t\tthis.component = component;\n\t}\n\n\t@Override\n\tpublic JID getComponentID() {\n\t\treturn component.getComponentId();\n\t}\n\n\t@Override\n\tpublic String getComponentVersion() {\n\t\treturn component.getComponentVersion();\n\t}\n\n\t@Override\n\tpublic String getDiscoCategory() {\n\t\treturn component.getDiscoCategory();\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn component.getDiscoCategoryType();\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn component.getDiscoDescription();\n\t}\n\n\t@Override\n\tpublic EventBus getEventBus() {\n\t\treturn component.getEventBus();\n\t}\n\n\t@Override\n\tpublic ModuleProvider getModuleProvider() {\n\t\treturn component.getModuleProvider();\n\t}\n\n\t@Override\n\tpublic PacketWriter getWriter() {\n\t\treturn component.getWriter();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/Context.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component;\n\nimport tigase.component.modules.ModuleProvider;\nimport tigase.disteventbus.EventBus;\nimport tigase.xmpp.JID;\n\n/**\n * Interface to provide configuration for an component.<br>\n * This interface should be extended if component requires access to database or\n * any other resources or informations.\n * \n * @author bmalkow\n * \n */\npublic interface Context {\n\n\tJID getComponentID();\n\n\t/**\n\t * Returns version of component. Used for Service Discovery purposes.\n\t * \n\t * @return version of component.\n\t */\n\tString getComponentVersion();\n\n\t/**\n\t * Returns category of component. Used for Service Discovery purposes.\n\t * \n\t * @return category of component.\n\t */\n\tString getDiscoCategory();\n\n\t/**\n\t * Returns type of component. Used for Service Discovery purposes.\n\t * \n\t * @return type of component.\n\t */\n\tString getDiscoCategoryType();\n\n\t/**\n\t * Returns human readable component name. Used for Service Discovery\n\t * purposes.\n\t * \n\t * @return name of component.\n\t */\n\tString getDiscoDescription();\n\n\t/**\n\t * Returns {@link EventBus}.\n\t * \n\t * @return {@link EventBus} instance.\n\t */\n\tEventBus getEventBus();\n\n\t/**\n\t * Returns {@link ModuleProvider}.\n\t * \n\t * @return {@link ModuleProvider} instance.\n\t */\n\tModuleProvider getModuleProvider();\n\n\t/**\n\t * Returns {@link PacketWriter}.\n\t * \n\t * @return {@link PacketWriter} instance.\n\t */\n\tPacketWriter getWriter();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/PacketWriter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component;\n\nimport java.util.Collection;\n\nimport tigase.component.responses.AsyncCallback;\nimport tigase.server.Packet;\n\n/**\n * Interface for writing {@linkplain Packet Packets} to XMPP stream.\n * \n * @author bmalkow\n * \n */\npublic interface PacketWriter {\n\n\t/**\n\t * Writes collection of {@linkplain Packet Packets}.\n\t * \n\t * @param packets\n\t *            collection of {@linkplain Packet Packets} to be written.\n\t */\n\tvoid write(Collection<Packet> packets);\n\n\t/**\n\t * Writes single {@linkplain Packet}.\n\t * \n\t * @param packet\n\t *            {@link Packet} to be written.\n\t */\n\tvoid write(final Packet packet);\n\n\tpublic void write(Packet packet, AsyncCallback callback);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport tigase.xmpp.JID;\n\npublic interface AdHocCommand {\n\n\tvoid execute(final AdhHocRequest request, AdHocResponse response) throws AdHocCommandException;\n\n\tString getName();\n\n\tString getNode();\n\n\tboolean isAllowedFor(JID jid);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocCommandException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\n\n/**\n * Class description\n * \n * \n */\npublic class AdHocCommandException extends Exception {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate Authorization errorCondition;\n\n\tprivate Element item;\n\n\tprivate String message;\n\n\tprivate String xmlns = \"urn:ietf:params:xml:ns:xmpp-stanzas\";\n\n\t/**\n\t * Constructs ...\n\t * \n\t * \n\t * @param errorCondition\n\t */\n\tpublic AdHocCommandException(final Authorization errorCondition) {\n\t\tthis(null, errorCondition, (String) null);\n\t}\n\n\t/**\n\t * Constructs ...\n\t * \n\t * \n\t * @param errorCondition\n\t * @param message\n\t */\n\tpublic AdHocCommandException(final Authorization errorCondition, String message) {\n\t\tthis(null, errorCondition, message);\n\t}\n\n\t/**\n\t * Constructs ...\n\t * \n\t * \n\t * @param item\n\t * @param errorCondition\n\t */\n\tpublic AdHocCommandException(final Element item, final Authorization errorCondition) {\n\t\tthis(item, errorCondition, (String) null);\n\t}\n\n\t/**\n\t * Constructs ...\n\t * \n\t * \n\t * @param item\n\t * @param errorCondition\n\t * @param message\n\t */\n\tpublic AdHocCommandException(final Element item, final Authorization errorCondition, final String message) {\n\t\tthis.item = item;\n\t\tthis.errorCondition = errorCondition;\n\t\tthis.message = message;\n\t}\n\n\t/**\n\t * @return Returns the code.\n\t */\n\tpublic String getCode() {\n\t\treturn String.valueOf(this.errorCondition.getErrorCode());\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @return\n\t */\n\tpublic Authorization getErrorCondition() {\n\t\treturn errorCondition;\n\t}\n\n\t/**\n\t * @return Returns the item.\n\t */\n\tpublic Element getItem() {\n\t\treturn item;\n\t}\n\n\t@Override\n\tpublic String getMessage() {\n\t\treturn message;\n\t}\n\n\t/**\n\t * @return Returns the name.\n\t */\n\tpublic String getName() {\n\t\treturn errorCondition.getCondition();\n\t}\n\n\t/**\n\t * @return Returns the type.\n\t */\n\tpublic String getType() {\n\t\treturn errorCondition.getErrorType();\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @return\n\t */\n\tpublic Element makeElement() {\n\t\treturn makeElement(true);\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param insertOriginal\n\t * \n\t * @return\n\t */\n\tpublic Element makeElement(boolean insertOriginal) {\n\t\tElement answer = insertOriginal ? item.clone() : new Element(item.getName());\n\n\t\tanswer.addAttribute(\"id\", item.getAttributeStaticStr(\"id\"));\n\t\tanswer.addAttribute(\"type\", \"error\");\n\t\tanswer.addAttribute(\"to\", item.getAttributeStaticStr(\"from\"));\n\t\tanswer.addAttribute(\"from\", item.getAttributeStaticStr(\"to\"));\n\t\tif (this.message != null) {\n\t\t\tElement text = new Element(\"text\", this.message, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-stanzas\" });\n\n\t\t\tanswer.addChild(text);\n\t\t}\n\t\tanswer.addChild(makeErrorElement());\n\n\t\treturn answer;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param sourceElement\n\t * \n\t * @return\n\t */\n\tpublic Element makeElement(Element sourceElement) {\n\t\tthis.item = sourceElement;\n\n\t\treturn makeElement(true);\n\t}\n\n\t/**\n\t * @return\n\t */\n\tpublic Element makeErrorElement() {\n\t\tElement error = new Element(\"error\");\n\n\t\terror.setAttribute(\"code\", String.valueOf(this.errorCondition.getErrorCode()));\n\t\terror.setAttribute(\"type\", this.errorCondition.getErrorType());\n\t\terror.addChild(new Element(this.errorCondition.getCondition(), new String[] { \"xmlns\" }, new String[] { xmlns }));\n\n\t\treturn error;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocCommandManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport tigase.component.adhoc.AdHocResponse.State;\nimport tigase.server.Packet;\nimport tigase.util.SimpleCache;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\n/**\n * Class description\n *\n *\n */\npublic class AdHocCommandManager {\n\tprivate final Map<String, AdHocCommand> commands = new HashMap<String, AdHocCommand>();\n\tprivate final SimpleCache<String, AdHocSession> sessions = new SimpleCache<String, AdHocSession>(100, 10 * 1000);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return\n\t */\n\tpublic Collection<AdHocCommand> getAllCommands() {\n\t\treturn this.commands.values();\n\t}\n\n\tpublic AdHocCommand getCommand(String nodeName) {\n\t\treturn this.commands.get(nodeName);\n\t}\n\n\t/**\n\t * Method checks if exists implementation for this command in this\n\t * CommandManager\n\t *\n\t * @param node\n\t * @return true - if command exists for this node\n\t */\n\tpublic boolean hasCommand(String node) {\n\t\treturn this.commands.containsKey(node);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * @return\n\t *\n\t * @throws AdHocCommandException\n\t */\n\tpublic Packet process(Packet packet) throws AdHocCommandException {\n\t\tfinal Element element = packet.getElement();\n\t\tfinal JID senderJid = packet.getStanzaFrom();\n\t\tfinal Element command = element.getChild(\"command\", \"http://jabber.org/protocol/commands\");\n\t\tfinal String node = command.getAttributeStaticStr(\"node\");\n\t\tfinal String action = command.getAttributeStaticStr(\"action\");\n\t\tfinal String sessionId = command.getAttributeStaticStr(\"sessionid\");\n\t\tAdHocCommand adHocCommand = getCommand(node);\n\n\t\tif (adHocCommand == null) {\n\t\t} else {\n\t\t\treturn process(packet, command, node, action, sessionId, adHocCommand);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic Packet process(Packet packet, Element commandElement, String node, String action, String sessionId,\n\t\t\tAdHocCommand adHocCommand) throws AdHocCommandException {\n\t\tState currentState = null;\n\t\tfinal AdhHocRequest request = new AdhHocRequest(packet, commandElement, node, packet.getStanzaFrom(), action,\n\t\t\t\tsessionId);\n\t\tfinal AdHocResponse response = new AdHocResponse(sessionId, currentState);\n\t\tfinal AdHocSession session = (sessionId == null) ? new AdHocSession() : this.sessions.get(sessionId);\n\n\t\tadHocCommand.execute(request, response);\n\n\t\tElement commandResult = new Element(\"command\", new String[] { \"xmlns\", \"node\", },\n\t\t\t\tnew String[] { \"http://jabber.org/protocol/commands\", node });\n\n\t\tcommandResult.addAttribute(\"status\", response.getNewState().name());\n\t\tif ((response.getCurrentState() == null) && (response.getNewState() == State.executing)) {\n\t\t\tthis.sessions.put(response.getSessionid(), session);\n\t\t} else if ((response.getSessionid() != null)\n\t\t\t\t&& ((response.getNewState() == State.canceled) || (response.getNewState() == State.completed))) {\n\t\t\tthis.sessions.remove(response.getSessionid());\n\t\t}\n\t\tif (response.getSessionid() != null) {\n\t\t\tcommandResult.addAttribute(\"sessionid\", response.getSessionid());\n\t\t}\n\t\tfor (Element r : response.getElements()) {\n\t\t\tcommandResult.addChild(r);\n\t\t}\n\n\t\treturn packet.okResult(commandResult, 0);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param command\n\t */\n\tpublic void registerCommand(AdHocCommand command) {\n\t\tif (!this.commands.containsKey(command.getNode()))\n\t\t\tthis.commands.put(command.getNode(), command);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocResponse.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.UUID;\n\nimport tigase.xml.Element;\n\npublic class AdHocResponse {\n\n\tstatic enum State {\n\t\tcanceled,\n\t\tcompleted,\n\t\texecuting\n\t}\n\n\tprivate final State currentState;\n\n\tprivate final ArrayList<Element> elements = new ArrayList<Element>();\n\n\tprivate State newState = State.completed;\n\n\tprivate String sessionid;\n\n\tAdHocResponse(String sessionid, State currState) {\n\t\tthis.sessionid = sessionid;\n\t\tthis.currentState = currState;\n\t}\n\n\tpublic void cancelSession() {\n\t\tthis.newState = State.canceled;\n\t}\n\n\tpublic void completeSession() {\n\t\tthis.newState = State.completed;\n\t}\n\n\tState getCurrentState() {\n\t\treturn currentState;\n\t}\n\n\tpublic Collection<Element> getElements() {\n\t\treturn elements;\n\t}\n\n\tState getNewState() {\n\t\treturn newState;\n\t}\n\n\tString getSessionid() {\n\t\treturn sessionid;\n\t}\n\n\tvoid setNewState(State newState) {\n\t\tthis.newState = newState;\n\t}\n\n\tvoid setSessionid(String sessionid) {\n\t\tthis.sessionid = sessionid;\n\t}\n\n\tpublic void startSession() {\n\t\tthis.newState = State.executing;\n\t\tthis.sessionid = UUID.randomUUID().toString();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocScriptCommandManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport java.util.List;\n\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\n/**\n * \n * @author andrzej\n */\npublic interface AdHocScriptCommandManager {\n\n\tList<Element> getCommandListItems(final JID senderJid, final JID toJid);\n\n\tList<Packet> process(Packet packet);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdHocSession.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\npublic class AdHocSession {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/adhoc/AdhHocRequest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.adhoc;\n\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\npublic class AdhHocRequest {\n\n\tprivate final String action;\n\n\tprivate final Element command;\n\n\tprivate final Packet iq;\n\n\tprivate final String node;\n\n\tprivate final JID sender;\n\n\tprivate final String sessionId;\n\n\tAdhHocRequest(Packet iq, Element command, String node, JID sender, String action, String sessionId) {\n\t\tsuper();\n\t\tthis.iq = iq;\n\t\tthis.command = command;\n\t\tthis.node = node;\n\t\tthis.action = action;\n\t\tthis.sessionId = sessionId;\n\t\tthis.sender = sender;\n\t}\n\n\tpublic String getAction() {\n\t\treturn action;\n\t}\n\n\tpublic Element getCommand() {\n\t\treturn command;\n\t}\n\n\tpublic Packet getIq() {\n\t\treturn iq;\n\t}\n\n\tpublic String getNode() {\n\t\treturn node;\n\t}\n\n\tpublic JID getSender() {\n\t\treturn sender;\n\t}\n\n\tpublic String getSessionId() {\n\t\treturn sessionId;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/exceptions/ComponentException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.exceptions;\n\nimport tigase.server.Packet;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.PacketErrorTypeException;\n\npublic class ComponentException extends Exception {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate Authorization errorCondition;\n\n\tprivate String text;\n\n\tpublic ComponentException(final Authorization errorCondition) {\n\t\tthis(errorCondition, (String) null, (String) null);\n\t}\n\n\t/**\n\t * \n\t * @param errorCondition\n\t * @param text\n\t *            human readable message will be send to client\n\t */\n\tpublic ComponentException(Authorization errorCondition, String text) {\n\t\tthis(errorCondition, text, (String) null);\n\t}\n\n\t/**\n\t * \n\t * @param errorCondition\n\t * @param message\n\t *            exception message for logging\n\t * @param text\n\t *            human readable message will be send to client\n\t */\n\tpublic ComponentException(Authorization errorCondition, String text, String message) {\n\t\tsuper(message);\n\t\tthis.errorCondition = errorCondition;\n\t\tthis.text = text;\n\t}\n\n\t/**\n\t * @return Returns the code.\n\t */\n\tpublic String getCode() {\n\t\treturn String.valueOf(this.errorCondition.getErrorCode());\n\t}\n\n\tpublic Authorization getErrorCondition() {\n\t\treturn errorCondition;\n\t}\n\n\tprotected String getErrorMessagePrefix() {\n\t\treturn \"XMPP error condition: \";\n\t}\n\n\t@Override\n\tpublic String getMessage() {\n\t\tfinal StringBuilder sb = new StringBuilder();\n\t\tsb.append(getErrorMessagePrefix());\n\t\tsb.append(errorCondition.getCondition()).append(\" \");\n\t\tif (text != null) {\n\t\t\tsb.append(\"with message: \\\"\").append(text).append(\"\\\" \");\n\t\t}\n\t\tif (super.getMessage() != null) {\n\t\t\tsb.append(\"(\").append(super.getMessage()).append(\") \");\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\tpublic String getMessageWithPosition() {\n\t\tfinal StringBuilder sb = new StringBuilder();\n\t\tsb.append(getMessage());\n\n\t\tStackTraceElement[] stack = getStackTrace();\n\t\tif (stack.length > 0) {\n\t\t\tsb.append(\"generated by \");\n\t\t\tsb.append(getStackTrace()[0].toString());\n\t\t\tsb.append(\" \");\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\t/**\n\t * @return Returns the name.\n\t */\n\tpublic String getName() {\n\t\treturn errorCondition.getCondition();\n\t}\n\n\tpublic String getText() {\n\t\treturn text;\n\t}\n\n\t/**\n\t * @return Returns the type.\n\t */\n\tpublic String getType() {\n\t\treturn errorCondition.getErrorType();\n\t}\n\n\tpublic Packet makeElement(Packet packet, boolean insertOriginal) throws PacketErrorTypeException {\n\t\tPacket result = errorCondition.getResponseMessage(packet, text, insertOriginal);\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/exceptions/RepositoryException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.exceptions;\n\npublic class RepositoryException extends Exception {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic RepositoryException() {\n\t\tsuper();\n\t}\n\n\tpublic RepositoryException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic RepositoryException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n\n\tpublic RepositoryException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/AbstractModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\nimport java.util.logging.Logger;\n\nimport tigase.component.Context;\nimport tigase.component.responses.AsyncCallback;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\n\n/**\n * Abstract class for help building a module. It has implemented few default\n * methods from {@link Module}, {@link ContextAware} and\n * {@link InitializingModule}.\n * \n * @author bmalkow\n * \n * @param <CTX>\n *            context of component.\n */\npublic abstract class AbstractModule<CTX extends Context> implements Module, ContextAware, InitializingModule {\n\n\tprotected CTX context;\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\t@Override\n\tpublic void afterRegistration() {\n\t}\n\n\t@Override\n\tpublic void beforeRegister() {\n\t\tif (context == null)\n\t\t\tthrow new RuntimeException(\"Context is not initialized!\");\n\t}\n\n\t/**\n\t * Fires event.\n\t * \n\t * @param event\n\t *            event to fire.\n\t */\n\tprotected void fireEvent(Element event) {\n\t\tcontext.getEventBus().fire(event);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@Override\n\tpublic void setContext(Context context) {\n\t\tthis.context = (CTX) context;\n\t}\n\n\t@Override\n\tpublic void unregisterModule() {\n\t}\n\n\t/**\n\t * Writes single {@linkplain Packet}.\n\t * \n\t * @param packet\n\t *            {@link Packet} to be written.\n\t */\n\tprotected void write(Packet packet) {\n\t\tcontext.getWriter().write(packet);\n\t}\n\n\tprotected void write(Packet packet, AsyncCallback asyncCallback) {\n\t\tcontext.getWriter().write(packet, asyncCallback);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/ContextAware.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\nimport tigase.component.Context;\n\n/**\n * Interface to be implemented by {@link Module} that wished to be aware of its\n * context.\n * \n * @author bmalkow\n * \n */\npublic interface ContextAware {\n\n\tvoid setContext(Context context);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/InitializingModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\n/**\n * Interface to be implemented by {@link Module modules} that need to be\n * informed about moments in module lifecycle.\n * \n * @author bmalkow\n * \n */\npublic interface InitializingModule {\n\n\t/**\n\t * Called after registration.\n\t */\n\tvoid afterRegistration();\n\n\t/**\n\t * Called before registering.\n\t */\n\tvoid beforeRegister();\n\n\t/**\n\t * Called before module is unregistered.\n\t */\n\tvoid unregisterModule();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/Module.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.criteria.Criteria;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\n\n/**\n * Basic interface to implement component module. Single module should implement\n * fragment of component logic. Is easy to add or remove in component (Server)\n * configuration.\n * \n * @author bmalkow\n * \n */\npublic interface Module {\n\n\t/**\n\t * Returns XMPP features offered by module. Features will be returned by\n\t * Service Discovery.\n\t * \n\t * @return array of features or <code>null</code>.\n\t */\n\tString[] getFeatures();\n\n\t/**\n\t * Returns critera used by Component to select module to handle incoming\n\t * stanza.\n\t * \n\t * @return criteria of selecting module.\n\t */\n\tCriteria getModuleCriteria();\n\n\t/**\n\t * Process incoming stanza.\n\t * \n\t * @param packet\n\t *            received {@link Packet stanza}.\n\t * @throws ComponentException\n\t *             if stanza can't be processed correctly. ComponentException is\n\t *             converted to error stanza and returned to stanza sender.\n\t * @throws TigaseStringprepException\n\t *             if there was an error during stringprep processing.\n\t */\n\tvoid process(final Packet packet) throws ComponentException, TigaseStringprepException;\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/ModuleProvider.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\nimport java.util.Set;\n\npublic interface ModuleProvider {\n\n\t/**\n\t * Returns features offered by registered modules.\n\t * \n\t * @return collection of available features.\n\t */\n\tpublic Set<String> getAvailableFeatures();\n\n\t/**\n\t * Return module implementation by module identifier.\n\t * \n\t * @param id\n\t *            identifier\n\t * @return module implementation.\n\t */\n\tpublic <T extends Module> T getModule(String id);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/ModulesManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.component.Context;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.criteria.Criteria;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\n\n/**\n * Implementation of modules provider. It keeps all registered modules and\n * decides what modules may handle incoming stanza.\n * \n * @author bmalkow\n * \n */\npublic class ModulesManager implements ModuleProvider {\n\n\tprivate Context context;\n\n\tprivate boolean dirty = true;\n\n\tprivate final Set<Module> initializationRequired = Collections.newSetFromMap(new ConcurrentHashMap<Module, Boolean>());\n\n\tprivate Logger log = Logger.getLogger(this.getClass().getName());\n\n\tprivate final ArrayList<Module> modules = new ArrayList<Module>();\n\n\tprivate final HashMap<String, Module> modulesById = new HashMap<String, Module>();\n\n\tpublic ModulesManager(Context context) {\n\t\tthis.context = context;\n\t}\n\n\t@Override\n\tpublic Set<String> getAvailableFeatures() {\n\t\tfinal HashSet<String> features = new HashSet<String>();\n\t\tfor (Module m : modules) {\n\t\t\tString[] fs = m.getFeatures();\n\t\t\tif (fs != null) {\n\t\t\t\tfor (String string : fs) {\n\t\t\t\t\tfeatures.add(string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn features;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@Override\n\tpublic <T extends Module> T getModule(String id) {\n\t\tinitIfRequired();\n\t\treturn (T) this.modulesById.get(id);\n\t}\n\n\tpublic void initIfRequired() {\n\t\tIterator<Module> it = this.initializationRequired.iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tModule module = it.next();\n\t\t\tit.remove();\n\t\t\tif (module instanceof InitializingModule) {\n\t\t\t\t((InitializingModule) module).afterRegistration();\n\t\t\t}\n\t\t}\n\t\tdirty = false;\n\t}\n\n\tpublic boolean isRegistered(final Module module) {\n\t\treturn this.modules.contains(module);\n\t}\n\n\tpublic boolean isRegistered(String id) {\n\t\treturn this.modulesById.containsKey(id);\n\t}\n\n\tpublic boolean process(final Packet packet) throws ComponentException, TigaseStringprepException {\n\t\tif (dirty)\n\t\t\tinitIfRequired();\n\n\t\tboolean handled = false;\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet.toString());\n\t\t}\n\n\t\tfor (Module module : this.modules) {\n\t\t\tCriteria criteria = module.getModuleCriteria();\n\t\t\tif (criteria != null && criteria.match(packet.getElement())) {\n\t\t\t\thandled = true;\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.finer(\"Handled by module \" + module.getClass());\n\t\t\t\t}\n\t\t\t\tmodule.process(packet);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Finished \" + module.getClass());\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn handled;\n\t}\n\n\tpublic synchronized <T extends Module> T register(final String id, final T module) {\n\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\tlog.config(\"Register Component module \" + id + \": \" + module.getClass().getCanonicalName());\n\n\t\t// if (skipIfExists) {\n\t\t// @SuppressWarnings(\"unchecked\")\n\t\t// T old = getByClass((Class<T>) module.getClass());\n\t\t// if (old != null)\n\t\t// return old;\n\t\t// }\n\n\t\tdirty = true;\n\n\t\tif (modulesById.containsKey(id)) {\n\t\t\tlog.config(\"Module \" + id + \" already registered. Skipped.\");\n\t\t\treturn null;\n\t\t}\n\n\t\tif (module instanceof ContextAware) {\n\t\t\t((ContextAware) module).setContext(context);\n\t\t}\n\n\t\tif (module instanceof InitializingModule) {\n\t\t\t((InitializingModule) module).beforeRegister();\n\t\t}\n\n\t\tthis.modules.add(module);\n\t\tthis.modulesById.put(id, module);\n\n\t\tinitializationRequired.add(module);\n\n\t\treturn module;\n\t}\n\n\tpublic synchronized void reset() {\n\t\tthis.modules.clear();\n\t\tthis.modulesById.clear();\n\t\tthis.initializationRequired.clear();\n\t}\n\n\tpublic synchronized void unregister(final Module module) {\n\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\tlog.config(\"Unregister Component module: \" + module.getClass().getCanonicalName());\n\n\t\tthis.modules.remove(module);\n\n\t\tIterator<Entry<String, Module>> it = this.modulesById.entrySet().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tEntry<String, Module> e = it.next();\n\t\t\tif (e.getValue().equals(module))\n\t\t\t\tit.remove();\n\t\t}\n\t\tthis.initializationRequired.remove(module);\n\n\t\tif (module instanceof InitializingModule) {\n\t\t\t((InitializingModule) module).unregisterModule();\n\t\t}\n\n\t}\n\n\tpublic void unregister(String id) {\n\t\tModule m = getModule(id);\n\t\tunregister(m);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/impl/AdHocCommandModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Queue;\n\nimport tigase.component.Context;\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocCommandManager;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.modules.AbstractModule;\nimport tigase.criteria.Criteria;\nimport tigase.criteria.ElementCriteria;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\npublic class AdHocCommandModule<CTX extends Context> extends AbstractModule<CTX> {\n\n\tpublic static interface ScriptCommandProcessor {\n\n\t\tList<Element> getScriptItems(String node, JID jid, JID from);\n\n\t\tboolean processScriptCommand(Packet pc, Queue<Packet> results);\n\n\t}\n\n\tprotected static final String[] COMMAND_PATH = { \"iq\", \"command\" };\n\n\tprotected static final Criteria CRIT = ElementCriteria.nameType(\"iq\", \"set\").add(\n\t\t\tElementCriteria.name(\"command\", Command.XMLNS));\n\n\tpublic final static String ID = \"commands\";\n\n\tpublic static final String XMLNS = Command.XMLNS;\n\n\tprotected AdHocCommandManager commandsManager;\n\n\tprotected ScriptCommandProcessor scriptProcessor;\n\n\tpublic AdHocCommandModule(ScriptCommandProcessor scriptProcessor) {\n\t\tthis.commandsManager = new AdHocCommandManager();\n\t\tthis.scriptProcessor = scriptProcessor;\n\t}\n\n\tpublic List<Element> getCommandListItems(final JID senderJid, final JID toJid) {\n\t\tArrayList<Element> commandsList = new ArrayList<Element>();\n\t\tfor (AdHocCommand command : this.commandsManager.getAllCommands()) {\n\t\t\tif (command.isAllowedFor(senderJid))\n\t\t\t\tcommandsList.add(new Element(\"item\", new String[] { \"jid\", \"node\", \"name\" }, new String[] { toJid.toString(),\n\t\t\t\t\t\tcommand.getNode(), command.getName() }));\n\t\t}\n\n\t\tList<Element> scriptCommandsList = scriptProcessor.getScriptItems(Command.XMLNS, toJid, senderJid);\n\t\tif (scriptCommandsList != null) {\n\t\t\tcommandsList.addAll(scriptCommandsList);\n\t\t}\n\t\treturn commandsList;\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn new String[] { Command.XMLNS };\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\tpublic List<Element> getScriptItems(String node, JID stanzaTo, JID stanzaFrom) {\n\t\tArrayList<Element> result = new ArrayList<Element>();\n\n\t\tfor (AdHocCommand c : commandsManager.getAllCommands()) {\n\t\t\tif (c.isAllowedFor(stanzaFrom)) {\n\t\t\t\tElement i = new Element(\"item\", new String[] { \"jid\", \"node\", \"name\" }, new String[] { stanzaTo.toString(),\n\t\t\t\t\t\tc.getNode(), c.getName() });\n\t\t\t\tresult.add(i);\n\t\t\t}\n\t\t}\n\n\t\tList<Element> scripts = scriptProcessor.getScriptItems(node, stanzaTo, stanzaFrom);\n\t\tif (scripts != null)\n\t\t\tresult.addAll(scripts);\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException {\n\t\tString node = packet.getAttributeStaticStr(COMMAND_PATH, \"node\");\n\t\tif (commandsManager.hasCommand(node)) {\n\t\t\ttry {\n\t\t\t\twrite(this.commandsManager.process(packet));\n\t\t\t} catch (AdHocCommandException e) {\n\t\t\t\tthrow new ComponentException(e.getErrorCondition(), e.getMessage());\n\t\t\t}\n\t\t} else {\n\t\t\tprocessScriptAdHoc(packet);\n\t\t}\n\t}\n\n\tprotected void processScriptAdHoc(Packet packet) {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tif (scriptProcessor.processScriptCommand(packet, results)) {\n\t\t\tfor (Packet p : results) {\n\t\t\t\twrite(p);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void register(AdHocCommand command) {\n\t\tthis.commandsManager.registerCommand(command);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/impl/DiscoveryModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules.impl;\n\nimport java.util.List;\n\nimport tigase.component.Context;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.exceptions.RepositoryException;\nimport tigase.component.modules.AbstractModule;\nimport tigase.criteria.Criteria;\nimport tigase.criteria.ElementCriteria;\nimport tigase.criteria.Or;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class DiscoveryModule<CTX extends Context> extends AbstractModule<CTX> {\n\n\tpublic final static String DISCO_INFO_XMLNS = \"http://jabber.org/protocol/disco#info\";\n\n\tpublic final static String DISCO_ITEMS_XMLNS = \"http://jabber.org/protocol/disco#items\";\n\n\tpublic final static String ID = \"disco\";\n\n\tprivate Criteria criteria;\n\n\tpublic DiscoveryModule() {\n\t\tthis.criteria = ElementCriteria.nameType(\"iq\", \"get\").add(\n\t\t\t\tnew Or(ElementCriteria.name(\"query\", DISCO_INFO_XMLNS), ElementCriteria.name(\"query\", DISCO_ITEMS_XMLNS)));\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn criteria;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException, TigaseStringprepException {\n\t\tfinal Element q = packet.getElement().getChild(\"query\");\n\t\tfinal JID senderJID = packet.getStanzaFrom();\n\t\tfinal JID jid = packet.getStanzaTo();\n\t\tfinal String node = q.getAttributeStaticStr(\"node\");\n\n\t\ttry {\n\t\t\tif (q.getXMLNS().equals(DISCO_INFO_XMLNS)) {\n\t\t\t\tprocessDiscoInfo(packet, jid, node, senderJID);\n\t\t\t} else if (q.getXMLNS().equals(DISCO_ITEMS_XMLNS) && node != null && node.equals(AdHocCommandModule.XMLNS)) {\n\t\t\t\tprocessAdHocCommandItems(packet, jid, node, senderJID);\n\t\t\t} else if (q.getXMLNS().equals(DISCO_ITEMS_XMLNS)) {\n\t\t\t\tprocessDiscoItems(packet, jid, node, senderJID);\n\t\t\t} else {\n\t\t\t\tthrow new ComponentException(Authorization.BAD_REQUEST);\n\t\t\t}\n\t\t} catch (ComponentException e) {\n\t\t\tthrow e;\n\t\t} catch (RepositoryException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprotected void processAdHocCommandItems(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tAdHocCommandModule<?> module = context.getModuleProvider().getModule(AdHocCommandModule.ID);\n\t\tif (module == null)\n\t\t\tthrow new ComponentException(Authorization.ITEM_NOT_FOUND);\n\n\t\tElement resultQuery = new Element(\"query\", new String[] { Packet.XMLNS_ATT }, new String[] { DISCO_ITEMS_XMLNS });\n\t\tPacket result = packet.okResult(resultQuery, 0);\n\n\t\tList<Element> items = module.getScriptItems(node, packet.getStanzaTo(), packet.getStanzaFrom());\n\n\t\tresultQuery.addChildren(items);\n\n\t\twrite(result);\n\t}\n\n\tprotected void processDiscoInfo(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tElement resultQuery = new Element(\"query\", new String[] { \"xmlns\" }, new String[] { DISCO_INFO_XMLNS });\n\t\tPacket resultIq = packet.okResult(resultQuery, 0);\n\n\t\tresultQuery.addChild(new Element(\"identity\", new String[] { \"category\", \"type\", \"name\" }, new String[] {\n\t\t\t\tcontext.getDiscoCategory(), context.getDiscoCategoryType(), context.getDiscoDescription() }));\n\t\tfor (String f : context.getModuleProvider().getAvailableFeatures()) {\n\t\t\tresultQuery.addChild(new Element(\"feature\", new String[] { \"var\" }, new String[] { f }));\n\t\t}\n\n\t\twrite(resultIq);\n\t}\n\n\tprotected void processDiscoItems(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tElement resultQuery = new Element(\"query\", new String[] { Packet.XMLNS_ATT }, new String[] { DISCO_ITEMS_XMLNS });\n\t\twrite(packet.okResult(resultQuery, 0));\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/impl/JabberVersionModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules.impl;\n\nimport tigase.component.Context;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.modules.AbstractModule;\nimport tigase.criteria.Criteria;\nimport tigase.criteria.ElementCriteria;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\n\n/**\n * Class description\n * \n * \n */\npublic class JabberVersionModule<CTX extends Context> extends AbstractModule<CTX> {\n\n\tprivate static final Criteria CRIT = ElementCriteria.nameType(\"iq\", \"get\").add(\n\t\t\tElementCriteria.name(\"query\", \"jabber:iq:version\"));\n\n\tpublic final static String ID = \"jabber:iq:version\";\n\n\tpublic JabberVersionModule() {\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn new String[] { \"jabber:iq:version\" };\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException {\n\t\tElement query = new Element(\"query\", new String[] { \"xmlns\" }, new String[] { \"jabber:iq:version\" });\n\n\t\tquery.addChild(new Element(\"name\", context.getDiscoDescription()));\n\t\tquery.addChild(new Element(\"version\", context.getComponentVersion()));\n\t\tquery.addChild(new Element(\"os\", System.getProperty(\"os.name\") + \"-\" + System.getProperty(\"os.arch\") + \"-\"\n\t\t\t\t+ System.getProperty(\"os.version\") + \", \" + System.getProperty(\"java.vm.name\") + \"-\"\n\t\t\t\t+ System.getProperty(\"java.version\") + \" \" + System.getProperty(\"java.vm.vendor\")));\n\n\t\twrite(packet.okResult(query, 0));\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/modules/impl/XmppPingModule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.component.modules.impl;\n\nimport tigase.component.Context;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.modules.AbstractModule;\nimport tigase.criteria.Criteria;\nimport tigase.criteria.ElementCriteria;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\n\npublic class XmppPingModule<CTX extends Context> extends AbstractModule<CTX> {\n\n\tprivate static final Criteria CRIT = ElementCriteria.nameType(\"iq\", \"get\").add(\n\t\t\tElementCriteria.name(\"ping\", \"urn:xmpp:ping\"));\n\n\tpublic XmppPingModule() {\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn new String[] { \"urn:xmpp:ping\" };\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\t@Override\n\tpublic void process(Packet iq) throws ComponentException {\n\t\tPacket reposnse = iq.okResult((Element) null, 0);\n\t\twrite(reposnse);\n\t}\n\n\tpublic final static String ID = \"urn:xmpp:ping\";\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/responses/AsyncCallback.java",
    "content": "package tigase.component.responses;\n\nimport tigase.server.Packet;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Main interface for callback of all <a\n * href='http://xmpp.org/rfcs/rfc6120.html#stanzas-semantics-iq'>IQ</a>\n * asynchronous request-response mechanism.\n * \n * @author bmalkow\n * \n */\npublic interface AsyncCallback {\n\n\t/**\n\t * Called when received response has type {@linkplain StanzaType#error\n\t * error}.\n\t * \n\t * @param responseStanza\n\t *            received IQ stanza\n\t * @param errorCondition \n\t *            error condition\n\t */\n\tvoid onError(Packet responseStanza, String errorCondition);\n\n\t/**\n\t * Called when received response has type {@linkplain StanzaType#result\n\t * result}.\n\t * \n\t * @param responseStanza\n\t *            received stanza\n\t */\n\tvoid onSuccess(Packet responseStanza);\n\n\t/**\n\t * Called when response wasn't received in given time.\n\t */\n\tvoid onTimeout();\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/responses/DefaultResponseHandler.java",
    "content": "package tigase.component.responses;\n\nimport tigase.component.responses.ResponseManager.Entry;\nimport tigase.server.Packet;\n\npublic class DefaultResponseHandler implements Runnable {\n\n\tprivate final Entry entry;\n\n\tprivate final Packet packet;\n\n\tpublic DefaultResponseHandler(Packet packet, ResponseManager.Entry entry) {\n\t\tthis.packet = packet;\n\t\tthis.entry = entry;\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\tfinal String type = this.packet.getElement().getAttributeStaticStr(\"type\");\n\n\t\tif (type != null && type.equals(\"result\")) {\n\t\t\tentry.getCallback().onSuccess(packet);\n\t\t} else if (type != null && type.equals(\"error\")) {\n\t\t\tString condition = packet.getErrorCondition();\n\t\t\tentry.getCallback().onError(packet, condition);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/component/responses/ResponseManager.java",
    "content": "package tigase.component.responses;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.logging.Logger;\n\nimport tigase.component.Context;\nimport tigase.server.Packet;\nimport tigase.xmpp.JID;\n\npublic class ResponseManager {\n\n\tprotected static final class Entry {\n\n\t\tprivate final AsyncCallback callback;\n\n\t\tprivate final JID jid;\n\n\t\tprivate final long timeout;\n\n\t\tprivate final long timestamp;\n\n\t\tpublic Entry(JID jid, long timestamp, long timeout, AsyncCallback callback) {\n\t\t\tsuper();\n\t\t\tthis.jid = jid;\n\t\t\tthis.timestamp = timestamp;\n\t\t\tthis.timeout = timeout;\n\t\t\tthis.callback = callback;\n\t\t}\n\n\t\tAsyncCallback getCallback() {\n\t\t\treturn callback;\n\t\t}\n\n\t\tJID getJid() {\n\t\t\treturn jid;\n\t\t}\n\n\t\tlong getTimeout() {\n\t\t\treturn timeout;\n\t\t}\n\n\t\tlong getTimestamp() {\n\t\t\treturn timestamp;\n\t\t}\n\n\t}\n\n\tpublic static final long DEFAULT_TIMEOUT = 1000 * 60;\n\n\tprivate final Map<String, Entry> handlers = new HashMap<String, Entry>();\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\tpublic ResponseManager(Context context) {\n\t}\n\n\tpublic void checkTimeouts() {\n\t\tlong now = (new Date()).getTime();\n\t\tIterator<java.util.Map.Entry<String, Entry>> it = this.getHandlers().entrySet().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tjava.util.Map.Entry<String, Entry> e = it.next();\n\t\t\tif (e.getValue().timestamp + e.getValue().timeout < now) {\n\t\t\t\tit.remove();\n\t\t\t\te.getValue().callback.onTimeout();\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected Map<String, Entry> getHandlers() {\n\t\treturn handlers;\n\t}\n\n\t/**\n\t * Returns handler for response of sent {@code  <iq/>} stanza.\n\t * \n\t * @param element\n\t *            response {@code  <iq/>} stanza.\n\t * @return Runnable object with handler\n\t */\n\tpublic Runnable getResponseHandler(final Packet element) {\n\t\tif (!\"iq\".equals(element.getElemName()))\n\t\t\treturn null;\n\n\t\tfinal String type = element.getElement().getAttributeStaticStr(\"type\");\n\t\tif (type == null || type.equals(\"set\") || type.equals(\"get\"))\n\t\t\treturn null;\n\n\t\tfinal String id = element.getElement().getAttributeStaticStr(\"id\");\n\t\tif (id == null)\n\t\t\treturn null;\n\t\tfinal Entry entry = this.getHandlers().get(id);\n\t\tif (entry == null)\n\t\t\treturn null;\n\n\t\tif (!verify(element, entry))\n\t\t\treturn null;\n\n\t\tthis.getHandlers().remove(id);\n\n\t\tRunnable r = new DefaultResponseHandler(element, entry);\n\t\treturn r;\n\t}\n\n\t/**\n\t * Register callback for response of sent {@code <iq/>} stanza.\n\t * \n\t * @param stanza\n\t *            sent {@code <iq/>} stanza.\n\t * @param timeout\n\t *            timeout. After it method\n\t *            {@linkplain AsyncCallback#onTimeout() onTimeout()} will be\n\t *            called.\n\t * @param callback\n\t *            callback\n\t * @return id of stanza\n\t */\n\tpublic String registerResponseHandler(final Packet stanza, final Long timeout, final AsyncCallback callback) {\n\t\tif (stanza == null)\n\t\t\treturn null;\n\t\tJID to = stanza.getStanzaTo();\n\t\tString id = stanza.getElement().getAttributeStaticStr(\"id\");\n\t\tif (id == null) {\n\t\t\tid = UUID.randomUUID().toString();\n\t\t\tstanza.getElement().setAttribute(\"id\", id);\n\t\t}\n\n\t\tif (callback != null) {\n\t\t\tEntry entry = new Entry(to, (new Date()).getTime(), timeout == null ? DEFAULT_TIMEOUT : timeout, callback);\n\t\t\tthis.getHandlers().put(id, entry);\n\t\t}\n\n\t\treturn id;\n\t}\n\n\tprivate boolean verify(final Packet response, final Entry entry) {\n\t\tfinal JID jid = response.getStanzaFrom();\n\n\t\tif (jid != null && entry.jid != null && jid.getBareJID().equals(entry.jid.getBareJID())) {\n\t\t\treturn true;\n\t\t} else if (entry.jid == null && jid == null) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigItem.java",
    "content": "/*\n * ConfigItem.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.comp.RepositoryItemAbstract;\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.util.DataTypes;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n/**\n * Created: Dec 10, 2009 2:40:26 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConfigItem\n\t\t\t\textends RepositoryItemAbstract {\n\t/** Field description */\n\tpublic static final String CLUSTER_NODE_ATTR = \"cluster-node\";\n\n\t/** Field description */\n\tpublic static final String COMPONENT_NAME_ATTR = \"comp-name\";\n\n\t// public static final String CLUSTER_NODE_LABEL = \"Cluster node\";\n\n\t/** Field description */\n\tpublic static final String COMPONENT_NAME_LABEL = \"Component name\";\n\n\t/** Field description */\n\tpublic static final String FLAG_ATTR = \"flag\";\n\n\t/** Field description */\n\tpublic static final String KEY_NAME_ATTR = \"key-name\";\n\n\t/** Field description */\n\tpublic static final String KEY_NAME_LABEL = \"Property key name\";\n\n\t/** Field description */\n\tpublic static final String NODE_NAME_ATTR = \"node-name\";\n\n\t/** Field description */\n\tpublic static final String NODE_NAME_LABEL = \"Property node name\";\n\n\t/** Field description */\n\tpublic static final String REPO_ITEM_ELEM_NAME = \"prop\";\n\n\t/** Field description */\n\tpublic static final String VALUE_ATTR = \"value\";\n\n\t/** Field description */\n\tpublic static final String VALUE_LABEL = \"Propety value\";\n\n\t/** Field description */\n\tpublic static final String VALUE_TYPE_ATTR = \"value-type\";\n\n\t/**\n\t * Private logger for class instance.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ConfigItem.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String clusterNode        = null;\n\tprivate String compName           = null;\n\tprivate String keyName            = null;\n\tprivate long lastModificationTime = -1;\n\tprivate String nodeName           = null;\n\tprivate Object value              = null;\n\tprivate FLAGS flag                = FLAGS.DEFAULT;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum FLAGS { INITIAL, DEFAULT, UPDATED; }\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addCommandFields(Packet packet) {\n\n\t\t// Command.addFieldValue(packet, CLUSTER_NODE_LABEL,\n\t\t// (clusterNode != null ? clusterNode : \"\"));\n\t\tif (compName != null) {\n\t\t\tCommand.addTextField(packet, COMPONENT_NAME_LABEL, compName);\n\t\t}\n\t\tif (nodeName != null) {\n\t\t\tCommand.addTextField(packet, NODE_NAME_LABEL, nodeName);\n\t\t}\n\t\tCommand.addTextField(packet, KEY_NAME_LABEL, ((keyName != null)\n\t\t\t\t\t\t? keyName\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addTextField(packet, \"    \", \"    \");\n\n\t\tString value_label = VALUE_LABEL;\n\t\tString value_str   = \"\";\n\n\t\tif (value != null) {\n\t\t\tvalue_str   = DataTypes.valueToString(value);\n\t\t\tvalue_label += \" [\" + DataTypes.getTypeId(value) + \"]\";\n\t\t}\n\t\tCommand.addFieldValue(packet, value_label, value_str);\n\t\tsuper.addCommandFields(packet);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getClusterNode() {\n\t\treturn clusterNode;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getCompName() {\n\t\treturn compName;\n\t}\n\n\t/**\n\t * Returns a configuration property key which is constructed in a following\n\t * way: <code>\n\t * nodeName + \"/\" + keyName\n\t * </code>\n\t *\n\t * \n\t */\n\tpublic String getConfigKey() {\n\t\treturn ((nodeName != null)\n\t\t\t\t\t\t? nodeName + \"/\"\n\t\t\t\t\t\t: \"\") + keyName;\n\t}\n\n\t/**\n\t * Returns a configuration property value.\n\t *\n\t * \n\t */\n\tpublic Object getConfigVal() {\n\t\treturn value;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getConfigValToString() {\n\t\treturn (value == null)\n\t\t\t\t\t ? null\n\t\t\t\t\t : DataTypes.valueToString(value);\n\t}\n\n\t@Override\n\tpublic String getElemName() {\n\t\treturn REPO_ITEM_ELEM_NAME;\n\t}\n\n\tpublic FLAGS getFlag() {\n\t\treturn flag;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Returns ConfigItem key which is constructed in a following way:\n\t * {@code compName + \"/\" + nodeName + \"/\" + keyName}\n\t * \n\t */\n\t@Override\n\tpublic String getKey() {\n\t\treturn ((compName != null)\n\t\t\t\t\t\t? compName + \"/\"\n\t\t\t\t\t\t: \"\") + ((nodeName != null)\n\t\t\t\t\t\t\t\t\t\t ? nodeName + \"/\"\n\t\t\t\t\t\t\t\t\t\t : \"\") + keyName;\n\t}\n\n\t/**\n\t * Returns a property key which is constructed in a following way:\n\t * {@code keyName}\n\t */\n\tpublic String getKeyName() {\n\t\treturn keyName;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getNodeName() {\n\t\treturn nodeName;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initFromCommand(Packet packet) {\n\t\tsuper.initFromCommand(packet);\n\n\t\tString tmp = Command.getFieldValue(packet, COMPONENT_NAME_LABEL);\n\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tcompName = tmp;\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, NODE_NAME_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tnodeName = tmp;\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, KEY_NAME_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tkeyName = tmp;\n\t\t}\n\n\t\tString value_label = Command.getFieldKeyStartingWith(packet, VALUE_LABEL);\n\t\tchar t             = DataTypes.decodeTypeIdFromName(value_label);\n\n\t\ttmp = Command.getFieldValue(packet, value_label);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tvalue = DataTypes.decodeValueType(t, tmp);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param elem\n\t */\n\t@Override\n\tpublic void initFromElement(Element elem) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param propString\n\t */\n\t@Override\n\tpublic void initFromPropertyString(String propString) {\n\t\tint idx_eq    = propString.indexOf('=');\n\t\n\t\t// String key = prop[0].trim();\n\t\t// Object val = prop[1];\n\t\tString key = propString.substring(0, idx_eq);\n\t\tObject val = propString.substring(idx_eq + 1);\n\t\tString[] prop = idx_eq == -1 ? new String[] { propString } : new String[] { key, (String) val };\n\n\t\tif (key.matches(\".*\\\\[[LISBlisb]\\\\]$\")) {\n\t\t\tchar c = key.charAt(key.length() - 2);\n\n\t\t\tkey = key.substring(0, key.length() - 3);\n\t\t\tval = DataTypes.decodeValueType(c, prop[1]);\n\t\t}\n\n\t\tint idx1 = key.indexOf(\"/\");\n\n\t\tif (idx1 > 0) {\n\t\t\tString compNameMeth = key.substring(0, idx1);\n\t\t\tint idx2            = key.lastIndexOf(\"/\");\n\t\t\tString nodeNameMeth = null;\n\t\t\tString keyNameMeth  = key.substring(idx2 + 1);\n\n\t\t\tif (idx1 != idx2) {\n\t\t\t\tnodeNameMeth = key.substring(idx1 + 1, idx2);\n\t\t\t}\n\t\t\tset(compNameMeth, nodeNameMeth, keyNameMeth, val);\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException(\"You have to provide a key with at least\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" 'component_name/key_name': \" + key);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param comp\n\t * @param node\n\t * @param key\n\t *\n\t * \n\t */\n\tpublic boolean isCompNodeKey(String comp, String node, String key) {\n\t\treturn isComponent(comp) && isNode(node) && isKey(key);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param o\n\t *\n\t * \n\t */\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (o instanceof ConfigItem) {\n\t\t\treturn getKey().equals(((ConfigItem) o).getKey());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\t@Override\n\tpublic int hashCode() {\n\t\treturn getKey().hashCode();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Checks if the given component name is equal to this item compName.\n\t *\n\t * @param comp\n\t * \n\t */\n\tpublic boolean isComponent(String comp) {\n\t\tif (compName != comp) {\n\t\t\treturn (compName != null)\n\t\t\t\t\t\t ? compName.equals(comp)\n\t\t\t\t\t\t : false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if the given key is equal to this item keyName.\n\t *\n\t * @param key\n\t * \n\t */\n\tpublic boolean isKey(String key) {\n\t\tif (keyName != key) {\n\t\t\treturn (keyName != null)\n\t\t\t\t\t\t ? keyName.equals(key)\n\t\t\t\t\t\t : false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if the given node is equal to this item nodeName\n\t *\n\t * @param node\n\t * \n\t */\n\tpublic boolean isNode(String node) {\n\t\tif (nodeName != node) {\n\n\t\t\t// At least one is not null\n\t\t\treturn (nodeName != null)\n\t\t\t\t\t\t ? nodeName.equals(node)\n\t\t\t\t\t\t : false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if the given node and key are equal to this item nodeName and\n\t * keyName. This method call works the same way as following statement: {@code\n\t * isNode(node) && isKey(key)\n\t * }\n\t *\n\t * @param node\n\t * @param key\n\t * \n\t */\n\tpublic boolean isNodeKey(String node, String key) {\n\t\treturn isNode(node) && isKey(key);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clusterNode_m\n\t * @param compName_m\n\t * @param nodeName_m\n\t * @param key_m\n\t * @param value_str_m\n\t * @param val_type_m\n\t * @param flag_str_m\n\t */\n\tpublic void set(String clusterNode_m, String compName_m, String nodeName_m,\n\t\t\t\t\t\t\t\t\tString key_m, String value_str_m, char val_type_m, String flag_str_m) {\n\t\tObject value_m = DataTypes.decodeValueType(val_type_m, value_str_m);\n\t\tFLAGS flag_m   = FLAGS.DEFAULT;\n\n\t\ttry {\n\t\t\tflag_m = FLAGS.valueOf(flag_str_m);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"Incorrect config item flag: \" + flag_str_m + \", setting DEFAULT.\");\n\t\t\tflag_m = FLAGS.DEFAULT;\n\t\t}\n\t\tset(clusterNode_m, compName_m, nodeName_m, key_m, value_m, flag_m);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clusterNode_m\n\t * @param compName_m\n\t * @param nodeName_m\n\t * @param key_m\n\t * @param value_m\n\t * @param flag_m\n\t */\n\tpublic void set(String clusterNode_m, String compName_m, String nodeName_m,\n\t\t\t\t\t\t\t\t\tString key_m, Object value_m, FLAGS flag_m) {\n\t\tif (clusterNode_m != null) {\n\t\t\tthis.clusterNode = clusterNode_m;\n\t\t}\n\t\tif (compName_m != null) {\n\t\t\tthis.compName = compName_m;\n\t\t}\n\t\tif (nodeName_m != null) {\n\t\t\tthis.nodeName = nodeName_m;\n\t\t}\n\t\tif (key_m != null) {\n\t\t\tthis.keyName = key_m;\n\t\t}\n\t\tif (value_m != null) {\n\t\t\tthis.value = value_m;\n\t\t}\n\t\tif (flag_m != null) {\n\t\t\tthis.flag = flag_m;\n\t\t}\n\t\tlastModificationTime = System.currentTimeMillis();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName_m\n\t * @param nodeName_m\n\t * @param key_m\n\t * @param value_str_m\n\t * @param val_type_m\n\t * @param flag_str_m\n\t */\n\tpublic void set(String compName_m, String nodeName_m, String key_m, String value_str_m,\n\t\t\t\t\t\t\t\t\tchar val_type_m, String flag_str_m) {\n\t\tset(null, compName_m, nodeName_m, key_m, value_str_m, val_type_m, flag_str_m);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName\n\t * @param nodeName\n\t * @param key\n\t * @param value\n\t */\n\tpublic void set(String compName, String nodeName, String key, Object value) {\n\t\tset(null, compName, nodeName, key, value, null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clusterNode\n\t * @param compName\n\t * @param nodeName\n\t * @param key\n\t * @param value\n\t */\n\tpublic void set(String clusterNode, String compName, String nodeName, String key,\n\t\t\t\t\t\t\t\t\tObject value) {\n\t\tset(clusterNode, compName, nodeName, key, value, null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clusterNode\n\t * @param compName\n\t * @param nodeKey\n\t * @param value\n\t */\n\tpublic void setNodeKey(String clusterNode, String compName, String nodeKey,\n\t\t\t\t\t\t\t\t\t\t\t\t Object value) {\n\t\tint key_idx        = nodeKey.lastIndexOf(\"/\");\n\t\tString method_key  = nodeKey;\n\t\tString method_node = null;\n\n\t\tif (key_idx >= 0) {\n\t\t\tmethod_key  = nodeKey.substring(key_idx + 1);\n\t\t\tmethod_node = nodeKey.substring(0, key_idx);\n\t\t}\n\t\tset(clusterNode, compName, method_node, method_key, value);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// public static final String REPO_ITEM_ELEM_NAME = \"prop\";\n\t// public static final String CLUSTER_NODE_ATTR = \"cluster-node\";\n\t// public static final String COMPONENT_NAME_ATTR = \"comp-name\";\n\t// public static final String NODE_NAME_ATTR = \"node-name\";\n\t// public static final String KEY_NAME_ATTR = \"key-name\";\n\t// public static final String VALUE_ATTR = \"value\";\n\t// public static final String FLAG_ATTR = \"flag\";\n\t// public static final String VALUE_TYPE_ATTR = \"value-type\";\n\t//\n\t// private String clusterNode = null;\n\t// private String compName = null;\n\t// private String nodeName = null;\n\t// private String keyName = null;\n\t// private Object value = null;\n\t// private FLAGS flag = FLAGS.DEFAULT;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\t@Override\n\tpublic Element toElement() {\n\t\tElement elem = super.toElement();\n\n\t\tif (clusterNode != null) {\n\t\t\telem.addAttribute(CLUSTER_NODE_ATTR, clusterNode);\n\t\t}\n\t\telem.addAttribute(COMPONENT_NAME_ATTR, compName);\n\t\tif (nodeName != null) {\n\t\t\telem.addAttribute(NODE_NAME_ATTR, nodeName);\n\t\t}\n\t\telem.addAttribute(KEY_NAME_ATTR, keyName);\n\t\telem.addAttribute(VALUE_ATTR, DataTypes.valueToString(value));\n\t\telem.addAttribute(VALUE_TYPE_ATTR, \"\" + DataTypes.getTypeId(value));\n\t\telem.addAttribute(FLAG_ATTR, flag.name());\n\n\t\treturn elem;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\t@Override\n\tpublic String toPropertyString() {\n\t\tchar t        = DataTypes.getTypeId(value);\n\t\tString result = getKey() + \"[\" + t + \"]=\";\n\t\tString varr   = DataTypes.valueToString(value);\n\n\t\tresult += varr;\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\t@Override\n\tpublic String toString() {\n\t\treturn getKey() + \"=\" + value;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/25\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigRepositoryIfc.java",
    "content": "/*\n * ConfigRepositoryIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.comp.ComponentRepository;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Created: Dec 10, 2009 2:04:20 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ConfigRepositoryIfc\n\t\t\t\textends ComponentRepository<ConfigItem> {\n\t/** Field description */\n\tpublic static final String RELOAD_DELAY = \"--reload-delay\";\n\n\t/** Field description */\n\tpublic static final String RESOURCE_URI = \"--resource-uri\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns all known settings for the given component name.\n\t * @param compName\n\t * \n\t * @throws ConfigurationException\n\t */\n\tMap<String, Object> getProperties(String compName) throws ConfigurationException;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName\n\t *\n\t * \n\t */\n\tSet<ConfigItem> getItemsForComponent(String compName);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Sets/adds properties for the given component name.\n\t * @param compName\n\t * @param props\n\t * @throws ConfigurationException\n\t */\n\tvoid putProperties(String compName, Map<String, Object> props)\n\t\t\t\t\tthrows ConfigurationException;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns a configuration setting for a given component, node and key. If the\n\t * configuration parameters is not found, returns given default value.\n\t * @param compName\n\t * @param node\n\t * @param key\n\t * @param def\n\t * \n\t */\n\tObject get(String compName, String node, String key, Object def);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Puts/sets/adds/updates a configuration setting to the configuration repository.\n\t * @param compName\n\t * @param node\n\t * @param key\n\t * @param value\n\t */\n\tvoid set(String compName, String node, String key, Object value);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns all component names for which there are some configuration settings\n\t * available.\n\t * \n\t */\n\tString[] getCompNames();\n\n\t/**\n\t * Returns an array of all configuration keys for a given component and configuration\n\t * node.\n\t * @param compName\n\t * @param node\n\t * \n\t */\n\tString[] getKeys(String compName, String node);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Removes a configuration setting from the configuration repository.\n\t * @param compName\n\t * @param node\n\t * @param key\n\t */\n\tvoid remove(String compName, String node, String key);\n\n\t/**\n\t * Method adds an Item to the configuration repository where the key is\n\t * the item key constructed of component name, node name and property key name.\n\t * @param key\n\t * @param value\n\t * @throws ConfigurationException\n\t */\n\tvoid addItem(String key, Object value) throws ConfigurationException;\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * This is used to load a configuration for a selected cluster node. The configuration\n\t * repository (file or database) may contain settings for all cluster nodes, some\n\t * of the settings may be exclusive to one or another cluster node. This method\n\t * informs the repository what node name (hostname) it is running on.\n\t * @param hostname\n\t */\n\tvoid setDefHostname(String hostname);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tMap<String, Object> getInitProperties();\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/04\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigSQLRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.util.DataTypes;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 15, 2009 10:44:00 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConfigSQLRepository extends ConfigurationCache {\n\n\t/** Field description */\n\tpublic static final String CONFIG_REPO_URI_PROP_KEY = \"tigase-config-repo-uri\";\n\n\t/** Field description */\n\tpublic static final String CONFIG_REPO_URI_INIT_KEY = \"--tigase-config-repo-uri\";\n\n\t/**\n\t * Private logger for class instancess.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ConfigSQLRepository.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JDBCAccess dbAccess = new JDBCAccess();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addItem(String compName, ConfigItem item) {\n\t\tdbAccess.addItem(item);\n\t}\n\n\t@Override\n\tpublic Collection<ConfigItem> allItems() throws TigaseDBException {\n\t\treturn dbAccess.getAllItems();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getCompNames() {\n\t\treturn dbAccess.getComponentNames();\n\t}\n\n\t@Override\n\tpublic ConfigItem getItem(String compName, String node, String key) {\n\t\treturn dbAccess.getItem(compName, node, key);\n\t}\n\n\t@Override\n\tpublic Set<ConfigItem> getItemsForComponent(String compName) {\n\t\treturn dbAccess.getCompItems(compName);\n\t}\n\n\t@Override\n\tpublic String[] getKeys(String compName, String node) {\n\t\treturn dbAccess.getKeys(compName, node);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String repo_uri, Map<String, String> params) throws DBInitException {\n\t\tString config_db_uri = System.getProperty(CONFIG_REPO_URI_PROP_KEY);\n\n\t\tif (config_db_uri == null) {\n\t\t\tconfig_db_uri = (String) params.get(CONFIG_REPO_URI_INIT_KEY);\n\t\t}\n\n\t\tif (config_db_uri == null) {\n\t\t\tconfig_db_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t}\n\n\t\tif (config_db_uri == null) {\n\t\t\tlog.severe(\"Missing configuration database connection string.\");\n\t\t\tlog.severe(\"Tigase needs a database connection string to load configuration.\");\n\t\t\tlog.severe(\"You can provide it in a few ways and the Tigase server checks\");\n\t\t\tlog.severe(\"following parameters in the order below:\");\n\t\t\tlog.severe(\"1. System property: -Dtigase-config-repo-uri=db-connection-string\");\n\t\t\tlog.severe(\"2. init.properties file or command line parameter: \"\n\t\t\t\t\t+ \"--tigase-config-repo-uri=db-connection-string\");\n\t\t\tlog.severe(\"3. init.properties file or command line parameter: \"\n\t\t\t\t\t+ \"--user-db-uri=db-connection-string\");\n\t\t\tlog.severe(\"Please correct the error and restart the server.\");\n\t\t\tSystem.exit(1);\n\t\t}\n\n\t\ttry {\n\t\t\tdbAccess.initRepository(config_db_uri, null);\n\t\t} catch (SQLException ex) {\n\t\t\tlog.log(Level.SEVERE, \"Problem connecting to configuration database: \", ex);\n\t\t\tlog.severe(\"Please check whether the database connection string is correct: \"\n\t\t\t\t\t+ config_db_uri);\n\t\t\tSystem.exit(1);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeItem(String compName, ConfigItem item) {\n\t\tdbAccess.removeItem(item);\n\t}\n\n\t@Override\n\tpublic int size() {\n\t\treturn dbAccess.getPropertiesCount();\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class JDBCAccess {\n\n\t\t/** Field description */\n\t\tpublic static final String TABLE_NAME = \"tigase_configuration\";\n\t\tprivate static final String CLUSTER_NODE_COLUMN = \"cluster_node\";\n\t\tprivate static final String COMPONENT_NAME_COLUMN = \"component_name\";\n\t\tprivate static final String NODE_NAME_COLUMN = \"key_node\";\n\t\tprivate static final String KEY_NAME_COLUMN = \"key_name\";\n\t\tprivate static final String VALUE_COLUMN = \"value\";\n\t\tprivate static final String FLAG_COLUMN = \"flag\";\n\t\tprivate static final String VALUE_TYPE_COLUMN = \"value_type\";\n\t\tprivate static final String LAST_UPDATE_COLUMN = \"last_update\";\n\t\tprivate static final String CREATE_TABLE_QUERY = \"create table \" + TABLE_NAME + \" (\" + \"  \"\n\t\t\t+ COMPONENT_NAME_COLUMN + \" varchar(127) NOT NULL,\" + \"  \" + KEY_NAME_COLUMN\n\t\t\t+ \" varchar(127) NOT NULL,\" + \"  \" + VALUE_COLUMN + \" varchar(8191) NOT NULL,\" + \"  \"\n\t\t\t+ CLUSTER_NODE_COLUMN + \" varchar(255) NOT NULL DEFAULT '',\" + \"  \" + NODE_NAME_COLUMN\n\t\t\t+ \" varchar(127) NOT NULL DEFAULT '',\" + \"  \" + FLAG_COLUMN\n\t\t\t+ \" varchar(32) NOT NULL DEFAULT 'DEFAULT',\" + \"  \" + VALUE_TYPE_COLUMN\n\t\t\t+ \" varchar(8) NOT NULL DEFAULT 'S',\" + \"  \" + LAST_UPDATE_COLUMN + \" timestamp,\"\n\t\t\t+ \"  primary key(\" + CLUSTER_NODE_COLUMN + \", \" + COMPONENT_NAME_COLUMN + \", \"\n\t\t\t+ NODE_NAME_COLUMN + \", \" + KEY_NAME_COLUMN + \", \" + FLAG_COLUMN + \"))\";\n\t\tprivate static final String CLUSTER_NODE_WHERE_PART = \" (\" + CLUSTER_NODE_COLUMN + \" = '' \"\n\t\t\t+ \" OR \" + CLUSTER_NODE_COLUMN + \" = ?) \";\n\t\tprivate static final String ITEM_WHERE_PART = \" where \" + CLUSTER_NODE_WHERE_PART + \" AND (\"\n\t\t\t+ COMPONENT_NAME_COLUMN + \" = ?) \" + \" AND (\" + NODE_NAME_COLUMN + \" = ?) \" + \" AND (\"\n\t\t\t+ KEY_NAME_COLUMN + \" = ?) \";\n\n\t\tprivate static final String GET_ITEM_QUERY = \"select * from \" + TABLE_NAME + ITEM_WHERE_PART;\n\t\tprivate static final String ADD_ITEM_QUERY = \"insert into \" + TABLE_NAME + \" (\"\n\t\t\t+ CLUSTER_NODE_COLUMN + \", \" + COMPONENT_NAME_COLUMN + \", \" + NODE_NAME_COLUMN + \", \"\n\t\t\t+ KEY_NAME_COLUMN + \", \" + VALUE_COLUMN + \", \" + VALUE_TYPE_COLUMN + \", \" + FLAG_COLUMN\n\t\t\t+ \") \" + \" values (?, ?, ?, ?, ?, ?, ?)\";\n\t\tprivate static final String UPDATE_ITEM_QUERY = \"update \" + TABLE_NAME + \" set \" + VALUE_COLUMN\n\t\t\t+ \" = ? \" + \" where (\" + CLUSTER_NODE_COLUMN + \" = ?) \" + \" AND (\" + COMPONENT_NAME_COLUMN\n\t\t\t+ \" = ?) \" + \" AND (\" + NODE_NAME_COLUMN + \" = ?) \" + \" AND (\" + KEY_NAME_COLUMN + \" = ?)\";\n\t\tprivate static final String DELETE_ITEM_QUERY = \"delete from \" + TABLE_NAME + ITEM_WHERE_PART;\n\t\tprivate static final String GET_ALL_ITEMS_QUERY = \"select * from \" + TABLE_NAME + \" where \"\n\t\t\t+ CLUSTER_NODE_WHERE_PART;\n\t\tprivate static final String GET_COMPONENT_ITEMS_QUERY = \"select * from \" + TABLE_NAME\n\t\t\t+ \" where \" + CLUSTER_NODE_WHERE_PART + \" AND (\" + COMPONENT_NAME_COLUMN + \" = ?)\";\n\t\tprivate static final String GET_UPDATED_ITEMS_QUERY = \"select * from \" + TABLE_NAME + \" where \"\n\t\t\t+ CLUSTER_NODE_WHERE_PART + \" AND (\" + FLAG_COLUMN + \" <> 'INITIAL')\" + \" AND (\"\n\t\t\t+ LAST_UPDATE_COLUMN + \" > ?)\";\n\t\tprivate static final String GET_COMPONENT_NAMES_QUERY = \"select distinct(\"\n\t\t\t+ COMPONENT_NAME_COLUMN + \") from \" + TABLE_NAME + \" where \" + CLUSTER_NODE_COLUMN;\n\t\tprivate static final String GET_PROPERTIES_COUNT_QUERY = \"select count(*) as count from \"\n\t\t\t+ TABLE_NAME + \" where \" + CLUSTER_NODE_COLUMN;\n\t\tprivate static final String GET_KEYS_QUERY = \"select \" + KEY_NAME_COLUMN + \" from \"\n\t\t\t+ TABLE_NAME + \" where \" + CLUSTER_NODE_WHERE_PART + \" AND (\" + COMPONENT_NAME_COLUMN\n\t\t\t+ \" = ?)\" + \" AND (\" + NODE_NAME_COLUMN + \" = ?)\";\n\n\t\t//~--- fields -------------------------------------------------------------\n\n\t\tprivate DataRepository data_repo = null;\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * @param conn_str\n\t\t * @param params\n\t\t *\n\t\t * @throws SQLException\n\t\t */\n\t\tpublic void initRepository(String conn_str, Map<String, String> params) throws SQLException {\n\t\t\ttry {\n\t\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, params);\n\n\t\t\t\t// Check if DB is correctly setup and contains all required tables.\n\t\t\t\tcheckDB();\n\t\t\t\tdata_repo.initPreparedStatement(GET_ITEM_QUERY, GET_ITEM_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_ALL_ITEMS_QUERY, GET_ALL_ITEMS_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_COMPONENT_ITEMS_QUERY, GET_COMPONENT_ITEMS_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(ADD_ITEM_QUERY, ADD_ITEM_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(UPDATE_ITEM_QUERY, UPDATE_ITEM_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(DELETE_ITEM_QUERY, DELETE_ITEM_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_UPDATED_ITEMS_QUERY, GET_UPDATED_ITEMS_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_COMPONENT_NAMES_QUERY, GET_COMPONENT_NAMES_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_PROPERTIES_COUNT_QUERY, GET_PROPERTIES_COUNT_QUERY);\n\t\t\t\tdata_repo.initPreparedStatement(GET_KEYS_QUERY, GET_KEYS_QUERY);\n\t\t\t} catch (Exception e) {}\n\t\t}\n\n\t\tprivate void addItem(ConfigItem item) {\n\t\t\ttry {\n\t\t\t\tPreparedStatement addItemSt = data_repo.getPreparedStatement(null, ADD_ITEM_QUERY);\n\n\t\t\t\tsynchronized (addItemSt) {\n\t\t\t\t\taddItemSt.setString(1, ((item.getClusterNode() != null) ? item.getClusterNode() : \"\"));\n\t\t\t\t\taddItemSt.setString(2, item.getCompName());\n\t\t\t\t\taddItemSt.setString(3, ((item.getNodeName() != null) ? item.getNodeName() : \"\"));\n\t\t\t\t\taddItemSt.setString(4, item.getKeyName());\n\t\t\t\t\taddItemSt.setString(5, item.getConfigValToString());\n\t\t\t\t\taddItemSt.setString(6, \"\" + DataTypes.getTypeId(item.getConfigVal()));\n\t\t\t\t\taddItemSt.setString(7, item.getFlag().name());\n\t\t\t\t\taddItemSt.executeUpdate();\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\n\t\t\t\t// Maybe the configuration item is already there, let's try to update it then\n\t\t\t\ttry {\n\t\t\t\t\tPreparedStatement updateItemSt = data_repo.getPreparedStatement(null, UPDATE_ITEM_QUERY);\n\n\t\t\t\t\tsynchronized (updateItemSt) {\n\t\t\t\t\t\tupdateItemSt.setString(1, item.getConfigValToString());\n\t\t\t\t\t\tupdateItemSt.setString(2,\n\t\t\t\t\t\t\t\t((item.getClusterNode() != null) ? item.getClusterNode() : \"\"));\n\t\t\t\t\t\tupdateItemSt.setString(3, item.getCompName());\n\t\t\t\t\t\tupdateItemSt.setString(4, ((item.getNodeName() != null) ? item.getNodeName() : \"\"));\n\t\t\t\t\t\tupdateItemSt.setString(5, item.getKeyName());\n\t\t\t\t\t\tupdateItemSt.executeUpdate();\n\t\t\t\t\t}\n\t\t\t\t} catch (SQLException ex) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Problem adding/updating an item to DB: \" + item.toElement() + \"\\n\", ex);\n\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.warning(e + \"Exception while adding config item: \" + item.toString());\n\t\t\t}\n\t\t}\n\n\t\tprivate void checkDB() throws SQLException {\n\t\t\tResultSet rs = null;\n\t\t\tStatement st = null;\n\n\t\t\ttry {\n\t\t\t\tif ( !data_repo.checkTable(TABLE_NAME)) {\n\t\t\t\t\tst = data_repo.createStatement(null);\n\t\t\t\t\tst.executeUpdate(CREATE_TABLE_QUERY);\n\t\t\t\t} else {\n\t\t\t\t\tlog.info(\"DB for server configuration OK.\");\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(st, rs);\n\t\t\t\trs = null;\n\t\t\t\tst = null;\n\t\t\t}\n\t\t}\n\n\t\tprivate ConfigItem createItemFromRS(ResultSet rs) throws SQLException {\n\t\t\tConfigItem result = getItemInstance();\n\t\t\tString clusterNode = rs.getString(CLUSTER_NODE_COLUMN);\n\t\t\tString compName = rs.getString(COMPONENT_NAME_COLUMN);\n\t\t\tString nodeName = rs.getString(NODE_NAME_COLUMN);\n\t\t\tString keyName = rs.getString(KEY_NAME_COLUMN);\n\t\t\tString value_str = rs.getString(VALUE_COLUMN);\n\t\t\tString value_type = rs.getString(VALUE_TYPE_COLUMN);\n\t\t\tString flag_str = rs.getString(FLAG_COLUMN);\n\n\t\t\tresult.set(clusterNode, compName, nodeName, keyName, value_str, value_type.charAt(0),\n\t\t\t\t\tflag_str);\n\n\t\t\treturn result;\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\tprivate Collection<ConfigItem> getAllItems() {\n\t\t\tList<ConfigItem> result = new ArrayList<ConfigItem>();\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getAllItemsSt = data_repo.getPreparedStatement(null, GET_ALL_ITEMS_QUERY);\n\n\t\t\t\tsynchronized (getAllItemsSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetAllItemsSt.setString(1, getDefHostname());\n\t\t\t\t\t\trs = getAllItemsSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tConfigItem item = createItemFromRS(rs);\n\n\t\t\t\t\t\t\tif (item.getFlag() != ConfigItem.FLAGS.INITIAL) {\n\t\t\t\t\t\t\t\tresult.add(item);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tprivate Set<ConfigItem> getCompItems(String compName) {\n\t\t\tSet<ConfigItem> result = new LinkedHashSet<ConfigItem>();\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getCompItemsSt =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, GET_COMPONENT_ITEMS_QUERY);\n\n\t\t\t\tsynchronized (getCompItemsSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetCompItemsSt.setString(1, getDefHostname());\n\t\t\t\t\t\tgetCompItemsSt.setString(2, compName);\n\t\t\t\t\t\trs = getCompItemsSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tConfigItem item = createItemFromRS(rs);\n\n\t\t\t\t\t\t\tif (item.getFlag() != ConfigItem.FLAGS.INITIAL) {\n\t\t\t\t\t\t\t\tresult.add(item);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tprivate String[] getComponentNames() {\n\t\t\tList<String> result = new ArrayList<String>();\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getCompNamesSt =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, GET_COMPONENT_NAMES_QUERY);\n\n\t\t\t\tsynchronized (getCompNamesSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetCompNamesSt.setString(1, getDefHostname());\n\t\t\t\t\t\trs = getCompNamesSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tresult.add(rs.getString(COMPONENT_NAME_COLUMN));\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting component names from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result.toArray(new String[result.size()]);\n\t\t}\n\n\t\tprivate ConfigItem getItem(String compName, String node, String key) {\n\t\t\tConfigItem result = null;\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getItemSt = data_repo.getPreparedStatement(null, GET_ITEM_QUERY);\n\n\t\t\t\tsynchronized (getItemSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetItemSt.setString(1, getDefHostname());\n\t\t\t\t\t\tgetItemSt.setString(2, compName);\n\t\t\t\t\t\tgetItemSt.setString(3, node);\n\t\t\t\t\t\tgetItemSt.setString(4, key);\n\t\t\t\t\t\trs = getItemSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tConfigItem item = createItemFromRS(rs);\n\n\t\t\t\t\t\t\tif (item.getFlag() != ConfigItem.FLAGS.INITIAL) {\n\t\t\t\t\t\t\t\tresult = item;\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tprivate String[] getKeys(String compName, String node) {\n\t\t\tList<String> result = new ArrayList<String>();\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getKeysSt = data_repo.getPreparedStatement(null, GET_KEYS_QUERY);\n\n\t\t\t\tsynchronized (getKeysSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetKeysSt.setString(1, getDefHostname());\n\t\t\t\t\t\tgetKeysSt.setString(2, compName);\n\t\t\t\t\t\tgetKeysSt.setString(3, node);\n\t\t\t\t\t\trs = getKeysSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tresult.add(rs.getString(KEY_NAME_COLUMN));\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting keys from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result.toArray(new String[result.size()]);\n\t\t}\n\n\t\tprivate int getPropertiesCount() {\n\t\t\tint result = 0;\n\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getPropertiesCountSt =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, GET_PROPERTIES_COUNT_QUERY);\n\n\t\t\t\tsynchronized (getPropertiesCountSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetPropertiesCountSt.setString(1, getDefHostname());\n\t\t\t\t\t\trs = getPropertiesCountSt.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tresult = rs.getInt(\"count\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting elements count from DB: \", e);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\tprivate void removeItem(ConfigItem item) {\n\t\t\ttry {\n\t\t\t\tPreparedStatement deleteItemSt = data_repo.getPreparedStatement(null, DELETE_ITEM_QUERY);\n\n\t\t\t\tsynchronized (deleteItemSt) {\n\t\t\t\t\tdeleteItemSt.setString(1, ((item.getClusterNode() != null) ? item.getClusterNode() : \"\"));\n\t\t\t\t\tdeleteItemSt.setString(2, item.getCompName());\n\t\t\t\t\tdeleteItemSt.setString(3, ((item.getNodeName() != null) ? item.getNodeName() : \"\"));\n\t\t\t\t\tdeleteItemSt.setString(4, item.getKeyName());\n\t\t\t\t\tdeleteItemSt.executeUpdate();\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem removing an item from DB: \" + item.toElement(), e);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigXMLRepository.java",
    "content": "\n/*\n* @(#)ConfigXMLRepository.java   2010.01.14 at 04:39:54 PST\n*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.DBInitException;\nimport tigase.db.TigaseDBException;\nimport tigase.xml.db.NodeNotFoundException;\nimport tigase.xml.db.XMLDB;\nimport tigase.xml.db.XMLDBException;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Class <code>ConfigXMLRepository</code> provides access to configuration\n * settings.\n *\n * <p>\n * Created: Sat Nov 13 18:53:21 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConfigXMLRepository extends ConfigurationCache {\n\n\t/** Field description */\n\tpublic static final String COMPONENT_NODE = \"component\";\n\n\t/** Field description */\n\tpublic static final String ROOT_NODE = \"tigase-config\";\n\n\t/** Field description */\n\tpublic static final String XMPP_CONFIG_FILE_PROPERTY_KEY = \"xmpp.config.file\";\n\n\t/** Field description */\n\tpublic static final String XMPP_CONFIG_FILE_PROPERTY_VAL = \"xmpp_server.xml\";\n\tprivate static ConfigXMLRepository def_config = null;\n\tprivate static final Logger log = Logger.getLogger(\"tigase.conf.ConfigRepository\");\n\tprivate static Map<String, ConfigXMLRepository> configs = new LinkedHashMap<String,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tConfigXMLRepository>();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String config_file = null;\n\tprivate XMLDB xmldb = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic ConfigXMLRepository() {}\n\n\tprivate ConfigXMLRepository(final boolean debug) throws XMLDBException {\n\t\tconfig_file = System.getProperty(XMPP_CONFIG_FILE_PROPERTY_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t XMPP_CONFIG_FILE_PROPERTY_VAL);\n\t\tinit();\n\t\tdef_config = this;\n\t}\n\n\tprivate ConfigXMLRepository(final boolean debug, final String file)\n\t\t\t\t\tthrows XMLDBException {\n\t\tconfig_file = file;\n\t\tinit();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t *\n\t * @throws XMLDBException\n\t */\n\tpublic static ConfigXMLRepository getConfigRepository() throws XMLDBException {\n\t\treturn getConfigRepository(null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param file_name\n\t *\n\t * \n\t *\n\t * @throws XMLDBException\n\t */\n\tpublic static ConfigXMLRepository getConfigRepository(final String file_name)\n\t\t\t\t\tthrows XMLDBException {\n\t\treturn getConfigRepository(false, file_name);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param debug\n\t * @param file_name\n\t *\n\t * \n\t *\n\t * @throws XMLDBException\n\t */\n\tpublic static ConfigXMLRepository getConfigRepository(final boolean debug,\n\t\t\t\t\tfinal String file_name)\n\t\t\t\t\tthrows XMLDBException {\n\t\tConfigXMLRepository config = null;\n\n\t\tif (file_name == null) {\n\t\t\tconfig = def_config;\n\t\t}    // end of if (file_name == null)\n\t\t\t\t\t\telse {\n\t\t\tconfig = configs.get(file_name);\n\t\t}    // end of if (file_name == null) else\n\n\t\tif (config == null) {\n\t\t\tif (file_name == null) {\n\t\t\t\tconfig = new ConfigXMLRepository(debug);\n\t\t\t}    // end of if (file_name == null)\n\t\t\t\t\t\t\telse {\n\t\t\t\tconfig = new ConfigXMLRepository(debug, file_name);\n\t\t\t}    // end of if (file_name == null) else\n\t\t}      // end of if (config == null)\n\n\t\treturn config;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addItem(String compName, ConfigItem item) {\n\t\ttry {\n\t\t\txmldb.setData(item.getCompName(),\n\t\t\t\t\t\t\t\t\t\titem.getNodeName(),\n\t\t\t\t\t\t\t\t\t\titem.getKeyName(),\n\t\t\t\t\t\t\t\t\t\titem.getConfigVal());\n\t\t} catch (NodeNotFoundException e1) {\n\t\t\ttry {\n\t\t\t\txmldb.addNode1(item.getCompName());\n\t\t\t\txmldb.setData(item.getCompName(),\n\t\t\t\t\t\t\t\t\t\t\titem.getNodeName(),\n\t\t\t\t\t\t\t\t\t\t\titem.getKeyName(),\n\t\t\t\t\t\t\t\t\t\t\titem.getConfigVal());\n\t\t\t} catch (Exception e2) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Can't add item for compName=\" + item.getCompName() + \", node=\"\n\t\t\t\t\t\t\t\t+ item.getNodeName() + \", key=\" + item.getKeyName() + \", value=\"\n\t\t\t\t\t\t\t\t+ item.getConfigValToString(),\n\t\t\t\t\t\t\t\te2);\n\t\t\t}    // end of try-catch\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Can't add item for compName=\" + item.getCompName() + \", node=\"\n\t\t\t\t\t\t\t+ item.getNodeName() + \", key=\" + item.getKeyName() + \", value=\"\n\t\t\t\t\t\t\t+ item.getConfigValToString(),\n\t\t\t\t\t\t\te);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Collection<ConfigItem> allItems() throws TigaseDBException {\n\t\tSet<ConfigItem> result = new LinkedHashSet<ConfigItem>();\n\t\tString[] compNames = getCompNames();\n\n\t\tif (compNames != null) {\n\t\t\tfor (String comp : compNames) {\n\t\t\t\tresult.addAll(getItemsForComponent(comp));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getCompNames() {\n\t\tList<String> comps = xmldb.getAllNode1s();\n\n\t\tif (comps != null) {\n\t\t\treturn comps.toArray(new String[comps.size()]);\n\t\t}    // end of if (comps != null)\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ConfigItem getItem(String compName, String node, String key) {\n\t\ttry {\n\t\t\tObject value = xmldb.getData(compName, node, key, null);\n\t\t\tConfigItem item = getItemInstance();\n\n\t\t\titem.set(compName, node, key, value);\n\n\t\t\treturn item;\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Can't load value for compName=\" + compName + \", node=\" + node + \", key=\"\n\t\t\t\t\t\t\t+ key,\n\t\t\t\t\t\t\te);\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Set<ConfigItem> getItemsForComponent(String compName) {\n\t\tSet<ConfigItem> result = new LinkedHashSet<ConfigItem>();\n\t\tList<String> allNodes = new ArrayList<String>();\n\t\tString subnode = \"\";\n\n\t\tgetSubnodes(allNodes, compName, subnode);\n\n\t\tString[] keys = getKeys(compName, null);\n\n\t\tlog.config(\"Found keys: \" + Arrays.toString(keys));\n\t\taddVals(result, compName, null, keys);\n\n\t\tfor (String node : allNodes) {\n\t\t\tkeys = getKeys(compName, node);\n\t\t\tlog.config(\"In node : '\" + node + \"' found keys: \" + Arrays.toString(keys));\n\t\t\taddVals(result, compName, node, keys);\n\t\t}    // end of for (String node : allNodes)\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(final String root, final String node) {\n\t\ttry {\n\t\t\treturn xmldb.getKeys(root, node);\n\t\t}    // end of try\n\t\t\t\t\t\tcatch (NodeNotFoundException e) {\n\t\t\treturn null;\n\t\t}    // end of try-catch\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String repo_uri, Map<String, String> params) throws DBInitException {\n\t\tconfig_file = (String) params.get(\"-c\");\n\n\t\ttry {\n\t\t\tinit();\n\t\t} catch (XMLDBException ex) {\n\t\t\tthrow new DBInitException(\"Can not initialize configuration repository: \",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ex);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cls\n\t *\n\t * \n\t */\n\tpublic String nodeForPackage(Class cls) {\n\t\treturn cls.getPackage().getName().replace('.', '/');\n\t}\n\n\t@Override\n\tpublic void removeItem(String compName, ConfigItem item) {\n\t\ttry {\n\t\t\txmldb.removeData(item.getCompName(), item.getNodeName(), item.getKeyName());\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Can't remove item for compName=\" + item.getCompName() + \", node=\"\n\t\t\t\t\t\t\t+ item.getNodeName() + \", key=\" + item.getKeyName() + \", value=\"\n\t\t\t\t\t\t\t+ item.getConfigValToString(),\n\t\t\t\t\t\t\te);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int size() {\n\t\treturn (int) xmldb.getAllNode1sCount();\n\t}\n\n\t@Override\n\tpublic void store() throws TigaseDBException {\n\t\ttry {\n\t\t\txmldb.sync();\n\t\t} catch (IOException ex) {\n\t\t\tthrow new TigaseDBException(\"Problem saving configuration data: \", ex);\n\t\t}\n\t}\n\n\t/** ************ Old code ************ */\n\tprivate void addVals(Set<ConfigItem> props, String compName, String node,\n\t\t\t\t\t\t\t\t\t\t\t String[] keys) {\n\t\tif (keys != null) {\n\t\t\tfor (String key : keys) {\n\t\t\t\ttry {\n\t\t\t\t\tObject value = xmldb.getData(compName, node, key, null);\n\t\t\t\t\tConfigItem item = getItemInstance();\n\n\t\t\t\t\titem.set(compName, node, key, value);\n\t\t\t\t\tprops.add(item);\n\t\t\t\t} catch (NodeNotFoundException ex) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\"Can't load value for compName=\" + compName + \", node=\" + node\n\t\t\t\t\t\t\t\t\t+ \", key=\" + key,\n\t\t\t\t\t\t\t\t\tex);\n\t\t\t\t}\n\t\t\t}    // end of for (String key : keys)\n\t\t}      // end of if (keys != null)\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate void getSubnodes(List<String> result, String root, String node) {\n\t\tString[] subnodes = getSubnodes(root, node);\n\t\tString node_tmp = (node.equals(\"\") ? node : node + \"/\");\n\n\t\tif (subnodes != null) {\n\t\t\tfor (String subnode : subnodes) {\n\t\t\t\tresult.add(node_tmp + subnode);\n\t\t\t\tlog.config(\"Adding subnode: \" + node_tmp + subnode);\n\t\t\t\tgetSubnodes(result, root, node_tmp + subnode);\n\t\t\t}    // end of for (String subnode : subnodes)\n\t\t}      // end of if (subnodes != null)\n\t}\n\n\tprivate String[] getSubnodes(final String root, final String node) {\n\t\ttry {\n\t\t\treturn xmldb.getSubnodes(root, node);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\treturn null;\n\t\t}    // end of try-catch\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void init() throws XMLDBException {\n\t\ttry {\n\t\t\tif (new File(config_file).exists()) {\n\t\t\t\txmldb = new XMLDB(config_file);\n\t\t\t} else {\n\t\t\t\txmldb = XMLDB.createDB(config_file, ROOT_NODE, COMPONENT_NODE);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tlog.warning(\"Can not open existing configuration file, creating new one, \" + e);\n\t\t\txmldb = XMLDB.createDB(config_file, ROOT_NODE, COMPONENT_NODE);\n\t\t}    // end of try-catch\n\n\t\tconfigs.put(config_file, this);\n\t}\n}    // ConfigXMLRepository\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/Configurable.java",
    "content": "/*\n * Configurable.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\n\nimport tigase.server.ServerComponent;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\n\n/**\n * Interface Configurable\n *\n * Objects inheriting this interface can be configured. In Tigase system object\n * can't request configuration properties. Configuration of the object is passed\n * to it at some time. Actually it can be passed at any time. This allows\n * dynamic system reconfiguration at runtime.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface Configurable\n\t\t\t\textends ServerComponent {\n\t/** Field description */\n\tpublic static final String ADMINS_PROP_KEY = \"admins\";\n\n\t/** Field description */\n\tpublic static final String AMP_CLASS_NAME = \"tigase.server.amp.AmpComponent\";\n\n\t/** Field description */\n\tpublic static final String AMP_CLUST_CLASS_NAME = \"tigase.cluster.AmpComponentClustered\";\n\t\n\t/** Field description */\n\tpublic static final String BOSH_CLUST_COMP_CLASS_NAME =\n\t\t\t\"tigase.cluster.BoshConnectionClustered\";\n\n\t/** Field description */\n\tpublic static final String BOSH_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.bosh.BoshConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String C2S_CLUST_COMP_CLASS_NAME =\n\t\t\t\"tigase.cluster.ClientConnectionClustered\";\n\n\t/** Field description */\n\tpublic static final String C2S_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.xmppclient.ClientConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String CL_COMP_CLASS_NAME =\n\t\t\t\"tigase.cluster.ClusterConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_CONECT = \"cluster-connect\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_CONTR_CLASS_NAME =\n\t\t\t\"tigase.cluster.ClusterController\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_LISTEN = \"cluster-listen\";\n\n\t/**\n\t * Constant <code>CLUSTER_MODE</code> sets the cluster mode to either\n\t * <code>true</code> or <code>false</code>. By default cluster mode is\n\t * set to <code>false</code>.\n\t */\n\tpublic static final String CLUSTER_MODE = \"--cluster-mode\";\n\n\t/**\n\t * Constant <code>CLUSTER_NODES</code> is for setting list of cluster nodes\n\t * the instance should try to connect to.\n\t */\n\tpublic static final String CLUSTER_NODES = \"--cluster-nodes\";\n\n\t/** Field description */\n\tpublic static final String CLUSTER_NODES_PROP_KEY = \"cluster-nodes\";\n\n\t/** Field description */\n\tpublic static final String COMP_PROT_CLASS_NAME = \"tigase.server.ext.ComponentProtocol\";\n\n\t/** Field description */\n\tpublic static final String COMPONENT_ID_PROP_KEY = \"component-id\";\n\n\t/** Field description */\n\tpublic static final String DEF_AMP_NAME = \"amp\";\n\n\t/** Field description */\n\tpublic static final String DEF_BOSH_NAME = \"bosh\";\n\n\t/** Field description */\n\tpublic static final String DEF_C2S_NAME = \"c2s\";\n\n\t/** Field description */\n\tpublic static final String DEF_CL_COMP_NAME = \"cl-comp\";\n\n\t/** Field description */\n\tpublic static final String DEF_CLUST_CONTR_NAME = \"cluster-contr\";\n\n\t/** Field description */\n\tpublic static final String DEF_COMP_PROT_NAME = \"ext\";\n\n\t/** Field description */\n\tpublic static final String DEF_EVENTBUS_NAME = \"eventbus\";\n\t\n\t/** Field description */\n\tpublic static final String DEF_EXT_COMP_NAME = \"ext-comp\";\n\n\t/** Field description */\n\tpublic static final String DEF_HOSTNAME_PROP_KEY = \"def-hostname\";\n\n\t/** Field description */\n\tpublic static final String DEF_MONITOR_NAME = \"monitor\";\n\n\t/** Field description */\n\tpublic static final String DEF_S2S_NAME = \"s2s\";\n\n\t/** Field description */\n\tpublic static final String DEF_SM_NAME = \"sess-man\";\n\n\t/** Field description */\n\tpublic static final String DEF_SRECV_NAME = \"srecv\";\n\n\t/** Field description */\n\tpublic static final String DEF_SSEND_NAME = \"ssend\";\n\n\t/** Field description */\n\tpublic static final String DEF_STATS_NAME = \"stats\";\n\n\t/** Field description */\n\tpublic static final String DEF_VHOST_MAN_NAME = \"vhost-man\";\n\n\t/** Field description */\n\tpublic static final String DEF_WS2S_NAME = \"ws2s\";\n\n\t/** Field description */\n\tpublic static final String EVENTBUS_CLASS_NAME = \"tigase.disteventbus.component.EventBusComponent\";\n\t\n\t/** Field description */\n\tpublic static final String EXT_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.xmppcomponent.ComponentConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String GEN_ADMINS = \"--admins\";\n\n\t/** Field description */\n\tpublic static final String GEN_COMP_CLASS = \"--comp-class\";\n\n\t/** Field description */\n\tpublic static final String GEN_COMP_NAME = \"--comp-name\";\n\n\t/** Field description */\n\tpublic static final String GEN_CONF = \"--gen-\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG</code> keeps the string with which all\n\t * configuration types starts.\n\t */\n\tpublic static final String GEN_CONFIG = \"--gen-config\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG_ALL</code> keeps parameter name for configuration\n\t * with all available components loaded directly to the server.\n\t */\n\tpublic static final String GEN_CONFIG_ALL = GEN_CONFIG + \"-all\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG_SM</code> keeps parameter name for configuration\n\t * with SessionManager loaded and XEP-0114 component preconfigured to connect\n\t * to server instance with ClientConnectionManager.\n\t */\n\tpublic static final String GEN_CONFIG_SM = GEN_CONFIG + \"-sm\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG_DEF</code> keeps parameter name for the most\n\t * typical configuration: SessionManager, ClientConnectionManager and\n\t * ServerConnectionManager loaded.\n\t */\n\tpublic static final String GEN_CONFIG_DEF = GEN_CONFIG + \"-default\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG_CS</code> keeps parameter name for configuration\n\t * with ClientConnectionManager loaded and XEP-0114 component preconfigured\n\t * to connect to server instance with SessionManager loaded.\n\t */\n\tpublic static final String GEN_CONFIG_CS = GEN_CONFIG + \"-cs\";\n\n\t/**\n\t * Constant <code>GEN_CONFIG_COMP</code> keeps parameter name for\n\t * configuration with a single (given as an extra parameter) component\n\t * and XEP-0114 or XEP-0225 component loaded and preconfigured to connect to other\n\t * Jabber/XMPP server instance (either Tigase or any different server).\n\t */\n\tpublic static final String GEN_CONFIG_COMP = GEN_CONFIG + \"-comp\";\n\n\t/** Field description */\n\tpublic static final String GEN_DEBUG = \"--debug\";\n\n\t/** Field description */\n\tpublic static final String GEN_DEBUG_PACKAGES = \"--debug-packages\";\n\n\t/** Field description */\n\tpublic static final String GEN_EXT_COMP = \"--ext-comp\";\n\n\t/** Field description */\n\tpublic static final String GEN_MAX_QUEUE_SIZE = \"--max-queue-size\";\n\n\t/** Field description */\n\tpublic static final String GEN_SCRIPT_DIR = \"--script-dir\";\n\n\t/** Field description */\n\tpublic static final String GEN_SM_PLUGINS = \"--sm-plugins\";\n\n\t/** Field description */\n\tpublic static final String GEN_SREC_ADMINS = \"--gen-srec-admins\";\n\n\t/** Field description */\n\tpublic static final String GEN_SREC_DB = \"--gen-srec-db\";\n\n\t/** Field description */\n\tpublic static final String GEN_SREC_DB_URI = \"--gen-srec-db-uri\";\n\n\t/** Field description */\n\tpublic static final String GEN_TEST = \"--test\";\n\n\t/** Field description */\n\tpublic static final String GEN_TRUSTED = \"--trusted\";\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String GEN_USER_DB = RepositoryFactory.GEN_USER_DB;\n\n\t/** Field description */\n\tpublic static final String GEN_VIRT_HOSTS = \"--virt-hosts\";\n\n\t/** Field description */\n\tpublic static final String HOSTNAMES_PROP_KEY = \"hostnames\";\n\n\t/** Field description */\n\tpublic static final String MONITOR_CLASS_NAME =\n\t\t\t\"tigase.monitor.MonitorComponent\";\n\n\t/** Field description */\n\tpublic static final String MONITOR_CLUST_CLASS_NAME = \"tigase.cluster.MonitorClustered\";\n\n\t/** Field description */\n\tpublic static final String MONITORING = \"--monitoring\";\n\n\t/** Field description */\n\tpublic static final String ROUTER_COMP_CLASS_NAME = \"tigase.server.MessageRouter\";\n\n\t/** Field description */\n\tpublic static final String S2S_CLUST_COMP_CLASS_NAME =\n\t\t\t\"tigase.cluster.S2SConnectionClustered\";\n\n\t/** Field description */\n\tpublic static final String S2S_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.xmppserver.S2SConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String SM_CLUST_COMP_CLASS_NAME =\n\t\t\t\"tigase.cluster.SessionManagerClustered\";\n\n\t/** Field description */\n\tpublic static final String SM_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.xmppsession.SessionManager\";\n\n\t/** Field description */\n\tpublic static final String SRECV_COMP_CLASS_NAME =\n\t\t\t\"tigase.server.sreceiver.StanzaReceiver\";\n\n\t/** Field description */\n\tpublic static final String SSEND_COMP_CLASS_NAME = \"tigase.server.ssender.StanzaSender\";\n\n\t/** Field description */\n\tpublic static final String STANZA_WHITE_CHAR_ACK = \"white-char\";\n\n\t/** Field description */\n\tpublic static final String STANZA_XMPP_ACK = \"xmpp\";\n\n\t/** Field description */\n\tpublic static final String STATS_CLASS_NAME = \"tigase.stats.StatisticsCollector\";\n\n\t/** Field description */\n\tpublic static final String STRINGPREP_PROCESSOR = \"--stringprep-processor\";\n\n\t/** Field description */\n\tpublic static final String TRUSTED_PROP_KEY = \"trusted\";\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_POOL_CLASS = RepositoryFactory\n\t\t\t.USER_REPO_POOL_CLASS;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_DOMAIN_POOL_CLASS = RepositoryFactory\n\t\t\t.USER_DOMAIN_POOL_CLASS;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String GEN_USER_DB_URI_PROP_KEY = RepositoryFactory\n\t\t\t.GEN_USER_DB_URI_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String GEN_USER_DB_URI = \"--\" + RepositoryFactory\n\t\t\t.GEN_USER_DB_URI_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String GEN_AUTH_DB_URI = RepositoryFactory.GEN_AUTH_DB_URI;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String GEN_AUTH_DB = RepositoryFactory.GEN_AUTH_DB;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_REPO_POOL_CLASS = RepositoryFactory\n\t\t\t.AUTH_REPO_POOL_CLASS;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS = RepositoryFactory\n\t\t\t.AUTH_DOMAIN_POOL_CLASS;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_POOL_SIZE = RepositoryFactory.USER_REPO_POOL_SIZE;\n\n\t/** Field description */\n\tpublic static final String VHOST_MAN_CLASS_NAME = \"tigase.vhosts.VHostManager\";\n\n\t/** Field description */\n\tpublic static final String VHOST_MAN_CLUST_CLASS_NAME =\n\t\t\t\"tigase.cluster.VHostManagerClustered\";\n\n\t/** Field description */\n\tpublic static final String WS2S_CLASS_NAME =\n\t\t\t\"tigase.server.websocket.WebSocketClientConnectionManager\";\n\n\t/** Field description */\n\tpublic static final String WS2S_CLUST_CLASS_NAME =\n\t\t\t\"tigase.cluster.WebSocketClientConnectionClustered\";\n\n\t/** Field description */\n\tpublic static final String XMPP_STANZA_ACK = \"--stanza-ack\";\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String XML_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.XML_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String XML_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.XML_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_URL_PROP_KEY = RepositoryFactory\n\t\t\t.USER_REPO_URL_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_POOL_SIZE_PROP_KEY = RepositoryFactory\n\t\t\t.USER_REPO_POOL_SIZE_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_PARAMS_NODE = RepositoryFactory\n\t\t\t.USER_REPO_PARAMS_NODE;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_REPO_DOMAINS_PROP_KEY = RepositoryFactory\n\t\t\t.USER_REPO_DOMAINS_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String TIGASE_CUSTOM_AUTH_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.TIGASE_CUSTOM_AUTH_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String TIGASE_AUTH_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.TIGASE_AUTH_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String TIGASE_AUTH_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.TIGASE_AUTH_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String SHARED_USER_REPO_PROP_KEY = RepositoryFactory\n\t\t\t.SHARED_USER_REPO_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String SHARED_USER_REPO_PARAMS_PROP_KEY = RepositoryFactory\n\t\t\t.SHARED_USER_REPO_PARAMS_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated\n\t */\n\t@Deprecated\n\tpublic static final String SHARED_AUTH_REPO_PROP_KEY = RepositoryFactory\n\t\t\t.SHARED_AUTH_REPO_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String SHARED_AUTH_REPO_PARAMS_PROP_KEY = RepositoryFactory\n\t\t\t.SHARED_AUTH_REPO_PARAMS_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String PGSQL_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.PGSQL_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String PGSQL_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.PGSQL_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String MYSQL_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.MYSQL_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String MYSQL_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.MYSQL_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String LIBRESOURCE_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.LIBRESOURCE_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String LIBRESOURCE_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.LIBRESOURCE_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String DUMMY_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.DUMMY_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String DRUPALWP_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.DRUPALWP_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String DRUPAL_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.DRUPAL_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String DERBY_REPO_URL_PROP_VAL = RepositoryFactory\n\t\t\t.DERBY_REPO_URL_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String DERBY_REPO_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.DERBY_REPO_CLASS_PROP_VAL;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_REPO_URL_PROP_KEY = RepositoryFactory\n\t\t\t.AUTH_REPO_URL_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_REPO_PARAMS_NODE = RepositoryFactory\n\t\t\t.AUTH_REPO_PARAMS_NODE;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_REPO_DOMAINS_PROP_KEY = RepositoryFactory\n\t\t\t.AUTH_REPO_DOMAINS_PROP_KEY;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns default configuration settings for the component as a\n\t * <code>Map</code> with keys as configuration property IDs and values as the\n\t * configuration property values. All the default parameters returned from\n\t * this method are later passed to the <code>setProperties(...)</code> method.\n\t * Some of them may have changed value if they have been overwritten in the\n\t * server configuration. The configuration property value can be of any of the\n\t * basic types: <code>int</code>, <code>long</code>, <code>boolean</code>,\n\t * <code>String</code>.\n\t *\n\t * @param params\n\t *          is a <code>Map</code> with some initial properties set for the\n\t *          starting up server. These parameters can be used as a hints to\n\t *          generate component's default configuration.\n\t *\n\t * @return a <code>Map</code> with the component default configuration.\n\t */\n\tMap<String, Object> getDefaults(Map<String, Object> params);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Sets all configuration properties for the object.\n\t *\n\t * @param properties {@link Map} with the configuration\n\t *\n\t * @throws tigase.conf.ConfigurationException - if setting configuration will\n\t *                                            fail which will make it unable\n\t *                                            to work\n\t */\n\tvoid setProperties(Map<String, Object> properties) throws ConfigurationException;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigurationCache.java",
    "content": "/*\n * ConfigurationCache.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.comp.RepositoryChangeListenerIfc;\nimport tigase.db.TigaseDBException;\n\nimport tigase.util.DataTypes;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.FileWriter;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\nimport tigase.db.DBInitException;\n\n/**\n * Created: Dec 10, 2009 2:02:41 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConfigurationCache\n\t\t\t\timplements ConfigRepositoryIfc {\n\t/** Field description */\n\tpublic static final String CONFIG_DUMP_FILE_PROP_DEF = \"etc/config-dump.properties\";\n\n\t/** Field description */\n\tpublic static final String CONFIG_DUMP_FILE_PROP_KEY = \"config-dump-file\";\n\n\t/**\n\t * Private logger for class instance.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ConfigurationCache.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * Even though every element has a component name field the whole\n\t * configuration is grouped by the component name anyway to improve\n\t * access time to the configuration.\n\t * Very rarely we need access to whole configuration, in most cases\n\t * we access configuration for a particular server component.\n\t */\n\tprivate Map<String, Set<ConfigItem>> config = new LinkedHashMap<String,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSet<ConfigItem>>();\n\tprivate String configDumpFileName                              =\n\t\tCONFIG_DUMP_FILE_PROP_DEF;\n\tprivate String hostname                                        = null;\n\tprivate RepositoryChangeListenerIfc<ConfigItem> repoChangeList = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addRepoChangeListener(\n\t\t\t\t\tRepositoryChangeListenerIfc<ConfigItem> repoChangeListener) {\n\t\tthis.repoChangeList = repoChangeListener;\n\t}\n\n\t@Override\n\tpublic void removeRepoChangeListener(\n\t\t\t\t\tRepositoryChangeListenerIfc<ConfigItem> repoChangeListener) {\n\t\tthis.repoChangeList = null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName\n\t * @param item\n\t */\n\tpublic void addItem(String compName, ConfigItem item) {\n\t\tSet<ConfigItem> confItems = config.get(compName);\n\n\t\tif (confItems == null) {\n\t\t\tconfItems = new LinkedHashSet<ConfigItem>();\n\t\t\tconfig.put(compName, confItems);\n\t\t}\n\n\t\tboolean updated = confItems.remove(item);\n\n\t\tconfItems.add(item);\n\t\tif (repoChangeList != null) {\n\t\t\tif (updated) {\n\t\t\t\trepoChangeList.itemUpdated(item);\n\t\t\t} else {\n\t\t\t\trepoChangeList.itemAdded(item);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addItemNoStore(ConfigItem item) {\n\t\taddItem(item.getCompName(), item);\n\t}\n\n\t@Override\n\tpublic void addItem(ConfigItem item) throws TigaseDBException {\n\t\taddItemNoStore(item);\n\t}\n\n\t@Override\n\tpublic void addItem(String key, Object value) throws ConfigurationException {\n\t\tint idx1 = key.indexOf(\"/\");\n\n\t\tif (idx1 > 0) {\n\t\t\tString compName = key.substring(0, idx1);\n\t\t\tint idx2        = key.lastIndexOf(\"/\");\n\t\t\tString nodeName = null;\n\t\t\tString keyName  = key.substring(idx2 + 1);\n\n\t\t\tif (idx1 != idx2) {\n\t\t\t\tnodeName = key.substring(idx1 + 1, idx2);\n\t\t\t}\n\n\t\t\tConfigItem item = getItemInstance();\n\n\t\t\titem.set(getDefHostname(), compName, nodeName, keyName, value);\n\t\t\taddItem(compName, item);\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException(\"You have to provide a key with at least\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" 'component_name/key_name': \" + key);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Collection<ConfigItem> allItems() throws TigaseDBException {\n\t\tList<ConfigItem> result = new ArrayList<ConfigItem>();\n\n\t\tfor (Set<ConfigItem> items : config.values()) {\n\t\t\tresult.addAll(items);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean contains(String key) {\n\t\treturn getItem(key) != null;\n\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do now, maybe later we would add some logic here to move \n\t\t// deinitialization of config repository here - added to implement all methods\n\t\t// needed by ComponentRepository interface which was extended while\n\t\t// implementing support for autodiscovery based on URI and adding\n\t\t// more flexibility in use of repositories\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Object get(String compName, String node, String key, Object def) {\n\t\tConfigItem item = getItem(compName, node, key);\n\n\t\tif (item != null) {\n\t\t\treturn item.getConfigVal();\n\t\t}\n\n\t\treturn def;\n\t}\n\n\t@Override\n\tpublic String[] getCompNames() {\n\t\treturn config.keySet().toArray(new String[config.size()]);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic String getDefHostname() {\n\t\treturn this.hostname;\n\t}\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tdefs.put(CONFIG_DUMP_FILE_PROP_KEY, CONFIG_DUMP_FILE_PROP_DEF);\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getInitProperties() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName\n\t * @param node\n\t * @param key\n\t *\n\t *\n\t */\n\tpublic ConfigItem getItem(String compName, String node, String key) {\n\t\tSet<ConfigItem> confItems = getItemsForComponent(compName);\n\n\t\tif (confItems != null) {\n\t\t\tfor (ConfigItem item : confItems) {\n\t\t\t\tif (item.isNodeKey(node, key)) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ConfigItem getItem(String key) {\n\t\tint idx1 = key.indexOf(\"/\");\n\n\t\tif (idx1 > 0) {\n\t\t\tString compName = key.substring(0, idx1);\n\t\t\tint idx2        = key.lastIndexOf(\"/\");\n\t\t\tString nodeName = null;\n\t\t\tString keyName  = key.substring(idx2 + 1);\n\n\t\t\tif (idx1 != idx2) {\n\t\t\t\tnodeName = key.substring(idx1 + 1, idx2);\n\t\t\t}\n\n\t\t\treturn getItem(compName, nodeName, keyName);\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException(\"You have to provide a key with at least\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" 'component_name/key_name': \" + key);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ConfigItem getItemInstance() {\n\t\treturn new ConfigItem();\n\t}\n\n\t@Override\n\tpublic Set<ConfigItem> getItemsForComponent(String compName) {\n\t\treturn config.get(compName);\n\t}\n\n\t@Override\n\tpublic String[] getKeys(String compName, String node) {\n\t\tSet<String> keysForNode   = new LinkedHashSet<String>();\n\t\tSet<ConfigItem> confItems = config.get(compName);\n\n\t\tfor (ConfigItem item : confItems) {\n\t\t\tif (item.isNode(node)) {\n\t\t\t\tkeysForNode.add(item.getKeyName());\n\t\t\t}\n\t\t}\n\t\tif (keysForNode.size() > 0) {\n\t\t\treturn keysForNode.toArray(new String[keysForNode.size()]);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getProperties(String compName)\n\t\t\t\t\tthrows ConfigurationException {\n\n\t\t// It must not return a null value, even if configuration for the\n\t\t// component does not exist yet, it has to initialized to create new one.\n\t\tMap<String, Object> result = new LinkedHashMap<String, Object>();\n\n\t\t// Let's convert the internal representation of the configuration to that\n\t\t// used by the components.\n\t\tSet<ConfigItem> confItems = getItemsForComponent(compName);\n\n\t\tif (confItems != null) {\n\t\t\tfor (ConfigItem item : confItems) {\n\t\t\t\tString key   = item.getConfigKey();\n\t\t\t\tObject value = item.getConfigVal();\n\n\t\t\t\tresult.put(key, value);\n\t\t\t}\n\t\t}\n\n\t\t// Hopefuly this doesn't happen.... or I have a bug somewhere\n\t\treturn result;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do..\n\t}\t\n\t\n\t@Override\n\tpublic Iterator<ConfigItem> iterator() {\n\t\ttry {\n\t\t\tCollection<ConfigItem> items = allItems();\n\n\t\t\treturn (items != null)\n\t\t\t\t\t\t ? items.iterator()\n\t\t\t\t\t\t : null;\n\t\t} catch (TigaseDBException ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem accessing repository: \", ex);\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void putProperties(String compName, Map<String, Object> props)\n\t\t\t\t\tthrows ConfigurationException {\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tConfigItem item = new ConfigItem();\n\n\t\t\titem.setNodeKey(getDefHostname(), compName, entry.getKey(), entry.getValue());\n\t\t\taddItem(compName, item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void reload() throws TigaseDBException {\n\n\t\t// Do nothing, this is in memory config repository only\n\t}\n\n\t@Override\n\tpublic void remove(String compName, String node, String key) {\n\t\tConfigItem item = getItem(compName, node, key);\n\n\t\tif (item != null) {\n\t\t\tremoveItem(compName, item);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compName\n\t * @param item\n\t */\n\tpublic void removeItem(String compName, ConfigItem item) {\n\t\tSet<ConfigItem> confItems = config.get(compName);\n\n\t\tif (confItems != null) {\n\t\t\tconfItems.remove(item);\n\t\t}\n\t\tif (repoChangeList != null) {\n\t\t\trepoChangeList.itemRemoved(item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeItem(String key) throws TigaseDBException {\n\t\tConfigItem item = getItem(key);\n\n\t\tif (item != null) {\n\t\t\tremoveItem(item.getCompName(), item);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void set(String compName, String node, String key, Object value) {\n\t\tConfigItem item = getItem(compName, node, key);\n\n\t\tif (item == null) {\n\t\t\titem = getItemInstance();\n\t\t}\n\t\titem.set(getDefHostname(), compName, node, key, value);\n\t\taddItem(compName, item);\n\t}\n\n\t@Override\n\tpublic void setDefHostname(String hostname) {\n\t\tthis.hostname = hostname;\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tconfigDumpFileName = (String) properties.get(CONFIG_DUMP_FILE_PROP_KEY);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int size() {\n\t\tint result = 0;\n\n\t\tfor (Set<ConfigItem> items : config.values()) {\n\t\t\tresult += items.size();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void store() throws TigaseDBException {\n\t\tif (!isOff(configDumpFileName)) {\n\t\t\tlog.log(Level.WARNING, \"Dumping server configuration to: {0}\", configDumpFileName);\n\t\t\ttry {\n\t\t\t\tFileWriter fw = new FileWriter(configDumpFileName, false);\n\n\t\t\t\tfor (Map.Entry<String, Set<ConfigItem>> entry : config.entrySet()) {\n\t\t\t\t\tfor (ConfigItem item : entry.getValue()) {\n\t\t\t\t\t\tfw.write(item.toPropertyString());\n\t\t\t\t\t\tfw.write(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfw.close();\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Cannot dump server configuration.\", e);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Dumping server configuration is OFF: {0}\",\n\t\t\t\t\t\t\tconfigDumpFileName);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isOff(String str) {\n\t\treturn (str == null) || str.trim().isEmpty() || str.equalsIgnoreCase(\"off\") ||\n\t\t\t\t\t str.equalsIgnoreCase(\"none\") || str.equalsIgnoreCase(\"false\") ||\n\t\t\t\t\t str.equalsIgnoreCase(\"no\");\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String validateItem(ConfigItem item) {\n\t\treturn null;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setAutoloadTimer(long delay) {}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfigurationException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.conf;\n\nimport java.io.IOException;\n\n/**\n *\n * @author kobit\n */\npublic class ConfigurationException extends IOException {\n\n  private static final long serialVersionUID = 1L;\n\n\t/**\n     * Creates a new instance of <code>ConfigurationException</code> without detail message.\n\t */\n\tpublic ConfigurationException() {\n\t\tsuper();\n\t}\n\n\n\t/**\n     * Constructs an instance of <code>ConfigurationException</code> with the specified detail message.\n     * @param msg the detail message.\n     */\n\tpublic ConfigurationException(String msg) {\n\t\tsuper(msg);\n\t}\n\n\tpublic ConfigurationException(String string, Exception e) {\n\t\tsuper(string, e);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/Configurator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.conf;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Dec 7, 2009 4:09:52 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Configurator extends ConfiguratorAbstract {\n\n\tprivate static final Logger log = Logger.getLogger(Configurator.class.getCanonicalName());\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Configuration management\";\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"generic\";\n\t}\n\n\t@Override\n\tpublic void componentAdded(Configurable component) throws ConfigurationException {\n\t\ttry {\n\t\t\tsuper.componentAdded(component);\n\t\t} catch (NullPointerException ex) {\n\t\t\tlog.log(Level.WARNING, \"ignoring NPE\", ex);\n\t\t}\n\t}\n\n\tpublic void updateMessageRouter() {\n\t\ttry {\n\t\t\tsetup(getComponent(\"message-router\"));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem instantiating component:\", e);\n\t\t}\t // end of try-catch\t\t\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfiguratorAbstract.java",
    "content": "/*\n * ConfiguratorAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.*;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.db.comp.RepositoryChangeListenerIfc;\nimport tigase.io.TLSUtil;\nimport tigase.server.AbstractComponentRegistrator;\nimport tigase.server.ServerComponent;\nimport tigase.stats.StatisticsContainer;\nimport tigase.stats.StatisticsList;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.DataTypes;\nimport tigase.xmpp.BareJID;\n\nimport javax.script.Bindings;\nimport java.io.*;\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\nimport java.util.logging.Logger;\n\nimport static tigase.io.SSLContextContainerIfc.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\n/**\n * Created: Dec 7, 2009 4:15:31 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class ConfiguratorAbstract\n\t\t\t\textends AbstractComponentRegistrator<Configurable>\n\t\t\t\timplements RepositoryChangeListenerIfc<ConfigItem>, StatisticsContainer {\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS_PROP_KEY = RepositoryFactory\n\t\t\t.AUTH_DOMAIN_POOL_CLASS_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.AUTH_DOMAIN_POOL_CLASS_PROP_VAL;\n\n\t/** Field description */\n\tpublic static final String CONFIG_REPO_CLASS_INIT_KEY = \"--tigase-config-repo-class\";\n\n\t/** Field description */\n\tpublic static final String CONFIG_REPO_CLASS_PROP_KEY = \"tigase-config-repo-class\";\n\n\t/** Field description */\n\tpublic static final String INIT_PROPERTIES_MAP_BIND = \"initProperties\";\n\n\t/** Field description */\n\tpublic static String logManagerConfiguration = null;\n\n\t/** Field description */\n\tpublic static final String PROPERTY_FILENAME_PROP_KEY = \"--property-file\";\n\tpublic static final String PROPERTY_FILENAME_PROP_DEF = \"etc/init.properties\";\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_DOMAIN_POOL_CLASS_PROP_KEY = RepositoryFactory\n\t\t\t.USER_DOMAIN_POOL_CLASS_PROP_KEY;\n\n\t/**\n\t * Field description\n\t * @deprecated moved to RepositoryFactory\n\t */\n\t@Deprecated\n\tpublic static final String USER_DOMAIN_POOL_CLASS_PROP_VAL = RepositoryFactory\n\t\t\t.USER_DOMAIN_POOL_CLASS_PROP_VAL;\n\tprivate static final String LOGGING_KEY = \"logging/\";\n\tprivate static final Logger log = Logger.getLogger(ConfiguratorAbstract.class\n\t\t\t.getName());\n\tprivate static MonitoringSetupIfc monitoring = null;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate AuthRepositoryMDImpl auth_repo_impl   = null;\n\tprivate Map<String, String>  auth_repo_params = null;\n\tprivate AuthRepository       auth_repository  = null;\n\tprivate UserRepositoryMDImpl user_repo_impl   = null;\n\tprivate Map<String, String>  user_repo_params = null;\n\n\t// Default user repository instance which can be shared among components\n\tprivate UserRepository user_repository   = null;\n\tprivate boolean        setup_in_progress = false;\n\n\t/**\n\t * Configuration settings read from the initRepository.properties file or any other\n\t * source which provides startup configuration.\n\t */\n\tprivate List<String> initSettings = new LinkedList<String>();\n\n\t/**\n\t * Properties from the command line parameters and initRepository.properties file or any\n\t * other source which are used to generate default configuration. All the\n\t * settings starting with '--'\n\t */\n\tprivate Map<String, Object> initProperties = new LinkedHashMap<String, Object>(100);\n\n\t// Default user auth repository instance which can be shared among components\n\tprivate ConfigRepositoryIfc configRepo = new ConfigurationCache();\n\n\t// Common logging setup\n\tprivate Map<String, String> loggingSetup = new LinkedHashMap<String, String>(10);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void componentAdded(Configurable component) throws ConfigurationException {\n\t\tif (log.isLoggable(Level.CONFIG)) {\n\t\t\tlog.log(Level.CONFIG, \" component: {0}\", component.getName());\n\t\t}\n\t\tsetup(component);\n\t}\n\n\t@Override\n\tpublic void componentRemoved(Configurable component) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t *\n\t * @throws ConfigurationException\n\t * @throws TigaseDBException\n\t */\n\tpublic void init(String[] args) throws ConfigurationException, TigaseDBException {\n\t\tparseArgs(args);\n\n\t\tString stringprep = (String) initProperties.get(STRINGPREP_PROCESSOR);\n\n\t\tif (stringprep != null) {\n\t\t\tBareJID.useStringprepProcessor(stringprep);\n\t\t}\n\n\t\tString cnf_class_name = System.getProperty(CONFIG_REPO_CLASS_PROP_KEY);\n\n\t\tif (cnf_class_name != null) {\n\t\t\tinitProperties.put(CONFIG_REPO_CLASS_INIT_KEY, cnf_class_name);\n\t\t}\n\t\tcnf_class_name = (String) initProperties.get(CONFIG_REPO_CLASS_INIT_KEY);\n\t\tif (cnf_class_name != null) {\n\t\t\ttry {\n\t\t\t\tconfigRepo = (ConfigRepositoryIfc) Class.forName(cnf_class_name).newInstance();\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem initializing configuration system: \", e);\n\t\t\t\tlog.log(Level.SEVERE, \"Please check settings, and rerun the server.\");\n\t\t\t\tlog.log(Level.SEVERE, \"Server is stopping now.\");\n\t\t\t\tSystem.err.println(\"Problem initializing configuration system: \" + e);\n\t\t\t\tSystem.err.println(\"Please check settings, and rerun the server.\");\n\t\t\t\tSystem.err.println(\"Server is stopping now.\");\n\t\t\t\tSystem.exit(1);\n\t\t\t}\n\t\t}\n\t\tconfigRepo.addRepoChangeListener(this);\n\t\tString host = getDefHostName() != null ? getDefHostName().getDomain() : DNSResolverFactory.getInstance().getDefaultHost();\n\t\tconfigRepo.setDefHostname(host);\n\t\ttry {\n\t\t\t// loss of generic types is intentional to make parameter match API\n\t\t\t// and internally all requests are done like:\n\t\t\t// String x = (String) initProperties.get(\"param\");\n\t\t\t// so it should be safe to loss generic types of Map\n\t\t\tconfigRepo.initRepository(null, (Map) initProperties);\n\t\t} catch (DBInitException ex) {\n\t\t\tthrow new ConfigurationException(ex.getMessage(), ex);\n\t\t}\n\t\tfor (String prop : initSettings) {\n\t\t\tConfigItem item = configRepo.getItemInstance();\n\n\t\t\titem.initFromPropertyString(prop);\n\t\t\tconfigRepo.addItem(item);\n\t\t}\n\n\t\tMap<String, Object> repoInitProps = configRepo.getInitProperties();\n\n\t\tif (repoInitProps != null) {\n\t\t\tinitProperties.putAll(repoInitProps);\n\t\t}\n\n\t\t// Not sure if this is the correct pleace to initialize monitoring\n\t\t// maybe it should be initialized initRepository initializationCompleted but\n\t\t// Then some stuff might be missing. Let's try to do it here for now\n\t\t// and maybe change it later.\n\t\tString property_filenames = (String) initProperties.get(PROPERTY_FILENAME_PROP_KEY);\n\n\t\tif (property_filenames != null) {\n\t\t\tString[] prop_files = property_filenames.split(\",\");\n\n\t\t\tinitMonitoring((String) initProperties.get(MONITORING), new File(prop_files[0])\n\t\t\t\t\t.getParent());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(ComponentRepository.COMP_REPO_BIND, configRepo);\n\t\tbinds.put(INIT_PROPERTIES_MAP_BIND, initProperties);\n\t}\n\n\t@Override\n\tpublic void initializationCompleted() {\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\treturn;\n\t\t}\n\t\tsuper.initializationCompleted();\n\t\tif (monitoring != null) {\n\t\t\tmonitoring.initializationCompleted();\n\t\t}\n\t\ttry {\n\n\t\t\t// Dump the configuration....\n\t\t\tconfigRepo.store();\n\t\t} catch (TigaseDBException ex) {\n\t\t\tlog.log(Level.WARNING, \"Cannot store configuration.\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemAdded(ConfigItem item) {\n\n\t\t// Ignored, adding configuration settings does not make sense, for now...\n\t\t// right now, just print a log message\n\t\t// log.log(Level.INFO, \"Adding configuration item not supported yet: {0}\", item);\n\t}\n\n\t@Override\n\tpublic void itemRemoved(ConfigItem item) {\n\n\t\t// Ignored, removing configuration settings does not make sense, for now...\n\t\t// right now, just print a log message\n\t\tlog.log(Level.INFO, \"Removing configuration item not supported yet: {0}\", item);\n\t}\n\n\t@Override\n\tpublic void itemUpdated(ConfigItem item) {\n\t\tlog.log(Level.INFO, \"Updating configuration item: {0}\", item);\n\n\t\tConfigurable component = getComponent(item.getCompName());\n\n\t\tif (component != null) {\n\t\t\tMap<String, Object> prop = Collections.singletonMap(item.getConfigKey(), item\n\t\t\t\t\t.getConfigVal());\n\n\t\t\ttry {\n\t\t\t\tcomponent.setProperties(prop);\n\t\t\t}\n\t\t\tcatch (ConfigurationException ex) {\n\t\t\t\tlog.log(Level.SEVERE, \"Component reconfiguration failed: \" + ex.getMessage(), ex);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Cannot find component for configuration item: {0}\", item);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param config\n\t */\n\tpublic static void loadLogManagerConfig(String config) {\n\t\tlogManagerConfiguration = config;\n\t\ttry {\n\t\t\tfinal ByteArrayInputStream bis = new ByteArrayInputStream(config.getBytes());\n\n\t\t\tLogManager.getLogManager().readConfiguration(bis);\n\t\t\tbis.close();\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not configure logManager\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t */\n\tpublic void parseArgs(String[] args) {\n\t\tinitProperties.put(GEN_TEST, Boolean.FALSE);\n\t\tinitProperties.put(\"config-type\", GEN_CONFIG_DEF);\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tString key = null;\n\t\t\t\tObject val = null;\n\n\t\t\t\tif (args[i].startsWith(GEN_CONFIG)) {\n\t\t\t\t\tkey = \"config-type\";\n\t\t\t\t\tval = args[i];\n\t\t\t\t}\n\t\t\t\tif (args[i].startsWith(GEN_TEST)) {\n\t\t\t\t\tkey = args[i];\n\t\t\t\t\tval = Boolean.TRUE;\n\t\t\t\t}\n\t\t\t\tif ((key == null) && args[i].startsWith(\"-\") &&!args[i].startsWith(GEN_CONFIG)) {\n\t\t\t\t\tkey = args[i];\n\t\t\t\t\tval = args[++i];\n\t\t\t\t}\n\t\t\t\tif ((key != null) && (val != null)) {\n\t\t\t\t\tinitProperties.put(key, val);\n\n\t\t\t\t\t// System.out.println(\"Setting defaults: \" + key + \"=\" +\n\t\t\t\t\t// val.toString());\n\t\t\t\t\tlog.log(Level.CONFIG, \"Setting defaults: {0} = {1}\", new Object[] { key,\n\t\t\t\t\t\t\tval.toString() });\n\t\t\t\t}    // end of if (key != null)\n\t\t\t}      // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\n\t\tString property_filenames = (String) initProperties.get(PROPERTY_FILENAME_PROP_KEY);\n\n\t\t// if no property file was specified then use default one.\n\t\tif (property_filenames == null) {\n\t\t\tproperty_filenames = PROPERTY_FILENAME_PROP_DEF;\n\t\t\t\tlog.log(Level.WARNING, \"No property file not specified! Using default one {0}\",\n\t\t\t\t\t\tproperty_filenames);\n\t\t}\n\n\t\tif (property_filenames != null) {\n\t\t\tString[] prop_files = property_filenames.split(\",\");\n\n\t\t\tif ( prop_files.length == 1 ){\n\t\t\t\tFile f = new File( prop_files[0] );\n\t\t\t\tif ( !f.exists() ){\n\t\t\t\t\tlog.log( Level.WARNING, \"Provided property file {0} does NOT EXISTS! Using default one {1}\",\n\t\t\t\t\t\t\t\t\t new String[] { f.getAbsolutePath(), PROPERTY_FILENAME_PROP_DEF } );\n\t\t\t\t\tprop_files[0] = PROPERTY_FILENAME_PROP_DEF;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (String property_filename : prop_files) {\n\t\t\t\tlog.log(Level.CONFIG, \"Loading initial properties from property file: {0}\",\n\t\t\t\t\t\tproperty_filename);\n\t\t\t\ttry {\n\t\t\t\t\tProperties defProps = new Properties();\n\n\t\t\t\t\tdefProps.load(new FileReader(property_filename));\n\n\t\t\t\t\tSet<String> prop_keys = defProps.stringPropertyNames();\n\n\t\t\t\t\tfor (String key : prop_keys) {\n\t\t\t\t\t\tString value = defProps.getProperty(key).trim();\n\n\t\t\t\t\t\tif (key.startsWith(\"-\") || key.equals(\"config-type\")) {\n\t\t\t\t\t\t\tif (GEN_TEST.equalsIgnoreCase(key)) {\n\t\t\t\t\t\t\t\tinitProperties.put(key.trim().substring(2), DataTypes.parseBool(value));\n\t\t\t\t\t\t\t\tinitProperties.put(key.trim(), DataTypes.parseBool(value));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tinitProperties.put(key.trim(), value);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// defProperties.remove(key);\n\t\t\t\t\t\t\tlog.log(Level.CONFIG, \"Added default config parameter: ({0}={1})\",\n\t\t\t\t\t\t\t\t\tnew Object[] { key,\n\t\t\t\t\t\t\t\t\tvalue });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinitSettings.add(key + \"=\" + value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (FileNotFoundException e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Given property file was not found: {0}\",\n\t\t\t\t\t\t\tproperty_filename);\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can not read property file: \" + property_filename, e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Set all parameters starting with '--' as a system properties with removed\n\t\t// the starting '-' characters.\n\t\tfor (Map.Entry<String, Object> entry : initProperties.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(\"--\")) {\n\t\t\t\tSystem.setProperty(entry.getKey().substring(2), ((entry.getValue() == null)\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: entry.getValue().toString()));\n\n\t\t\t\t// In cluster mode we switch DB cache off as this does not play well.\n\t\t\t\tif (CLUSTER_MODE.equals(entry.getKey())) {\n\t\t\t\t\tif (\"true\".equalsIgnoreCase(entry.getValue().toString())) {\n\t\t\t\t\t\tSystem.setProperty(\"tigase.cache\", \"false\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param objName\n\t * @param bean\n\t */\n\tpublic static void putMXBean(String objName, Object bean) {\n\t\tif (monitoring != null) {\n\t\t\tmonitoring.putMXBean(objName, bean);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compId\n\t * @param props\n\t *\n\t * @throws ConfigurationException\n\t */\n\tpublic void putProperties(String compId, Map<String, Object> props)\n\t\t\t\t\tthrows ConfigurationException {\n\t\tconfigRepo.putProperties(compId, props);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param component\n\t */\n\tpublic void setup(Configurable component) throws ConfigurationException {\n\n\t\t// Try to avoid recursive execution of the method\n\t\tif (component == this) {\n\t\t\tif (setup_in_progress) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tsetup_in_progress = true;\n\t\t\t}\n\t\t}\n\n\t\tString compId = component.getName();\n\n\t\tlog.log(Level.CONFIG, \"Setting up component: {0}\", compId);\n\n\t\tMap<String, Object> prop = null;\n\n\t\ttry {\n\t\t\tprop = configRepo.getProperties(compId);\n\t\t} catch (ConfigurationException ex) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Propblem retrieving configuration properties for component: \" + compId, ex);\n\n\t\t\treturn;\n\t\t}\n\n\t\tMap<String, Object> defs = component.getDefaults(getDefConfigParams());\n\n\t\tlog.log(Level.CONFIG, \"Component {0} defaults: {1}\", new Object[] { compId, defs });\n\n\t\tSet<Map.Entry<String, Object>> defs_entries = defs.entrySet();\n\t\tboolean                        modified     = false;\n\n\t\tfor (Map.Entry<String, Object> entry : defs_entries) {\n\t\t\tif (!prop.containsKey(entry.getKey())) {\n\t\t\t\tprop.put(entry.getKey(), entry.getValue());\n\t\t\t\tmodified = true;\n\t\t\t}    // end of if ()\n\t\t}      // end of for ()\n\t\tif (modified) {\n\t\t\ttry {\n\t\t\t\tlog.log(Level.CONFIG, \"Component {0} configuration: {1}\", new Object[] { compId,\n\t\t\t\t\t\tprop });\n\t\t\t\tconfigRepo.putProperties(compId, prop);\n\t\t\t} catch (ConfigurationException ex) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"Propblem with saving configuration properties for component: \" + compId, ex);\n\t\t\t}\n\t\t}    // end of if (modified)\n\t\tprop.put(RepositoryFactory.SHARED_USER_REPO_PROP_KEY, user_repo_impl);\n\t\tprop.put(RepositoryFactory.SHARED_USER_REPO_PARAMS_PROP_KEY, user_repo_params);\n\t\tprop.put(RepositoryFactory.SHARED_AUTH_REPO_PROP_KEY, auth_repo_impl);\n\t\tprop.put(RepositoryFactory.SHARED_AUTH_REPO_PARAMS_PROP_KEY, auth_repo_params);\n\t\tcomponent.setProperties(prop);\n\t\tif (component == this) {\n\t\t\tsetup_in_progress = false;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defaults = super.getDefaults(params);\n\t\tString              levelStr = \".level\";\n\n\t\tif ((Boolean) params.get(GEN_TEST)) {\n\t\t\tdefaults.put(LOGGING_KEY + levelStr, \"WARNING\");\n\t\t} else {\n\t\t\tdefaults.put(LOGGING_KEY + levelStr, \"CONFIG\");\n\t\t}\n\t\tdefaults.put(LOGGING_KEY + \"handlers\",\n\t\t\t\t\"java.util.logging.ConsoleHandler java.util.logging.FileHandler\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.ConsoleHandler.formatter\",\n\t\t\t\t\"tigase.util.LogFormatter\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.ConsoleHandler.level\", \"WARNING\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.append\", \"true\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.count\", \"5\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.formatter\",\n\t\t\t\t\"tigase.util.LogFormatter\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.limit\", \"10000000\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.pattern\",\n\t\t\t\t\"logs/tigase.log\");\n\t\tdefaults.put(LOGGING_KEY + \"tigase.useParentHandlers\", \"true\");\n\t\tdefaults.put(LOGGING_KEY + \"java.util.logging.FileHandler.level\", \"ALL\");\n\t\tif (params.get(GEN_DEBUG) != null) {\n\t\t\tString[] packs = ((String) params.get(GEN_DEBUG)).split(\",\");\n\n\t\t\tfor (String pack : packs) {\n\t\t\t\tdefaults.put(LOGGING_KEY + \"tigase.\" + pack + \".level\", \"ALL\");\n\t\t\t}    // end of for (String pack: packs)\n\t\t}\n\t\tif (params.get(GEN_DEBUG_PACKAGES) != null) {\n\t\t\tString[] packs = ((String) params.get(GEN_DEBUG_PACKAGES)).split(\",\");\n\n\t\t\tfor (String pack : packs) {\n\t\t\t\tdefaults.put(LOGGING_KEY + pack + \".level\", \"ALL\");\n\t\t\t}    // end of for (String pack: packs)\n\t\t}\n\n\t\tString repo_pool = null;\n\n\t\trepo_pool = (String) params.get(RepositoryFactory.USER_DOMAIN_POOL_CLASS);\n\t\tif (repo_pool == null) {\n\t\t\trepo_pool = RepositoryFactory.USER_DOMAIN_POOL_CLASS_PROP_VAL;\n\t\t}\n\t\tdefaults.put(RepositoryFactory.USER_DOMAIN_POOL_CLASS_PROP_KEY, repo_pool);\n\t\trepo_pool = (String) params.get(RepositoryFactory.AUTH_DOMAIN_POOL_CLASS);\n\t\tif (repo_pool == null) {\n\t\t\trepo_pool = RepositoryFactory.AUTH_DOMAIN_POOL_CLASS_PROP_VAL;\n\t\t}\n\t\tdefaults.put(RepositoryFactory.AUTH_DOMAIN_POOL_CLASS_PROP_KEY, repo_pool);\n\n\t\tString user_repo_class = null;//RepositoryFactory.DUMMY_REPO_CLASS_PROP_VAL;\n\t\tString user_repo_url   = RepositoryFactory.DERBY_REPO_URL_PROP_VAL;\n\t\tString auth_repo_class = null;//RepositoryFactory.DUMMY_REPO_CLASS_PROP_VAL;\n\t\tString auth_repo_url   = RepositoryFactory.DERBY_REPO_URL_PROP_VAL;\n\n\t\tif (params.get(RepositoryFactory.GEN_USER_DB) != null) {\n\t\t\tuser_repo_class = (String) params.get(RepositoryFactory.GEN_USER_DB);\n\t\t\tauth_repo_class = RepositoryFactory.TIGASE_CUSTOM_AUTH_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (params.get(RepositoryFactory.GEN_USER_DB_URI) != null) {\n\t\t\tuser_repo_url = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t\tauth_repo_url = user_repo_url;\n\t\t}\n\t\tif (params.get(RepositoryFactory.GEN_AUTH_DB) != null) {\n\t\t\tauth_repo_class = (String) params.get(RepositoryFactory.GEN_AUTH_DB);\n\t\t}\n\t\tif (params.get(RepositoryFactory.GEN_AUTH_DB_URI) != null) {\n\t\t\tauth_repo_url = (String) params.get(RepositoryFactory.GEN_AUTH_DB_URI);\n\t\t}\n\t\tif (params.get(RepositoryFactory.USER_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.USER_REPO_POOL_SIZE));\n\t\t} else {\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_POOL_SIZE_PROP_KEY, RepositoryFactory\n\t\t\t\t\t.USER_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tif (params.get(RepositoryFactory.DATA_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.DATA_REPO_POOL_SIZE));\n\t\t} else if (params.get(RepositoryFactory.USER_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.USER_REPO_POOL_SIZE));\n\t\t} else {\n\t\t\tdefaults.put(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, RepositoryFactory\n\t\t\t\t\t.DATA_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tif (params.get(RepositoryFactory.AUTH_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.AUTH_REPO_POOL_SIZE));\n\t\t} else if (params.get(RepositoryFactory.DATA_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.DATA_REPO_POOL_SIZE));\n\t\t} else if (params.get(RepositoryFactory.USER_REPO_POOL_SIZE) != null) {\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_POOL_SIZE_PROP_KEY, params.get(\n\t\t\t\t\tRepositoryFactory.USER_REPO_POOL_SIZE));\n\t\t} else {\n\t\t\tdefaults.put(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, RepositoryFactory\n\t\t\t\t\t.AUTH_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tif (user_repo_class != null)\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_CLASS_PROP_KEY, user_repo_class);\n\t\tdefaults.put(RepositoryFactory.USER_REPO_URL_PROP_KEY, user_repo_url);\n\t\tif (auth_repo_class != null)\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_CLASS_PROP_KEY, auth_repo_class);\n\t\tdefaults.put(RepositoryFactory.AUTH_REPO_URL_PROP_KEY, auth_repo_url);\n\n\t\tList<String> user_repo_domains = new ArrayList<String>(10);\n\t\tList<String> auth_repo_domains = new ArrayList<String>(10);\n\n\t\tfor (Map.Entry<String, Object> entry : params.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(RepositoryFactory.GEN_USER_DB_URI)) {\n\t\t\t\tString[] domains = parseUserRepoParams(entry, params, user_repo_class, defaults);\n\n\t\t\t\tif (domains != null) {\n\t\t\t\t\tuser_repo_domains.addAll(Arrays.asList(domains));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (entry.getKey().startsWith(RepositoryFactory.GEN_AUTH_DB_URI)) {\n\t\t\t\tString[] domains = parseAuthRepoParams(entry, params, auth_repo_class, defaults);\n\n\t\t\t\tif (domains != null) {\n\t\t\t\t\tauth_repo_domains.addAll(Arrays.asList(domains));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (user_repo_domains.size() > 0) {\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_DOMAINS_PROP_KEY, user_repo_domains\n\t\t\t\t\t.toArray(new String[user_repo_domains.size()]));\n\t\t}\n\t\tif (auth_repo_domains.size() > 0) {\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_DOMAINS_PROP_KEY, auth_repo_domains\n\t\t\t\t\t.toArray(new String[auth_repo_domains.size()]));\n\t\t}\n\n\t\t// TLS/SSL configuration\n\t\tif (params.get(\"--\" + SSL_CONTAINER_CLASS_KEY) != null) {\n\t\t\tdefaults.put(SSL_CONTAINER_CLASS_KEY, (String) params.get(\"--\" +\n\t\t\t\t\tSSL_CONTAINER_CLASS_KEY));\n\t\t} else {\n\t\t\tdefaults.put(SSL_CONTAINER_CLASS_KEY, SSL_CONTAINER_CLASS_VAL);\n\t\t}\n\t\tif (params.get(\"--\" + SERVER_CERTS_LOCATION_KEY) != null) {\n\t\t\tdefaults.put(SERVER_CERTS_LOCATION_KEY, (String) params.get(\"--\" +\n\t\t\t\t\tSERVER_CERTS_LOCATION_KEY));\n\t\t} else {\n\t\t\tdefaults.put(SERVER_CERTS_LOCATION_KEY, SERVER_CERTS_LOCATION_VAL);\n\t\t}\n\t\tif (params.get(\"--\" + DEFAULT_DOMAIN_CERT_KEY) != null) {\n\t\t\tdefaults.put(DEFAULT_DOMAIN_CERT_KEY, (String) params.get(\"--\" +\n\t\t\t\t\tDEFAULT_DOMAIN_CERT_KEY));\n\t\t} else {\n\t\t\tdefaults.put(DEFAULT_DOMAIN_CERT_KEY, DEFAULT_DOMAIN_CERT_VAL);\n\t\t}\n\t\tconfigRepo.getDefaults(defaults, params);\n\n\t\treturn defaults;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Map<String, Object> getDefConfigParams() {\n\t\treturn initProperties;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getMessageRouterClassName() {\n\t\treturn \"tigase.server.MessageRouter\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param objName\n\t *\n\t * \n\t */\n\tpublic static Object getMXBean(String objName) {\n\t\tif (monitoring != null) {\n\t\t\treturn monitoring.getMXBean(objName);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param nodeId\n\t *\n\t * \n\t *\n\t * @throws ConfigurationException\n\t */\n\tpublic Map<String, Object> getProperties(String nodeId) throws ConfigurationException {\n\t\treturn configRepo.getProperties(nodeId);\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tRepositoryFactory.statistics.getStatistics(list);\n\t}\n\n\t@Override\n\tpublic boolean isCorrectType(ServerComponent component) {\n\t\treturn component instanceof Configurable;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.size() == 0) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Properties size is 0, incorrect system state, probably OSGI mode and configuration is not yet loaded.\");\n\n\t\t\treturn;\n\t\t} else {\n\t\t\tlog.log(Level.INFO, \"Propeties size is {0}, and here are all propeties: {1}\",\n\t\t\t\t\tnew Object[] { props.size(),\n\t\t\t\t\tprops });\n\t\t}\n\t\tsetupLogManager(props);\n\t\tsuper.setProperties(props);\n\t\tif (props.size() == 1) {\n\t\t\tlog.log(Level.INFO, \"Propeties size is {0}, and here are all propeties: {1}\",\n\t\t\t\t\tnew Object[] { props.size(),\n\t\t\t\t\tprops });\n\n\t\t\treturn;\n\t\t}\n\t\tconfigRepo.setProperties(props);\n\t\tTLSUtil.configureSSLContext(props);\n\n\n\t\tString[] user_repo_domains = (String[]) props.get(RepositoryFactory\n\t\t\t\t.USER_REPO_DOMAINS_PROP_KEY);\n\t\tString[] auth_repo_domains = (String[]) props.get(RepositoryFactory\n\t\t\t\t.AUTH_REPO_DOMAINS_PROP_KEY);\n\t\tString authRepoMDImpl = (String) props.get(RepositoryFactory\n\t\t\t\t.AUTH_DOMAIN_POOL_CLASS_PROP_KEY);\n\t\tString userRepoMDImpl = (String) props.get(RepositoryFactory\n\t\t\t\t.USER_DOMAIN_POOL_CLASS_PROP_KEY);\n\n\t\ttry {\n\n\t\t\t// Authentication multi-domain repository pool initialization\n\t\t\tMap<String, String> params = getRepoParams(props, RepositoryFactory\n\t\t\t\t\t.AUTH_REPO_PARAMS_NODE, null);\n\t\t\tString conn_url = (String) props.get(RepositoryFactory.AUTH_REPO_URL_PROP_KEY);\n\n\t\t\tauth_repo_impl = (AuthRepositoryMDImpl) Class.forName(authRepoMDImpl).newInstance();\n\t\t\tauth_repo_impl.initRepository(conn_url, params);\n\n\t\t\t// User multi-domain repository pool initialization\n\t\t\tparams         = getRepoParams(props, RepositoryFactory.USER_REPO_PARAMS_NODE,\n\t\t\t\t\tnull);\n\t\t\tconn_url       = (String) props.get(RepositoryFactory.USER_REPO_URL_PROP_KEY);\n\t\t\tuser_repo_impl = (UserRepositoryMDImpl) Class.forName(userRepoMDImpl).newInstance();\n\t\t\tuser_repo_impl.initRepository(conn_url, params);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"An error initializing domain repository pool: \", ex);\n\t\t}\n\t\tuser_repository = null;\n\t\tauth_repository = null;\n\t\tif (user_repo_domains != null) {\n\t\t\tfor (String domain : user_repo_domains) {\n\t\t\t\ttry {\n\t\t\t\t\taddUserRepo(props, domain);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize user repository for domain: \" + domain,\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (user_repository == null) {\n\t\t\ttry {\n\t\t\t\taddUserRepo(props, null);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize user default repository: \", e);\n\t\t\t}\n\t\t}\n\t\tif (auth_repo_domains != null) {\n\t\t\tfor (String domain : auth_repo_domains) {\n\t\t\t\ttry {\n\t\t\t\t\taddAuthRepo(props, domain);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize user repository for domain: \" + domain,\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (auth_repository == null) {\n\t\t\ttry {\n\t\t\t\taddAuthRepo(props, null);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize auth default repository: \", e);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void addAuthRepo(Map<String, Object> props, String domain)\n\t\t\t\t\tthrows DBInitException, ClassNotFoundException, InstantiationException,\n\t\t\t\t\t\t\tIllegalAccessException {\n\t\tMap<String, String> params = getRepoParams(props, RepositoryFactory\n\t\t\t\t.AUTH_REPO_PARAMS_NODE, domain);\n\t\tString cls_name = (String) props.get(RepositoryFactory.AUTH_REPO_CLASS_PROP_KEY +\n\t\t\t\t((domain == null)\n\t\t\t\t ? \"\"\n\t\t\t\t : \"/\" + domain));\n\t\tString conn_url = (String) props.get(RepositoryFactory.AUTH_REPO_URL_PROP_KEY +\n\t\t\t\t((domain == null)\n\t\t\t\t ? \"\"\n\t\t\t\t : \"/\" + domain));\n\n\t\tAuthRepository repo = RepositoryFactory.getAuthRepository(cls_name, conn_url, params);\n\n\t\tif ((domain == null) || domain.trim().isEmpty()) {\n\t\t\tauth_repo_impl.addRepo(\"\", repo);\n\t\t\tauth_repo_impl.setDefault(repo);\n\t\t\tauth_repository = repo;\n\t\t} else {\n\t\t\tauth_repo_impl.addRepo(domain, repo);\n\t\t}\n\t\tlog.log(Level.INFO,\n\t\t\t\t\"[{0}] Initialized {1} as user auth repository pool, url: {3}\",\n\t\t\t\tnew Object[] { ((domain != null)\n\t\t\t\t? domain\n\t\t\t\t: \"DEFAULT\"), cls_name, conn_url });\n\t}\n\n\tprivate void addUserRepo(Map<String, Object> props, String domain)\n\t\t\t\t\tthrows DBInitException, ClassNotFoundException, InstantiationException,\n\t\t\t\t\t\t\tIllegalAccessException {\n\t\tMap<String, String> params = getRepoParams(props, RepositoryFactory\n\t\t\t\t.USER_REPO_PARAMS_NODE, domain);\n\t\tString cls_name = (String) props.get(RepositoryFactory.USER_REPO_CLASS_PROP_KEY +\n\t\t\t\t((domain == null)\n\t\t\t\t ? \"\"\n\t\t\t\t : \"/\" + domain));\n\t\tString conn_url = (String) props.get(RepositoryFactory.USER_REPO_URL_PROP_KEY +\n\t\t\t\t((domain == null)\n\t\t\t\t ? \"\"\n\t\t\t\t : \"/\" + domain));\n\n\n\t\tUserRepository repo = RepositoryFactory.getUserRepository(cls_name, conn_url, params);\n\n\t\tif ((domain == null) || domain.trim().isEmpty()) {\n\t\t\tuser_repo_impl.addRepo(\"\", repo);\n\t\t\tuser_repo_impl.setDefault(repo);\n\t\t\tuser_repository = repo;\n\t\t} else {\n\t\t\tuser_repo_impl.addRepo(domain, repo);\n\t\t}\n\t\tlog.log(Level.INFO, \"[{0}] Initialized {1} as user repository pool, url: {2}\",\n\t\t\t\tnew Object[] { ((domain != null)\n\t\t\t\t? domain\n\t\t\t\t: \"DEFAULT\"), cls_name, conn_url });\n\t}\n\n\tprivate void initMonitoring(String settings, String configDir) {\n\t\tif ((monitoring == null) && (settings != null)) {\n\t\t\ttry {\n\t\t\t\tString mon_cls = \"tigase.management.MonitoringSetup\";\n\n\t\t\t\tmonitoring = (MonitoringSetupIfc) Class.forName(mon_cls).newInstance();\n\t\t\t\tmonitoring.initMonitoring(settings, configDir);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can not initialize monitoring: \", e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate String[] parseAuthRepoParams(Entry<String, Object> entry, Map<String,\n\t\t\tObject> params, String auth_repo_class, Map<String, Object> defaults) {\n\t\tString key      = entry.getKey();\n\t\tint    br_open  = key.indexOf('[');\n\t\tint    br_close = key.indexOf(']');\n\n\t\tif ((br_open < 0) || (br_close < 0)) {\n\n\t\t\t// default database is configured elsewhere\n\t\t\treturn null;\n\t\t}\n\n\t\tString   repo_class = auth_repo_class;\n\t\tString   options    = key.substring(br_open + 1, br_close);\n\t\tString[] domains    = options.split(\",\");\n\n\t\tlog.log(Level.INFO, \"Found DB domain: {0}\", Arrays.toString(domains));\n\n\t\tString get_user_db = RepositoryFactory.GEN_AUTH_DB + \"[\" + options + \"]\";\n\n\t\tif (params.get(get_user_db) != null) {\n\t\t\trepo_class = (String) params.get(get_user_db);\n\t\t}\n\t\tfor (String domain : domains) {\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_CLASS_PROP_KEY + \"/\" + domain, repo_class);\n\t\t\tlog.log(Level.CONFIG, \"Setting defaults: {0}/{1}={2}\", new Object[] {\n\t\t\t\t\tRepositoryFactory.AUTH_REPO_CLASS_PROP_KEY,\n\t\t\t\t\tdomain, repo_class });\n\t\t\tdefaults.put(RepositoryFactory.AUTH_REPO_URL_PROP_KEY + \"/\" + domain, entry\n\t\t\t\t\t.getValue());\n\t\t\tlog.log(Level.CONFIG, \"Setting defaults: {0}{1}={2}\", new Object[] {\n\t\t\t\t\tRepositoryFactory.AUTH_REPO_URL_PROP_KEY,\n\t\t\t\t\tdomain, entry.getValue() });\n\t\t}\n\n\t\treturn domains;\n\t}\n\n\tprivate String[] parseUserRepoParams(Entry<String, Object> entry, Map<String,\n\t\t\tObject> params, String user_repo_class, Map<String, Object> defaults) {\n\t\tString key      = entry.getKey();\n\t\tint    br_open  = key.indexOf('[');\n\t\tint    br_close = key.indexOf(']');\n\n\t\tif ((br_open < 0) || (br_close < 0)) {\n\n\t\t\t// default database is configured elsewhere\n\t\t\treturn null;\n\t\t}\n\n\t\tString   repo_class = user_repo_class;\n\t\tString   options    = key.substring(br_open + 1, br_close);\n\t\tString[] domains    = options.split(\",\");\n\n\t\tlog.log(Level.INFO, \"Found DB domain: {0}\", Arrays.toString(domains));\n\n\t\tString get_user_db = RepositoryFactory.GEN_USER_DB + \"[\" + options + \"]\";\n\n\t\tif (params.get(get_user_db) != null) {\n\t\t\trepo_class = (String) params.get(get_user_db);\n\t\t}\n\t\tfor (String domain : domains) {\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_CLASS_PROP_KEY + \"/\" + domain, repo_class);\n\t\t\tlog.log(Level.CONFIG, \"Setting defaults: {0}{1}={2}\", new Object[] {\n\t\t\t\t\tRepositoryFactory.USER_REPO_CLASS_PROP_KEY,\n\t\t\t\t\tdomain, repo_class });\n\t\t\tdefaults.put(RepositoryFactory.USER_REPO_URL_PROP_KEY + \"/\" + domain, entry\n\t\t\t\t\t.getValue());\n\t\t\tlog.log(Level.CONFIG, \"Setting defaults: {0}{1}={2}\", new Object[] {\n\t\t\t\t\tRepositoryFactory.USER_REPO_URL_PROP_KEY,\n\t\t\t\t\tdomain, entry.getValue() });\n\t\t}\n\n\t\treturn domains;\n\t}\n\n\tprivate void setupLogManager( Map<String, Object> properties ) {\n\t\tSet<Map.Entry<String, Object>> entries = properties.entrySet();\n\t\tStringBuilder buff = new StringBuilder( 200 );\n\n\t\tfor ( Map.Entry<String, Object> entry : entries ) {\n\t\t\tif ( entry.getKey().startsWith( LOGGING_KEY ) ){\n\t\t\t\tString key = entry.getKey().substring( LOGGING_KEY.length() );\n\t\t\t\tloggingSetup.put( key, entry.getValue().toString() );\n\t\t\t}\n\t\t}\n\n\t\tfor ( String key : loggingSetup.keySet() ) {\n\t\t\tString entry = loggingSetup.get( key );\n\t\t\tbuff.append( key ).append( \"=\" ).append( entry ).append( \"\\n\" );\n\t\t\tif ( key.equals( \"java.util.logging.FileHandler.pattern\" ) ){\n\t\t\t\tFile log_path = new File( entry ).getParentFile();\n\t\t\t\tif ( !log_path.exists() ){\n\t\t\t\t\tlog_path.mkdirs();\n\t\t\t\t}\n\t\t\t}    // end of if (key.equals())\n\t\t}      // end of if (entry.getKey().startsWith(LOGGING_KEY))\n\n\t\t// System.out.println(\"Setting logging: \\n\" + buff.toString());\n\t\tloadLogManagerConfig(buff.toString());\n\t\tlog.config(\"DONE\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate Map<String, String> getRepoParams(Map<String, Object> props, String repo_type,\n\t\t\tString domain) {\n\t\tMap<String, String> result     = new LinkedHashMap<String, String>(10);\n\t\tString              prop_start = repo_type + ((domain == null)\n\t\t\t\t? \"\"\n\t\t\t\t: \"/\" + domain);\n\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(prop_start)) {\n\n\t\t\t\t// Split the key to configuration nodes separated with '/'\n\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t// The plugin ID part may contain many IDs separated with comma ','\n\t\t\t\t// We have to make sure that the default repository does not pick up\n\t\t\t\t// properties set for a specific domain\n\t\t\t\tif (((domain == null) && (nodes.length == 2)) || ((domain != null) && (nodes\n\t\t\t\t\t\t.length == 3))) {\n\n\t\t\t\t\t// if (nodes.length > 1) {\n\t\t\t\t\tresult.put(nodes[nodes.length - 1], entry.getValue().toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/06/08\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/ConfiguratorOld.java",
    "content": "/*\n * ConfiguratorOld.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.conf;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\n\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\n\nimport tigase.server.Command;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Iq;\nimport tigase.server.MessageReceiver;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\n\nimport tigase.util.ClassUtil;\n\nimport tigase.xml.db.Types.DataType;\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.IOException;\n\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.TreeMap;\n\n/**\n * Class ConfiguratorOld\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConfiguratorOld\n\t\t\t\textends ConfiguratorAbstract {\n\tprivate static String             key        = null;\n\tprivate static final Logger       log = Logger.getLogger(\"tigase.conf.Configurator\");\n\tprivate static MonitoringSetupIfc monitoring = null;\n\tprivate static String             value      = null;\n\tprivate static boolean            set        = false;\n\tprivate static boolean            print      = false;\n\tprivate static boolean            force      = true;\n\tprivate static boolean            add        = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String              config_file_name = null;\n\tprivate ServiceEntity       config_list      = null;\n\tprivate ServiceEntity       config_set       = null;\n\tprivate ConfigXMLRepository repository       = null;\n\tprivate Map<String, Object> defProperties    = new LinkedHashMap<String, Object>();\n\tprivate Map<String, Object> defConfigParams  = new LinkedHashMap<String, Object>();\n\n\t/**\n\t * This variable is used only for configuration at run-time to add new\n\t * components....\n\t */\n\tprivate String        routerCompName = null;\n\tprivate ServiceEntity serviceEntity  = null;\n\tprivate boolean       demoMode       = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic ConfiguratorOld() {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void componentAdded(Configurable component) throws ConfigurationException {\n\t\tsuper.componentAdded(component);\n\t\tif (log.isLoggable(Level.CONFIG)) {\n\t\t\tlog.config(\" component: \" + component.getName());\n\t\t}\n\n\t\tServiceEntity item = config_list.findNode(component.getName());\n\n\t\tif (item == null) {\n\t\t\titem = new ServiceEntity(getName(), component.getName(), \"Component: \" + component\n\t\t\t\t\t.getName());\n\t\t\titem.addFeatures(CMD_FEATURES);\n\t\t\titem.addIdentities(new ServiceIdentity[] { new ServiceIdentity(\"automation\",\n\t\t\t\t\t\"command-node\", \"Component: \" + component.getName()) });\n\t\t\tconfig_list.addItems(new ServiceEntity[] { item });\n\t\t}\n\t\tif (config_set.findNode(component.getName()) == null) {\n\t\t\tconfig_set.addItems(new ServiceEntity[] { item });\n\t\t}\n\t\tif (component.getClass().getName().equals(ROUTER_COMP_CLASS_NAME)) {\n\t\t\trouterCompName = component.getName();\n\t\t}    // end of if (component.getClass().getName().equals())\n\t}\n\n\t@Override\n\tpublic void init(String[] args) throws ConfigurationException {\n\n\t\t// String fileName, String[] args) throws XMLDBException {\n\t\t// System.out.println(\"configurator init...\");\n\t\tparseArgs(args);\n\n\t\t// System.out.println(\"configurator after parse args, reading config from file: \" + fileName);\n\t\ttry {\n\t\t\trepository = ConfigXMLRepository.getConfigRepository(config_file_name);\n\t\t} catch (Exception e) {\n\t\t\tthrow new ConfigurationException(\"Problem reading configuration repository\", e);\n\t\t}\n\n\t\t// System.out.println(\"configurator after config repository load\");\n\t\tdefConfigParams.putAll(getAllProperties(null));\n\n\t\t// System.out.println(\"configurator after defparams.putall all properties\");\n\t\tSet<String> prop_keys = defProperties.keySet();\n\n\t\t// System.out.println(\"configurator starting loop....\");\n\t\tfor (String key : prop_keys) {\n\n\t\t\t// System.out.println(\"Analyzing key: \" + key);\n\t\t\tint idx1 = key.indexOf(\"/\");\n\n\t\t\tif (idx1 > 0) {\n\t\t\t\tString root     = key.substring(0, idx1);\n\t\t\t\tString node     = key.substring(idx1 + 1);\n\t\t\t\tString prop_key = null;\n\t\t\t\tint    idx2     = node.lastIndexOf(\"/\");\n\n\t\t\t\tif (idx2 > 0) {\n\t\t\t\t\tprop_key = node.substring(idx2 + 1);\n\t\t\t\t\tnode     = node.substring(0, idx2);\n\t\t\t\t} else {\n\t\t\t\t\tprop_key = node;\n\t\t\t\t\tnode     = null;\n\t\t\t\t}\n\t\t\t\trepository.set(root, node, prop_key, defProperties.get(key));\n\t\t\t\tlog.config(\"Added default config property: (\" + key + \"=\" + defProperties.get(\n\t\t\t\t\t\tkey) + \"), classname: \" + defProperties.get(key).getClass().getName());\n\n\t\t\t\t// System.out.println(\"Added default config property: (\"\n\t\t\t\t// + key + \"=\" + defProperties.getProperty(key) + \")\");\n\t\t\t} else {\n\t\t\t\tlog.warning(\"Ignoring default property, component part is missing: \" + key);\n\t\t\t}\n\t\t}\n\n\t\t// Not sure if this is the correct pleace to initialize monitoring\n\t\t// maybe it should be initialized init initializationCompleted but\n\t\t// Then some stuff might be missing. Let's try to do it here for now\n\t\t// and maybe change it later.\n\t\tinitMonitoring((String) defConfigParams.get(MONITORING), new File(config_file_name)\n\t\t\t\t.getParent());\n\t}\n\n\t@Override\n\tpublic void initializationCompleted() {\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\treturn;\n\t\t}\n\t\tsuper.initializationCompleted();\n\t\tif (monitoring != null) {\n\t\t\tmonitoring.initializationCompleted();\n\t\t}\n\t}\n\n\t/**\n\t * Describe <code>main</code> method here.\n\t *\n\t * @param args a <code>String[]</code> value\n\t * @throws Exception\n\t */\n\tpublic static void main(final String[] args) throws Exception {\n\t\tforce = false;\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tif (args[i].equals(\"-h\")) {\n\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-key\")) {\n\t\t\t\t\tkey = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-value\")) {\n\t\t\t\t\tvalue = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-set\")) {\n\t\t\t\t\tset = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-add\")) {\n\t\t\t\t\tadd = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-print\")) {\n\t\t\t\t\tprint = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].equals(\"-f\")) {\n\t\t\t\t\tforce = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t}      // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\n\t\tConfiguratorOld conf = new ConfiguratorOld();\n\n\t\tconf.init(args);\n\t\tif (set || add) {\n\t\t\tconf.setValue(key, value, add, true, null);\n\t\t}    // end of if (set)\n\t\tif (print) {\n\t\t\tMap<String, Object> allprop = conf.getAllProperties(key);\n\n\t\t\tfor (Map.Entry<String, Object> entry : allprop.entrySet()) {\n\t\t\t\tprint(entry.getKey(), entry.getValue());\n\t\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\t\t}      // end of if (print)\n\t}\n\n\t@Override\n\tpublic void parseArgs(final String[] args) {\n\t\tdefConfigParams.put(GEN_TEST, Boolean.FALSE);\n\t\tdefConfigParams.put(\"config-type\", GEN_CONFIG_DEF);\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tString key = null;\n\t\t\t\tObject val = null;\n\n\t\t\t\tif (args[i].equals(\"-c\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\tconfig_file_name = args[++i];\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\t\t\t\tif (args[i].startsWith(GEN_CONFIG)) {\n\t\t\t\t\tkey = \"config-type\";\n\t\t\t\t\tval = args[i];\n\t\t\t\t}\n\t\t\t\tif (args[i].startsWith(GEN_TEST)) {\n\t\t\t\t\tkey = args[i];\n\t\t\t\t\tval = Boolean.TRUE;\n\t\t\t\t}\n\t\t\t\tif (args[i].equals(RepositoryFactory.GEN_USER_DB) || args[i].equals(\n\t\t\t\t\t\tRepositoryFactory.GEN_USER_DB_URI) || args[i].equals(RepositoryFactory\n\t\t\t\t\t\t.GEN_AUTH_DB) || args[i].equals(RepositoryFactory.GEN_AUTH_DB_URI) || args[i]\n\t\t\t\t\t\t.startsWith(GEN_COMP_NAME) || args[i].startsWith(GEN_COMP_CLASS) || args[i]\n\t\t\t\t\t\t.startsWith(GEN_EXT_COMP) || args[i].equals(GEN_VIRT_HOSTS) || args[i].equals(\n\t\t\t\t\t\tGEN_ADMINS) || args[i].equals(GEN_DEBUG) || (args[i].startsWith(GEN_CONF) &&\n\t\t\t\t\t\t!args[i].startsWith(GEN_CONFIG)) || args[i].equals(\n\t\t\t\t\t\tPROPERTY_FILENAME_PROP_KEY) || args[i].equals(CLUSTER_MODE)) {\n\t\t\t\t\tkey = args[i];\n\t\t\t\t\tval = args[++i];\n\t\t\t\t}\n\t\t\t\tif (key != null) {\n\t\t\t\t\tdefConfigParams.put(key, val);\n\n\t\t\t\t\t// System.out.println(\"Setting defaults: \" + key + \"=\" + val.toString());\n\t\t\t\t\tlog.config(\"Setting defaults: \" + key + \"=\" + val.toString());\n\t\t\t\t}    // end of if (key != null)\n\t\t\t}      // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\n\t\tString property_filename = (String) defConfigParams.get(PROPERTY_FILENAME_PROP_KEY);\n\n\t\tif (property_filename != null) {\n\t\t\tlog.config(\"Loading initial properties from property file: \" + property_filename);\n\t\t\ttry {\n\t\t\t\tProperties defProps = new Properties();\n\n\t\t\t\tdefProps.load(new FileReader(property_filename));\n\n\t\t\t\tSet<String> prop_keys = defProps.stringPropertyNames();\n\n\t\t\t\tfor (String key : prop_keys) {\n\t\t\t\t\tString value = defProps.getProperty(key).trim();\n\n\t\t\t\t\tif (key.startsWith(\"--\") || key.equals(\"config-type\")) {\n\t\t\t\t\t\tdefConfigParams.put(key.trim(), value);\n\n\t\t\t\t\t\t// defProperties.remove(key);\n\t\t\t\t\t\tlog.config(\"Added default config parameter: (\" + key + \"=\" + value + \")\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tObject val = value;\n\n\t\t\t\t\t\tif (key.matches(\".*\\\\[[LISBlisb]\\\\]$\")) {\n\t\t\t\t\t\t\tchar c = key.charAt(key.length() - 2);\n\n\t\t\t\t\t\t\tkey = key.substring(0, key.length() - 3);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tswitch (c) {\n\t\t\t\t\t\t\t\tcase 'L' :\n\n\t\t\t\t\t\t\t\t\t// Long value\n\t\t\t\t\t\t\t\t\tval = Long.decode(value);\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'I' :\n\n\t\t\t\t\t\t\t\t\t// Integer value\n\t\t\t\t\t\t\t\t\tval = Integer.decode(value);\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'B' :\n\n\t\t\t\t\t\t\t\t\t// Boolean value\n\t\t\t\t\t\t\t\t\tval = Boolean.valueOf(Boolean.parseBoolean(value));\n\t\t\t\t\t\t\t\t\tlog.config(\"Found Boolean property: \" + val.toString());\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 's' :\n\n\t\t\t\t\t\t\t\t\t// Comma separated, Strings array\n\t\t\t\t\t\t\t\t\tval = value.split(\",\");\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'i' :\n\n\t\t\t\t\t\t\t\t\t// Comma separated, int array\n\t\t\t\t\t\t\t\t\tString[] ints_str = value.split(\",\");\n\t\t\t\t\t\t\t\t\tint[]    ints     = new int[ints_str.length];\n\t\t\t\t\t\t\t\t\tint      k        = 0;\n\n\t\t\t\t\t\t\t\t\tfor (String i : ints_str) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tints[k++] = Integer.parseInt(i);\n\t\t\t\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\t\t\t\tlog.warning(\"Incorrect int array settins: \" + i);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tval = ints;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'l' :\n\n\t\t\t\t\t\t\t\t\t// Comma separated, long array\n\t\t\t\t\t\t\t\t\tString[] longs_str = value.split(\",\");\n\t\t\t\t\t\t\t\t\tlong[]   longs     = new long[longs_str.length];\n\t\t\t\t\t\t\t\t\tint      j         = 0;\n\n\t\t\t\t\t\t\t\t\tfor (String i : longs_str) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tlongs[j++] = Long.parseLong(i);\n\t\t\t\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\t\t\t\tlog.warning(\"Incorrect long array settins: \" + i);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tval = longs;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault :\n\n\t\t\t\t\t\t\t\t\t// Do nothing, default to String\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tlog.log(Level.CONFIG, \"Incorrect parameter modifier\", e);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefProperties.put(key.trim(), val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (FileNotFoundException e) {\n\t\t\t\tlog.warning(\"Given property file was not found: \" + property_filename);\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can not read property file: \" + property_filename, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet, final Queue<Packet> results) {\n\t\tif (!packet.isCommand()) {\n\t\t\treturn;\n\t\t}\n\n\t\tIq iqc = (Iq) packet;\n\n\t\tif ((iqc.getType() != null) && (iqc.getType() == StanzaType.error)) {\n\t\t\tlog.info(\"Ignoring error packet: \" + iqc.toString());\n\n\t\t\treturn;\n\t\t}\n\n\t\tString nick = iqc.getTo().getLocalpart();\n\n\t\tif ((nick == null) ||!getName().equals(nick)) {\n\t\t\treturn;\n\t\t}\n\n\t\tString msg = \"Please be careful, you are service admin and all changes\" +\n\t\t\t\t\" you make are instantly applied to live system!\";\n\t\tboolean admin = true;\n\n\t\tif (iqc.getPermissions() != Permissions.ADMIN) {\n\t\t\tif (demoMode) {\n\t\t\t\tadmin = false;\n\t\t\t\tmsg = \"You are not admin. You can safely play with the settings as\" +\n\t\t\t\t\t\t\" you can not change anything.\";\n\t\t\t\tif ((iqc.getStrCommand() != null) && iqc.getStrCommand().endsWith(DEF_SM_NAME)) {\n\t\t\t\t\tPacket result = iqc.commandResult(Command.DataType.result);\n\n\t\t\t\t\tCommand.addFieldValue(result, \"Note\", msg, \"fixed\");\n\t\t\t\t\tCommand.addFieldValue(result, \"Note\",\n\t\t\t\t\t\t\t\"Restricted area, only admin can see these settings.\", \"fixed\");\n\t\t\t\t\tresults.offer(result);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"You are not authorized for this action.\", true));\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.warning(\"Packet processing exception: \" + e);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Command received: \" + iqc.toString());\n\t\t}\n\n\t\tCommand.Action action = Command.getAction(iqc);\n\n\t\tif (action == Command.Action.cancel) {\n\t\t\tPacket result = iqc.commandResult(null);\n\n\t\t\tresults.offer(result);\n\n\t\t\treturn;\n\t\t}\n\t\tswitch (iqc.getCommand()) {\n\t\tcase OTHER :\n\t\t\tif (iqc.getStrCommand() != null) {\n\t\t\t\tif (iqc.getStrCommand().startsWith(\"config/list/\")) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString[] spl    = iqc.getStrCommand().split(\"/\");\n\t\t\t\t\t\tPacket   result = iqc.commandResult(Command.DataType.result);\n\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Note\", msg, \"fixed\");\n\n\t\t\t\t\t\tMap<String, Object> allprop = getAllProperties(spl[2]);\n\n\t\t\t\t\t\tfor (Map.Entry<String, Object> entry : allprop.entrySet()) {\n\t\t\t\t\t\t\tCommand.addFieldValue(result, XMLUtils.escape(entry.getKey()), XMLUtils\n\t\t\t\t\t\t\t\t\t.escape(objectToString(entry.getValue())));\n\t\t\t\t\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t} catch (ConfigurationException ex) {\n\t\t\t\t\t\tLogger.getLogger(ConfiguratorOld.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (iqc.getStrCommand().startsWith(\"config/set/\")) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString[] spl    = iqc.getStrCommand().split(\"/\");\n\t\t\t\t\t\tPacket   result = iqc.commandResult(Command.DataType.result);\n\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Note\", msg, \"fixed\");\n\t\t\t\t\t\tif (Command.getData(packet) == null) {\n\t\t\t\t\t\t\tprepareConfigData(result, spl[2]);\n\t\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tupdateConfigChanges(packet, result, spl[2], admin);\n\t\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (ConfigurationException ex) {\n\t\t\t\t\t\tLogger.getLogger(ConfiguratorOld.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param objName\n\t * @param bean\n\t */\n\tpublic static void putMXBean(String objName, Object bean) {\n\t\tif (monitoring != null) {\n\t\t\tmonitoring.putMXBean(objName, bean);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t * @throws tigase.conf.ConfigurationException\n\t */\n\tpublic void setup(String name) throws ConfigurationException {\n\t\tConfigurable component = getComponent(name);\n\n\t\tsetup(component);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t *\n\t * \n\t *\n\t * @throws ConfigurationException\n\t */\n\tpublic Map<String, Object> getAllProperties(String key) throws ConfigurationException {\n\t\tMap<String, Object> result = new LinkedHashMap<String, Object>();\n\t\tString[]            comps  = getComponents();\n\n\t\tif (comps != null) {\n\t\t\tfor (String comp : comps) {\n\t\t\t\tMap<String, Object> prop = getProperties(comp);\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : prop.entrySet()) {\n\t\t\t\t\tString entry_key = comp + \"/\" + entry.getKey();\n\n\t\t\t\t\tif (key == null) {\n\t\t\t\t\t\tresult.put(entry_key, entry.getValue());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (entry_key.startsWith(key)) {\n\t\t\t\t\t\t\tresult.put(entry_key, entry.getValue());\n\t\t\t\t\t\t}    // end of if (entry_key.startsWith(key))\n\t\t\t\t\t}      // end of if (key == null) else\n\t\t\t\t}        // end of for (Map.Entry entry: prop.entrySet())\n\t\t\t}          // end of for (String comp: comps)\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String[] getComponents() {\n\t\treturn repository.getCompNames();\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defaults = super.getDefaults(params);\n\n\t\tdefaults.put(\"demo-mode\", demoMode);\n\n\t\treturn defaults;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefConfigParams() {\n\t\treturn defConfigParams;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tif ((jid != null) && getName().equals(jid.getLocalpart()) && isAdmin(from)) {\n\t\t\treturn serviceEntity.getDiscoInfo(node);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\t\tif (isAdmin(from)) {\n\t\t\tif (getName().equals(jid.getLocalpart())) {\n\t\t\t\treturn serviceEntity.getDiscoItems(node, jid.toString());\n\t\t\t} else {\n\t\t\t\tif (node == null) {\n\t\t\t\t\treturn Arrays.asList(serviceEntity.getDiscoItem(null, BareJID.toString(\n\t\t\t\t\t\t\tgetName(), jid.toString())));\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param objName\n\t *\n\t * \n\t */\n\tpublic static Object getMXBean(String objName) {\n\t\tif (monitoring != null) {\n\t\t\treturn monitoring.getMXBean(objName);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t\tserviceEntity = new ServiceEntity(name, \"config\", \"Server configuration\");\n\t\tserviceEntity.addIdentities(new ServiceIdentity[] { new ServiceIdentity(\"automation\",\n\t\t\t\t\"command-list\", \"Configuration commands\") });\n\t\tserviceEntity.addFeatures(DEF_FEATURES);\n\t\tconfig_list = new ServiceEntity(name, \"list\", \"List\");\n\t\tconfig_list.addIdentities(new ServiceIdentity[] { new ServiceIdentity(\"automation\",\n\t\t\t\t\"command-list\", \"Config listings\") });\n\t\tconfig_list.addFeatures(DEF_FEATURES);\n\t\tconfig_set = new ServiceEntity(name, \"set\", \"Set\");\n\t\tconfig_set.addIdentities(new ServiceIdentity[] { new ServiceIdentity(\"automation\",\n\t\t\t\t\"command-list\", \"Config settings\") });\n\t\tconfig_set.addFeatures(DEF_FEATURES);\n\n\t\tServiceEntity item = new ServiceEntity(getName(), \"--none--\", \"Add new component...\");\n\n\t\titem.addFeatures(CMD_FEATURES);\n\t\titem.addIdentities(new ServiceIdentity(\"automation\", \"command-node\",\n\t\t\t\t\"Add new component...\"));\n\t\tconfig_set.addItems(item);\n\t\tserviceEntity.addItems(config_list, config_set);\n\t}\n\n\t@Override\n\tpublic void setProperties(final Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\n\t\t// setupLogManager(props);\n\t\tdemoMode = (Boolean) props.get(\"demo-mode\");\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t * @param val\n\t * @param result_pack\n\t * @param admin\n\t *\n\t * \n\t */\n\tpublic Object setPropertyValue(String key, String val, Packet result_pack,\n\t\t\tboolean admin) {\n\t\tObject result = null;\n\n\t\ttry {\n\t\t\tif (admin) {\n\t\t\t\tresult = setValue(key, val, false, false, null);\n\t\t\t}\n\t\t\tif (result != null) {\n\t\t\t\tCommand.addFieldValue(result_pack, XMLUtils.escape(key), XMLUtils.escape(val));\n\t\t\t} else {\n\t\t\t\tCommand.addFieldValue(result_pack, \"Note\",\n\t\t\t\t\t\t\"You can not set new properties yet, you can just modify existing ones.\",\n\t\t\t\t\t\t\"fixed\");\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tCommand.addFieldValue(result_pack, \"Note\", \"Error setting property: \" + e, \"fixed\");\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node_key\n\t * @param value\n\t * @param add\n\t * @param feedback\n\t * @param orig\n\t *\n\t * \n\t *\n\t * @throws Exception\n\t */\n\tpublic Object setValue(String node_key, String value, boolean add, boolean feedback,\n\t\t\tMap<String, Object> orig)\n\t\t\t\t\tthrows Exception {\n\t\tint    root_idx = node_key.indexOf('/');\n\t\tString root     = (root_idx > 0)\n\t\t\t\t? node_key.substring(0, root_idx)\n\t\t\t\t: \"\";\n\t\tint    key_idx  = node_key.lastIndexOf('/');\n\t\tString key      = (key_idx > 0)\n\t\t\t\t? node_key.substring(key_idx + 1)\n\t\t\t\t: node_key;\n\t\tString subnode  = null;\n\n\t\tif (root_idx != key_idx) {\n\t\t\tsubnode = node_key.substring(root_idx + 1, key_idx);\n\t\t}\n\n\t\tObject old_val = null;\n\n\t\tif (orig == null) {\n\t\t\told_val = repository.get(root, subnode, key, null);\n\t\t} else {\n\t\t\told_val = orig.get(node_key);\n\t\t}    // end of if (orig == null) else\n\t\tif (old_val != null) {\n\t\t\tObject   new_val = null;\n\t\t\tDataType type    = DataType.valueof(old_val.getClass().getSimpleName());\n\n\t\t\tswitch (type) {\n\t\t\tcase INTEGER :\n\t\t\t\tnew_val = Integer.decode(value);\n\n\t\t\t\tbreak;\n\n\t\t\tcase INTEGER_ARR :\n\t\t\t\tif (add) {\n\t\t\t\t\tint old_len = ((int[]) old_val).length;\n\n\t\t\t\t\tnew_val                    = Arrays.copyOf((int[]) old_val, old_len + 1);\n\t\t\t\t\t((int[]) new_val)[old_len] = Integer.decode(value);\n\t\t\t\t} else {\n\t\t\t\t\tString[] spl = value.split(\",\");\n\n\t\t\t\t\tnew_val = new int[spl.length];\n\t\t\t\t\tfor (int i = 0; i < spl.length; i++) {\n\t\t\t\t\t\t((int[]) new_val)[i] = Integer.decode(spl[i].trim());\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (add) else\n\n\t\t\t\tbreak;\n\n\t\t\tcase LONG :\n\t\t\t\tnew_val = Long.decode(value);\n\n\t\t\t\tbreak;\n\n\t\t\tcase LONG_ARR :\n\t\t\t\tif (add) {\n\t\t\t\t\tint old_len = ((long[]) old_val).length;\n\n\t\t\t\t\tnew_val                     = Arrays.copyOf((long[]) old_val, old_len + 1);\n\t\t\t\t\t((long[]) new_val)[old_len] = Long.decode(value);\n\t\t\t\t} else {\n\t\t\t\t\tString[] spl = value.split(\",\");\n\n\t\t\t\t\tnew_val = new long[spl.length];\n\t\t\t\t\tfor (int i = 0; i < spl.length; i++) {\n\t\t\t\t\t\t((long[]) new_val)[i] = Long.decode(spl[i].trim());\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (add) else\n\n\t\t\t\tbreak;\n\n\t\t\tcase STRING :\n\t\t\t\tnew_val = value;\n\n\t\t\t\tbreak;\n\n\t\t\tcase STRING_ARR :\n\t\t\t\tif (add) {\n\t\t\t\t\tint old_len = ((String[]) old_val).length;\n\n\t\t\t\t\tnew_val                       = Arrays.copyOf((String[]) old_val, old_len + 1);\n\t\t\t\t\t((String[]) new_val)[old_len] = value;\n\t\t\t\t} else {\n\t\t\t\t\tString[] spl = value.split(\",\");\n\n\t\t\t\t\tnew_val = new String[spl.length];\n\t\t\t\t\tfor (int i = 0; i < spl.length; i++) {\n\t\t\t\t\t\t((String[]) new_val)[i] = spl[i].trim();\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (add) else\n\n\t\t\t\tbreak;\n\n\t\t\tcase DOUBLE :\n\t\t\t\tnew_val = new Double(Double.parseDouble(value));\n\n\t\t\t\tbreak;\n\n\t\t\tcase DOUBLE_ARR :\n\t\t\t\tif (add) {\n\t\t\t\t\tint old_len = ((double[]) old_val).length;\n\n\t\t\t\t\tnew_val                       = Arrays.copyOf((double[]) old_val, old_len + 1);\n\t\t\t\t\t((double[]) new_val)[old_len] = Double.parseDouble(value);\n\t\t\t\t} else {\n\t\t\t\t\tString[] spl = value.split(\",\");\n\n\t\t\t\t\tnew_val = new double[spl.length];\n\t\t\t\t\tfor (int i = 0; i < spl.length; i++) {\n\t\t\t\t\t\t((double[]) new_val)[i] = Double.parseDouble(spl[i].trim());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase BOOLEAN :\n\t\t\t\tnew_val = Boolean.valueOf(parseBoolean(value));\n\n\t\t\t\tbreak;\n\n\t\t\tcase BOOLEAN_ARR :\n\t\t\t\tif (add) {\n\t\t\t\t\tint old_len = ((boolean[]) old_val).length;\n\n\t\t\t\t\tnew_val                        = Arrays.copyOf((boolean[]) old_val, old_len +\n\t\t\t\t\t\t\t1);\n\t\t\t\t\t((boolean[]) new_val)[old_len] = parseBoolean(value);\n\t\t\t\t} else {\n\t\t\t\t\tString[] spl = value.split(\",\");\n\n\t\t\t\t\tnew_val = new boolean[spl.length];\n\t\t\t\t\tfor (int i = 0; i < spl.length; i++) {\n\t\t\t\t\t\t((boolean[]) new_val)[i] = parseBoolean(spl[i].trim());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tnew_val = value;\n\n\t\t\t\tbreak;\n\t\t\t}      // end of switch (type)\n\t\t\tif (orig == null) {\n\t\t\t\trepository.set(root, subnode, key, new_val);\n\t\t\t\trepository.store();\n\t\t\t} else {\n\t\t\t\torig.put(node_key, new_val);\n\t\t\t}      // end of if (orig == null) else\n\n\t\t\treturn new_val;\n\t\t} else {\n\t\t\tif (force) {\n\t\t\t\tif (orig == null) {\n\t\t\t\t\trepository.set(root, subnode, key, value);\n\t\t\t\t\trepository.store();\n\t\t\t\t} else {\n\t\t\t\t\torig.put(node_key, value);\n\t\t\t\t}    // end of if (orig == null) else\n\t\t\t\tif (feedback) {\n\t\t\t\t\tSystem.out.println(\"Forced to set new key=value: \" + key + \"=\" + value);\n\t\t\t\t}\n\n\t\t\t\treturn value;\n\t\t\t} else {\n\t\t\t\tif (feedback) {\n\t\t\t\t\tSystem.out.println(\"Error, given key does not exist in config yet.\");\n\t\t\t\t\tSystem.out.println(\"You can only modify existing values, you can add new.\");\n\t\t\t\t\tSystem.out.println(\"Use '-f' switch to force creation of the new property.\");\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t}      // end of if (force) else\n\t\t}        // end of else\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n//private boolean isValidCompName(String name) {\n//  return !(name.contains(\" \")\n//    || name.contains(\"\\t\")\n//    || name.contains(\"@\")\n//    || name.contains(\"&\"));\n//}\n\tprivate boolean checkComponentName(Packet result, String name) {\n\t\tString msg = name;\n\n\t\tif (msg != null) {\n\t\t\tCommand.addFieldValue(result, \"Info\", \"Note!! \" + msg +\n\t\t\t\t\t\", please provide valid component name.\", \"fixed\");\n\t\t\tnewComponentCommand(result);\n\n\t\t\treturn false;\n\t\t}    // end of if (new_comp_name == null || new_comp_name.length() == 0)\n\n\t\tString[] comp_names = getComponents();\n\n\t\tfor (String comp_name : comp_names) {\n\t\t\tif (comp_name.equals(name)) {\n\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\"Note!! Component with provided name already exists.\", \"fixed\");\n\t\t\t\tCommand.addFieldValue(result, \"Info\", \"Please provide different component name.\",\n\t\t\t\t\t\t\"fixed\");\n\t\t\t\tnewComponentCommand(result);\n\n\t\t\t\treturn false;\n\t\t\t}    // end of if (comp_name.equals(new_comp_name))\n\t\t}      // end of for (String comp_name: comp_names)\n\n\t\treturn true;\n\t}\n\n\tprivate void createNewComponent(Packet packet, Packet result, boolean admin) {\n\t\tString new_comp_name  = Command.getFieldValue(packet, \"Component name\");\n\t\tString new_comp_class = Command.getFieldValue(packet, \"Component class\");\n\n\t\ttry {\n\t\t\tMessageReceiver mr = (MessageReceiver) Class.forName(new_comp_class).newInstance();\n\n\t\t\tmr.setName(new_comp_name);\n\t\t\tif (mr instanceof Configurable) {\n\t\t\t\tMap<String, Object> comp_props = ((Configurable) mr).getDefaults(defConfigParams);\n\t\t\t\tMap<String, Object> new_params = new LinkedHashMap<String, Object>(comp_props);\n\n\t\t\t\t// Convert String values to proper Objecy values\n\t\t\t\tfor (Map.Entry<String, Object> entry : comp_props.entrySet()) {\n\t\t\t\t\tString val = Command.getFieldValue(packet, XMLUtils.escape(entry.getKey()));\n\n\t\t\t\t\tif (val == null) {\n\t\t\t\t\t\tval = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tval = XMLUtils.unescape(val);\n\t\t\t\t\tlog.info(\"New component value: \" + entry.getKey() + \"=\" + val);\n\t\t\t\t\tsetValue(entry.getKey(), val, false, false, new_params);\n\t\t\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\t\t\t\tif (admin) {\n\n\t\t\t\t\t// Now we can save all properties to config repository:\n\t\t\t\t\tfor (Map.Entry<String, Object> entry : new_params.entrySet()) {\n\t\t\t\t\t\tString key     = entry.getKey();\n\t\t\t\t\t\tString subnode = null;\n\t\t\t\t\t\tint    key_idx = entry.getKey().lastIndexOf('/');\n\n\t\t\t\t\t\tif (key_idx > 0) {\n\t\t\t\t\t\t\tkey     = entry.getKey().substring(key_idx + 1);\n\t\t\t\t\t\t\tsubnode = entry.getKey().substring(0, key_idx);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlog.info(\"Saving property to repository: \" + \"root=\" + new_comp_name +\n\t\t\t\t\t\t\t\t\", subnode=\" + subnode + \", key=\" + key + \", value=\" + entry.getValue());\n\t\t\t\t\t\trepository.set(new_comp_name, subnode, key, entry.getValue());\n\t\t\t\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\n\t\t\t\t\t// And load the component itself.....\n\t\t\t\t\t// Set class name for the component\n\t\t\t\t\trepository.set(routerCompName, \"/components/msg-receivers\", new_comp_name +\n\t\t\t\t\t\t\t\".class\", new_comp_class);\n\n\t\t\t\t\t// Activate the component\n\t\t\t\t\trepository.set(routerCompName, \"/components/msg-receivers\", new_comp_name +\n\t\t\t\t\t\t\t\".active\", true);\n\n\t\t\t\t\t// Add to the list of automaticaly loaded components\n\t\t\t\t\tsetValue(routerCompName + \"/components/msg-receivers/id-names\", new_comp_name,\n\t\t\t\t\t\t\ttrue, false, null);\n\n\t\t\t\t\t// repository.sync();\n\t\t\t\t\tsetup(routerCompName);\n\t\t\t\t}    // end of if (admin)\n\t\t\t}\n\t\t\tCommand.addNote(result, \"New component created: \" + new_comp_name);\n\t\t\tCommand.addFieldValue(result, \"Note\", \"New component created: \" + new_comp_name,\n\t\t\t\t\t\"fixed\");\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem instantiating component:\", e);\n\t\t\tCommand.addFieldValue(result, \"Component class\",\n\t\t\t\t\t\"ERROR!! Problem instantiating component, \" +\n\t\t\t\t\t\"look in log file for details...\", \"text-single\", \"Component class\");\n\t\t}    // end of try-catch\n\t}\n\n\tprivate static String help() {\n\t\treturn \"\\n\" + \"Parameters:\\n\" + \" -h             this help message\\n\" +\n\t\t\t\t\" -c file        configuration file\\n\" +\n\t\t\t\t\" -key key       node/key for the value to set\\n\" +\n\t\t\t\t\" -value value   value to set in configuration file\\n\" +\n\t\t\t\t\" -set           set given value for given key\\n\" +\n\t\t\t\t\" -add           add given value to the values list for given key\\n\" +\n\t\t\t\t\" -print         print content of all configuration settings or of given node/key\\n\" +\n\t\t\t\t\" -f             force creation of the new property - dangerous option...\\n\" +\n\t\t\t\t\"Samples:\\n\" + \" Setting admin account - overwriting any previous value(s)\\n\" +\n\t\t\t\t\" $ ./scripts/config.sh -c tigase-config.xml -print -set -key \" + DEF_SM_NAME +\n\t\t\t\t\"/admins -value admin1@localhost\\n\" +\n\t\t\t\t\" Adding next admin account leaving old value(s)\\n\" +\n\t\t\t\t\" $ ./scripts/config.sh -c tigase-config.xml -print -add -key \" + DEF_SM_NAME +\n\t\t\t\t\"/admins -value admin2@localhost\\n\" + \"\\n\" +\n\t\t\t\t\"Note: adding -print option is useful always, even with -set or -add\\n\" +\n\t\t\t\t\"      option as it prints set value afterwards.\\n\"\n\t\t;\n\t}\n\n\tprivate void initMonitoring(String settings, String configDir) {\n\t\tif ((monitoring == null) && (settings != null)) {\n\t\t\ttry {\n\t\t\t\tmonitoring = (MonitoringSetupIfc) Class.forName(\n\t\t\t\t\t\t\"tigase.management.MonitoringSetup\").newInstance();\n\t\t\t\tmonitoring.initMonitoring(settings, configDir);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can not initialize monitoring: \", e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void newComponentCommand(Packet result) {\n\t\tCommand.addFieldValue(result, \"Info\", \"Press:\", \"fixed\");\n\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\"'Next' to set all parameters for the new component.\", \"fixed\");\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addAction(result, Command.Action.next);\n\t\tCommand.addFieldValue(result, \"Component name\", \"\", \"text-single\", \"Component name\");\n\t\ttry {\n\t\t\tSet<Class<MessageReceiver>> receiv_cls = ClassUtil.getClassesImplementing(\n\t\t\t\t\tMessageReceiver.class);\n\n\t\t\t// All message receivers except MessageRouter\n\t\t\tString[] receiv_cls_names  = new String[receiv_cls.size() - 1];\n\t\t\tString[] receiv_cls_simple = new String[receiv_cls.size() - 1];\n\t\t\tint      idx               = 0;\n\n\t\t\tfor (Class<MessageReceiver> reciv : receiv_cls) {\n\t\t\t\tif (!reciv.getName().equals(ROUTER_COMP_CLASS_NAME)) {\n\t\t\t\t\treceiv_cls_names[idx]    = reciv.getName();\n\t\t\t\t\treceiv_cls_simple[idx++] = reciv.getSimpleName();\n\t\t\t\t}    // end of if (!reciv.getName().equals(ROUTER_COMP_CLASS_NAME))\n\t\t\t}      // end of for (MessageReceiver.class reciv: receiv_cls)\n\t\t\tCommand.addFieldValue(result, \"Component class\", EXT_COMP_CLASS_NAME,\n\t\t\t\t\t\"Component class\", receiv_cls_simple, receiv_cls_names);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem loading MessageReceiver implementations\", e);\n\t\t\tCommand.addFieldValue(result, \"Component class\",\n\t\t\t\t\t\"ERROR!! Problem loading MessageReceiver implementations, \" +\n\t\t\t\t\t\"look in log file for details...\", \"text-single\", \"Component class\");\n\t\t}    // end of try-catch\n\t}\n\n\tprivate void newComponentCommand(Packet packet, Packet result, boolean admin) {\n\t\tString params_set = Command.getFieldValue(packet, \"Params set\");\n\n\t\tif ((Command.getAction(packet) != null) && Command.getAction(packet).equals(\"prev\")) {\n\t\t\tnewComponentCommand(result);\n\n\t\t\treturn;\n\t\t}    // end of if ()\n\t\tif (params_set != null) {\n\t\t\tcreateNewComponent(packet, result, admin);\n\n\t\t\treturn;\n\t\t}    // end of if (params_set != null)\n\n\t\tString new_comp_name  = Command.getFieldValue(packet, \"Component name\");\n\t\tString new_comp_class = Command.getFieldValue(packet, \"Component class\");\n\n\t\tif (!checkComponentName(result, new_comp_name)) {\n\t\t\treturn;\n\t\t}    // end of if (!checkComponentName(new_comp_name))\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addFieldValue(result, \"Component name\", new_comp_name, \"hidden\");\n\t\tCommand.addFieldValue(result, \"Component class\", new_comp_class, \"hidden\");\n\t\tCommand.addFieldValue(result, \"Info1\", \"Press:\", \"fixed\");\n\t\ttry {\n\t\t\tMessageReceiver mr = (MessageReceiver) Class.forName(new_comp_class).newInstance();\n\n\t\t\tCommand.addFieldValue(result, \"Info4\", \"Component name: \" + new_comp_name +\n\t\t\t\t\t\", class: \" + mr.getClass().getSimpleName(), \"fixed\");\n\t\t\tif (mr instanceof ConnectionManager) {\n\t\t\t\tString ports = Command.getFieldValue(packet, \"TCP/IP ports\");\n\n\t\t\t\tif (ports == null) {\n\t\t\t\t\tCommand.addFieldValue(result, \"Info2\",\n\t\t\t\t\t\t\t\"1. 'Next' to set more component parameters.\", \"fixed\");\n\t\t\t\t\tCommand.addFieldValue(result, \"Info3\",\n\t\t\t\t\t\t\t\"2. 'Previous' to go back and select different component.\", \"fixed\");\n\t\t\t\t\tCommand.addAction(result, Command.Action.next);\n\t\t\t\t\tCommand.addAction(result, Command.Action.prev);\n\t\t\t\t\tCommand.addFieldValue(result, \"Info4\",\n\t\t\t\t\t\t\t\"This component uses TCP/IP ports, please provide port numbers:\", \"fixed\");\n\t\t\t\t\tCommand.addFieldValue(result, \"TCP/IP ports\", \"5557\");\n\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tString[] ports_arr = ports.split(\",\");\n\t\t\t\t\tint[]    ports_i   = new int[ports_arr.length];\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (int i = 0; i < ports_arr.length; i++) {\n\t\t\t\t\t\t\tports_i[i] = Integer.decode(ports_arr[i].trim());\n\t\t\t\t\t\t}    // end of for (int i = 0; i < ports_arr.length; i++)\n\t\t\t\t\t\tdefConfigParams.put(new_comp_name + \"/connections/ports\", ports_i);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info2\",\n\t\t\t\t\t\t\t\t\"1. 'Next' to set more component parameters.\", \"fixed\");\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info3\",\n\t\t\t\t\t\t\t\t\"2. 'Previous' to go back and select different component.\", \"fixed\");\n\t\t\t\t\t\tCommand.addAction(result, Command.Action.next);\n\t\t\t\t\t\tCommand.addAction(result, Command.Action.prev);\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info4\",\n\t\t\t\t\t\t\t\t\"Incorrect TCP/IP ports provided, please provide port numbers:\", \"fixed\");\n\t\t\t\t\t\tCommand.addFieldValue(result, \"TCP/IP ports\", ports);\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}    // end of try-catch\n\t\t\t\t}      // end of else\n\t\t\t}\n\t\t\tCommand.addFieldValue(result, \"Info2\",\n\t\t\t\t\t\"1. 'Finish' to create component with this parameters.\", \"fixed\");\n\t\t\tCommand.addFieldValue(result, \"Info3\",\n\t\t\t\t\t\"2. 'Previous' to go back and select different component.\", \"fixed\");\n\t\t\tCommand.addAction(result, Command.Action.complete);\n\t\t\tCommand.addAction(result, Command.Action.prev);\n\t\t\tmr.setName(new_comp_name);\n\t\t\tif (mr instanceof Configurable) {\n\n\t\t\t\t// Load defaults into sorted Map:\n\t\t\t\tMap<String, Object> comp_props = new TreeMap<String, Object>(((Configurable) mr)\n\t\t\t\t\t\t.getDefaults(defConfigParams));\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : comp_props.entrySet()) {\n\t\t\t\t\tCommand.addFieldValue(result, XMLUtils.escape(entry.getKey()), XMLUtils.escape(\n\t\t\t\t\t\t\tobjectToString(entry.getValue())));\n\t\t\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\t\t\t} else {\n\t\t\t\tCommand.addFieldValue(result, \"Info6\",\n\t\t\t\t\t\t\"Component is not configurable, do you want to create it?\", \"fixed\");\n\t\t\t}    // end of else\n\t\t\tCommand.addFieldValue(result, \"Params set\", \"true\", \"hidden\");\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem instantiating component:\", e);\n\t\t\tCommand.addFieldValue(result, \"Component class\",\n\t\t\t\t\t\"ERROR!! Problem instantiating component, \" +\n\t\t\t\t\t\"look in log file for details...\", \"text-single\", \"Component class\");\n\t\t}    // end of try-catch\n\t}\n\n\tprivate static String objectToString(Object value) {\n\t\tString   val_str = null;\n\t\tDataType type    = DataType.valueof(value.getClass().getSimpleName());\n\n\t\ttry {\n\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\tswitch (type) {\n\t\t\tcase STRING_ARR :\n\t\t\t\tfor (String s : (String[]) value) {\n\t\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\t\tsb.append(s);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.append(\", \").append(s);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (String s: (String[])value)\n\t\t\t\tval_str = sb.toString();\n\n\t\t\t\tbreak;\n\n\t\t\tcase INTEGER_ARR :\n\t\t\t\tfor (int s : (int[]) value) {\n\t\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\t\tsb.append(s);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.append(\", \").append(s);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (String s: (String[])value)\n\t\t\t\tval_str = sb.toString();\n\n\t\t\t\tbreak;\n\n\t\t\tcase LONG_ARR :\n\t\t\t\tfor (long s : (long[]) value) {\n\t\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\t\tsb.append(s);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.append(\", \").append(s);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (String s: (String[])value)\n\t\t\t\tval_str = sb.toString();\n\n\t\t\t\tbreak;\n\n\t\t\tcase DOUBLE_ARR :\n\t\t\t\tfor (double s : (double[]) value) {\n\t\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\t\tsb.append(s);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.append(\", \").append(s);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (String s: (String[])value)\n\t\t\t\tval_str = sb.toString();\n\n\t\t\t\tbreak;\n\n\t\t\tcase BOOLEAN_ARR :\n\t\t\t\tfor (boolean s : (boolean[]) value) {\n\t\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\t\tsb.append(s);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.append(\", \").append(s);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (String s: (String[])value)\n\t\t\t\tval_str = sb.toString();\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tval_str = value.toString();\n\n\t\t\t\tbreak;\n\t\t\t}        // end of switch (type)\n\t\t} catch (ClassCastException e) {\n\t\t\tlog.warning(\"ERROR! Problem with type casting for property: \" + key);\n\t\t}          // end of try-catch\n\n\t\treturn val_str;\n\t}\n\n\tprivate boolean parseBoolean(String val) {\n\t\treturn val.equalsIgnoreCase(\"true\") || val.equalsIgnoreCase(\"yes\") || val\n\t\t\t\t.equalsIgnoreCase(\"on\")\n\t\t;\n\t}\n\n\tprivate void prepareConfigData(Packet result, String comp_name)\n\t\t\t\t\tthrows ConfigurationException {\n\t\tif (comp_name.equals(\"--none--\")) {\n\t\t\tnewComponentCommand(result);\n\n\t\t\treturn;\n\t\t}    // end of if (comp_name.equals(\"--none--\"))\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addAction(result, Command.Action.complete);\n\n\t\t// Let's try to sort them to make it easier to find options on\n\t\t// configuration page.\n\t\tMap<String, Object> allprop = new TreeMap<String, Object>(getAllProperties(\n\t\t\t\tcomp_name));\n\n\t\tfor (Map.Entry<String, Object> entry : allprop.entrySet()) {\n\t\t\tCommand.addFieldValue(result, XMLUtils.escape(entry.getKey()), XMLUtils.escape(\n\t\t\t\t\tobjectToString(entry.getValue())));\n\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\t\tCommand.addFieldValue(result, XMLUtils.escape(\"new-prop-name\"), XMLUtils.escape(\n\t\t\t\tcomp_name + \"/\"), \"text-single\", \"New property name\");\n\t\tCommand.addFieldValue(result, XMLUtils.escape(\"new-prop-value\"), \"\", \"text-single\",\n\t\t\t\t\"New property value\");\n\t}\n\n\tprivate static void print(String key, Object value) {\n\t\tSystem.out.println(key + \" = \" + objectToString(value));\n\t}\n\n\tprivate void updateConfigChanges(Packet packet, Packet result, String comp_name,\n\t\t\tboolean admin)\n\t\t\t\t\tthrows ConfigurationException {\n\t\tif (comp_name.equals(\"--none--\")) {\n\t\t\tnewComponentCommand(packet, result, admin);\n\n\t\t\treturn;\n\t\t}    // end of if (comp_name.equals(\"--none--\"))\n\t\tCommand.addNote(result, \"You changed following settings:\");\n\t\tCommand.addFieldValue(result, \"Note\", \"You changed following settings:\", \"fixed\");\n\n\t\tMap<String, Object> allprop = getAllProperties(comp_name);\n\t\tboolean             changed = false;\n\n\t\tfor (Map.Entry<String, Object> entry : allprop.entrySet()) {\n\t\t\tString tmp_val = Command.getFieldValue(packet, XMLUtils.escape(entry.getKey()));\n\t\t\tString old_val = objectToString(entry.getValue());\n\t\t\tString new_val = old_val;\n\n\t\t\tif (tmp_val != null) {\n\t\t\t\tnew_val = XMLUtils.unescape(tmp_val);\n\t\t\t}\n\t\t\tif ((new_val != null) && (old_val != null) &&!new_val.equals(old_val)) {\n\t\t\t\tdefConfigParams.put(entry.getKey(), setPropertyValue(entry.getKey(), new_val,\n\t\t\t\t\t\tresult, admin));\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}    // end of for (Map.Entry entry: prop.entrySet())\n\n\t\tString prop_value = Command.getFieldValue(packet, \"new-prop-value\");\n\n\t\tif ((prop_value != null) && (prop_value.trim().length() > 0)) {\n\t\t\tsetPropertyValue(XMLUtils.unescape(Command.getFieldValue(packet, \"new-prop-name\")),\n\t\t\t\t\tXMLUtils.unescape(prop_value), result, admin);\n\t\t\tchanged = true;\n\t\t}\n\t\tif (changed && admin) {\n\t\t\tsetup(comp_name);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/06/08\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/conf/MonitoringSetupIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.conf;\n\n/**\n * Created: Jan 10, 2009 8:43:04 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface MonitoringSetupIfc {\n\t\n\tpublic enum MONITOR { jmx, http, snmp; }\n\t\n\tvoid initMonitoring(String settings, String configDir);\n\n\tvoid initializationCompleted();\n\n\tvoid putMXBean(String objName, Object bean);\n\n\tObject getMXBean(String objName);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/AuthRepository.java",
    "content": "/*\n * AuthRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.Map;\n\n/**\n * Interface <code>AuthRepository</code> defines a proxy bridge between user\n * authentication data storage and the Tigase server authentication logic. Important\n * thing about the authentication repository is that it not only stores login credentials\n * but also performs actual user authentication.\n * This is because available authentication mechanisms depend on the way data are stored\n * in the repository (database).\n *\n * Created: Sun Nov  5 21:15:46 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface AuthRepository extends Repository {\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide an\n\t * extra authentication data by the client to the authentication logic.\n\t * Please note the <code>RESULT_KEY</code> property key is used to provide authentication\n\t * data from the server to the client. This property is used to provide authentication data\n\t * from the client to the server.\n\t */\n\tpublic static final String DATA_KEY = \"data\";\n\n\t/** Field description */\n\tpublic static final String DIGEST_ID_KEY = \"digest-id\";\n\n\t/** Field description */\n\tpublic static final String DIGEST_KEY = \"digest\";\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide\n\t * desired authentication mechanism to the authentication logic.\n\t */\n\tpublic static final String MACHANISM_KEY = \"mechanism\";\n\n\t/** Field description */\n\tpublic static final String PASSWORD_KEY = \"password\";\n\n\t// Query params (and otherAuth)\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide\n\t * desired authentication protocol to the authentication logic.\n\t */\n\tpublic static final String PROTOCOL_KEY = \"protocol\";\n\n\t/**\n\t * Property value for <code>otherAuth</code> method call. It is used to provide\n\t * desired authentication NON-SASL protocol to the authentication logic.\n\t */\n\tpublic static final String PROTOCOL_VAL_NONSASL = \"nonsasl\";\n\n\t/**\n\t * Property value for <code>otherAuth</code> method call. It is used to provide\n\t * desired authentication SASL protocol to the authentication logic.\n\t */\n\tpublic static final String PROTOCOL_VAL_SASL = \"sasl\";\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide\n\t * authentication realm to the authentication logic. In most cases, the realm is just\n\t * a domain name.\n\t */\n\tpublic static final String REALM_KEY = \"realm\";\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide\n\t * authentication handshaking data during login process. Some authentication mechanisms\n\t * require exchanging requests between the client and the server. This property key points\n\t * back to the data which need to be sent back to the client.\n\t */\n\tpublic static final String RESULT_KEY = \"result\";\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide\n\t * authentication domain to the authentication logic. It is highly recommended that this\n\t * property is always set, even if the authentication protocol/mechanism does not need it\n\t * strictly.\n\t */\n\tpublic static final String SERVER_NAME_KEY = \"server-name\";\n\n\t/**\n\t * Property key name for <code>otherAuth</code> method call. It is used to provide a user\n\t * ID on successful user login. Please note, the key points to the object of\n\t * <code>BareJID</code> type.\n\t */\n\tpublic static final String USER_ID_KEY = \"user-id\";\n\n\t/** Field description */\n\tpublic static final String USERNAME_KEY = \"username\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Describe <code>addUser</code> method here.\n\t *\n\t * @param user a <code>BareJID</code> value\n\t * @param password a <code>String</code> value\n\t * @exception UserExistsException if an error occurs\n\t * @exception TigaseDBException if an error occurs\n\t */\n\tvoid addUser(BareJID user, String password)\n\t\t\t\t\tthrows UserExistsException, TigaseDBException;\n\n\t/**\n\t * <code>digestAuth</code> method performs non-sasl, digest authentication\n\t * as described in non-sasl authentication\n\t * <a href=\"http://www.xmpp.org/extensions/xep-0078.html\">XEP-0078</a>\n\t * For now it is empty and always returns <code>false</code> as I don't\n\t * have description for database with passwords.\n\t *\n\t * @param user a <code>BareJID</code> value of user name\n\t * @param digest a <code>String</code> value password digest sum\n\t * @param id a <code>String</code> value session ID used for digest sum\n\t * calculation.\n\t * @param alg a <code>String</code> value of algorithm ID used for digest sum\n\t * calculation.\n\t * @return a <code>boolean</code> value <code>true</code> on successful\n\t * authentication, <code>false</code> on authentication failure.\n\t * @exception UserNotFoundException if an given user name is not found in\n\t * the authentication repository.\n\t * @exception TigaseDBException if an error occurs during during accessing\n\t * database;\n\t * @exception AuthorizationException if an error occurs during authentication\n\t * process.\n\t */\n\t@Deprecated\n\tboolean digestAuth(BareJID user, String digest, String id, String alg)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * <code>getResourceUri</code> method returns database connection string.\n\t *\n\t * @return a <code>String</code> value of database connection string.\n\t */\n\tString getResourceUri();\n\n\t/**\n\t * This method is only used by the server statistics component to report\n\t * number of registered users.\n\t * @return a <code>long</code> number of registered users in the repository.\n\t */\n\tlong getUsersCount();\n\n\t/**\n\t * This method is only used by the server statistics component to report\n\t * number of registered users for given domain.\n\t * @param domain\n\t * @return a <code>long</code> number of registered users in the repository.\n\t */\n\tlong getUsersCount(String domain);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Describe <code>logout</code> method here.\n\t *\n\t * @param user a <code>BareJID</code> value\n\t * @exception UserNotFoundException if an error occurs\n\t * @exception TigaseDBException if an error occurs\n\t */\n\tvoid logout(BareJID user) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * Describe <code>otherAuth</code> method here.\n\t *\n\t * @param authProps\n\t *            a <code>Map</code> value\n\t * @return a <code>boolean</code> value\n\t * @exception UserNotFoundException\n\t *                if an error occurs\n\t * @exception TigaseDBException\n\t *                if an error occurs\n\t * @exception AuthorizationException\n\t *                if an error occurs\n\t *\n\t */\n\tboolean otherAuth(Map<String, Object> authProps)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException;\n\n\t/**\n\t * <code>plainAuth</code> method performs non-sasl, plain authentication\n\t * as described in non-sasl authentication\n\t * <a href=\"http://www.xmpp.org/extensions/xep-0078.html\">XEP-0078</a>.\n\t *\n\t * @param user a <code>BareJID</code> value of user name\n\t * @param password a <code>String</code> value of plain user password.\n\t * @return a <code>boolean</code> value <code>true</code> on successful\n\t * authentication, <code>false</code> on authentication failure.\n\t * @exception UserNotFoundException if an given user name is not found in\n\t * the authentication repository.\n\t * @exception TigaseDBException if an error occurs during during accessing\n\t * database;\n\t * @exception AuthorizationException if an error occurs during authentication\n\t * process.\n\t * @deprecated use method\n\t *             {@linkplain AuthRepository#otherAuth(Map)}\n\t *             because this method is preferred. In a long term plans all authentication\n\t *             methods should use otherAuth(...) calls.\n\t */\n\t@Deprecated\n\tboolean plainAuth(BareJID user, String password)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException;\n\n\t/**\n\t * <code>queryAuth</code> returns mechanisms available for authentication.\n\t *\n\t * @param authProps a <code>Map</code> value with parameters for authentication.\n\t */\n\tvoid queryAuth(Map<String, Object> authProps);\n\n\t/**\n\t * Describe <code>removeUser</code> method here.\n\t *\n\t * @param user a <code>BareJID</code> value\n\t * @exception UserNotFoundException if an error occurs\n\t * @exception TigaseDBException if an error occurs\n\t */\n\tvoid removeUser(BareJID user) throws UserNotFoundException, TigaseDBException;\n\n\t String getPassword(BareJID user)\n\t\t\tthrows UserNotFoundException, TigaseDBException ;\n\n\t\n\t/**\n\t * Describe <code>updatePassword</code> method here.\n\t *\n\t * @param user a <code>BareJID</code> value\n\t * @param password a <code>String</code> value\n\t * @throws UserNotFoundException\n\t * @exception TigaseDBException if an error occurs\n\t */\n\tvoid updatePassword(BareJID user, String password)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException;\n\t\n\tboolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException;\n\t\n\tvoid setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException;\n\t\n}    // AuthRepository\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/AuthRepositoryImpl.java",
    "content": "/*\n * AuthRepositoryImpl.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.Algorithms;\nimport tigase.util.Base64;\n\nimport tigase.xmpp.BareJID;\n\nimport static tigase.db.AuthRepository.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.TreeMap;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.RealmCallback;\nimport javax.security.sasl.Sasl;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\n\n/**\n * Describe class AuthRepositoryImpl here.\n *\n *\n * Created: Sat Nov 11 21:46:50 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AuthRepositoryImpl\n\t\t\t\timplements AuthRepository {\n\t/** Field description */\n\tprotected static final Logger log = Logger.getLogger(\n\t\t\t\"tigase.db.UserAuthRepositoryImpl\");\n\n\t/** Field description */\n\tprotected static final String DISABLED_KEY   = \"disabled\";\n\tprotected static final String PASSWORD_KEY   = \"password\";\n\tprivate static final String[] non_sasl_mechs = { \"password\", \"digest\" };\n\tprivate static final String[] sasl_mechs     = { \"PLAIN\", \"DIGEST-MD5\", \"CRAM-MD5\" };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate UserRepository repo = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>AuthRepositoryImpl</code> instance.\n\t *\n\t *\n\t * @param repo\n\t */\n\tpublic AuthRepositoryImpl(UserRepository repo) {\n\t\tthis.repo = repo;\n\t}\n\n\n\t@Override\n\tpublic void addUser(BareJID user, final String password)\n\t\t\t\t\tthrows UserExistsException, TigaseDBException {\n\t\trepo.addUser(user);\n\t\tlog.info(\"Repo user added: \" + user);\n\t\tupdatePassword(user, password);\n\t\tlog.info(\"Password updated: \" + user + \":\" + password);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, final String digest, final String id,\n\t\t\tfinal String alg)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tfinal String db_password = getPassword(user);\n\n\t\ttry {\n\t\t\tfinal String digest_db_pass = Algorithms.hexDigest(id, db_password, alg);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Comparing passwords, given: \" + digest + \", db: \" + digest_db_pass);\n\t\t\t}\n\n\t\t\treturn digest.equals(digest_db_pass);\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tthrow new AuthorizationException(\"No such algorithm.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn repo.getResourceUri();\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\treturn repo.getUsersCount();\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\treturn repo.getUsersCount(domain);\n\t}\n\n\t@Override\n\tpublic void initRepository(final String string, Map<String, String> params)\n\t\t\t\t\tthrows DBInitException {}\n\n\t@Override\n\tpublic void logout(BareJID user) {}\n\n\t@Override\n\tpublic boolean otherAuth(final Map<String, Object> props)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"otherAuth: {0}\", props);\n\t\t}\n\n\t\tString proto = (String) props.get(PROTOCOL_KEY);\n\n\t\t// TODO: this equals should be most likely replaced with == here.\n\t\t// The property value is always set using the constant....\n\t\tif (proto.equals(PROTOCOL_VAL_SASL)) {\n\t\t\treturn saslAuth(props);\n\t\t}    // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\t\tif (proto.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tString  password = (String) props.get(PASSWORD_KEY);\n\t\t\tBareJID user_id  = (BareJID) props.get(USER_ID_KEY);\n\n\t\t\tif (password != null) {\n\t\t\t\treturn plainAuth(user_id, password);\n\t\t\t}\n\n\t\t\tString digest = (String) props.get(DIGEST_KEY);\n\n\t\t\tif (digest != null) {\n\t\t\t\tString digest_id = (String) props.get(DIGEST_ID_KEY);\n\n\t\t\t\treturn digestAuth(user_id, digest, digest_id, \"SHA\");\n\t\t\t}\n\t\t}    // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tthrow new AuthorizationException(\"Protocol is not supported.\");\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, final String password)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"plainAuth: {0}:{1}\", new Object[] { user, password });\n\t\t}\n\n\t\tString db_password = getPassword(user);\n\n\t\treturn (password != null) && (db_password != null) && db_password.equals(password);\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\tpublic void queryAuth(final Map<String, Object> authProps) {\n\t\tString protocol = (String) authProps.get(PROTOCOL_KEY);\n\n\t\tif (protocol.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tauthProps.put(RESULT_KEY, non_sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\t\tif (protocol.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tauthProps.put(RESULT_KEY, sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\trepo.removeUser(user);\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, final String password)\n\t\t\t\t\tthrows TigaseDBException {\n\t\trepo.setData(user, PASSWORD_KEY, password);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic String getPassword(BareJID user)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn repo.getData(user, PASSWORD_KEY);\n\t}\n\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tString value = repo.getData(user, DISABLED_KEY);\n\t\treturn Boolean.parseBoolean(value);\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {\n\t\tif (value == null || !value) {\n\t\t\trepo.removeData(user, DISABLED_KEY);\n\t\t} else {\n\t\t\trepo.setData(user, DISABLED_KEY, String.valueOf(value));\n\t\t}\n\t}\n\t\n\t// ~--- methods --------------------------------------------------------------\n\tprivate boolean saslAuth(final Map<String, Object> props)\n\t\t\t\t\tthrows AuthorizationException {\n\t\ttry {\n\t\t\tSaslServer ss = (SaslServer) props.get(\"SaslServer\");\n\n\t\t\tif (ss == null) {\n\t\t\t\tMap<String, String> sasl_props = new TreeMap<String, String>();\n\n\t\t\t\tsasl_props.put(Sasl.QOP, \"auth\");\n\t\t\t\tss = Sasl.createSaslServer((String) props.get(MACHANISM_KEY), \"xmpp\",\n\t\t\t\t\t\t(String) props.get(SERVER_NAME_KEY), sasl_props, new SaslCallbackHandler(\n\t\t\t\t\t\tprops));\n\t\t\t\tprops.put(\"SaslServer\", ss);\n\t\t\t}    // end of if (ss == null)\n\n\t\t\tString data_str = (String) props.get(DATA_KEY);\n\t\t\tbyte[] in_data  = ((data_str != null)\n\t\t\t\t\t? Base64.decode(data_str)\n\t\t\t\t\t: new byte[0]);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"response: \" + new String(in_data));\n\t\t\t}\n\n\t\t\tbyte[] challenge = ss.evaluateResponse(in_data);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"challenge: \" + ((challenge != null)\n\t\t\t\t\t\t? new String(challenge)\n\t\t\t\t\t\t: \"null\"));\n\t\t\t}\n\n\t\t\tString challenge_str = (((challenge != null) && (challenge.length > 0))\n\t\t\t\t\t? Base64.encode(challenge)\n\t\t\t\t\t: null);\n\n\t\t\tprops.put(RESULT_KEY, challenge_str);\n\t\t\tif (ss.isComplete()) {\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}    // end of if (ss.isComplete()) else\n\t\t} catch (SaslException e) {\n\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t}      // end of try-catch\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class SaslCallbackHandler\n\t\t\t\t\timplements CallbackHandler {\n\t\tprivate Map<String, Object> options = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate SaslCallbackHandler(final Map<String, Object> options) {\n\t\t\tthis.options = options;\n\t\t}\n\n\t\t@Override\n\t\tpublic void handle(final Callback[] callbacks)\n\t\t\t\tthrows IOException, UnsupportedCallbackException {\n\t\t\tBareJID jid = null;\n\n\t\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Callback: \" + callbacks[i].getClass().getSimpleName());\n\t\t\t\t}\n\t\t\t\tif (callbacks[i] instanceof RealmCallback) {\n\t\t\t\t\tRealmCallback rc    = (RealmCallback) callbacks[i];\n\t\t\t\t\tString        realm = (String) options.get(REALM_KEY);\n\n\t\t\t\t\tif (realm != null) {\n\t\t\t\t\t\trc.setText(realm);\n\t\t\t\t\t}        // end of if (realm == null)\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"RealmCallback: \" + realm);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (callbacks[i] instanceof NameCallback) {\n\t\t\t\t\t\tNameCallback nc        = (NameCallback) callbacks[i];\n\t\t\t\t\t\tString       user_name = nc.getName();\n\n\t\t\t\t\t\tif (user_name == null) {\n\t\t\t\t\t\t\tuser_name = nc.getDefaultName();\n\t\t\t\t\t\t}      // end of if (name == null)\n\t\t\t\t\t\tjid = BareJID.bareJIDInstanceNS(user_name, (String) options.get(REALM_KEY));\n\t\t\t\t\t\toptions.put(USER_ID_KEY, jid);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"NameCallback: \" + user_name);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (callbacks[i] instanceof PasswordCallback) {\n\t\t\t\t\t\t\tPasswordCallback pc = (PasswordCallback) callbacks[i];\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tString passwd = getPassword(jid);\n\n\t\t\t\t\t\t\t\tpc.setPassword(passwd.toCharArray());\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.finest(\"PasswordCallback: \" + passwd);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tthrow new IOException(\"Password retrieving problem.\", e);\n\t\t\t\t\t\t\t}    // end of try-catch\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (callbacks[i] instanceof AuthorizeCallback) {\n\t\t\t\t\t\t\t\tAuthorizeCallback authCallback = ((AuthorizeCallback) callbacks[i]);\n\t\t\t\t\t\t\t\tString            authenId     = authCallback.getAuthenticationID();\n\t\t\t\t\t\t\t\tString            authorId     = authCallback.getAuthorizationID();\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.finest(\"AuthorizeCallback: authenId: \" + authenId);\n\t\t\t\t\t\t\t\t\tlog.finest(\"AuthorizeCallback: authorId: \" + authorId);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// if (authenId.equals(authorId)) {\n\t\t\t\t\t\t\t\tauthCallback.setAuthorized(true);\n\n\t\t\t\t\t\t\t\t// } // end of if (authenId.equals(authorId))\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedCallbackException(callbacks[i],\n\t\t\t\t\t\t\t\t\t\t\"Unrecognized Callback\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}    // AuthRepositoryImpl\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/AuthRepositoryMDImpl.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.xml.Element;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Mar 27, 2010 9:10:21 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AuthRepositoryMDImpl implements AuthRepository {\n\tprivate static final Logger log = Logger.getLogger(AuthRepositoryMDImpl.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate AuthRepository def = null;\n\tprivate EventBus eventBus = EventBusFactory.getInstance();\n\tprivate ConcurrentSkipListMap<String, AuthRepository> repos =\n\t\tnew ConcurrentSkipListMap<String, AuthRepository>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t * @param repo\n\t */\n\tpublic void addRepo(String domain, AuthRepository repo) {\n\t\trepos.put(domain, repo);\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user, String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.addUser(user, password);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, String digest, String id, String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.digestAuth(user, digest, id, alg);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t * \n\t */\n\tpublic AuthRepository getRepo(String domain) {\n\t\tAuthRepository result = repos.get(domain);\n\n\t\tif (result == null) {\n\t\t\tresult = def;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn def.getResourceUri();\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\tlong result = 0;\n\n\t\tfor (AuthRepository repo : repos.values()) {\n\t\t\tresult += repo.getUsersCount();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tAuthRepository repo = getRepo(domain);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getUsersCount(domain);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + domain + \", not even default one!\");\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\tlog.info(\"Multi-domain repository pool initialized: \" + resource_uri + \", params: \"\n\t\t\t\t+ params);\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.logout(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(Map<String, Object> authProps)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = getRepo((String) authProps.get(SERVER_NAME_KEY));\n\n\t\tif (repo != null) {\n\t\t\treturn repo.otherAuth(authProps);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \"\n\t\t\t\t\t\t+ (String) authProps.get(SERVER_NAME_KEY) + \", not even default one!\");\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.plainAuth(user, password);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) {\n\t\tAuthRepository repo = getRepo((String) authProps.get(SERVER_NAME_KEY));\n\n\t\tif (repo != null) {\n\t\t\trepo.queryAuth(authProps);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \"\n\t\t\t\t\t\t+ (String) authProps.get(SERVER_NAME_KEY) + \", not even default one!\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t * \n\t */\n\tpublic AuthRepository removeRepo(String domain) {\n\t\treturn repos.remove(domain);\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.removeUser(user);\n\t\t\t\n\t\t\tElement event = new Element(\"remove\", new String[] { \"xmlns\" }, \n\t\t\t\t\tnew String[] { \"tigase:user\" });\n\t\t\tevent.addChild(new Element(\"jid\", user.toString()));\n\t\t\teventBus.fire(event);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t */\n\tpublic void setDefault(AuthRepository repo) {\n\t\tdef = repo;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void updatePassword(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.updatePassword(user, password);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getPassword(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t+ \", not even default one!\");\n\t\t\treturn null;\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.isUserDisabled(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t+ \", not even default one!\");\n\t\t\treturn false;\n\t\t}\t\t\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.setUserDisabled(user, value);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t+ \", not even default one!\");\n\t\t}\t\t\n\t}\t\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/AuthRepositoryPool.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.Map;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Mar 27, 2010 11:31:17 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AuthRepositoryPool implements AuthRepository {\n\tprivate static final Logger log = Logger.getLogger(AuthRepositoryPool.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate LinkedBlockingQueue<AuthRepository> repoPool =\n\t\tnew LinkedBlockingQueue<AuthRepository>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t */\n\tpublic void addRepo(AuthRepository repo) {\n\t\trepoPool.offer(repo);\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user, String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.addUser(user, password);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, String digest, String id, String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.digestAuth(user, digest, id, alg);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getResourceUri();\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUsersCount();\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUsersCount(domain);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.logout(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(Map<String, Object> authProps)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.otherAuth(authProps);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.plainAuth(user, password);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.queryAuth(authProps);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.removeUser(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic AuthRepository takeRepo() {\n\t\ttry {\n\t\t\treturn repoPool.take();\n\t\t} catch (InterruptedException ex) {\n\t\t\tlog.log(Level.WARNING, \"Couldn't obtain user auth repository from the pool\", ex);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.updatePassword(user, password);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getPassword(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t\treturn null;\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.isUserDisabled(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {\n\t\tAuthRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.setUserDisabled(user, value);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"repo is NULL, pool empty? - \" + repoPool.size());\n\t\t}\n\t}\t\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/AuthorizationException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n/**\n * Describe class AuthorizationException here.\n *\n *\n * Created: Fri Nov 10 18:07:21 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AuthorizationException extends Exception {\n\n  private static final long serialVersionUID = 1L;\n\n\t/**\n\t * Creates a new <code>AuthorizationException</code> instance.\n\t *\n\t */\n\tpublic AuthorizationException() { super(); }\n\n\tpublic AuthorizationException(String message) { super(message); }\n\n  public AuthorizationException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // AuthorizationException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/DBInitException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n/**\n * Describe class DBInitException here.\n *\n *\n * Created: Thu Oct 26 12:18:05 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DBInitException extends TigaseDBException {\n\n  private static final long serialVersionUID = 1L;\n\n\tpublic DBInitException(String message) { super(message); }\n\n  public DBInitException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // DBInitException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/DataOverwriteException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n/**\n * The <code>DataOverwriteException</code> exception is thrown when application\n * tries to ovrewrite data in repository but does not have permission to do so.\n * <br>\n * Created: Wed Oct 27 14:17:44 2004\n * <br>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class DataOverwriteException extends TigaseDBException {\n\n  private static final long serialVersionUID = 1L;\n\n  /**\n   * Creates a new <code>DataOverwriteException</code> instance.\n   *\n   */\n  public DataOverwriteException(String message) { super(message); }\n\n  /**\n   * Creates a new <code>DataOverwriteException</code> instance.\n   *\n   */\n  public DataOverwriteException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // DataOverwriteException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/DataRepository.java",
    "content": "/*\n * DataRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport java.util.Map;\n\n/**\n * The interface defines a generic data repository for storing arbitrary data in\n * any application specific form. This interface unifies database (repository)\n * access allowing for easier way to create database connections pools or\n * database fail-over mechanisms.\n *\n * Created: Jun 16, 2010 3:34:32 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface DataRepository extends Repository {\n\t/**\n\t * Helper enumeration with types of supported databases.\n\t *\n\t */\n\tpublic static enum dbTypes {\n\t\tderby, mysql, postgresql, jtds, sqlserver, other\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method checks whether a table for the given name exists in the\n\t * database.\n\t *\n\t * @param tableName\n\t *          is a <code>String</code> value of the table name to check\n\t * @return <code>true</code> <code>boolean</code> value if the table exist in\n\t *         the database and <code>false</code> if the table was not found.\n\t * @throws SQLException\n\t *           if there was a problem accessing database.\n\t */\n\tboolean checkTable(String tableName) throws SQLException;\n\n\t/**\n\t * The method checks whether a table for the given name exists in the\n\t * database and if it does not, it automatically creates it.\n\t *\n\t * @param tableName\n\t *          is a <code>String</code> value of the table name to check\n\t * @param createTableQuery\n\t *          is a <code>String</code> with the query to create table\n\t * @return <code>true</code> <code>boolean</code> value if the table exist in\n\t *         the database and <code>false</code> if the table was not found.\n\t * @throws SQLException\n\t *           if there was a problem accessing database.\n\t */\n\tboolean checkTable(String tableName, String createTableQuery) throws SQLException;\n\n\t/**\n\t * Commits current transaction on the DataRepository connection. Please note\n\t * that calling this method on the repository pool has no effect. You have to\n\t * obtain particular repository handle first, before you can start\n\t * transaction.\n\t *\n\t * @throws SQLException\n\t */\n\tvoid commit() throws SQLException;\n\n\t/**\n\t * Creates a SQL statement on which SQL queries can be executed later by the\n\t * higher repository layer.\n\t *\n\t * @param user_id user id for which the statement has to be created. This is an\n\t * optional parameter and null can be provided. It is used mainly to group queries\n\t * for the same user on the same DB connection.\n\t * @return a newly created <code>Statement</code>\n\t * @throws SQLException\n\t *           if a JDBC error occurs.\n\t */\n\tStatement createStatement(BareJID user_id) throws SQLException;\n\n\t/**\n\t * Ends current transaction on the DataRepository connection. Please note that\n\t * calling this method on the repository pool has no effect. You have to\n\t * obtain particular repository handle first, before you can start\n\t * transaction.\n\t *\n\t * @throws SQLException\n\t */\n\tvoid endTransaction() throws SQLException;\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Initializes a prepared statement for a given query and stores it internally\n\t * under the given id key. It can be retrieved later using\n\t * <code>getPreparedStatement(stIdKey)</code> method.\n\t *\n\t * @param stIdKey\n\t *          is a statement identification key.\n\t * @param query\n\t *          is a query for the prepared statement.\n\t * @throws SQLException\n\t */\n\tvoid initPreparedStatement(String stIdKey, String query) throws SQLException;\n\n\t/**\n\t * Initializes a prepared statement for a given query and stores it internally\n\t * under the given id key. It can be retrieved later using\n\t * <code>getPreparedStatement(stIdKey)</code> method.\n\t *\n\t * @param stIdKey\n\t *          is a statement identification key.\n\t * @param query\n\t *          is a query for the prepared statement.\n\t * @param autoGeneratedKeys\n\t *\t\t\tdefines if statement should return auto generated keys\n\t * @throws SQLException\n\t */\n\tvoid initPreparedStatement(String stIdKey, String query, int autoGeneratedKeys) throws SQLException;\t\n\t\n\t/**\n\t * A helper method to release resources from the statement and result set.\n\t * This is most common operation for all database calls, therefore it does\n\t * make sense to add such a utility method to the API.\n\t *\n\t * @param stmt\n\t *          a <code>Statement</code> variable to release resources for. Might\n\t *          be null.\n\t * @param rs\n\t *          a <code>ResultSet</code> variable to release resources for. Might\n\t *          be null.\n\t */\n\tvoid release(Statement stmt, ResultSet rs);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo is a <code>DataRepository</code>\n\t */\n\tvoid releaseRepoHandle(DataRepository repo);\n\n\t/**\n\t * Rolls back started transaction on the DataRepository connection. Please\n\t * note that calling this method on the repository pool has no effect. You\n\t * have to obtain particular repository handle first, before you can start\n\t * transaction.\n\t *\n\t * @throws SQLException\n\t */\n\tvoid rollback() throws SQLException;\n\n\t/**\n\t * Starts transaction on the DataRepository connection. Please note that\n\t * calling this method on the repository pool has no effect. You have to\n\t * obtain particular repository handle first, before you can start\n\t * transaction.\n\t *\n\t * @throws SQLException\n\t */\n\tvoid startTransaction() throws SQLException;\n\n\t/**\n\t * Returns <code>DataRepository</code> instance. If this is a repository pool\n\t * then it returns particular instance from the pool. It this is a real\n\t * repository instance it returns itself. This is exclusive take, no other\n\t * thread may use this handle until it is returned to the pool.\n\t *\n\t * @param user_id\n\t *          is user account ID for which we acquire the handle.\n\t * @return DataRepository instance.\n\t */\n\tDataRepository takeRepoHandle(BareJID user_id);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns type of DataRepository database\n\t *\n\t *\n\t *\n\t * @return a value of <code>dbTypes</code>\n\t */\n\tdbTypes getDatabaseType();\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns a prepared statement for a given key.\n\t *\n\t * @param user_id user id for which the statement has to be created. This is\n\t * an optional parameter and null can be provided. It is used mainly to group\n\t * queries for the same user on the same DB connection.\n\t * @param stIdKey\n\t *          is a statement identification key.\n\t * @return a <code>PreparedStatement</code> for the given id key or null if\n\t *         such a statement does not exist.\n\t * @throws SQLException\n\t */\n\tPreparedStatement getPreparedStatement(BareJID user_id, String stIdKey)\n\t\t\t\t\tthrows SQLException;\n\n\t/**\n\t * Returns a DB connection string or DB connection URI.\n\t *\n\t * @return a <code>String</code> value representing database connection\n\t *         string.\n\t */\n\tString getResourceUri();\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/DataRepositoryPool.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport tigase.stats.StatisticsProviderIfc;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.BareJID;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Sep 4, 2010 2:13:22 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DataRepositoryPool implements DataRepository, StatisticsProviderIfc {\n\tprivate static final Logger log = Logger.getLogger(DataRepositoryPool.class.getName());\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\tprivate CopyOnWriteArrayList<DataRepository> repoPool =\n\t\t\tnew CopyOnWriteArrayList<DataRepository>();\n\tprivate String resource_uri = null;\n\tprivate dbTypes database = null;\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param repo\n\t */\n\tpublic void addRepo(DataRepository repo) {\n\t\trepoPool.addIfAbsent(repo);\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic DataRepository takeRepo(BareJID user_id) {\n\t\tint idx = user_id != null ? Math.abs(user_id.hashCode() % repoPool.size()) : 0;\n\t\tDataRepository result = null;\n\t\ttry {\n\t\t\tresult = repoPool.get(idx);\n\t\t} catch (IndexOutOfBoundsException ioobe) {\n\t\t\tresult = repoPool.get(0);\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic DataRepository takeRepoHandle(BareJID user_id) {\n\t\treturn takeRepo(user_id);\n\t}\n\n\t@Override\n\tpublic void releaseRepoHandle(DataRepository repo) {\n\t\t// addRepo(repo);\n\t}\n\n\t@Override\n\tpublic boolean checkTable(String tableName) throws SQLException {\n\t\tDataRepository repo = takeRepo(null);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.checkTable(tableName);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean checkTable(String tableName, String createTableQuery) throws SQLException {\n\t\tDataRepository repo = takeRepo(null);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.checkTable(tableName, createTableQuery);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic Statement createStatement(BareJID user_id) throws SQLException {\n\t\tDataRepository repo = takeRepo(user_id);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.createStatement(user_id);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic PreparedStatement getPreparedStatement(BareJID user_id, String stIdKey) throws SQLException {\n\t\tDataRepository repo = takeRepo(user_id);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getPreparedStatement(user_id, stIdKey);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn resource_uri;\n\t}\n\n\n\t@Override\n\tpublic dbTypes getDatabaseType() {\n\t\treturn database;\n\t}\n\n\t@Override\n\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\tlist.add(compName, \"repository \" + getResourceUri() + \" connections count\", repoPool.size(), Level.FINE);\n\t\tfor (DataRepository repo : repoPool) {\n\t\t\tif (repo instanceof StatisticsProviderIfc) {\n\t\t\t\t((StatisticsProviderIfc) repo).getStatistics(compName, list);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initPreparedStatement(String stIdKey, String query) throws SQLException {\n\t\tfor (DataRepository dataRepository : repoPool) {\n\t\t\tdataRepository.initPreparedStatement(stIdKey, query);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initPreparedStatement(String stIdKey, String query, int autoGeneratedKeys) throws SQLException {\n\t\tfor (DataRepository dataRepository : repoPool) {\n\t\t\tdataRepository.initPreparedStatement(stIdKey, query, autoGeneratedKeys);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\tthis.resource_uri = resource_uri;\n\t\t\n\t\tfor (DataRepository dataRepository : repoPool) {\n\t\t\tdataRepository.initRepository(resource_uri, params);\n\t\t\tthis.database = dataRepository.getDatabaseType();\n\t\t}\n\t\tif ( this.database == null ){\n\t\t\tif ( resource_uri.startsWith( \"jdbc:postgresql\" ) ){\n\t\t\t\tdatabase = dbTypes.postgresql;\n\t\t\t} else if ( resource_uri.startsWith( \"jdbc:mysql\" ) ){\n\t\t\t\tdatabase = dbTypes.mysql;\n\t\t\t} else if ( resource_uri.startsWith( \"jdbc:derby\" ) ){\n\t\t\t\tdatabase = dbTypes.derby;\n\t\t\t} else if ( resource_uri.startsWith( \"jdbc:jtds:sqlserver\" ) ){\n\t\t\t\tdatabase = dbTypes.jtds;\n\t\t\t} else if ( resource_uri.startsWith( \"jdbc:sqlserver\" ) ){\n\t\t\t\tdatabase = dbTypes.sqlserver;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void release(Statement stmt, ResultSet rs) {\n\t\tif (rs != null) {\n\t\t\ttry {\n\t\t\t\trs.close();\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t}\n\t\t}\n\n\t\tif (stmt != null) {\n\t\t\ttry {\n\t\t\t\tstmt.close();\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void startTransaction() throws SQLException {\n\t\t// TODO Auto-generated method stub\n\t}\n\n\t@Override\n\tpublic void commit() throws SQLException {\n\t\t// TODO Auto-generated method stub\n\t}\n\n\t@Override\n\tpublic void rollback() throws SQLException {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic void endTransaction() throws SQLException {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/DummyRepository.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.List;\nimport java.util.Map;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * DummyRepository is a class with all methods empty. They don't return\n * anything and they don't throw exception. SessionManager requires a\n * user repository to work properly but in some installations there is\n * no need for user repository as authentication is done through external\n * data source and user roster is pulled dynamically.\n *\n * Created: Sat Nov  3 16:17:03 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Repository.Meta( supportedUris = { \"dummy\" } )\npublic class DummyRepository implements UserRepository, AuthRepository {\n\n\t@Override\n\tpublic void addDataList(BareJID user, String subnode, String key, String[] list) {}\n\n\t@Override\n\tpublic void addUser(BareJID user) {}\n\n\t@Override\n\tpublic void addUser(BareJID user, String password)\n\t\t\tthrows UserExistsException, TigaseDBException {}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, String digest, String id, String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t// Implementation of tigase.db.UserRepository\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * @return a <code>String</code> value of null always.\n\t */\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key, String def) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * @return a <code>String</code> value of null always.\n\t */\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * @return a <code>String</code> value of null always.\n\t */\n\t@Override\n\tpublic String getData(BareJID user, String key) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getDataList(BareJID user, String subnode, String key) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user, String subnode) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user, String subnode) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUserUID(BareJID user) throws TigaseDBException {\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic List<BareJID> getUsers() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\treturn 0;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String string, Map<String, String> params) {}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {}\n\n\t@Override\n\tpublic boolean otherAuth(Map<String, Object> authProps)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) {}\n\n\t@Override\n\tpublic void removeData(BareJID user, String subnode, String key) {}\n\n\t@Override\n\tpublic void removeData(BareJID user, String key) {}\n\n\t@Override\n\tpublic void removeSubnode(BareJID user, String subnode) {}\n\n\t@Override\n\tpublic void removeUser(BareJID user) {}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setData(BareJID user, String subnode, String key, String value) {}\n\n\t@Override\n\tpublic void setData(BareJID user, String key, String value) {}\n\n\t@Override\n\tpublic void setDataList(BareJID user, String subnode, String key, String[] list) {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void updatePassword(BareJID user, String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {}\n\n\t@Override\n\tpublic boolean userExists(BareJID user) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\t\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Feature not supported\");\n\t}\t\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/MsgRepositoryIfc.java",
    "content": "\n/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Queue;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- interfaces -------------------------------------------------------------\n/**\n * Interface for storing and restoring offline Elements.\n *\n * Created: May 11, 2010 6:56:14 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface MsgRepositoryIfc extends Repository {\n\n\t/**\n\t * Loads head of the payloads queue which holds items that would be expired after\n\t * stated time with an option to delete them from repository after being\n\t * retrieved.\n\t * This is blocking method, which means if there is not data to return, implementation\n\t * should block the call until data is available.\n\t *\n\t * @param time   time in milliseconds representing time after which given\n\t *               message would be considered as expired\n\t * @param delete boolean parameter controlling whether messages should be\n\t *               removed from repository after they retrieved.\n\t *\n\t * @return head of the payloads queue which holds items that would be expired after\n\t * stated time with an option to delete them from repository after being\n\t * retrieved.\n\t */\n\tElement getMessageExpired( long time, boolean delete );\n\n\t//~--- methods --------------------------------------------------------------\n\t/**\n\t * Loads all payloads for the given user's {@link JID} from repository.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param delete boolean parameter controlling whether messages should be\n\t *               removed from repository after they retrieved.\n\t *\n\t * @return a {@link Queue} of {@link Element} objects representing stored\n\t *         payloads for the given user's {@link JID}\n\t *\n\t * @throws UserNotFoundException\n\t */\n\tQueue<Element> loadMessagesToJID( XMPPResourceConnection session, boolean delete ) throws UserNotFoundException;\n\n\t/**\n\t * Saves the massage to the repository\n\t *\n\t * @param from    {@link JID} denotes address of the sender\n\t * @param to      {@link JID} denotes address of the receiver\n\t * @param expired {@link Date} object denoting expiration date of the message\n\t * @param msg     {@link Element} payload of the stanza to be saved\n\t * @param userRepo {@link NonAuthUserRepository} instance of non auth user repository \n\t *\t\t\t\t\tto get user settings for offline messages\n\t * \n\t * @return {@code true} if the packet was correctly saved to repository,\n\t *         {@code false} otherwise.\n\t *\n\t * @throws UserNotFoundException\n\t */\n\tboolean storeMessage( JID from, JID to, Date expired, Element msg, NonAuthUserRepository userRepo ) throws UserNotFoundException;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/NonAuthUserRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface WriteOnlyUserRepository here.\n *\n *\n * Created: Sat Oct 14 20:42:30 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface NonAuthUserRepository {\n\n\t/** Field description */\n\tpublic static final String PUBLIC_DATA_NODE = \"public\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_DATA_NODE = \"offline\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * <code>addDataList</code> method adds mode entries to existing data list\n\t * associated with given key in repository under given node path.\n\t * This method is very similar to <code>setDataList(...)</code> except it\n\t * doesn't remove existing data.\n\t *\n\t * @param user a <code>String</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the specified values list is to\n\t * be associated.\n\t * @param value a <code>String</code> is an array of values to be assosiated\n\t * with the specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in reository.\n\t * @throws DataOverwriteException\n\t */\n\tvoid addOfflineData(BareJID user, String subnode, String key, String value)\n\t\t\tthrows UserNotFoundException, DataOverwriteException;\n\n\t/**\n\t * <code>addDataList</code> method adds mode entries to existing data list\n\t * associated with given key in repository under given node path.\n\t * This method is very similar to <code>setDataList(...)</code> except it\n\t * doesn't remove existing data.\n\t *\n\t * @param user a <code>String</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the specified values list is to\n\t * be associated.\n\t * @param list a <code>String[]</code> is an array of values to be assosiated\n\t * with the specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in reository.\n\t */\n\tvoid addOfflineDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Retrieves and returns a value associated with given subnode and key from a publicly\n\t * available space. The space is specific to given virtual domain and is shared among all\n\t * running cluster nodes. The data are stored in some temporary space outside of the\n\t * registered user data so no information for registered users can be retrieved.<br>\n\t *\n\t * @param domain is a DNS domain name with which the data is associated.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the needed value is\n\t * associated.\n\t * @param def a {@link String} value which is returned in case if data\n\t * for specified key does not exixist in repository.\n\t * @return a {@link String} value for a given subnode and key or {@code def]}\n\t * if no entry has been found.\n\t * @throws TigaseDBException if there was an error during reading data from the repository.\n\t */\n\tString getDomainTempData(BareJID domain, String subnode, String key, String def)\n\t\t\tthrows TigaseDBException;\n\n\t/**\n\t * <code>getPublicData</code> method returns a value associated with given key for\n\t * user repository in given subnode.\n\t * If key is not found in repository given default value is returned.\n\t *\n\t * @param user a {@link String} value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the needed value is\n\t * associated.\n\t * @param def a {@link String} value which is returned in case if data\n\t * for specified key does not exixist in repository.\n\t * @return a {@link String} value for a given subnode and key or {@code def}\n\t * if no entry has been found.\n\t * @exception UserNotFoundException if user id hasn't been found in reository.\n\t */\n\tString getPublicData(BareJID user, String subnode, String key, String def)\n\t\t\tthrows UserNotFoundException;\n\n\t/**\n\t * <code>getPublicDataList</code> method returns array of values associated with\n\t * given key or <code>null</code> if given key does not exist for given user\n\t * ID in given node path.\n\t *\n\t * @param user a {@link String} value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the needed values list is\n\t * associated.\n\t * @return a <code>String[]</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in reository.\n\t */\n\tString[] getPublicDataList(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException;\n\n\t/**\n\t * Retrieves and returns a value associated with given subnode and key from a publicly\n\t * available space. The space is specific for the Tigase instance and is not shared among\n\t * different cluster nodes. The data is stored in some temporary space outside of the\n\t * registered user data. So no information for registered users can be retrieved.<br>\n\t *\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the needed value is\n\t * associated.\n\t * @param def a {@link String} value which is returned in case if data\n\t * for specified key does not exixist in repository.\n\t * @return a {@link String} value for a given subnode and key or <code>def</code>\n\t * if no entry has been found.\n\t * @throws TigaseDBException if there was an error during reading data from the repository.\n\t */\n\tString getTempData(String subnode, String key, String def) throws TigaseDBException;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method allows to store some temporary data by the plugin in publicly available\n\t * space. The space is specific to given virtual domain and is shared among all\n\t * running cluster nodes. The data is stored in some place outside of the normal user space\n\t * so no information for registered user can be overwriten.<br>\n\t * If there is already a value for a given subnode and key it will be overwritten otherwise\n\t * a new entry will be created.\n\t * @param domain is a DNS domain name with which the data is associated.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the specified values list is to\n\t * be associated.\n\t * @param value a {@link String} is an array of values to be assosiated\n\t * with the specified key.\n\t * @throws TigaseDBException if there was an error during writing data to the repository.\n\t */\n\tvoid putDomainTempData(BareJID domain, String subnode, String key, String value)\n\t\t\tthrows TigaseDBException;\n\n\t/**\n\t * The method allows to store some temporary data by the plugin in publicly available\n\t * space. The space is specific for the Tigase instance and is not shared among different\n\t * cluster nodes. The data is stored in some place outside of the normal user space so\n\t * no information for registered user can be overwriten.<br>\n\t * If there is already a value for a given subnode and key it will be overwritten otherwise\n\t * a new entry will be created.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the specified values list is to\n\t * be associated.\n\t * @param value a {@link String} is an array of values to be assosiated\n\t * with the specified key.\n\t * @throws TigaseDBException if there was an error during writing data to the repository.\n\t */\n\tvoid putTempData(String subnode, String key, String value) throws TigaseDBException;\n\n\t/**\n\t * The method allows to remove existing data stored in a temporary storage space associated\n\t * with a given DNS domain.\n\t * @param domain is a DNS domain name with which the data is associated.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the specified values list is to\n\t * be associated.\n\t * @throws TigaseDBException if there was an error during writing data to the repository.\n\t */\n\tvoid removeDomainTempData(BareJID domain, String subnode, String key)\n\t\t\tthrows TigaseDBException;\n\n\t/**\n\t * The method allows to remove existing data stored in the Tigase instance specific\n\t * temporary storage.\n\t * @param subnode a {@link String} value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a {@link String} with which the specified values list is to\n\t * be associated.\n\t * @throws TigaseDBException if there was an error during writing data to the repository.\n\t */\n\tvoid removeTempData(String subnode, String key) throws TigaseDBException;\n}    // WriteOnlyUserRepository\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/NonAuthUserRepositoryImpl.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: May 3, 2010 1:23:45 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NonAuthUserRepositoryImpl implements NonAuthUserRepository {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log =\n\t\tLogger.getLogger(NonAuthUserRepositoryImpl.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate BareJID defDomain = null;\n\tprivate final Set<BareJID> existing_domains = new ConcurrentSkipListSet<BareJID>();\n\tprivate boolean autoCreateOffline = false;\n\tprivate final UserRepository rep;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param userRep\n\t * @param defDomain\n\t * @param autoCreateOffline\n\t */\n\tpublic NonAuthUserRepositoryImpl(UserRepository userRep, BareJID defDomain,\n\t\t\tboolean autoCreateOffline) {\n\t\trep = userRep;\n\t\tthis.defDomain = defDomain;\n\t\tthis.autoCreateOffline = autoCreateOffline;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addOfflineData(BareJID user, String subnode, String key, String value)\n\t\t\tthrows UserNotFoundException, DataOverwriteException {\n\t\tString node = calcNode(OFFLINE_DATA_NODE, subnode);\n\n\t\ttry {\n\t\t\tString data = rep.getData(user, node, key);\n\n\t\t\tif (data == null) {\n\t\t\t\trep.setData(user, node, key, value);\n\t\t\t} else {\n\t\t\t\tthrow new DataOverwriteException(\"Not authorized attempt to overwrite data.\");\n\t\t\t}    // end of if (data == null) else\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem accessing repository data.\", e);\n\t\t}      // end of try-catch\n\t}\n\n\t@Override\n\tpublic void addOfflineDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException {\n\t\ttry {\n\t\t\tif (autoCreateOffline || rep.userExists(user)) {\n\t\t\t\trep.addDataList(user, calcNode(OFFLINE_DATA_NODE, subnode), key, list);\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(\"User: \" + user\n\t\t\t\t\t\t+ \" has not been found inthe repository.\");\n\t\t\t}\n\t\t} catch (UserNotFoundException e) {\n\n\t\t\t// This is quite normal for anonymous users.\n\t\t\tlog.log(Level.INFO, \"User not found in repository: {0}\", user);\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem accessing repository data.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getDomainTempData(BareJID domain, String subnode, String key, String def)\n\t\t\tthrows TigaseDBException {\n\t\tcheckDomain(domain);\n\n\t\treturn rep.getData(domain, subnode, key, def);\n\t}\n\n\t@Override\n\tpublic String getPublicData(BareJID user, String subnode, String key, String def)\n\t\t\tthrows UserNotFoundException {\n\t\ttry {\n\t\t\treturn (rep.userExists(user)\n\t\t\t\t\t? rep.getData(user, calcNode(PUBLIC_DATA_NODE, subnode), key, def) : null);\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem accessing repository data.\", e);\n\n\t\t\treturn null;\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[] getPublicDataList(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException {\n\t\ttry {\n\t\t\treturn (rep.userExists(user)\n\t\t\t\t\t? rep.getDataList(user, calcNode(PUBLIC_DATA_NODE, subnode), key) : null);\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem accessing repository data.\", e);\n\n\t\t\treturn null;\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String getTempData(String subnode, String key, String def) throws TigaseDBException {\n\t\tcheckDomain(defDomain);\n\n\t\treturn rep.getData(defDomain, subnode, key, def);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void putDomainTempData(BareJID domain, String subnode, String key, String value)\n\t\t\tthrows TigaseDBException {\n\t\tcheckDomain(domain);\n\t\trep.setData(domain, subnode, key, value);\n\t}\n\n\t@Override\n\tpublic void putTempData(String subnode, String key, String value) throws TigaseDBException {\n\t\tcheckDomain(defDomain);\n\t\trep.setData(defDomain, subnode, key, value);\n\t}\n\n\t@Override\n\tpublic void removeDomainTempData(BareJID domain, String subnode, String key)\n\t\t\tthrows TigaseDBException {\n\t\tcheckDomain(defDomain);\n\t\trep.removeData(domain, subnode, key);\n\t}\n\n\t@Override\n\tpublic void removeTempData(String subnode, String key) throws TigaseDBException {\n\t\tcheckDomain(defDomain);\n\t\trep.removeData(defDomain, subnode, key);\n\t}\n\n\tprivate String calcNode(String base, String subnode) {\n\t\tif (subnode == null) {\n\t\t\treturn base;\n\t\t}    // end of if (subnode == null)\n\n\t\treturn base + \"/\" + subnode;\n\t}\n\n\tprivate void checkDomain(BareJID domain) throws TigaseDBException {\n\t\tif ( !existing_domains.contains(domain) &&!rep.userExists(domain)) {\n\t\t\trep.addUser(domain);\n\t\t\texisting_domains.add(domain);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/Repository.java",
    "content": "/*\n * Repository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.db;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\nimport java.util.Map;\n\n/**\n * Base interface which should be implemented by every repository to have one \n * common interface\n * \n * @author andrzej\n */\npublic interface Repository {\n\n\t/**\n\t * Meta created to add possibility to retrieve informations about \n implementation of repository (ie. supported database URI)\n\t */\n\t@Retention(RetentionPolicy.RUNTIME)\n\t@Target(ElementType.TYPE)\n\tpublic static @interface Meta {\n\t\tboolean isDefault() default false;\n\t\tString[] supportedUris();\n\t}\n\t\n\t/**\n\t * The method is called to initialize the data repository. Depending on the implementation\n\t * all the initialization parameters can be passed either via <code>resource_uri</code>\n\t * parameter as the database connection string or via <code>params</code> map if\n\t * the required repository parameters are more complex or both.\n\t * @param resource_uri value in most cases representing the database connection string.\n\t * @param params is a <code>Map</code> with repository properties necessary to initialize\n\t * and perform all the functions. The initialization parameters are implementation dependent.\n\t * @throws tigase.db.DBInitException if there was an error during repository initialization.\n\t * Some implementations, though, perform so called lazy initialization so even though there\n\t * is a problem with the underlying repository it may not be signaled through this method\n\t * call.\n\t */\n\tvoid initRepository(String resource_uri, Map<String, String> params) throws DBInitException;\t\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/RepositoryFactory.java",
    "content": "/*\n * RepositoryFactory.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.stats.StatisticsContainerIfc;\nimport tigase.stats.StatisticsProviderIfc;\nimport tigase.stats.StatisticsList;\nimport tigase.util.ClassUtil;\n\nimport java.sql.SQLException;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.regex.Pattern;\n\n/**\n * Describe class RepositoryFactory here.\n *\n *\n * Created: Tue Oct 24 22:13:52 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class RepositoryFactory {\n\t/** Field description */\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS = \"--auth-domain-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS_PROP_KEY = \"auth-domain-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String AUTH_DOMAIN_POOL_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.AuthRepositoryMDImpl\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_CLASS_PROP_KEY = \"auth-repo-class\";\n\n\t/** Field description */\n\t@Deprecated\n\tpublic static final String AUTH_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.TigaseCustomAuth\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_DOMAINS_PROP_KEY = \"auth-repo-domains\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_PARAMS_NODE = \"auth-repo-params\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_CLASS = \"--auth-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_CLASS_PROP_DEF =\n\t\t\t\"tigase.db.AuthRepositoryPool\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_CLASS_PROP_KEY = \"auth-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_CLASS_PROP_VAL = null;\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_SIZE = \"--auth-repo-pool-size\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_POOL_SIZE_PROP_KEY = \"auth-repo-pool-size\";\n\n\tpublic static final int REPO_POOL_SIZE_FACTOR_PROP_VAL = 4;\n\n\t// AuthRepository properties\n\n\t/** Field description */\n\tpublic static final int AUTH_REPO_POOL_SIZE_PROP_VAL = Math.max( 10, Runtime.getRuntime().availableProcessors()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t * REPO_POOL_SIZE_FACTOR_PROP_VAL);\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO_URL_PROP_KEY = \"auth-repo-url\";\n\n\t/** Field description */\n\tpublic static final String DATA_REPO_CLASS_PROP_KEY = \"data-repo\";\n\n\t/** Field description */\n\t@Deprecated\n\tpublic static final String DATA_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.jdbc.DataRepositoryImpl\";\n\n\t/** Field description */\n\tpublic static final String DATA_REPO_POOL_CLASS_PROP_KEY = \"data-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String DATA_REPO_POOL_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.DataRepositoryPool\";\n\n\t/** Field description */\n\tpublic static final String DATA_REPO_POOL_SIZE = \"--data-repo-pool-size\";\n\n\t/** Field description */\n\tpublic static final String DATA_REPO_POOL_SIZE_PROP_KEY = \"data-repo-pool-size\";\n\n\tprivate static final String REPO_POOL_SIZE_PROP_KEY = \"repo-pool-size\";\n\tprivate static final String DEF_REPO_POOL_SIZE_PROP_KEY = \"def-repo-pool-size\";\n\n\t// DataRepository properties\n\n\t/** Field description */\n\tpublic static final int DATA_REPO_POOL_SIZE_PROP_VAL = Math.max( 10, Runtime.getRuntime().availableProcessors()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t * REPO_POOL_SIZE_FACTOR_PROP_VAL );\n\n\t// repositories classes and URLs\n\n\t/** Field description */\n\tpublic static final String DERBY_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.JDBCRepository\";\n\n\t/** Field description */\n\tpublic static final String DERBY_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:derby:tigase-derbydb;create=true\";\n\n\t/** Field description */\n\tpublic static final String DRUPAL_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:mysql://localhost/drupal?user=root&password=mypass\";\n\n\t/** Field description */\n\tpublic static final String DRUPALWP_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.DrupalWPAuth\";\n\n\t/** Field description */\n\tpublic static final String DUMMY_REPO_CLASS_PROP_VAL = \"tigase.db.DummyRepository\";\n\n\t/** Field description */\n\tpublic static final String GEN_AUTH_DB = \"--auth-db\";\n\n\t/** Field description */\n\tpublic static final String GEN_AUTH_DB_URI = \"--auth-db-uri\";\n\n\t/** Field description */\n\tpublic static final String GEN_USER_DB_PROP_KEY = \"user-db\";\n\tpublic static final String GEN_USER_DB = \"--\" + GEN_USER_DB_PROP_KEY;\n\n\t/** Field description */\n\tpublic static final String GEN_USER_DB_URI_PROP_KEY = \"user-db-uri\";\n\tpublic static final String GEN_USER_DB_URI = \"--\" + GEN_USER_DB_URI_PROP_KEY;\n\n\t/** Field description */\n\tpublic static final String LIBRESOURCE_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.jdbc.LibreSourceAuth\";\n\n\t/** Field description */\n\tpublic static final String LIBRESOURCE_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:postgresql://localhost/libresource?user=demo\";\n\n\t/** Default MS SQL Server JDBC class */\n\tpublic static final String SQLSERVER_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.jdbc.JDBCRepository\";\n\n\t/** Default MS SQL Server JDBC connection string */\n\tpublic static final String SQLSERVER_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:sqlserver://localhost:1433;databaseName=tigasedb;user=tigase;password=tigase;schema=dbo\";\n\n\t/** Field description */\n\tpublic static final String MYSQL_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.JDBCRepository\";\n\n\t/** Field description */\n\tpublic static final String MYSQL_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:mysql://localhost/tigase?user=root&password=mypass\";\n\n\t/** Field description */\n\tpublic static final String PGSQL_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.JDBCRepository\";\n\n\t/** Field description */\n\tpublic static final String PGSQL_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:postgresql://localhost/tigase?user=tigase\";\n\n\t/** Field description */\n\tpublic static final String SHARED_AUTH_REPO_PARAMS_PROP_KEY = \"shared-auth-repo-params\";\n\n\t/** Field description */\n\tpublic static final String SHARED_AUTH_REPO_PROP_KEY = \"shared-auth-repo\";\n\n\t/** Field description */\n\tpublic static final String SHARED_USER_REPO_PARAMS_PROP_KEY = \"shared-user-repo-params\";\n\n\t/** Field description */\n\tpublic static final String SHARED_USER_REPO_PROP_KEY = \"shared-user-repo\";\n\n\t/** Field description */\n\tpublic static final String TIGASE_AUTH_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.jdbc.TigaseAuth\";\n\n\t/** Field description */\n\tpublic static final String TIGASE_AUTH_REPO_URL_PROP_VAL =\n\t\t\t\"jdbc:mysql://localhost/tigasedb?user=tigase_user&password=mypass\";\n\n\t/** Field description */\n\tpublic static final String TIGASE_CUSTOM_AUTH_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.jdbc.TigaseCustomAuth\";\n\n\t/** Field description */\n\tpublic static final String USER_DOMAIN_POOL_CLASS = \"--user-domain-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String USER_DOMAIN_POOL_CLASS_PROP_KEY = \"user-domain-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String USER_DOMAIN_POOL_CLASS_PROP_VAL =\n\t\t\t\"tigase.db.UserRepositoryMDImpl\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_CLASS_PROP_KEY = \"user-repo-class\";\n\n\t/** Field description */\t\n\t@Deprecated\n\tpublic static final String USER_REPO_CLASS_PROP_VAL = \"tigase.db.jdbc.JDBCRepository\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_DOMAINS_PROP_KEY = \"user-repo-domains\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_PARAMS_NODE = \"user-repo-params\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_CLASS = \"--user-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_CLASS_PROP_DEF =\n\t\t\t\"tigase.db.UserRepositoryPool\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_CLASS_PROP_KEY = \"user-repo-pool\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_CLASS_PROP_VAL = null;\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_SIZE = \"--user-repo-pool-size\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO_POOL_SIZE_PROP_KEY = \"user-repo-pool-size\";\n\n\t// UserRepository properties\n\n\t/** Field description */\n\tpublic static final int USER_REPO_POOL_SIZE_PROP_VAL = Math.max( 10, Runtime.getRuntime().availableProcessors()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t * REPO_POOL_SIZE_FACTOR_PROP_VAL);\n\n\t/** Field description */\n\tpublic static final String USER_REPO_URL_PROP_KEY = \"user-repo-url\";\n\n\t/** Field description */\n\tpublic static final String XML_REPO_CLASS_PROP_VAL = \"tigase.db.xml.XMLRepository\";\n\n\t/** Field description */\n\tpublic static final String XML_REPO_URL_PROP_VAL = \"user-repository.xml\";\n\n\t/** Field description */\n\tpublic static final String DATABASE_TYPE_PROP_KEY = \"database-type\";\n\n\tpublic static final StatisticsContainerIfc statistics = new RepositoryFactoryStatisticsContainer();\n\n\tprivate static final Logger log = Logger.getLogger(RepositoryFactory.class.getCanonicalName());\n\t\n\t/** Field description */\n\tprivate static final ConcurrentMap<String, UserRepository> user_repos =\n\t\t\tnew ConcurrentHashMap<String, UserRepository>(USER_REPO_POOL_SIZE_PROP_VAL);\n\tprivate static final ConcurrentMap<String, DataRepository> data_repos =\n\t\t\tnew ConcurrentHashMap<String, DataRepository>(DATA_REPO_POOL_SIZE_PROP_VAL);\n\tprivate static final ConcurrentMap<String, AuthRepository> auth_repos =\n\t\t\tnew ConcurrentHashMap<String, AuthRepository>(AUTH_REPO_POOL_SIZE_PROP_VAL);\n\n\tprivate static final CopyOnWriteArraySet<Class> internalRepositoryClasses = new CopyOnWriteArraySet<Class>();\n\t\n\tstatic {\n\t\ttry {\n\t\t\tSet<Class<Repository>> classes = ClassUtil.getClassesImplementing(Repository.class);\n\t\t\tinitialize(classes);\n\t\t} catch (Exception ex) {\n\t\t}\n\t}\n\t\n\tpublic static void initialize(Collection<Class<Repository>> classes) {\n\t\tinternalRepositoryClasses.addAll(classes);\n\t}\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param class_name\n\t * @param resource\n\t * @param params\n\t *\n\t * \n\t *\n\t * @throws ClassNotFoundException\n\t * @throws DBInitException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t */\n\tpublic static AuthRepository getAuthRepository(String class_name, String resource,\n\t\t\tMap<String, String> params)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException,\n\t\t\t\t\t\t\tDBInitException {\n\t\tString cls = class_name;\n\n\t\tif (cls == null) {\n\t\t\tcls = System.getProperty(AUTH_REPO_CLASS_PROP_KEY);\n\t\t\tif (cls == null) {\n\t\t\t\tcls = getRepoClassName(AuthRepository.class, resource);\n\t\t\t}\n\t\t}\t\t\n\t\tif (params == null) {\n\t\t\tparams = new LinkedHashMap<String, String>(AUTH_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tcls = getRepoClass(cls);\n\n\t\tAuthRepository repo = auth_repos.get(cls + resource);\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Getting AuthRepository using: {0} for: {1}; repository instance: \",\n\t\t\t\t\t\t\t new Object[] { cls, resource, repo } );\n\t\t}\n\n\t\tif (repo == null) {\n\t\t\tString repo_pool_cls = System.getProperty(AUTH_REPO_POOL_CLASS_PROP_KEY,\n\t\t\t\t\tAUTH_REPO_POOL_CLASS_PROP_VAL);\n\t\t\tint repo_pool_size;\n\n\t\t\tif ( params.get( RepositoryFactory.AUTH_REPO_POOL_SIZE_PROP_KEY ) != null ){\n\t\t\t\trepo_pool_size = Integer.parseInt( params.get( RepositoryFactory.AUTH_REPO_POOL_SIZE_PROP_KEY ) );\n\t\t\t\tparams.put( RepositoryFactory.REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t} else if ( Integer.getInteger( AUTH_REPO_POOL_SIZE_PROP_KEY ) != null ){\n\t\t\t\trepo_pool_size = Integer.getInteger( AUTH_REPO_POOL_SIZE_PROP_KEY );\n\t\t\t\tparams.put( RepositoryFactory.REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t} else {\n\t\t\t\trepo_pool_size = AUTH_REPO_POOL_SIZE_PROP_VAL;\n\t\t\t\tparams.put( RepositoryFactory.DEF_REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t}\n\t\t\tparams.put(RepositoryFactory.DATABASE_TYPE_PROP_KEY, class_name);\n\t\t\tif (repo_pool_cls != null) {\n\t\t\t\tAuthRepositoryPool repo_pool = (AuthRepositoryPool) ModulesManagerImpl.getInstance().forName(repo_pool_cls)\n\t\t\t\t\t\t.newInstance();\n\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"No AuthRepository, creating new; repo_pool_cls: {0}, repo_pool_size: {1}\",\n\t\t\t\t\t\t\t\t new Object[] { repo_pool_cls, repo_pool_size } );\n\t\t\t\t}\n\n\t\t\t\trepo_pool.initRepository(resource, params);\n\t\t\t\tfor (int i = 0; i < repo_pool_size; i++) {\n\t\t\t\t\trepo = (AuthRepository) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\t\trepo.initRepository(resource, params);\n\t\t\t\t\trepo_pool.addRepo(repo);\n\t\t\t\t}\n\t\t\t\trepo = repo_pool;\n\t\t\t} else {\n\t\t\t\trepo = (AuthRepository) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\trepo.initRepository(resource, params);\n\t\t\t}\n\t\t\tauth_repos.put(cls + resource, repo);\n\t\t}\n\n\t\treturn repo;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param class_name\n\t * @param resource\n\t * @param params\n\t *\n\t * \n\t *\n\t * @throws ClassNotFoundException\n\t * @throws DBInitException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t * @throws SQLException\n\t */\n\tpublic static DataRepository getDataRepository(String class_name, String resource,\n\t\t\tMap<String, String> params)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException,\n\t\t\t\t\t\t\tDBInitException, SQLException {\n\t\tString cls = class_name;\n\n\t\tif (cls == null) {\n\t\t\tcls = System.getProperty(DATA_REPO_CLASS_PROP_KEY);\n\t\t\tif (cls == null) {\n\t\t\t\tcls = getRepoClassName(DataRepository.class, resource);\n\t\t\t}\n\t\t}\n\t\tif (params == null) {\n\t\t\tparams = new LinkedHashMap<String, String>(DATA_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tcls = getRepoClass(cls);\n\n\t\tDataRepository repo = data_repos.get(cls + resource);\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Getting DataRepository: {0} for: {1}; repository instance: \",\n\t\t\t\t\t\t\t new Object[] { cls, resource, repo } );\n\t\t}\n\n\t\tif (repo == null) {\n\t\t\tint repo_pool_size;\n\n\t\t\tif (params.get(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY) != null) {\n\t\t\t\trepo_pool_size = Integer.parseInt(params.get(RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY));\n\t\t\t} else if (params.get(RepositoryFactory.REPO_POOL_SIZE_PROP_KEY) != null) {\n\t\t\t\trepo_pool_size = Integer.parseInt(params.get(RepositoryFactory.REPO_POOL_SIZE_PROP_KEY));\n\t\t\t} else if (Integer.getInteger(DATA_REPO_POOL_SIZE_PROP_KEY) != null) {\n\t\t\t\trepo_pool_size = Integer.getInteger(DATA_REPO_POOL_SIZE_PROP_KEY);\n\t\t\t} else if (params.get(RepositoryFactory.DEF_REPO_POOL_SIZE_PROP_KEY) != null) {\n\t\t\t\trepo_pool_size = Integer.parseInt(params.get(RepositoryFactory.DEF_REPO_POOL_SIZE_PROP_KEY));\n\t\t\t} else {\n\t\t\t\trepo_pool_size = Integer.getInteger(DATA_REPO_POOL_SIZE_PROP_KEY,DATA_REPO_POOL_SIZE_PROP_VAL);\n\t\t\t}\n\t\t\tparams.put(RepositoryFactory.DATABASE_TYPE_PROP_KEY, class_name);\n\t\t\tString repo_pool_cls = System.getProperty(DATA_REPO_POOL_CLASS_PROP_KEY, DATA_REPO_POOL_CLASS_PROP_VAL);\n\n\t\t\tDataRepositoryPool repo_pool = (DataRepositoryPool) ModulesManagerImpl.getInstance().forName(repo_pool_cls)\n\t\t\t\t\t.newInstance();\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"No DataRepository, creating new; repo_pool_cls: {0}, repo_pool_size: {1}\",\n\t\t\t\t\t\t\t\t new Object[] { repo_pool_cls, repo_pool_size } );\n\t\t\t}\n\n\t\t\trepo_pool.initRepository(resource, params);\n\t\t\tfor (int i = 0; i < repo_pool_size; i++) {\n\t\t\t\trepo = (DataRepository) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\trepo.initRepository(resource, params);\n\t\t\t\trepo_pool.addRepo(repo);\n\t\t\t}\n\t\t\trepo = repo_pool;\n\t\t\tdata_repos.put(cls + resource, repo);\n\t\t}\n\n\t\treturn repo;\n\t}\n\n\t/**\n\t * Method returns class which would be by default used as implementation of class \n\t *\n\t * @param cls\n\t * @param uri\n\t * @return \n\t * @throws tigase.db.DBInitException\n\t *\n\t * \n\t */\n\tpublic static <T extends Class<? extends Repository>> T getRepoClass(T cls, String uri) throws DBInitException {\n\t\tSet<T> classes = ModulesManagerImpl.getInstance().getImplementations(cls);\n\t\tclasses.addAll(getRepoInternalClasses(cls));\n\t\tSet<T> supported = new HashSet<T>();\n\t\tfor (T clazz : classes) {\n\t\t\tRepository.Meta annotation = (Repository.Meta) clazz.getAnnotation(Repository.Meta.class);\n\t\t\tif (annotation != null) {\n\t\t\t\tString[] supportedUris = annotation.supportedUris();\n\t\t\t\tif (supportedUris != null) {\n\t\t\t\t\tfor (String supportedUri : supportedUris) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"checking if {0} for {1} supports {2} while it supports {3} result = {4}\", \n\t\t\t\t\t\t\t\t\tnew Object[]{clazz.getCanonicalName(), cls.getCanonicalName(), uri, supportedUri, Pattern.matches(supportedUri, uri)});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Pattern.matches(supportedUri, uri))\n\t\t\t\t\t\t\tsupported.add(clazz);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsupported.add(clazz);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsupported.add(clazz);\n\t\t\t}\n\t\t}\n\t\tif (supported.isEmpty())\n\t\t\tthrow new DBInitException(\"Not found class supporting uri = \" + uri);\n\t\tT result = null;\n\t\tfor (T clazz : supported) {\n\t\t\tif (result == null)\n\t\t\t\tresult = clazz;\n\t\t\telse {\n\t\t\t\tRepository.Meta ar = (Repository.Meta) result.getAnnotation(Repository.Meta.class);\n\t\t\t\tRepository.Meta ac = (Repository.Meta) clazz.getAnnotation(Repository.Meta.class);\n\t\t\t\tif (ac == null)\n\t\t\t\t\tcontinue;\n\t\t\t\tif ((ar == null && ac != null) || (!ar.isDefault() && ((ar.supportedUris() == null && ac.supportedUris() != null) || ac.isDefault()))) {\n\t\t\t\t\tresult = clazz;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\t\n\t/**\n\t * Returns name of class which would be used as repository implementation\n\t * \n\t * @param cls - interface class needs to implement\n\t * @param uri - uri which needs to be supported by implementation\n\t * @return\n\t * @throws DBInitException \n\t */\n\tpublic static String getRepoClassName(Class cls, String uri) throws DBInitException {\n\t\tClass result = getRepoClass(cls, uri);\n\t\treturn result.getCanonicalName();\n\t}\n\t\n\t/**\n\t * Method returns internal (available in server classpath) implementation of classes extending or\n\t * implementing class passed as cls parameter.\n\t * \n\t * @param cls - class for which we look for implementations of extensions\n\t * @return set of classes matching criteria\n\t */\n\tprivate static <T extends Class<? extends Repository>> Set<T> getRepoInternalClasses(T cls) {\n\t\tHashSet<T> result = new HashSet<T>();\n\t\tfor (Class<Repository> clazz : internalRepositoryClasses) {\n\t\t\tif (cls.isAssignableFrom(clazz))\n\t\t\t\tresult.add((T) clazz);\n\t\t}\n\t\treturn result;\n\t} \n\t\n\tpublic static String getRepoClass(String repo_name) {\n\t\tString result = repo_name;\n\n\t\tif (repo_name.equals(\"mysql\")) {\n\t\t\tresult = MYSQL_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"pgsql\")) {\n\t\t\tresult = PGSQL_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"derby\")) {\n\t\t\tresult = DERBY_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"tigase-custom-auth\") || repo_name.equals(\"tigase-custom\") ||\n\t\t\t\trepo_name.equals(\"custom-auth\")) {\n\t\t\tresult = TIGASE_CUSTOM_AUTH_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"tigase-auth\")) {\n\t\t\tresult = TIGASE_AUTH_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"drupal\") || repo_name.equals(\"wp\")) {\n\t\t\tresult = DRUPALWP_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"libresource\")) {\n\t\t\tresult = LIBRESOURCE_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tif (repo_name.equals(\"sqlserver\")) {\n\t\t\tresult = SQLSERVER_REPO_CLASS_PROP_VAL;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param class_name\n\t * @param resource\n\t * @param params\n\t *\n\t * \n\t *\n\t * @throws ClassNotFoundException\n\t * @throws DBInitException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t */\n\tpublic static UserRepository getUserRepository(String class_name, String resource,\n\t\t\tMap<String, String> params)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException,\n\t\t\t\t\t\t\tDBInitException {\n\t\tString cls = class_name;\n\n\t\tif (resource == null ) {\n\t\t\tresource = System.getProperty( GEN_USER_DB_URI_PROP_KEY );\n\t\t}\n\n\t\tif ( cls == null ){\n\t\t\tcls = System.getProperty( USER_REPO_CLASS_PROP_KEY );\n\t\t\tif ( cls == null ){\n\t\t\t\tcls = getRepoClassName( UserRepository.class, resource );\n\t\t\t\tif ( cls == null ){\n\t\t\t\t\tcls = System.getProperty( GEN_USER_DB_PROP_KEY );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (params == null) {\n\t\t\tparams = new LinkedHashMap<String, String>(USER_REPO_POOL_SIZE_PROP_VAL);\n\t\t}\n\t\tcls = getRepoClass(cls);\n\n\t\tUserRepository repo = user_repos.get(cls + resource);\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Getting UserRepository: {0} for: {1}; repository instance: \",\n\t\t\t\t\t\t\t new Object[] { cls, resource, repo } );\n\t\t}\n\n\t\tif (repo == null) {\n\t\t\tString repo_pool_cls = System.getProperty(USER_REPO_POOL_CLASS_PROP_KEY,\n\t\t\t\t\tUSER_REPO_POOL_CLASS_PROP_VAL);\n\t\t\tint repo_pool_size;\n\n\t\t\tif ( params.get( RepositoryFactory.USER_REPO_POOL_SIZE_PROP_KEY ) != null ){\n\t\t\t\trepo_pool_size = Integer.parseInt( params.get( RepositoryFactory.USER_REPO_POOL_SIZE_PROP_KEY ) );\n\t\t\t\tparams.put( RepositoryFactory.REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t} else if ( Integer.getInteger( USER_REPO_POOL_SIZE_PROP_KEY ) != null ){\n\t\t\t\trepo_pool_size = Integer.getInteger( USER_REPO_POOL_SIZE_PROP_KEY );\n\t\t\t\tparams.put( RepositoryFactory.REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t} else {\n\t\t\t\trepo_pool_size = USER_REPO_POOL_SIZE_PROP_VAL;\n\t\t\t\tparams.put( RepositoryFactory.DEF_REPO_POOL_SIZE_PROP_KEY, String.valueOf(\n\t\t\t\t\t\t\t\t\t\trepo_pool_size ) );\n\t\t\t}\n\n\t\t\tparams.put(RepositoryFactory.DATABASE_TYPE_PROP_KEY, class_name);\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"No UserRepository, creating new; repo_pool_cls: {0}, repo_pool_size: {1}\",\n\t\t\t\t\t\t\t\t new Object[] { repo_pool_cls, repo_pool_size } );\n\t\t\t}\n\n\t\t\tif (repo_pool_cls != null) {\n\t\t\t\tUserRepositoryPool repo_pool = (UserRepositoryPool) ModulesManagerImpl.getInstance().forName(repo_pool_cls)\n\t\t\t\t\t\t.newInstance();\n\n\t\t\t\trepo_pool.initRepository(resource, params);\n\t\t\t\tfor (int i = 0; i < repo_pool_size; i++) {\n\t\t\t\t\trepo = (UserRepository) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\t\trepo.initRepository(resource, params);\n\t\t\t\t\trepo_pool.addRepo(repo);\n\t\t\t\t}\n\t\t\t\trepo = repo_pool;\n\t\t\t} else {\n\t\t\t\trepo = (UserRepository) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\trepo.initRepository(resource, params);\n\t\t\t}\n\t\t\tuser_repos.put(cls + resource, repo);\n\t\t}\n\n\t\treturn repo;\n\t}\n\n\tpublic static class RepositoryFactoryStatisticsContainer implements StatisticsContainerIfc {\n\n\t\t@Override\n\t\tpublic String getName() {\n\t\t\treturn \"repo-factory\";\n\t\t}\n\n\t\t@Override\n\t\tpublic void getStatistics(StatisticsList list) {\n\t\t\tlist.add(getName(), \"Number of data repositories\", data_repos.size(), Level.FINE);\n\t\t\tfor (DataRepository dataRepository : data_repos.values()) {\n\t\t\t\tif (dataRepository instanceof StatisticsProviderIfc) {\n\t\t\t\t\t((StatisticsProviderIfc) dataRepository).getStatistics(getName(), list);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n}    // RepositoryFactory\n\n\n//~ Formatted in Tigase Code Convention on 13/05/27\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/TigaseDBException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n/**\n * Describe class TigaseDBException here.\n *\n *\n * Created: Thu Oct 26 12:15:36 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TigaseDBException extends Exception {\n\n  private static final long serialVersionUID = 1L;\n\n\t/**\n\t * Creates a new <code>TigaseDBException</code> instance.\n\t *\n\t */\n\tpublic TigaseDBException(String message) { super(message); }\n\n  public TigaseDBException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // TigaseDBException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/UserExistsException.java",
    "content": "/* \n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db;\n\n//~--- classes ----------------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n\n/**\n * The <code>UserExistsException</code> is thrown when application tries to add\n * new user with user ID which already exists in repository.\n * According to <code>UserRepository</code> specification there can be the only\n * one registered user with particular ID.\n * <p>\n * Created: Wed Oct 27 14:17:44 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UserExistsException extends TigaseDBException {\n\tprivate BareJID userId = null;\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tpublic UserExistsException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic UserExistsException(BareJID user, String message, Throwable cause) {\n\t\tsuper(message + \" (\" + user + \")\", cause );\n\t\tuserId = user;\n\t}\n\n\tpublic UserExistsException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n\n\tpublic BareJID getUserId() {\n\t\treturn userId;\n\t}\n} \n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/UserNotFoundException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db;\n\n/**\n * The <code>UserNotFoundException</code> exception is thrown when application\n * tries to access data for user which does not exist in repository.\n * <p>\n * Created: Wed Oct 27 14:17:44 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UserNotFoundException extends TigaseDBException {\n\n  private static final long serialVersionUID = 1L;\n\n  /**\n   * Creates a new <code>UserNotFoundException</code> instance.\n   *\n   */\n  public UserNotFoundException(String message) { super(message); }\n\n  /**\n   * Creates a new <code>UserNotFoundException</code> instance.\n   *\n   */\n  public UserNotFoundException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // UserNotFoundException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/UserRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db;\n\nimport tigase.xmpp.BareJID;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * <code>UserRepository</code> interface defines all functionalities required\n * to store user data.\n * It contains adding, removing and searching methods. User repository is\n * organized as hierarchical data base. It means you can add items to repository\n * on different levels like files in file systems. Instead, however of working\n * with directories you work with nodes. You can create many levels of nodes and\n * store data on any level. It helps to organize data in more logical order.\n *\n * <p>\n * Created: Tue Oct 26 15:09:28 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface UserRepository extends Repository {\n\n\t/**\n\t * <code>addDataList</code> method adds mode entries to existing data list\n\t * associated with given key in repository under given node path.\n\t * This method is very similar to <code>setDataList(...)</code> except it\n\t * doesn't remove existing data.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the specified values list is to\n\t * be associated.\n\t * @param list a <code>String[]</code> is an array of values to be associated\n\t * with the specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid addDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * This <code>addUser</code> method allows to add new user to repository.\n\t * It <b>must</b> throw en exception <code>UserExistsException</code> if such\n\t * user already exists because user <b>must</b> be unique within user\n\t * repository data base.<br>\n\t * As one <em>XMPP</em> server can support many virtual internet domains it\n\t * is required that <code>user</code> id consists of user name and domain\n\t * address: <em>username@domain.address.net</em> for example.\n\t *\n\t * @param user a <code>BareJID</code> value of user id consisting of user name\n\t * and domain address.\n\t * @exception UserExistsException if user with the same id already exists.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid addUser(BareJID user) throws UserExistsException, TigaseDBException;\n\n\t/**\n\t * <code>getData</code> method returns a value associated with given key for\n\t * user repository in given subnode.\n\t * If key is not found in repository given default value is returned.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the needed value is\n\t * associated.\n\t * @param def a <code>String</code> value which is returned in case if data\n\t * for specified key does not exixist in repository.\n\t * @return a <code>String</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString getData(BareJID user, String subnode, String key, String def)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getData</code> method returns a value associated with given key for\n\t * user repository in given subnode.\n\t * If key is not found in repository <code>null</code> value is returned.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the needed value is\n\t * associated.\n\t * @return a <code>String</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString getData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getData</code> method returns a value associated with given key for\n\t * user repository in default subnode.\n\t * If key is not found in repository <code>null</code> value is returned.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param key a <code>String</code> with which the needed value is\n\t * associated.\n\t * @return a <code>String</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString getData(BareJID user, String key) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getDataList</code> method returns array of values associated with\n\t * given key or <code>null</code> if given key does not exist for given user\n\t * ID in given node path.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the needed values list is\n\t * associated.\n\t * @return a <code>String[]</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString[] getDataList(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getKeys</code> method returns list of all keys stored in given\n\t * subnode in user repository.\n\t * There is a value (or list of values) associated with each key. It is up to\n\t * user (developer) to know what key keeps one value and what key keeps list\n\t * of values.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @return a <code>String[]</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString[] getKeys(BareJID user, String subnode) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getKeys</code> method returns list of all keys stored in default user\n\t * repository node.\n\t * There is some a value (or list of values) associated with each key. It is\n\t * up to user (developer) to know what key keeps one value and what key keeps\n\t * list of values.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored or retrieved. User ID consists of user name and domain name.\n\t * @return a <code>String[]</code> value\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString[] getKeys(BareJID user) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * Returns a DB connection string or DB connection URI.\n\t * @return a <code>String</code> value representing database connection string.\n\t */\n\tString getResourceUri();\n\n\t/**\n\t * <code>getSubnodes</code> method returns list of all direct subnodes from\n\t * given node.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @return a <code>String[]</code> value is an array of all direct subnodes.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString[] getSubnodes(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>getSubnodes</code> method returns list of all <em>root</em> nodes for\n\t * given user.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @return a <code>String[]</code> value is an array of all <em>root</em>\n\t * nodes for given user.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tString[] getSubnodes(BareJID user) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * Returns a user unique ID number within the given repository. Please note it is also\n\t * possible that the ID number is unique only for the user domain. The ID is a positive\n\t * number if the user exists and negative if the user was not found in the repository.\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored or retrieved. User ID consists of user name and domain name.\n\t * @return a user inique ID number within the repository or domain. The ID is a positive\n\t * number if the user exists and negative if the user was not found in the repository.\n\t * @throws TigaseDBException if there is a problem with accessing user repository.\n\t */\n\tlong getUserUID(BareJID user) throws TigaseDBException;\n\n\t/**\n\t * This method is only used by the data conversion tools. They attempt\n\t * to copy whole user repositories from one to another database. Databases\n\t * might not be compatible but as long as the API is implemented and they\n\t * support adding user the user database can be copied to a different data\n\t * source.\n\t * @return returns a collection of all user IDs (Jabber IDs) stored in\n\t * the user repository.\n\t * @throws tigase.db.TigaseDBException\n\t */\n\tList<BareJID> getUsers() throws TigaseDBException;\n\n\t/**\n\t * This method is only used by the server statistics component to report\n\t * number of registered users.\n\t * @return a <code>long</code> number of registered users in the repository.\n\t */\n\tlong getUsersCount();\n\n\t/**\n\t * This method is only used by the server statistics component to report\n\t * number of registered users for given domain.\n\t * @param domain\n\t * @return a <code>long</code> number of registered users in the repository.\n\t */\n\tlong getUsersCount(String domain);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * <code>removeData</code> method removes pair (key, value) from user\n\t * repository in given subnode.\n\t * If the key exists in user repository there is always a value\n\t * associated with this key - even empty <code>String</code>. If key does not\n\t * exist the <code>null</code> value is returned from repository backend or\n\t * given default value.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> for which the value is to be removed.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid removeData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>removeData</code> method removes pair (key, value) from user\n\t * repository in default repository node.\n\t * If the key exists in user repository there is always a value\n\t * associated with this key - even empty <code>String</code>. If key does not\n\t * exist the <code>null</code> value is returned from repository backend or\n\t * given default value.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param key a <code>String</code> for which the value is to be removed.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid removeData(BareJID user, String key) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>removeSubnode</code> method removes given subnode with all subnodes\n\t * in this node and all data stored in this node and in all subnodes.\n\t * Effectively it removes entire repository tree starting from given node.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path to subnode which\n\t * has to be removed. Node path has the same form as directory path on file\n\t * system: <pre>/root/subnode1/subnode2</pre>.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid removeSubnode(BareJID user, String subnode) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * This <code>removeUser</code> method allows to remove user and all his data\n\t * from user repository.\n\t * If given user id does not exist <code>UserNotFoundException</code> must be\n\t * thrown. As one <em>XMPP</em> server can support many virtual internet\n\t * domains it is required that <code>user</code> id consists of user name and\n\t * domain address: <em>username@domain.address.net</em> for example.\n\t *\n\t * @param user a <code>BareJID</code> value of user id consisting of user name\n\t * and domain address.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid removeUser(BareJID user) throws UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>setData</code> method sets data value for given user ID in repository\n\t * under given node path and associates it with given key.\n\t * If there already exists value for given key in given node, old value is\n\t * replaced with new value. No warning or exception is thrown in case if\n\t * methods overwrites old value.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the specified value is to be\n\t * associated.\n\t * @param value a <code>String</code> value to be associated with the\n\t * specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid setData(BareJID user, String subnode, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * This <code>setData</code> method sets data value for given user ID\n\t * associated with given key in default repository node.\n\t * Default node is dependent on implementation and usually it is root user\n\t * node. If there already exists value for given key in given node, old value\n\t * is replaced with new value. No warning or exception is thrown in case if\n\t * methods overwrites old value.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param key a <code>String</code> with which the specified value is to be\n\t * associated.\n\t * @param value a <code>String</code> value to be associated with the\n\t * specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid setData(BareJID user, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t/**\n\t * <code>setDataList</code> method sets list of values for given user\n\t * associated given key in repository under given node path.\n\t * If there already exist values for given key in given node, all old values are\n\t * replaced with new values. No warning or exception is thrown in case if\n\t * methods overwrites old value.\n\t *\n\t * @param user a <code>BareJID</code> value of user ID for which data must be\n\t * stored. User ID consists of user name and domain name.\n\t * @param subnode a <code>String</code> value is a node path where data is\n\t * stored. Node path has the same form as directory path on file system:\n\t * <pre>/root/subnode1/subnode2</pre>.\n\t * @param key a <code>String</code> with which the specified values list is to\n\t * be associated.\n\t * @param list a <code>String[]</code> is an array of values to be associated\n\t * with the specified key.\n\t * @exception UserNotFoundException if user id hasn't been found in repository.\n\t * @throws TigaseDBException if database backend error occurs.\n\t */\n\tvoid setDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method <code>userExists</code> checks whether the user (or repository top node)\n\t * exists in the database. The method doesn't throw any exception nor it creates\n\t * the user in case it is missing. It just checks whether the user is already\n\t * in the database.\n\t *\n\t * Please don't overuse this method. All other methods\n\t * throw <code>UserNotFoundException</code> exception in case the user is missing\n\t * for which you executed the method. The exception is thrown unless\n\t * <code>userAutoCreate</code> property is set to true. In such case the exception\n\t * is never thrown and the methods are executed for given parameters prior to\n\t * creating user entry if it is missing.\n\t *\n\t * Therefore this method should be used only to check whether the account exists\n\t * without creating it.\n\t *\n\t * @param user a <code>BareJID</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\tboolean userExists(BareJID user);\n}    // UserRepository\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/UserRepositoryMDImpl.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Mar 27, 2010 6:43:02 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UserRepositoryMDImpl implements UserRepository {\n\tprivate static final Logger log = Logger.getLogger(UserRepositoryMDImpl.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate UserRepository def = null;\n\tprivate ConcurrentSkipListMap<String, UserRepository> repos =\n\t\tnew ConcurrentSkipListMap<String, UserRepository>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.addDataList(user, subnode, key, list);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t * @param repo\n\t */\n\tpublic void addRepo(String domain, UserRepository repo) {\n\t\trepos.put(domain, repo);\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user) throws UserExistsException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.addUser(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key, String def)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getData(user, subnode, key, def);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getData(user, subnode, key);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getData(user, key);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getDataList(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getDataList(user, subnode, key);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getKeys(user, subnode);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getKeys(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t * \n\t */\n\tpublic UserRepository getRepo(String domain) {\n\t\tif (domain == null ) {\n\t\t\treturn def;\n\t\t}\n\t\tUserRepository result = repos.get(domain);\n\n\t\tif (result == null) {\n\t\t\tresult = def;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn def.getResourceUri();\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getSubnodes(user, subnode);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.getSubnodes(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUserUID(BareJID user) throws TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getUserUID(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic List<BareJID> getUsers() throws TigaseDBException {\n\t\tList<BareJID> result = new ArrayList<BareJID>();\n\n\t\tfor (UserRepository repo : repos.values()) {\n\t\t\tresult.addAll(repo.getUsers());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\tlong result = 0;\n\n\t\tfor (UserRepository repo : repos.values()) {\n\t\t\tresult += repo.getUsersCount();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tUserRepository repo = getRepo(domain);\n\n\t\tif (repo != null) {\n\t\t\treturn repo.getUsersCount(domain);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + domain + \", not even default one!\");\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\tlog.info(\"Multi-domain repository pool initialized: \" + resource_uri + \", params: \"\n\t\t\t\t+ params);\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.removeData(user, subnode, key);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.removeData(user, key);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t * \n\t */\n\tpublic UserRepository removeRepo(String domain) {\n\t\treturn repos.remove(domain);\n\t}\n\n\t@Override\n\tpublic void removeSubnode(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.removeSubnode(user, subnode);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.removeUser(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setData(BareJID user, String subnode, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.setData(user, subnode, key, value);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setData(BareJID user, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.setData(user, key, value);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\trepo.setDataList(user, subnode, key, list);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t */\n\tpublic void setDefault(UserRepository repo) {\n\t\tdef = repo;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean userExists(BareJID user) {\n\t\tUserRepository repo = getRepo(user.getDomain());\n\n\t\tif (repo != null) {\n\t\t\treturn repo.userExists(user);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Couldn't obtain user repository for domain: \" + user.getDomain()\n\t\t\t\t\t\t+ \", not even default one!\");\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/UserRepositoryPool.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.SimpleCache;\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jan 28, 2009 8:46:53 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UserRepositoryPool implements UserRepository {\n\tprivate static final Logger log = Logger.getLogger(UserRepositoryPool.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Map<String, Object> cache = null;\n\tprivate LinkedBlockingQueue<UserRepository> repoPool =\n\t\tnew LinkedBlockingQueue<UserRepository>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.addDataList(user, subnode, key, list);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t */\n\tpublic void addRepo(UserRepository repo) {\n\t\trepoPool.offer(repo);\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user) throws UserExistsException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.addUser(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key, String def)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tString data = (String) cache.get(user + \"/\" + subnode + \"/\" + key);\n\n\t\tif (data != null) {\n\t\t\treturn data;\n\t\t}\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getData(user, subnode, key, def);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tString data = (String) cache.get(user + \"/\" + subnode + \"/\" + key);\n\n\t\tif (data != null) {\n\t\t\treturn data;\n\t\t}\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getData(user, subnode, key);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tString data = (String) cache.get(user + \"/\" + key);\n\n\t\tif (data != null) {\n\t\t\treturn data;\n\t\t}\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getData(user, key);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getDataList(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getDataList(user, subnode, key);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getKeys(user, subnode);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getKeys(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getSubnodes(user, subnode);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getSubnodes(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUserUID(BareJID user) throws TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUserUID(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic List<BareJID> getUsers() throws TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUsers();\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUsersCount();\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.getUsersCount(domain);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\tif (resource_uri.contains(\"cacheRepo=off\")) {\n\t\t\tlog.fine(\"Disabling cache.\");\n\t\t\tcache = Collections.synchronizedMap(new RepoCache(0, -1000));\n\t\t} else {\n\t\t\tcache = Collections.synchronizedMap(new RepoCache(10000, 60 * 1000));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user, String subnode, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tcache.remove(user + \"/\" + subnode + \"/\" + key);\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.removeData(user, subnode, key);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user, String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tcache.remove(user + \"/\" + key);\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.removeData(user, key);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeSubnode(BareJID user, String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tcache.remove(user + \"/\" + subnode);\n\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.removeSubnode(user, subnode);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.removeUser(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setData(BareJID user, String subnode, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.setData(user, subnode, key, value);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\tcache.put(user + \"/\" + subnode + \"/\" + key, value);\n\t}\n\n\t@Override\n\tpublic void setData(BareJID user, String key, String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.setData(user, key, value);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\tcache.put(user + \"/\" + key, value);\n\t}\n\n\t@Override\n\tpublic void setDataList(BareJID user, String subnode, String key, String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\trepo.setDataList(user, subnode, key, list);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic UserRepository takeRepo() {\n\t\ttry {\n\t\t\treturn repoPool.take();\n\t\t} catch (InterruptedException ex) {\n\t\t\tlog.log(Level.WARNING, \"Couldn't obtain user repository from the pool\", ex);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean userExists(BareJID user) {\n\t\tUserRepository repo = takeRepo();\n\n\t\tif (repo != null) {\n\t\t\ttry {\n\t\t\t\treturn repo.userExists(user);\n\t\t\t} finally {\n\t\t\t\taddRepo(repo);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"repo is NULL, pool empty? - {0}\", repoPool.size());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class RepoCache extends SimpleCache<String, Object> {\n\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param maxsize\n\t\t * @param cache_time\n\t\t */\n\t\tpublic RepoCache(int maxsize, long cache_time) {\n\t\t\tsuper(maxsize, cache_time);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic Object remove(Object key) {\n\t\t\tif (cache_off) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tObject val = super.remove(key);\n\t\t\tString strk = key.toString();\n\t\t\tIterator<String> ks = keySet().iterator();\n\n\t\t\twhile (ks.hasNext()) {\n\t\t\t\tString k = ks.next().toString();\n\n\t\t\t\tif (k.startsWith(strk)) {\n\t\t\t\t\tks.remove();\n\t\t\t\t}    // end of if (k.startsWith(strk))\n\t\t\t}      // end of while (ks.hasNext())\n\n\t\t\treturn val;\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/ComponentRepository.java",
    "content": "/*\n * ComponentRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db.comp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Collection;\nimport java.util.Map;\nimport tigase.db.Repository;\nimport tigase.db.TigaseDBException;\n\n/**\n * A convenience interface for a unified access to component specific repository\n * data. This is not intended to keep huge number of elements. Rather then it is\n * more like for storing Component dynamic configuration data. In simple cases\n * this data can be stored in configuration file, in more complex cases it can\n * be a database represented by UserRepository or even something else.\n * <br>\n * The repository is intended to store elements of a single type only. Each\n * element is identified by a unique key. All elements are cached in memory for\n * a fast retrieval so this kind of repository is recommended for small data\n * only when you need very fast and efficient access to all the information.<br>\n * Some implementations however may behave differently and not cache all the\n * repository items in memory.\n * <br>\n * Created: Oct 3, 2009 1:46:25 PM\n *\n * @param <Item>\n *          An element stored in the component repository.\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ComponentRepository<Item extends RepositoryItem>\n\t\t\t\textends Iterable<Item>, Repository {\n\t/** Field description */\n\tpublic static final String COMP_REPO_BIND = \"comp_repo\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Adds a listener for repository Item change.\n\t * @param repoChangeListener\n\t */\n\tvoid addRepoChangeListener(RepositoryChangeListenerIfc<Item> repoChangeListener);\n\n\t/**\n\t * Removes a listener for repository Item change.\n\t * @param repoChangeListener\n\t */\n\tvoid removeRepoChangeListener(RepositoryChangeListenerIfc<Item> repoChangeListener);\n\n\t/**\n\t * The method adds a new or updates existing Item in the repository. It needs\n\t * to have all fields set correctly. After this method call is finished a new\n\t * added item must be available in the component repository. The method adds\n\t * the item to memory cache and permanent storage.\n\t *\n\t * @param item\n\t *          a <code>Item</code> with all it's configuration parameters.\n\t * @throws TigaseDBException\n\t */\n\tvoid addItem(Item item) throws TigaseDBException;\n\n\t/**\n\t * The method adds a new or updates existing Item. It needs\n\t * to have all fields set correctly. After this method call is finished a new\n\t * added item must be available in the component repository. The method adds\n\t * the item to memory cache but not to a permanent storage.\n\t *\n\t * @param item\n\t *          a <code>Item</code> with all it's configuration parameters.\n\t */\n\tvoid addItemNoStore(Item item);\n\n\t/**\n\t * Returns a collection with all items stored in the repository.\n\t *\n\t *\n\t * @throws TigaseDBException\n\t */\n\tCollection<Item> allItems() throws TigaseDBException;\n\n\t/**\n\t * The method checks whether the item is stored in the repository.\n\t *\n\t * @param key\n\t *          a <code>String</code> with key to search for.\n\t * @return a <code>boolean</code> value <code>true</code> if the item exists\n\t *         in the repository or <code>false</code> of it does not.\n\t */\n\tboolean contains(String key);\n\t\n\t/**\n\t * Method destroys this instance of ComponentRepository releasing resources\n\t * allocated for this instance of ComponentRepository if possible\n\t */\n\tvoid destroy();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * The method is called to obtain default configuration settings if there are\n\t * any for this repository implementation The configuration settings are\n\t * implementation dependent and there are no defaults set by the server.\n\t * Default settings returned by this method are then saved in the\n\t * configuration file and presented to the admin for further adjustments.\n\t *\n\t * @param defs\n\t *          is a <code>Map</code> collection where all repository\n\t *          configuration defaults must be put.\n\t * @param params\n\t *          is a <code>Map</code> collection with some preset properties for\n\t *          the server. These settings can be used to adjust repository\n\t *          defaults, for example they can contain database connection URL or\n\t *          initial list of virtual domains.\n\t */\n\tvoid getDefaults(Map<String, Object> defs, Map<String, Object> params);\n\n\t/**\n\t * The method returns all item configuration parameters for a key or\n\t * <code>null</code> if the item does not exist in the repository.\n\t *\n\t * @param key\n\t *          a <code>String</code> with item identifier to search for.\n\t * @return a <code>Item</code> for a given key or <code>null</code> if the\n\t *         item is not in the repository.\n\t */\n\tItem getItem(String key);\n\n\t/**\n\t * Creates a new, uninitialized instance of the repository Item.\n\t *\n\t * @return a new, uninitialized instance of the repository Item.\n\t */\n\tItem getItemInstance();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * This method is called to reload items from the database or other permanent\n\t * storage. It is possible that items list is modified externally by\n\t * third-party system. When all modifications are done this method is called\n\t * to refresh the class cache. Whether the implementation load whole list or\n\t * just last modifications is implementation dependent.\n\t *\n\t * @throws TigaseDBException\n\t */\n\tvoid reload() throws TigaseDBException;\n\n\t/**\n\t * The method is called to remove given Item from the memory cache and\n\t * permanent storage. After this method is completed the item should no longer\n\t * be available in the component repository.\n\t *\n\t * @param key\n\t *          a <code>String</code> with domain name to remove.\n\t * @throws TigaseDBException\n\t */\n\tvoid removeItem(String key) throws TigaseDBException;\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * The method is called to set configuration for this repository\n\t * implementation. The configuration is repository implementation dependent.\n\t * There are no default settings for the repository.\n\t *\n\t * @param properties\n\t *          a <code>Map</code> with configuration settings. Content of this\n\t *          <code>Map</code> must not be modified. This read-only collection.\n\t */\n\tvoid setProperties(Map<String, Object> properties);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method returns number of items in the repository.\n\t *\n\t * @return an <code>int</code> value with number of items in the repository.\n\t */\n\tint size();\n\n\t/**\n\t * The method is called to store all data in the database. It is used when the\n\t * repository has been changed in some way and the changes have to be put to a\n\t * permanent storage for later retrieval.\n\t *\n\t * @throws TigaseDBException\n\t */\n\tvoid store() throws TigaseDBException;\n\n\t/**\n\t * Performs Item validation to check whether it meets the repository policy.\n\t * If validation is successful the method returns <code>null</code>, otherwise\n\t * it returns an error description.\n\t *\n\t * @param item\n\t *          is an <code>Item</code> object to perform validation checking\n\t *          upon.\n\t * @return <code>null</code> on success and an error message otherwise.\n\t */\n\tString validateItem(Item item);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Sets autoload task to periodically reload data from database.\n\t *\n\t *\n\t * @param delay in seconds between each database reload.\n\t */\n\tvoid setAutoloadTimer(long delay);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/ConfigRepository.java",
    "content": "/*\n * ConfigRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db.comp;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.Repository;\n\n/**\n * Created: Oct 3, 2009 2:58:41 PM\n *\n * @param <Item>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class ConfigRepository<Item extends RepositoryItem>\n\t\t\t\timplements ComponentRepository<Item> {\n\tprivate static final Logger log = Logger.getLogger(ConfigRepository.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected Map<String, Item> items;\n\tprotected int itemsHash = 0;\n\tprivate Timer                             autoLoadTimer  = null;\n\tprivate RepositoryChangeListenerIfc<Item> repoChangeList = null;\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setAutoloadTimer(long delay) {\n\t\tlong interval = delay * 1000;\n\n\t\tif (autoLoadTimer != null) {\n\t\t\tautoLoadTimer.cancel();\n\t\t\tautoLoadTimer = null;\n\t\t}\n\t\tif (interval > 0) {\n\t\t\tautoLoadTimer = new Timer(getConfigKey(), true);\n\t\t\tautoLoadTimer.schedule(new TimerTask() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treload();\n\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"exception during reload of config repository items\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, interval, interval);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addRepoChangeListener(\n\t\t\tRepositoryChangeListenerIfc<Item> repoChangeListener) {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Adding new repository listener: {0}\", repoChangeListener );\n\t\t}\n\t\tthis.repoChangeList = repoChangeListener;\n\t}\n\n\t@Override\n\tpublic void removeRepoChangeListener(\n\t\t\tRepositoryChangeListenerIfc<Item> repoChangeListener) {\n\t\tthis.repoChangeList = null;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn items.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic abstract String getConfigKey();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic abstract String[] getDefaultPropetyItems();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic abstract String getPropertyKey();\n\n\t//~--- methods --------------------------------------------------------------\n\n\n\n\t@Override\n\tpublic void addItem(Item item) {\n\t\taddItemNoStore(item);\n\n\t\tstore();\n\t}\n\n\t@Override\n\tpublic void addItemNoStore(Item item) {\n\t\tItem old = items.put(item.getKey(), item);\n\n\t\tif (repoChangeList != null) {\n\t\t\tif (old == null) {\n\t\t\t\tlog.log(Level.INFO, \"Calling itemAdded for: {0}\", item);\n\t\t\t\trepoChangeList.itemAdded(item);\n\t\t\t} else {\n\t\t\t\tif (itemChanged(old, item)) {\n\t\t\t\t\tlog.log(Level.INFO, \"Calling itemUpadted for: {0}\", item);\n\t\t\t\t\trepoChangeList.itemUpdated(item);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Not calling itemUpadted for: {0}, item unchanged.\",\n\t\t\t\t\t\t\t\titem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"No repoChangeListener for: {0}\", item );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method create instance of items Map. By overriding it it's possible to\n\t * change implementation and it's settings.\n\t */\n\tprotected void initItemsMap() {\n\t\tif ( null == items ){\n\t\t\titems = new ConcurrentSkipListMap<String, Item>( String.CASE_INSENSITIVE_ORDER );\n\t\t}\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param oldItem\n\t * @param newItem\n\t *\n\t *\n\t */\n\tpublic boolean itemChanged(Item oldItem, Item newItem) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic Collection<Item> allItems() {\n\t\treturn items.values();\n\t}\n\n\t@Override\n\tpublic boolean contains(String key) {\n\t\treturn items.keySet().contains(key);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tinitItemsMap();\n\t\tString[] items_arr = getDefaultPropetyItems();\n\n\t\tif (params.get(getPropertyKey()) != null) {\n\t\t\titems_arr = ((String) params.get(getPropertyKey())).split(\",\");\n\t\t\tfor (int i = 0; i < items_arr.length; i++) {\n\t\t\t\titems_arr[i] = items_arr[i].trim();\n\t\t\t}\n\t\t}\n\t\tdefs.put(getConfigKey(), items_arr);\n\t}\n\n\t@Override\n\tpublic Item getItem(String key) {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Getting item: {0} of items: {1}\", new Object[] {key, items.keySet()} );\n\t\t}\n\n\t\treturn items.get(key);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Iterator<Item> iterator() {\n\t\treturn items.values().iterator();\n\t}\n\n\t@Override\n\tpublic void reload() {}\n\n\t@Override\n\tpublic void removeItem(String key) {\n\t\tItem item = items.remove(key);\n\n\t\tif (item != null) {\n\t\t\tstore();\n\t\t\tif (repoChangeList != null) {\n\t\t\t\trepoChangeList.itemRemoved(item);\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Removing item: {0}\", item );\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tinitItemsMap();\n\t\tString[] items_arr = (String[]) properties.get(getConfigKey());\n\n\t\tif ((items_arr != null) && (items_arr.length > 0)) {\n\t\t\titems.clear();\n\t\t\tfor (String it : items_arr) {\n\t\t\t\tlog.log(Level.CONFIG, \"Loading config item: {0}\", it);\n\n\t\t\t\tItem item = getItemInstance();\n\n\t\t\t\titem.initFromPropertyString(it);\n\t\t\t\taddItem(item);\n\t\t\t\tlog.log(Level.CONFIG, \"Loaded config item: {0}\", item);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"Items list is not set in the configuration file!!\");\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int size() {\n\t\treturn items.size();\n\t}\n\n\t@Override\n\tpublic void store() {}\n\n\t@Override\n\tpublic String validateItem(Item item) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/RepositoryChangeListenerIfc.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.db.comp;\n\n/**\n * @author Artur Hefczyc\n * Created May 23, 2011\n */\npublic interface RepositoryChangeListenerIfc<Item extends RepositoryItem> {\n\n\tvoid itemAdded(Item item);\n\t\n\tvoid itemUpdated(Item item);\n\n\tvoid itemRemoved(Item item);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/RepositoryItem.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db.comp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * The interface defines a contract for a repository item handled by\n * ComponentRepository implementation.\n * Created: Oct 3, 2009 2:35:58 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface RepositoryItem {\n\n\t/**\n\t * The method is used for handling ad-hoc commands. The 'empty' ad-hoc command\n\t * packet is provided and the Item should fill it with fields for the user.\n\t * @param packet with empty ad-hoc command to fill with fields\n\t */\n\tvoid addCommandFields(Packet packet);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns an array with the Item administrators, that is people IDs who can manage,\n\t * configure and control less critical elements of the Item, like changing less critical\n\t * configuration settings. Administrators cannot remove the Item or change the owner or\n\t * add/remove administrators.\n\t * @return an array with the Item administrators IDs.\n\t */\n\tString[] getAdmins();\n\n\t/**\n\t * Returns a unique key for the item in the repository. All items are stored in\n\t * a memory cache which is a Map. And the key returned by this method is the\n\t * item identifier in the Map.\n\t * @return an Item key.\n\t */\n\tString getKey();\n\n\t/**\n\t * Returns the owner ID of the item.  This is used for a management to allow fine tuned\n\t * service administration with roles assigned to specific elements and items. Normally only\n\t * owner can perform some critical actions like removing the item, managing item\n\t * administrators or changing owner.<br>\n\t * There can be only one Item owner.\n\t * @return an ID of the Item owner.\n\t */\n\tString getOwner();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method used for handling ad-hoc commands. After a user fills all given field\n\t * the ad-hoc command packet is passed back to the item to initialize it with\n\t * data. Similar method to initFromElement(), but the data source is different.\n\t * @param packet with ad-hoc command filled by the user.\n\t */\n\tvoid initFromCommand(Packet packet);\n\n\t/**\n\t * The item can be also initialized from a more complex repositories: XML repository\n\t * or SQL database. In such a case more complex representation is prefered, possibly\n\t * carrying more information about the item. The method is called to initialize the\n\t * item with a data parsed from an XML representation of the repository.\n\t *\n\t * @param elem XML Element with all the item initialization data.\n\t */\n\tvoid initFromElement(Element elem);\n\n\t/**\n\t * The item can be initialized based on the data loaded from a configuration file.\n\t * In such a case the item representation is usually very simplified as a list of\n\t * parameters separated by a marker. Please note, usually each item is separated\n\t * from another with a comma, therefore do not use a comma in the item property\n\t * string. Double collon is commonly used alternative.\n\t *\n\t * @param propString is a property string to initialize the RepositoryItem.\n\t */\n\tvoid initFromPropertyString(String propString);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * The method checks whether the given id is one of the administrators set for the Item.\n\t * @param id is an ID of a person for which we check access permissions.\n\t * @return true of the given ID is on a list of administrators and false otherwise.\n\t */\n\tboolean isAdmin(String id);\n\n\t/**\n\t * The method checks whether the person with given ID is the Item owner.\n\t * @param id is an ID of a person for whom we check access permissions.\n\t * @return true of the given ID is on the Item owner and false otherwise.\n\t */\n\tboolean isOwner(String id);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Returns an array with the Item administrators, that is people IDs who can manage,\n\t * configure and control less critical elements of the Item, like changing less critical\n\t * configuration settings. Administrators cannot remove the Item or change the owner or\n\t * add/remove administrators.\n\t *\n\t * @param admins is an array with the Item administrators IDs to set for the Item.\n\t */\n\tvoid setAdmins(String[] admins);\n\n\t/**\n\t * Set the Item owner.  This is used for a management to allow fine tuned\n\t * service administration with roles assigned to specific elements and items. Normally only\n\t * owner can perform some critical actions like removing the item, managing item\n\t * administrators or changing owner.<br>\n\t * There can be only one Item owner.\n\t * @param owner is the Item owner ID.\n\t */\n\tvoid setOwner(String owner);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Item data can be stored in a more complex form than a simple property string.\n\t * The XML Element can contain much more detailed information about the element\n\t * than the simplified form and is used to store the repository item in more advanced\n\t * repositories then just property file. XML repository or SQL database can keep many\n\t * records for repository item with as much detailed information as needed.\n\t *\n\t * @return an XML Element with all the item initialization data.\n\t */\n\tElement toElement();\n\n\t/**\n\t * The item can be initialized based on the data loaded from a configuration file.\n\t * In such a case the item representation is usually very simplified as a list of\n\t * parameters separated by a marker. Please note, usually each item is separated\n\t * from another with a comma, therefore do not use a comma in the item property\n\t * string. Double collon is commonly used alternative.\n\t *\n\t * @return a property string representing the repository item in a simplified form.\n\t */\n\tString toPropertyString();\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/RepositoryItemAbstract.java",
    "content": "/*\n * RepositoryItemAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db.comp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n/**\n * Created: Sep 23, 2010 6:53:14 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class RepositoryItemAbstract\n\t\t\t\timplements RepositoryItem {\n\t/** Field description */\n\tpublic static final String ADMINS_ATT = \"admins\";\n\n\t/** Field description */\n\tpublic static final String ADMINS_LABEL = \"Administrators\";\n\n\t/** Field description */\n\tpublic static final String OWNER_ATT = \"owner\";\n\n\t/** Field description */\n\tpublic static final String OWNER_LABEL = \"Owner\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] admins = null;\n\tprivate String owner    = null;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract String getElemName();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addCommandFields(Packet packet) {\n\t\tCommand.addFieldValue(packet, OWNER_LABEL, (owner != null)\n\t\t\t\t\t\t? owner\n\t\t\t\t\t\t: packet.getStanzaTo().getBareJID().toString());\n\t\tCommand.addFieldValue(packet, ADMINS_LABEL, adminsToString(admins));\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getAdmins() {\n\t\treturn admins;\n\t}\n\n\t@Override\n\tpublic String getOwner() {\n\t\treturn owner;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initFromCommand(Packet packet) {\n\t\towner = Command.getFieldValue(packet, OWNER_LABEL);\n\t\tif ((owner == null) || owner.trim().isEmpty()) {\n\t\t\towner = packet.getStanzaFrom().getBareJID().toString();\n\t\t}\n\t\tadmins = adminsFromString(Command.getFieldValue(packet, ADMINS_LABEL));\n\t}\n\n\t@Override\n\tpublic void initFromElement(Element elem) {\n\t\towner  = elem.getAttributeStaticStr(OWNER_ATT);\n\t\tadmins = adminsFromString(elem.getAttributeStaticStr(ADMINS_ATT));\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isAdmin(String id) {\n\t\tif (admins == null) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (String admin : admins) {\n\t\t\tif (admin.equals(id)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOwner(String id) {\n\t\treturn ((owner == null)\n\t\t\t\t\t\t? false\n\t\t\t\t\t\t: owner.equals(id));\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setAdmins(String[] admins) {\n\t\tthis.admins = admins;\n\t}\n\n\t@Override\n\tpublic void setOwner(String owner) {\n\t\tthis.owner = owner;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Element toElement() {\n\t\tElement elem = new Element(getElemName());\n\n\t\tif (owner != null) {\n\t\t\telem.addAttribute(OWNER_ATT, owner);\n\t\t}\n\t\tif (admins != null) {\n\t\t\telem.addAttribute(ADMINS_ATT, adminsToString(admins));\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tprivate String[] adminsFromString(String admins_m) {\n\t\tString[] result = null;\n\n\t\tif ((admins_m != null) && (admins_m.trim().length() > 0)) {\n\t\t\tString[] tmp = admins_m.split(\",\");\n\n\t\t\tresult = new String[tmp.length];\n\t\t\tfor (int i = 0; i < tmp.length; i++) {\n\t\t\t\tresult[i] = tmp[i].trim();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate String adminsToString(String[] admins_m) {\n\t\tStringBuilder sb = new StringBuilder(100);\n\n\t\tif ((admins_m != null) && (admins_m.length > 0)) {\n\t\t\tfor (String adm : admins_m) {\n\t\t\t\tif (sb.length() == 0) {\n\t\t\t\t\tsb.append(adm);\n\t\t\t\t} else {\n\t\t\t\t\tsb.append(',').append(adm);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/comp/UserRepoRepository.java",
    "content": "/*\n * UserRepoRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db.comp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserRepository;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Created: Oct 3, 2009 3:55:27 PM\n *\n * @param <Item>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class UserRepoRepository<Item extends RepositoryItem>\n\t\t\t\textends ConfigRepository<Item> {\n\t/** Field description */\n\tpublic static final String REPO_CLASS_PROP_KEY = \"repo-class\";\n\n\t/** Field description */\n\tpublic static final String REPO_URI_PROP_KEY = \"repo-uri\";\n\tprivate static final Logger log              =\n\t\tLogger.getLogger(UserRepoRepository.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String items_list_pkey = \"items-lists\";\n\tprivate UserRepository repo    = null;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic abstract BareJID getRepoUser();\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\n\t\t// Something to initialize database with, in case it is empty\n\t\t// Otherwise the server would not work at all with empty Items database\n\t\tsuper.getDefaults(defs, params);\n\n\t\t// Do not create defaults for this, let it to use the shared repo pool as\n\t\t// a default one. Only if the user sets settings manually it means he wants\n\t\t// a different from the shared default.\n//  // Now the real items data storage:\n//  String repo_class = DERBY_REPO_CLASS_PROP_VAL;\n//  String repo_uri = DERBY_REPO_URL_PROP_VAL;\n//\n//  if (params.get(GEN_USER_DB) != null) {\n//    repo_class = (String) params.get(GEN_USER_DB);\n//  }\n//\n//  if (params.get(GEN_USER_DB_URI) != null) {\n//    repo_uri = (String) params.get(GEN_USER_DB_URI);\n//  }\n//  defs.put(REPO_CLASS_PROP_KEY, repo_class);\n//  defs.put(REPO_URI_PROP_KEY, repo_uri);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic String getItemsListPKey() {\n\t\treturn items_list_pkey;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\t@Override\n\tpublic void reload() {\n\t\tint hashCode = 0;\n\t\tsuper.reload();\n\t\ttry {\n\n\t\t\t// It is now time to load all Items' settings from the database:\n\t\t\tString items_list = repo.getData(getRepoUser(), getItemsListPKey());\n\n\t\t\tif ( items_list != null ){\n\t\t\t\thashCode = items_list.hashCode();\n\n\t\t\t\tif ( !items_list.isEmpty() && hashCode != itemsHash ){\n\t\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\t\tSimpleParser parser = SingletonFactory.getParserInstance();\n\n\t\t\t\t\tparser.parse( domHandler, items_list.toCharArray(), 0, items_list.length() );\n\n\t\t\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\n\t\t\t\t\tif ( ( elems != null ) && ( elems.size() > 0 ) ){\n\t\t\t\t\t\tfor ( Element elem : elems ) {\n\t\t\t\t\t\t\tItem item = getItemInstance();\n\n\t\t\t\t\t\t\titem.initFromElement( elem );\n\t\t\t\t\t\t\taddItemNoStore( item );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlog.log( Level.CONFIG, \"All loaded items: {0}\", items );\n\t\t\t\t\titemsHash = hashCode;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseDBException ex) {\n\t\t\tlog.log(Level.SEVERE, \"Problem with loading items list from the database.\", ex);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param properties\n\t */\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\n\t\t// Let's load items from configuration first. Later we can overwrite\n\t\t// them with items settings in the database.\n\t\tsuper.setProperties(properties);\n\n\t\tString repo_class = (String) properties.get(REPO_CLASS_PROP_KEY);\n\t\tString repo_uri   = (String) properties.get(REPO_URI_PROP_KEY);\n\n\t\tif (repo_uri != null) {\n\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\"Initializing custom component repository: {0}, db connection: {1}\",\n\t\t\t\t\t\t\tnew Object[] { repo_class,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t repo_uri });\n\t\t\ttry {\n\t\t\t\trepo = RepositoryFactory.getUserRepository(repo_class, repo_uri, null);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize Items repository\", e);\n\t\t\t\trepo = null;\n\t\t\t}\n\t\t}\n\t\tif (repo == null) {\n\t\t\trepo = (UserRepository) properties.get(RepositoryFactory.SHARED_USER_REPO_PROP_KEY);\n\t\t\tlog.config(\"Using shared repository instance.\");\n\t\t}\n\t\tif (repo != null) {\n\n\t\t\t// If this is the first run of the Items manager the database might not\n\t\t\t// be properly initialized yet....\n\t\t\ttry {\n\t\t\t\tif (!repo.userExists(getRepoUser())) {\n\t\t\t\t\trepo.addUser(getRepoUser());\n\t\t\t\t}\n\t\t\t\trepo.addUser(getRepoUser());\n\t\t\t} catch (UserExistsException e) {\n\n\t\t\t\t// This is expected when the Items repository has been already running on\n\t\t\t\t// this databaseso and can be ignored.\n\t\t\t} catch (Exception e) {\n\n\t\t\t\t// This is not expected so let's signal an error:\n\t\t\t\tlog.log(Level.SEVERE,\n\t\t\t\t\t\t\t\t\"Problem with adding '\" + getRepoUser() + \"' user to the database\", e);\n\t\t\t}\n\t\t\treload();\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\t@Override\n\tpublic void store() {\n\t\tsuper.store();\n\t\tif (repo != null) {\n\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\tfor (Item item : items.values()) {\n\t\t\t\tsb.append(item.toElement().toString());\n\t\t\t}\n\t\t\ttry {\n\t\t\t\trepo.setData(getRepoUser(), getItemsListPKey(), sb.toString());\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Error storing items list in the repository\", e);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/derby/StoredProcedures.java",
    "content": "package tigase.db.derby;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.Algorithms;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.BufferedReader;\nimport java.security.MessageDigest;\n\nimport java.sql.*;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Class description\n *\n *\n * @version        5.1.0, 2010.09.11 at 02:08:58 BST\n * @author         Artur Hefczyc\n */\npublic class StoredProcedures {\n\tprivate static final Logger log = Logger.getLogger(StoredProcedures.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigActiveAccounts(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id, last_login, last_logout, online_status, failed_logins, account_status from tig_users where account_status > 0\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param parentNid\n\t * @param uid\n\t * @param node\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigAddNode(long parentNid, long uid, String node, ResultSet[] data)\n\t\t\tthrows SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"insert into tig_nodes (parent_nid, uid, node) values (?, ?, ?)\",\n\t\t\t\t\tStatement.RETURN_GENERATED_KEYS);\n\n\t\t\tps.setLong(1, parentNid);\n\t\t\tps.setLong(2, uid);\n\t\t\tps.setString(3, node);\n\t\t\tps.executeUpdate();\n\t\t\tdata[0] = ps.getGeneratedKeys();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigAddUser(String userId, String userPw, ResultSet[] data)\n\t\t\tthrows SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\n\t\ttry {\n\t\t\t// check whether user exists\n\t\t\tPreparedStatement ps_check = conn.prepareStatement(\"select uid from tig_users where lower(user_id)=?\");\n\t\t\tps_check.setString(1, userId.toLowerCase());\n\t\t\tResultSet rs_check = ps_check.executeQuery();\n\t\t\tif (rs_check.next()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"insert into tig_users (user_id, user_pw) values (?, ?)\",\n\t\t\t\t\tStatement.RETURN_GENERATED_KEYS);\n\n\t\t\tps.setString(1, userId);\n\t\t\tps.setString(2, userPw);\n\t\t\tps.executeUpdate();\n\n\t\t\tResultSet rs = ps.getGeneratedKeys();\n\n\t\t\trs.next();\n\n\t\t\tlong generatedKey = rs.getLong(1);\n\t\t\tPreparedStatement ps3 = conn.prepareStatement(\"select uid from tig_users where uid=?\");\n\n\t\t\tps3.setLong(1, generatedKey);\n\t\t\tdata[0] = ps3.executeQuery();\n\n\t\t\tPreparedStatement ps2 =\n\t\t\t\tconn.prepareStatement(\"insert into tig_nodes (parent_nid, uid, node) values (NULL, ?, 'root')\");\n\n\t\t\tps2.setLong(1, generatedKey);\n\t\t\tps2.executeUpdate();\n\n\t\t\tif (null == userPw) {\n\t\t\t\tPreparedStatement ps4 =\n\t\t\t\t\t\tconn.prepareStatement(\"update tig_users set account_status = -1 where uid = ?\");\n\n\t\t\t\tps4.setLong(1, generatedKey);\n\t\t\t\tps4.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigAddUserPlainPw(String userId, String userPw, ResultSet[] data)\n\t\t\tthrows SQLException {\n\t\tString encMethod = tigGetDBProperty(\"password-encoding\");\n\t\tString encp = encodePassword(encMethod, userId, userPw);\n\n\t\ttigAddUser(userId, encp, data);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigAllUsers(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id, last_login, last_logout, online_status, failed_logins, account_status from tig_users\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigAllUsersCount(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps = conn.prepareStatement(\"select count(*) as res_cnt from tig_users\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigDisableAccount(final String userId) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"update tig_users set account_status = 0 where lower(user_id) = ?\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigDisabledAccounts(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id, last_login, last_logout, online_status, failed_logins, account_status from tig_users where account_status = 0\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigEnableAccount(final String userId) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"update tig_users set account_status = 1 where lower(user_id) = ?\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t *\n\t * \n\t *\n\t * @throws SQLException\n\t */\n\tpublic static String tigGetDBProperty(final String key) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tString result = null;\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"function tigGetDBProperty('\" + key + \"') called\");\n\t\t\t}\n\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select pval from tig_pairs, tig_users where (pkey = ?) AND (user_id = 'db-properties') AND (tig_pairs.uid = tig_users.uid)\");\n\t\t\tResultSet rs;\n\n\t\t\tps.setString(1, key.toLowerCase());\n\t\t\trs = ps.executeQuery();\n\n\t\t\tif (rs.next()) {\n\t\t\t\tresult = rs.getString(1);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigGetPassword(String userId, ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_pw from tig_users where lower(user_id) = ?\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigGetUserDBUid(String userId, ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps = conn.prepareStatement(\"select uid from tig_users where lower(user_id) = ?\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigInitdb() throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps = conn.prepareStatement(\"update tig_users set online_status = 0\");\n\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigOfflineUsers(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id, last_login, last_logout, online_status, failed_logins, account_status from tig_users where online_status = 0\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigOnlineUsers(ResultSet[] data) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id, last_login, last_logout, online_status, failed_logins, account_status from tig_users where online_status > 0\");\n\n\t\t\tdata[0] = ps.executeQuery();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t * @param value\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigPutDBProperty(final String key, final String value) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"procedure tigPutDBProperty('\" + key + \"', '\" + value + \"') called\");\n\t\t\t}\n\n\t\t\tint result;\n\n\t\t\tif (tigGetDBProperty(key) != null) {\n\t\t\t\tPreparedStatement ps =\n\t\t\t\t\tconn.prepareStatement(\"update tig_pairs set tig_pairs.pval = ? where (pkey = ?) and uid = (select uid from tig_users where tig_users.user_id = 'db-properties')\");\n\n\t\t\t\tps.setString(1, value);\n\t\t\t\tps.setString(2, key);\n\t\t\t\tresult = ps.executeUpdate();\n\t\t\t} else {\n\t\t\t\tPreparedStatement ps =\n\t\t\t\t\tconn.prepareStatement(\"insert into tig_pairs (pkey, pval, uid, nid) select ?, ?, tu.uid, tn.nid from tig_users tu left join tig_nodes tn on tn.uid=tu.uid where (user_id = 'db-properties' and tn.node='root' ) \");\n\n\t\t\t\tps.setString(1, key);\n\t\t\t\tClob c = conn.createClob();\n\t\t\t\tc.setString( 1, value);\n\t\t\t\tps.setClob( 2, c);\n//\t\t\t\tps.setString(2, value);\n\t\t\t\tresult = ps.executeUpdate();\n\t\t\t}\n\n\t\t\tif (result != 1) {\n\t\t\t\tlog.severe(\"Error on put properties\");\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigRemoveUser(final String userId) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps3 = conn.prepareStatement(\"select uid from tig_users where lower(user_id) = ?\");\n\n\t\t\tps3.setString(1, userId.toLowerCase());\n\n\t\t\tResultSet rs = ps3.executeQuery();\n\n\t\t\trs.next();\n\n\t\t\tlong uid = rs.getLong(1);\n\t\t\tPreparedStatement ps1 = conn.prepareStatement(\"delete from tig_pairs where uid = ?\");\n\n\t\t\tps1.setLong(1, uid);\n\t\t\tps1.executeUpdate();\n\n\t\t\tPreparedStatement ps2 = conn.prepareStatement(\"delete from tig_nodes where uid = ?\");\n\n\t\t\tps2.setLong(1, uid);\n\t\t\tps2.executeUpdate();\n\n\t\t\tPreparedStatement ps = conn.prepareStatement(\"delete from tig_users where uid = ?\");\n\n\t\t\tps.setLong(1, uid);\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n        /**\n         *\n         * @param nid\n         * @param uid\n         * @param key\n         * @param value\n         * @throws SQLException\n         */\n        public static void tigUpdatePairs(long nid, long uid, String key, Clob value) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps = conn.prepareStatement(\"select 1 from tig_pairs where nid = ? and uid = ? and pkey = ?\");\n\n                        ps.setLong(1, nid);\n                        ps.setLong(2, uid);\n                        ps.setString(3, key);\n\n                        ResultSet rs = ps.executeQuery();\n                        if (rs.next()) {\n                                PreparedStatement ps1 = conn.prepareStatement(\"update tig_pairs set pval = ? where nid = ? and uid = ? and pkey = ?\");\n\n                                ps1.setClob(1, value);\n                                ps1.setLong(2, nid);\n                                ps1.setLong(3, uid);\n                                ps1.setString(4, key);\n\n                                ps1.executeUpdate();\n                        }\n                        else {\n                                PreparedStatement ps1 = conn.prepareStatement(\"insert into tig_pairs (nid, uid, pkey, pval) values (?, ?, ?, ?)\");\n\n                                ps1.setLong(1, nid);\n                                ps1.setLong(2, uid);\n                                ps1.setString(3, key);\n                                ps1.setClob(4, value);\n\n                                ps1.executeUpdate();\n                        }\n\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n        }\n\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUpdatePassword(String userId, String userPw) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"update tig_users set user_pw = ? where lower(user_id) = ?\");\n\n\t\t\tps.setString(1, userPw);\n\t\t\tps.setString(2, userId.toLowerCase());\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUpdatePasswordPlainPw(String userId, String userPw) throws SQLException {\n\t\tString encMethod = tigGetDBProperty(\"password-encoding\");\n\t\tString encp = encodePassword(encMethod, userId, userPw);\n\n\t\ttigUpdatePassword(userId, encp);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userPw\n\t * @param userId\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUpdatePasswordPlainPwRev(String userPw, String userId) throws SQLException {\n\t\ttigUpdatePasswordPlainPw(userId, userPw);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUserLogin(String userId, String userPw, ResultSet[] data)\n\t\t\tthrows SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"select user_id from tig_users where (account_status > 0) AND ( lower(user_id) = ?) AND (user_pw = ?)\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tps.setString(2, userPw);\n\n\t\t\tResultSet rs = ps.executeQuery();\n\n\t\t\tif (rs.next()) {\n\t\t\t\tPreparedStatement x = conn.prepareStatement(\"values '\" + userId + \"'\");\n\n\t\t\t\tdata[0] = x.executeQuery();\n\n\t\t\t\tPreparedStatement flps =\n\t\t\t\t\tconn.prepareStatement(\"update tig_users set online_status = online_status + 1, last_login = current timestamp where lower(user_id) =  ?\");\n\n\t\t\t\tflps.setString(1, userId.toLowerCase());\n\t\t\t\tflps.executeUpdate();\n\t\t\t} else {\n\t\t\t\tPreparedStatement x = conn.prepareStatement(\"values '-'\");\n\n\t\t\t\tdata[0] = x.executeQuery();\n\n\t\t\t\tPreparedStatement flps =\n\t\t\t\t\tconn.prepareStatement(\"update tig_users set failed_logins = failed_logins + 1 where lower(user_id) = ?\");\n\n\t\t\t\tflps.setString(1, userId.toLowerCase());\n\t\t\t\tflps.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param userPw\n\t * @param data\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUserLoginPlainPw(String userId, String userPw, ResultSet[] data)\n\t\t\tthrows SQLException {\n\t\tString encMethod = tigGetDBProperty(\"password-encoding\");\n\t\tString encp = encodePassword(encMethod, userId, userPw);\n\n\t\ttigUserLogin(userId, encp, data);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t *\n\t * @throws SQLException\n\t */\n\tpublic static void tigUserLogout(final String userId) throws SQLException {\n\t\tConnection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n\t\tconn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n\n\t\ttry {\n\t\t\tPreparedStatement ps =\n\t\t\t\tconn.prepareStatement(\"update tig_users set online_status = online_status - 1, last_logout = current timestamp where lower(user_id) =  ?\");\n\n\t\t\tps.setString(1, userId.toLowerCase());\n\t\t\tps.executeUpdate();\n\t\t} catch (SQLException e) {\n\n\t\t\t// e.printStackTrace();\n\t\t\t// log.log(Level.SEVERE, \"SP error\", e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tconn.close();\n\t\t}\n\t}\n\n\tprivate static String encodePassword(String encMethod, String userId, String userPw) {\n\t\tif ((encMethod != null) && \"MD5-PASSWORD\".equals(encMethod)) {\n\t\t\treturn md5(userPw);\n\t\t} else if ((encMethod != null) && \"MD5-USERID-PASSWORD\".equals(encMethod)) {\n\t\t\treturn md5(userId + userPw);\n\t\t} else if ((encMethod != null) && \"MD5-USERNAME-PASSWORD\".equals(encMethod)) {\n\t\t\treturn md5(userId.substring(0, userId.indexOf(\"@\")) + userPw);\n\t\t} else {\n\t\t\treturn userPw;\n\t\t}\n\n\t}\n\n\tprivate static String md5(String data) {\n\t\ttry {\n\t\t\tMessageDigest md = MessageDigest.getInstance(\"MD5\");\n\n\t\t\tif (data != null) {\n\t\t\t\tmd.update(data.getBytes());\n\t\t\t}\n\n\t\t\tbyte[] digest = md.digest();\n\n\t\t\treturn Algorithms.bytesToHex(digest);\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(\"Error on encoding password\", e);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/DataRepositoryImpl.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db.jdbc;\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.Repository;\nimport tigase.stats.CounterValue;\nimport tigase.stats.StatisticsProviderIfc;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.BareJID;\n\nimport java.sql.*;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Sep 3, 2010 5:55:41 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Repository.Meta( isDefault=true, supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class DataRepositoryImpl implements DataRepository, StatisticsProviderIfc {\n\tprivate static final Logger log = Logger.getLogger(DataRepositoryImpl.class.getName());\n\n\t/** Field description */\n\tpublic static final String DERBY_CONNVALID_QUERY = \"values 1\";\n\n\t/** Field description */\n\tpublic static final String JDBC_CONNVALID_QUERY = \"select 1\";\n\n\t/** Field description */\n\tpublic static final String MYSQL_CHECK_TABLE_QUERY =\n\t\t\t\"select * from information_schema.tables where table_name = ? and table_schema = ?\";\n\n\t/** Field description */\n\tpublic static final String PGSQL_CHECK_TABLE_QUERY =\n\t\t\t\"select * from pg_tables where tablename = ? and schemaname = ?\";\n\n\t/** Field description */\n\tpublic static final String DERBY_CHECK_TABLE_QUERY =\n\t\t\t\"select * from SYS.SYSTABLES where tablename = UPPER(?) and ? is not null\";\n\n\t/** Field description */\n\tpublic static final String SQLSERVER_CHECK_TABLE_QUERY =\n\t\t\t\"SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE' AND  TABLE_NAME = ? and TABLE_SCHEMA = ?\";\n\n\t/** Field description */\n\tpublic static final String OTHER_CHECK_TABLE_QUERY = \"\";\n\n\t/** Field description */\n\tpublic static final String SP_STARTS_WITH = \"{ call\";\n\n\tpublic static final String QUERY_TIMEOUT_PROP_KEY = \"sql-query-timeout\";\n\t/** Field description */\n\tpublic static final int QUERY_TIMEOUT = 10;\n\n\tpublic static final String DB_CONN_TIMEOUT_PROP_KEY = \"db-conn-timeout\";\n\t/** Field description */\n\tpublic static final int DB_CONN_TIMEOUT = 15;\n\n\tprivate dbTypes database = null;\n\n\tprivate Connection conn = null;\n\tprivate PreparedStatement conn_valid_st = null;\n\tprivate long connectionValidateInterval = 1000 * 60;\n\tprivate String db_conn = null;\n\tprivate long lastConnectionValidated = 0;\n\tprivate boolean derby_mode = false;\n\tprivate Map<String, PreparedStatement> db_statements =\n\t\t\tnew ConcurrentSkipListMap<String, PreparedStatement>();\n\tprivate Map<String, DBQuery> db_queries = new ConcurrentSkipListMap<String, DBQuery>();\n\tprivate String check_table_query = OTHER_CHECK_TABLE_QUERY;\n\tprivate String table_schema = null;\n\tprivate int query_timeout = QUERY_TIMEOUT;\n\tprivate int db_conn_timeout = DB_CONN_TIMEOUT;\n\n\tprivate CounterValue reconnectionCounter = null;\n\tprivate CounterValue reconnectionFailedCounter = null;\n\n\t@Override\n\tpublic boolean checkTable(String tableName) throws SQLException {\n\t\tPreparedStatement checkTableSt = getPreparedStatement(null, check_table_query);\n\n\t\tif (checkTableSt == null) {\n\t\t\treturn true;\n\t\t}\n\n\t\tboolean result = false;\n\t\tResultSet rs = null;\n\n\t\tsynchronized (checkTableSt) {\n\t\t\ttry {\n\t\t\t\tcheckTableSt.setString(1, tableName);\n\t\t\t\tcheckTableSt.setString(2, table_schema);\n\t\t\t\trs = checkTableSt.executeQuery();\n\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\trelease(null, rs);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean checkTable(String tableName, String createTableQuery)\n\t\t\tthrows SQLException {\n\t\tResultSet rs = null;\n\t\tStatement st = null;\n\t\tboolean result = false;\n\n\t\ttry {\n\t\t\tlog.log(Level.INFO, \"Checking if table {0} exists in DB {1}.\", new Object[] {\n\t\t\t\t\ttableName, table_schema });\n\t\t\tif (!checkTable(tableName)) {\n\t\t\t\tlog.log(Level.INFO, \"Table {0} not found in database, creating: {1}\",\n\t\t\t\t\t\tnew Object[] { tableName, createTableQuery });\n\t\t\t\tst = createStatement(null);\n\t\t\t\tif (!db_conn.contains(\"derby\")) {\n\t\t\t\t\tst.executeUpdate(createTableQuery);\n\t\t\t\t} else {\n\t\t\t\t\tString[] queries = createTableQuery.split(\";\");\n\t\t\t\t\tfor (String query : queries) {\n\t\t\t\t\t\tquery = query.trim();\n\t\t\t\t\t\tif (query.isEmpty())\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tst.executeUpdate(query);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = true;\n\t\t\t} else {\n\t\t\t\tlog.log(Level.INFO, \"OK table {0} found in database.\", tableName);\n\t\t\t}\n\t\t} finally {\n\t\t\trelease(st, rs);\n\t\t\trs = null;\n\t\t\tst = null;\n\n\t\t\t// stmt = null;\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic Statement createStatement(BareJID user_id) throws SQLException {\n\t\tcheckConnection();\n\t\t// This synchronization is used to prevent call when the connection and\n\t\t// all prepared statements are being recreated.\n\t\tsynchronized (db_statements) {\n\t\t\treturn conn.createStatement();\n\t\t}\n\t}\n\n\t@Override\n\tpublic PreparedStatement getPreparedStatement(BareJID user_id, String stIdKey)\n\t\t\tthrows SQLException {\n\t\tcheckConnection();\n\n\t\t// This synchronization is used to prevent call when the connection and\n\t\t// all prepared statements are being recreated.\n\t\tsynchronized (db_statements) {\n\t\t\treturn db_statements.get(stIdKey);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn db_conn;\n\t}\n\n\t@Override\n\tpublic dbTypes getDatabaseType() {\n\t\treturn database;\n\t}\n\n\t@Override\n\tpublic void initPreparedStatement(String key, String query) throws SQLException {\n\t\tdb_queries.put(key, new DBQuery(query, Statement.NO_GENERATED_KEYS));\n\t\tinitStatement(key);\n\t}\n\n\t@Override\n\tpublic void initPreparedStatement(String key, String query, int autoGeneratedKeys) throws SQLException {\n\t\tdb_queries.put(key, new DBQuery(query, autoGeneratedKeys));\n\t\tinitStatement(key);\n\t}\t\n\t\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\tString driverClass = null;\n\n\t\tif ( resource_uri.startsWith( \"jdbc:postgresql\" ) ){\n\t\t\tdatabase = dbTypes.postgresql;\n\t\t} else if ( resource_uri.startsWith( \"jdbc:mysql\" ) ){\n\t\t\tdatabase = dbTypes.mysql;\n\t\t} else if ( resource_uri.startsWith( \"jdbc:derby\" ) ){\n\t\t\tdatabase = dbTypes.derby;\n\t\t} else if ( resource_uri.startsWith( \"jdbc:jtds:sqlserver\" ) ){\n\t\t\tdatabase = dbTypes.jtds;\n\t\t} else if ( resource_uri.startsWith( \"jdbc:sqlserver\" ) ){\n\t\t\tdatabase = dbTypes.sqlserver;\n\t\t}\n\t\t\n\t\tif (database == null) {\n\t\t\tthrow new DBInitException(\"Database not supported\");\n\t\t}\n\t\t\n\t\tswitch ( database ) {\n\t\t\tcase postgresql:\n\t\t\t\tdriverClass = \"org.postgresql.Driver\";\n\t\t\t\tcheck_table_query = PGSQL_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t\tcase mysql:\n\t\t\t\tdriverClass = \"com.mysql.jdbc.Driver\";\n\t\t\t\tcheck_table_query = MYSQL_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t\tcase derby:\n\t\t\t\tdriverClass = \"org.apache.derby.jdbc.EmbeddedDriver\";\n\t\t\t\tcheck_table_query = DERBY_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t\tcase jtds:\n\t\t\t\tdriverClass = \"net.sourceforge.jtds.jdbc.Driver\";\n\t\t\t\tcheck_table_query = SQLSERVER_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t\tcase sqlserver:\n\t\t\t\tdriverClass = \"com.microsoft.sqlserver.jdbc.SQLServerDriver\";\n\t\t\t\tcheck_table_query = SQLSERVER_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdriverClass = \"net.sf.log4jdbc.sql.jdbcapi.DriverSpy\";\n\t\t\t\tcheck_table_query = OTHER_CHECK_TABLE_QUERY;\n\t\t\t\tbreak;\n\t\t}\n\n\t\ttry {\n\t\t\tClass.forName( driverClass, true, this.getClass().getClassLoader() );\n\t\t} catch ( ClassNotFoundException ex ) {\n\t\t\tLogger.getLogger( DataRepositoryImpl.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\n\t\tdb_conn = resource_uri;\n\t\tdb_conn_timeout = getParam( DB_CONN_TIMEOUT_PROP_KEY, params, DB_CONN_TIMEOUT );\n\t\tquery_timeout = getParam( QUERY_TIMEOUT_PROP_KEY, params, QUERY_TIMEOUT );\n\n\t\tif ( db_conn != null ){\n\n\t\t\tswitch ( database ) {\n\t\t\t\tcase jtds:\n\t\t\t\tcase sqlserver:\n\t\t\t\t\ttable_schema = \"dbo\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase postgresql:\n\t\t\t\t\ttable_schema = \"public\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tString[] slashes = db_conn.split( \"/\" );\n\t\t\t\t\ttable_schema = slashes[slashes.length - 1].split( \"\\\\?\" )[0];\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlog.log( Level.INFO, \"Table schema found: {0}, database type: {1}, database driver: {2}\",\n\t\t\t\t\t\t\t new Object[] { table_schema, database.toString(), driverClass } );\n\t\t}\n\t\ttry {\n\t\t\treconnectionCounter = new CounterValue(\"repository \" + getResourceUri() + \" reconnections\", Level.FINER);\n\t\t\treconnectionFailedCounter = new CounterValue(\"repository \" + getResourceUri() + \" failed reconnections\", Level.FINER);\n\t\t\tinitRepo();\n\n\t\t\tif (!check_table_query.isEmpty()) {\n\t\t\t\tinitPreparedStatement(check_table_query, check_table_query);\n\t\t\t}\n\t\t} catch (SQLException ex) {\n\t\t\tthrow new DBInitException(\"Database initialization failed\", ex);\n\t\t}\n\n\t\tlog.log(Level.INFO, \"Initialized database connection: {0}\", resource_uri);\n\t}\n\n\tprotected int getParam(String key, Map<String, String> params, int def) {\n\t\tint result = def;\n\t\tString temp = System.getProperty(key);\n\t\tif (temp != null) {\n\t\t\ttry {\n\t\t\t\tresult = Integer.parseInt(temp);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\tresult = def;\n\t\t\t}\n\t\t}\n\t\tif (params != null) {\n\t\t\ttemp = params.get(key);\n\t\t\tif (temp != null) {\n\t\t\t\ttry {\n\t\t\t\t\tresult = Integer.parseInt(temp);\n\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\tresult = def;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void release(Statement stmt, ResultSet rs) {\n\t\tif (rs != null) {\n\t\t\ttry {\n\t\t\t\trs.close();\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t}\n\t\t}\n\n\t\tif (stmt != null) {\n\t\t\ttry {\n\t\t\t\tstmt.close();\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * <code>checkConnection</code> method checks database connection before any\n\t * query. For some database servers (or JDBC drivers) it happens the\n\t * connection is dropped if not in use for a long time or after certain\n\t * timeout passes. This method allows us to detect the problem and\n\t * reinitialize database connection. This method must not be called\n\t * concurrently, therefore it is synchronized.\n\t * \n\t * @return a <code>boolean</code> value if the database connection is working.\n\t * @exception SQLException\n\t *              if an error occurs on database query.\n\t */\n\tprivate synchronized boolean checkConnection() throws SQLException {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tlong tmp = System.currentTimeMillis();\n\n\t\t\t// synchronized (conn_valid_st) {\n\t\t\tif ((tmp - lastConnectionValidated) >= connectionValidateInterval) {\n\t\t\t\tlastConnectionValidated = tmp;\n\t\t\t\trs = conn_valid_st.executeQuery();\n\t\t\t} // end of if ()\n\t\t\t// }\n\n\t\t\tif (((conn_valid_st == null) || conn_valid_st.isClosed())\n\t\t\t\t\t&& ((tmp - lastConnectionValidated) >= 1000)) {\n\t\t\t\tinitRepo();\n\t\t\t} // end of if ()\n\t\t} catch (Exception e) {\n\t\t\tinitRepo();\n\t\t} finally {\n\t\t\trelease(null, rs);\n\t\t} // end of try-catch\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * <code>initPreparedStatements</code> method initializes internal database\n\t * connection variables such as prepared statements.\n\t * \n\t * @exception SQLException\n\t *              if an error occurs on database query.\n\t */\n\tprivate void initPreparedStatements() throws SQLException {\n\t\tString query = (derby_mode ? DERBY_CONNVALID_QUERY : JDBC_CONNVALID_QUERY);\n\n\t\tconn_valid_st = prepareQuery(query, Statement.NO_GENERATED_KEYS);\n\t\ttry {\n\t\t\tconn_valid_st.setQueryTimeout(query_timeout);\n\t\t} catch (SQLException ex) {\n\t\t\t// Ignore for now, it seems that PostgreSQL does not support this method\n\t\t\t// call yet\n\t\t}\n\n\t\tfor (String key : db_queries.keySet()) {\n\t\t\tinitStatement(key);\n\t\t}\n\t}\n\n\tprivate void initStatement(String key) throws SQLException {\n\t\tDBQuery dbQuery = db_queries.get(key);\n\n\t\tPreparedStatement st = prepareQuery(dbQuery.query, dbQuery.autoGeneratedKeys);\n\n\t\ttry {\n\t\t\tst.setQueryTimeout(query_timeout);\n\t\t} catch (SQLException ex) {\n\t\t\t// Ignore for now, it seems that PostgreSQL does not support this method\n\t\t\t// call yet\n\t\t}\n\t\tdb_statements.put(key, st);\n\t}\n\n\t/**\n\t * <code>initRepo</code> method initializes database connection and data\n\t * repository.\n\t * \n\t * @exception SQLException\n\t *              if an error occurs on database query.\n\t */\n\tprivate void initRepo() throws SQLException {\n\n\t\t// Statement stmt = null;\n//\t\tResultSet rs = null;\n\n\t\tboolean failure = true;\n\t\ttry {\n\t\t\tif (conn != null) {\n\t\t\t\treconnectionCounter.inc();\n\t\t\t}\n\t\t\tsynchronized (db_statements) {\n\t\t\t\tdb_statements.clear();\n\t\t\t\tDriverManager.setLoginTimeout(db_conn_timeout);\n\t\t\t\tconn = DriverManager.getConnection(db_conn);\n\t\t\t\tconn.setAutoCommit(true);\n\t\t\t\tderby_mode = db_conn.startsWith(\"jdbc:derby\");\n\t\t\t\tinitPreparedStatements();\n\n\t\t\t\tfailure = false;\n\t\t\t\t// stmt = conn.createStatement();\n\t\t\t}\n\t\t} finally {\n\t\t\trelease(null, null);\n\n\t\t\tif (failure) {\n\t\t\t\treconnectionFailedCounter.inc();\n\t\t\t}\n\t\t\t// release(stmt, rs);\n\t\t\t// stmt = null;\n//\t\t\trs = null;\n\t\t}\n\t}\n\n\tprivate PreparedStatement prepareQuery(String query, int autoGeneratedKeys) throws SQLException {\n\t\tif (query.startsWith(SP_STARTS_WITH)) {\n\t\t\treturn conn.prepareCall( query );\n\t\t} else {\n\t\t\tswitch ( database ) {\n\t\t\t\tcase sqlserver:\n\t\t\t\t\treturn conn.prepareStatement( query, Statement.RETURN_GENERATED_KEYS );\n\t\t\t\tdefault:\n\t\t\t\t\treturn conn.prepareStatement( query, autoGeneratedKeys );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic DataRepository takeRepoHandle(BareJID user_id) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void startTransaction() throws SQLException {\n\t\tconn.setAutoCommit(false);\n\t}\n\n\t@Override\n\tpublic void commit() throws SQLException {\n\t\tconn.commit();\n\t}\n\n\t@Override\n\tpublic void rollback() throws SQLException {\n\t\tconn.rollback();\n\t}\n\n\t@Override\n\tpublic void endTransaction() throws SQLException {\n\t\tconn.setAutoCommit(true);\n\t}\n\n\t@Override\n\tpublic void releaseRepoHandle(DataRepository repo) {\n\t}\n\n\t@Override\n\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\tlong reconnections = list.getValue(compName, reconnectionCounter.getName(), 0L) + reconnectionCounter.getValue();\n\t\tlist.add(compName, reconnectionCounter.getName(), reconnections, Level.FINER);\n\t\tlong failedReconnections = list.getValue(compName, reconnectionFailedCounter.getName(), 0L) + reconnectionFailedCounter.getValue();\n\t\tlist.add(compName, reconnectionFailedCounter.getName(),failedReconnections, Level.FINER);\n\t}\n\t\n\tprivate class DBQuery {\n\t\tfinal String query;\n\t\tfinal int autoGeneratedKeys;\n\t\t\n\t\tDBQuery(String query, int autoGeneratedKeys) {\n\t\t\tthis.query = query;\n\t\t\tthis.autoGeneratedKeys = autoGeneratedKeys;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/DrupalWPAuth.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db.jdbc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.security.NoSuchAlgorithmException;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.RealmCallback;\nimport javax.security.sasl.Sasl;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\nimport tigase.db.AuthRepository;\nimport tigase.db.AuthorizationException;\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.Repository.Meta;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\nimport tigase.util.Algorithms;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\n//~--- JDK imports ------------------------------------------------------------\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class DrupalWPAuth here.\n *\n *\n * Created: Sat Nov 11 22:22:04 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Meta( supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class DrupalWPAuth implements AuthRepository {\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(DrupalWPAuth.class.getName());\n\tprivate static final String[] non_sasl_mechs = { \"password\" };\n\tprivate static final String[] sasl_mechs = { \"PLAIN\" };\n\n\t/** Field description */\n\tpublic static final String DRUPAL_USERS_TBL = \"users\";\n\n\t/** Field description */\n\tpublic static final String DRUPAL_NAME_FLD = \"name\";\n\n\t/** Field description */\n\tpublic static final String DRUPAL_PASS_FLD = \"pass\";\n\n\t/** Field description */\n\tpublic static final String DRUPAL_STATUS_FLD = \"status\";\n\n\t/** Field description */\n\tpublic static final int DRUPAL_OK_STATUS_VAL = 1;\n\n\t/** Field description */\n\tpublic static final String WP_USERS_TBL = \"wp_users\";\n\n\t/** Field description */\n\tpublic static final String WP_NAME_FLD = \"user_login\";\n\n\t/** Field description */\n\tpublic static final String WP_PASS_FLD = \"user_pass\";\n\n\t/** Field description */\n\tpublic static final String WP_STATUS_FLD = \"user_status\";\n\n\t/** Field description */\n\tpublic static final int WP_OK_STATUS_VAL = 0;\n\tprivate static final String SELECT_PASSWORD_QUERY_KEY = \"select-password-drupal-wp-query-key\";\n\tprivate static final String SELECT_STATUS_QUERY_KEY = \"select-status-drupal-wp-query-key\";\n\tprivate static final String INSERT_USER_QUERY_KEY = \"insert-user-drupal-wp-query-key\";\n\tprivate static final String UPDATE_LAST_LOGIN_QUERY_KEY = \"update-last-login-drupal-wp-query-key\";\n\tprivate static final String UPDATE_ONLINE_STATUS_QUERY_KEY =\n\t\t\"update-online-status-drupal-wp-query-key\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\tprivate String name_fld = DRUPAL_NAME_FLD;\n\tprivate String users_tbl = DRUPAL_USERS_TBL;\n\tprivate int status_val = DRUPAL_OK_STATUS_VAL;\n\tprivate String status_fld = DRUPAL_STATUS_FLD;\n\tprivate String pass_fld = DRUPAL_PASS_FLD;\n\tprivate boolean online_status = false;\n\tprivate boolean last_login = true;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addUser(BareJID user, final String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\ttry {\n\t\t\tPreparedStatement user_add_st = data_repo.getPreparedStatement(user, INSERT_USER_QUERY_KEY);\n\n\t\t\tsynchronized (user_add_st) {\n\t\t\t\tuser_add_st.setString(1, user.getLocalpart());\n\t\t\t\tuser_add_st.setString(2, Algorithms.hexDigest(\"\", password, \"MD5\"));\n\t\t\t\tuser_add_st.executeUpdate();\n\t\t\t}\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tthrow new TigaseDBException(\"Password encoding algorithm is not supported.\", e);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new UserExistsException(\"Error while adding user to repository, user exists?\", e);\n\t\t}\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, final String digest, final String id, final String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tthrow new AuthorizationException(\"Not supported.\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn data_repo.getResourceUri();\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\treturn -1;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(final String connection_str, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, connection_str, params);\n\n\t\t\tif (connection_str.contains(\"online_status=true\")) {\n\t\t\t\tonline_status = true;\n\t\t\t}\n\n\t\t\tif (connection_str.contains(\"wp_mode=true\")) {\n\t\t\t\tonline_status = false;\n\t\t\t\tlast_login = false;\n\t\t\t\tname_fld = WP_NAME_FLD;\n\t\t\t\tusers_tbl = WP_USERS_TBL;\n\t\t\t\tstatus_val = WP_OK_STATUS_VAL;\n\t\t\t\tstatus_fld = WP_STATUS_FLD;\n\t\t\t\tpass_fld = WP_PASS_FLD;\n\t\t\t\tlog.log(Level.INFO, \"Initializing Wordpress repository: {0}\", connection_str);\n\t\t\t} else {\n\t\t\t\tlog.log(Level.INFO, \"Initializing Drupal repository: {0}\", connection_str);\n\t\t\t}\n\n\t\t\tString query = \"select \" + pass_fld + \" from \" + users_tbl + \" where \" + name_fld + \" = ?\";\n\n\t\t\tdata_repo.initPreparedStatement(SELECT_PASSWORD_QUERY_KEY, query);\n\t\t\tquery = \"select \" + status_fld + \" from \" + users_tbl + \" where \" + name_fld + \" = ?\";\n\t\t\tdata_repo.initPreparedStatement(SELECT_STATUS_QUERY_KEY, query);\n\t\t\tquery = \"insert into \" + users_tbl + \" (\" + name_fld + \", \" + pass_fld + \", \" + status_fld\n\t\t\t\t\t+ \")\" + \" values (?, ?, \" + status_val + \")\";\n\t\t\tdata_repo.initPreparedStatement(INSERT_USER_QUERY_KEY, query);\n\t\t\tquery = \"update \" + users_tbl + \" set access=?, login=? where \" + name_fld + \" = ?\";\n\t\t\tdata_repo.initPreparedStatement(UPDATE_LAST_LOGIN_QUERY_KEY, query);\n\t\t\tquery = \"update \" + users_tbl + \" set online_status=online_status+? where \" + name_fld\n\t\t\t\t\t+ \" = ?\";\n\t\t\tdata_repo.initPreparedStatement(UPDATE_ONLINE_STATUS_QUERY_KEY, query);\n\t\t} catch (Exception e) {\n\t\t\tdata_repo = null;\n\n\t\t\tthrow new DBInitException(\"Problem initializing jdbc connection: \" + connection_str, e);\n\t\t}\n\n\t\ttry {\n\t\t\tif (online_status) {\n\t\t\t\tStatement stmt = data_repo.createStatement(null);\n\n\t\t\t\tstmt.executeUpdate(\"update users set online_status = 0;\");\n\t\t\t\tstmt.close();\n\t\t\t\tstmt = null;\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tif (e.getMessage().contains(\"'online_status'\")) {\n\t\t\t\ttry {\n\t\t\t\t\tStatement stmt = data_repo.createStatement(null);\n\n\t\t\t\t\tstmt.executeUpdate(\"alter table users add online_status int default 0;\");\n\t\t\t\t\tstmt.close();\n\t\t\t\t\tstmt = null;\n\t\t\t\t} catch (SQLException ex) {\n\t\t\t\t\tdata_repo = null;\n\n\t\t\t\t\tthrow new DBInitException(\"Problem initializing jdbc connection: \" + connection_str, ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdata_repo = null;\n\n\t\t\t\tthrow new DBInitException(\"Problem initializing jdbc connection: \" + connection_str, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tupdateOnlineStatus(user, -1);\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(final Map<String, Object> props)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tString proto = (String) props.get(PROTOCOL_KEY);\n\n\t\tif (proto.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tString mech = (String) props.get(MACHANISM_KEY);\n\n\t\t\ttry {\n\t\t\t\tif (mech.equals(\"PLAIN\")) {\n\t\t\t\t\tboolean login_ok = saslAuth(props);\n\n\t\t\t\t\tif (login_ok) {\n\t\t\t\t\t\tBareJID user = (BareJID) props.get(USER_ID_KEY);\n\n\t\t\t\t\t\t// Unfortunately, unlike with plainAuth we have to check whether the user\n\t\t\t\t\t\t// is active after successful authentication as before it is completed the\n\t\t\t\t\t\t// user id is not known\n\t\t\t\t\t\tif ( !isActive(user)) {\n\t\t\t\t\t\t\tthrow new AuthorizationException(\"User account has been blocked.\");\n\t\t\t\t\t\t}    // end of if (!isActive(user))\n\n\t\t\t\t\t\tupdateLastLogin(user);\n\t\t\t\t\t\tupdateOnlineStatus(user, 1);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"User authenticated: {0}\", user);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"User NOT authenticated\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn login_ok;\n\t\t\t\t}        // end of if (mech.equals(\"PLAIN\"))\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"OTHER authentication error: \", e);\n\t\t\t\t}\n\n\t\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t\t}          // end of try-catch\n\n\t\t\tthrow new AuthorizationException(\"Mechanism is not supported: \" + mech);\n\t\t}            // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tif (proto.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tString password = (String) props.get(PASSWORD_KEY);\n\t\t\tBareJID user_id = (BareJID) props.get(USER_ID_KEY);\n\t\t\tif (password != null) {\n\t\t\t\treturn plainAuth(user_id, password);\n\t\t\t}\n\t\t\tString digest = (String) props.get(DIGEST_KEY);\n\t\t\tif (digest != null) {\n\t\t\t\tString digest_id = (String) props.get(DIGEST_ID_KEY);\n\t\t\t\treturn digestAuth(user_id, digest, digest_id, \"SHA\");\n\t\t\t}\n\t\t} // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tthrow new AuthorizationException(\"Protocol is not supported: \" + proto);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\ttry {\n\t\t\tif ( !isActive(user)) {\n\t\t\t\tthrow new AuthorizationException(\"User account has been blocked.\");\n\t\t\t}    // end of if (!isActive(user))\n\n\t\t\tString enc_passwd = Algorithms.hexDigest(\"\", password, \"MD5\");\n\t\t\tString db_password = getPassword(user);\n\t\t\tboolean login_ok = db_password.equals(enc_passwd);\n\n\t\t\tif (login_ok) {\n\t\t\t\tupdateLastLogin(user);\n\t\t\t\tupdateOnlineStatus(user, 1);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"User authenticated: {0}\", user);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"User NOT authenticated: {0}\", user);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn login_ok;\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tthrow new AuthorizationException(\"Password encoding algorithm is not supported.\", e);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}      // end of catch\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\tpublic void queryAuth(final Map<String, Object> authProps) {\n\t\tString protocol = (String) authProps.get(PROTOCOL_KEY);\n\n\t\tif (protocol.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tauthProps.put(RESULT_KEY, non_sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\n\t\tif (protocol.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tauthProps.put(RESULT_KEY, sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Removing user is not supported.\");\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Updating user password is not supported.\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException  {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tPreparedStatement pass_st = data_repo.getPreparedStatement(user, SELECT_PASSWORD_QUERY_KEY);\n\n\t\t\tsynchronized (pass_st) {\n\t\t\t\ttry {\n\t\t\t\t\tpass_st.setString(1, user.getLocalpart());\n\t\t\t\t\trs = pass_st.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\treturn rs.getString(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user);\n\t\t\t\t\t}    // end of if (isnext) else\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem with retrieving user password.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Feature not supported\");\t\t\n\t}\n\t\n\tprivate boolean isActive(BareJID user) throws SQLException, UserNotFoundException {\n\t\tResultSet rs = null;\n\n\t\tPreparedStatement status_st = data_repo.getPreparedStatement(user, SELECT_STATUS_QUERY_KEY);\n\n\t\tsynchronized (status_st) {\n\t\t\ttry {\n\t\t\t\tstatus_st.setString(1, user.getLocalpart());\n\t\t\t\trs = status_st.executeQuery();\n\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\treturn (rs.getInt(1) == status_val);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user);\n\t\t\t\t}    // end of if (isnext) else\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate boolean saslAuth(final Map<String, Object> props) throws AuthorizationException {\n\t\ttry {\n\t\t\tSaslServer ss = (SaslServer) props.get(\"SaslServer\");\n\n\t\t\tif (ss == null) {\n\t\t\t\tMap<String, String> sasl_props = new TreeMap<String, String>();\n\n\t\t\t\tsasl_props.put(Sasl.QOP, \"auth\");\n\t\t\t\tsasl_props.put(\"password-encryption\", \"MD5\");\n\t\t\t\tss = Sasl.createSaslServer((String) props.get(MACHANISM_KEY), \"xmpp\",\n\t\t\t\t\t\t(String) props.get(SERVER_NAME_KEY), sasl_props, new SaslCallbackHandler(props));\n\t\t\t\tprops.put(\"SaslServer\", ss);\n\t\t\t}    // end of if (ss == null)\n\n\t\t\tString data_str = (String) props.get(DATA_KEY);\n\t\t\tbyte[] in_data = ((data_str != null) ? Base64.decode(data_str) : new byte[0]);\n\t\t\tbyte[] challenge = ss.evaluateResponse(in_data);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"challenge: {0}\",\n\t\t\t\t\t\t((challenge != null) ? new String(challenge) : \"null\"));\n\t\t\t}\n\n\t\t\tString challenge_str = (((challenge != null) && (challenge.length > 0))\n\t\t\t\t? Base64.encode(challenge) : null);\n\n\t\t\tprops.put(RESULT_KEY, challenge_str);\n\n\t\t\tif (ss.isComplete()) {\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}    // end of if (ss.isComplete()) else\n\t\t} catch (SaslException e) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"SASL authentication error: \", e);\n\t\t\t}\n\n\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t} catch (Exception e) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"SASL authentication error: \", e);\n\t\t\t}\n\n\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t}      // end of try-catch\n\t}\n\n\tprivate void updateLastLogin(BareJID user) throws TigaseDBException {\n\t\tif (last_login) {\n\t\t\ttry {\n\t\t\t\tPreparedStatement update_last_login_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(user, UPDATE_LAST_LOGIN_QUERY_KEY);\n\n\t\t\t\tsynchronized (update_last_login_st) {\n\t\t\t\t\tBigDecimal bd = new BigDecimal((System.currentTimeMillis() / 1000));\n\n\t\t\t\t\tupdate_last_login_st.setBigDecimal(1, bd);\n\t\t\t\t\tupdate_last_login_st.setBigDecimal(2, bd);\n\t\t\t\t\tupdate_last_login_st.setString(3, user.getLocalpart());\n\t\t\t\t\tupdate_last_login_st.executeUpdate();\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tthrow new TigaseDBException(\"Error accessing repository.\", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\tprivate void updateOnlineStatus(BareJID user, int status) throws TigaseDBException {\n\t\tif (online_status) {\n\t\t\ttry {\n\t\t\t\tPreparedStatement update_online_status =\n\t\t\t\t\tdata_repo.getPreparedStatement(user, UPDATE_ONLINE_STATUS_QUERY_KEY);\n\n\t\t\t\tsynchronized (update_online_status) {\n\t\t\t\t\tupdate_online_status.setInt(1, status);\n\t\t\t\t\tupdate_online_status.setString(2, user.getLocalpart());\n\t\t\t\t\tupdate_online_status.executeUpdate();\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tthrow new TigaseDBException(\"Error accessing repository.\", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class SaslCallbackHandler implements CallbackHandler {\n\t\tprivate Map<String, Object> options = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate SaslCallbackHandler(final Map<String, Object> options) {\n\t\t\tthis.options = options;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t// Implementation of javax.security.auth.callback.CallbackHandler\n\n\t\t@Override\n\t\tpublic void handle(final Callback[] callbacks)\n\t\t\t\tthrows IOException, UnsupportedCallbackException {\n\t\t\tBareJID jid = null;\n\n\t\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t\t}\n\n\t\t\t\tif (callbacks[i] instanceof RealmCallback) {\n\t\t\t\t\tRealmCallback rc = (RealmCallback) callbacks[i];\n\t\t\t\t\tString realm = (String) options.get(REALM_KEY);\n\n\t\t\t\t\tif (realm != null) {\n\t\t\t\t\t\trc.setText(realm);\n\t\t\t\t\t}        // end of if (realm == null)\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"RealmCallback: {0}\", realm);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (callbacks[i] instanceof NameCallback) {\n\t\t\t\t\t\tNameCallback nc = (NameCallback) callbacks[i];\n\t\t\t\t\t\tString user_name = nc.getName();\n\n\t\t\t\t\t\tif (user_name == null) {\n\t\t\t\t\t\t\tuser_name = nc.getDefaultName();\n\t\t\t\t\t\t}      // end of if (name == null)\n\n\t\t\t\t\t\tjid = BareJID.bareJIDInstanceNS(user_name, (String) options.get(REALM_KEY));\n\t\t\t\t\t\toptions.put(USER_ID_KEY, jid);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (callbacks[i] instanceof PasswordCallback) {\n\t\t\t\t\t\t\tPasswordCallback pc = (PasswordCallback) callbacks[i];\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tString passwd = getPassword(jid);\n\n\t\t\t\t\t\t\t\tpc.setPassword(passwd.toCharArray());\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"PasswordCallback: {0}\", passwd);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tthrow new IOException(\"Password retrieving problem.\", e);\n\t\t\t\t\t\t\t}    // end of try-catch\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (callbacks[i] instanceof AuthorizeCallback) {\n\t\t\t\t\t\t\t\tAuthorizeCallback authCallback = ((AuthorizeCallback) callbacks[i]);\n\t\t\t\t\t\t\t\tString authenId = authCallback.getAuthenticationID();\n\t\t\t\t\t\t\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// if (authenId.equals(authorId)) {\n\t\t\t\t\t\t\t\tauthCallback.setAuthorized(true);\n\n\t\t\t\t\t\t\t\t// }    // end of if (authenId.equals(authorId))\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedCallbackException(callbacks[i], \"Unrecognized Callback\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}    // DrupalWPAuth\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/JDBCRepository.java",
    "content": "/*\n * JDBCRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.db.jdbc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.*;\nimport tigase.xmpp.BareJID;\nimport tigase.util.SimpleCache;\n\nimport java.sql.*;\nimport java.util.*;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Not synchronized implementation! Musn't be used by more than one thread at\n * the same time.\n * <p>\n * Thanks to Daniele for better unique IDs handling. Created: Thu Oct 26\n * 11:48:53 2006\n * </p>\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @author <a href=\"mailto:piras@tiscali.com\">Daniele</a>\n * @version $Rev$\n */\n@Repository.Meta( supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class JDBCRepository\n\t\t\t\timplements AuthRepository, UserRepository {\n\t/** Field description */\n\tpublic static final String CURRENT_DB_SCHEMA_VER = \"7.1\";\n\n\t/** Field description */\n\tpublic static final String DEF_MAXIDS_TBL = \"tig_max_ids\";\n\n\t/** Field description */\n\tpublic static final String DEF_NODES_TBL = \"tig_nodes\";\n\n\t/** Field description */\n\tpublic static final String DEF_PAIRS_TBL = \"tig_pairs\";\n\n\t/** Field description */\n\tpublic static final String DEF_ROOT_NODE = \"root\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERS_TBL = \"tig_users\";\n\n\t/** Field description */\n\tpublic static final String DERBY_GETSCHEMAVER_QUERY =\n\t\t\"values TigGetDBProperty('schema-version')\";\n\n\t/** Stored procedure used to check version of the schema\n\t * \n\t * neither MS SQL Server JDBC driver supports default\n\t * schema prefix in connection string for stored functions\n\t */\n\tpublic static final String SQLSERVER_GETSCHEMAVER_QUERY =\n\t\t\"select dbo.TigGetDBProperty('schema-version')\";\n\n\t/** Field description */\n\tpublic static final String JDBC_GETSCHEMAVER_QUERY =\n\t\t\"select TigGetDBProperty('schema-version')\";\n\n\t/** Field description */\n\tpublic static final String SCHEMA_UPGRADE_LINK =\n\t\t\"Administration Guide > Tigase Server Schema v7.1 Updates (available locally in docs directory and online http://docs.tigase.org)\";\n\tprivate static final String ADD_NODE_QUERY          = \"{ call TigAddNode(?, ?, ?) }\";\n\tprivate static final String ADD_USER_PLAIN_PW_QUERY =\n\t\t\"{ call TigAddUserPlainPw(?, ?) }\";\n\tprivate static final String COUNT_USERS_FOR_DOMAIN_QUERY =\n\t\t\"select count(*) from tig_users where user_id like ?\";\n\tprivate static final String DEF_GET_USERS_QUERY   = \"{ call TigAllUsers() }\";\n\tprivate static final String GET_USER_DB_UID_QUERY = \"{ call TigGetUserDBUid(?) }\";\n\tprivate static final String GET_USERS_COUNT_QUERY = \"{ call TigAllUsersCount() }\";\n\tprivate static final Logger log                   =\n\t\tLogger.getLogger(JDBCRepository.class.getName());\n\tprivate static final String PGSQL_GET_USERS_QUERY = \"select TigAllUsers()\";\n\tprivate static final String REMOVE_USER_QUERY     = \"{ call TigRemoveUser(?) }\";\n\tprivate static final String UPDATE_PAIRS_QUERY    =\n\t\t\"{ call TigUpdatePairs(?, ?, ?, ?) }\";\n\tprivate static final String USER_STR              = \"User: \";\n\tprivate static final String REMOVE_KEY_DATA_QUERY = \"delete from \" + DEF_PAIRS_TBL +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\" where (nid = ?) AND (pkey = ?)\";\n\tprivate static final String NODES_FOR_NODE_QUERY = \"select nid, node from \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t DEF_NODES_TBL +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" where parent_nid = ?\";\n\tprivate static final String KEYS_FOR_NODE_QUERY = \"select pkey from \" + DEF_PAIRS_TBL +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\" where (nid = ?)\";\n\tprivate static final String INSERT_KEY_VAL_QUERY = \"insert into \" + DEF_PAIRS_TBL +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" (nid, uid, pkey, pval) \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" values (?, ?, ?, ?)\";\n\tprivate static final String DATA_FOR_NODE_QUERY = \"select pval from \" + DEF_PAIRS_TBL +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\" where (nid = ?) AND (pkey = ?)\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate AuthRepository auth = null;\n\n\t// Cache moved to connection pool\n\tprivate Map<String, Object> cache = null;\n\tprivate DataRepository data_repo  = null;\n\tprivate String get_users_query    = null;\n\tprivate boolean autoCreateUser    = false;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// ~--- methods --------------------------------------------------------------\n\tprivate void addDataList(DataRepository repo, BareJID user_id, final String subnode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t final String key, final String[] list)\n\t\t\t\t\tthrows UserNotFoundException, SQLException, UserNotFoundException {\n\t\tlong uid = -2;\n\t\tlong nid = -2;\n\n\t\ttry {\n\n\t\t\t// OK\n\t\t\tuid = getUserUID(repo, user_id, autoCreateUser);\n\n\t\t\t// OK\n\t\t\tnid = getNodeNID(repo, uid, subnode);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Saving data adding data list, user_id: {0}, subnode: {1}, key: {2}, \" +\n\t\t\t\t\t\t\t\t\"uid: {3}, nid: {4}, list: {5}\", new Object[] {\n\t\t\t\t\tuser_id, subnode, key, uid, nid, Arrays.toString(list)\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (nid < 0) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// OK\n\t\t\t\t\tnid = createNodePath(repo, user_id, subnode);\n\t\t\t\t} catch (SQLException e) {\n\n\t\t\t\t\t// This may happen in cluster node, when 2 nodes at the same\n\t\t\t\t\t// time write data to the same location, like offline messages....\n\t\t\t\t\t// Let's try to get the nid again.\n\t\t\t\t\t// OK\n\t\t\t\t\tnid = getNodeNID(repo, uid, subnode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPreparedStatement insert_key_val_st = null;\n\n\t\t\tif (repo == null) {\n\t\t\t\tinsert_key_val_st = data_repo.getPreparedStatement(user_id, INSERT_KEY_VAL_QUERY);\n\t\t\t} else {\n\t\t\t\tinsert_key_val_st = repo.getPreparedStatement(user_id, INSERT_KEY_VAL_QUERY);\n\t\t\t}\n\t\t\tsynchronized (insert_key_val_st) {\n\t\t\t\tinsert_key_val_st.setLong(1, nid);\n\t\t\t\tinsert_key_val_st.setLong(2, uid);\n\t\t\t\tinsert_key_val_st.setString(3, key);\n\t\t\t\tfor (String val : list) {\n\t\t\t\t\tinsert_key_val_st.setString(4, val);\n\t\t\t\t\tinsert_key_val_st.executeUpdate();\n\t\t\t\t}    // end of for (String val: list)\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Error adding data list, user_id: \" + user_id + \", subnode: \" + subnode +\n\t\t\t\t\t\t\t\", key: \" + key + \", uid: \" + uid + \", nid: \" + nid + \", list: \" +\n\t\t\t\t\t\t\tArrays.toString(list), e);\n\n\t\t\tthrow e;\n\t\t}\n\n\t\t// cache.put(user_id+\"/\"+subnode+\"/\"+key, list);\n\t}\n\n\t@Override\n\tpublic void addDataList(BareJID user_id, final String subnode, final String key,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] list)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\taddDataList(null, user_id, subnode, key, list);\n\t\t} catch (SQLException ex) {\n\t\t\tthrow new TigaseDBException(\"Problem adding data list to repository\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user_id) throws UserExistsException, TigaseDBException {\n\t\ttry {\n\t\t\taddUserRepo(null, user_id);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error adding user to repository: \", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user, final String password)\n\t\t\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tauth.addUser(user, password);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, final String digest, final String id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String alg)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.digestAuth(user, digest, id, alg);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getData(BareJID user_id, final String subnode, final String key,\n\t\t\t\t\t\t\t\t\t\t\t\tfinal String def)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\n\t\ttry {\n\t\t\tlong nid = getNodeNID(null, user_id, subnode);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(\n\t\t\t\t\t\tLevel.FINEST,\n\t\t\t\t\t\t\"Loading data for key: {0}, user: {1}, node: {2}, def: {3}, found nid: {4}\",\n\t\t\t\t\t\tnew Object[] { key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t user_id, subnode, def, nid });\n\t\t\t}\n\n\t\t\tif (nid > 0) {\n\t\t\t\tResultSet rs = null;\n\n\t\t\t\tPreparedStatement data_for_node_st = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\tDATA_FOR_NODE_QUERY);\n\n\t\t\t\tsynchronized (data_for_node_st) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString result = def;\n\n\t\t\t\t\t\tdata_for_node_st.setLong(1, nid);\n\t\t\t\t\t\tdata_for_node_st.setString(2, key);\n\t\t\t\t\t\trs = data_for_node_st.executeQuery();\n\t\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\t\tresult = rs.getString(1);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Found data: {0}\", result);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// cache.put(user_id+\"/\"+subnode+\"/\"+key, new String[] {result});\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn def;\n\t\t\t}    // end of if (nid > 0) else\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting user data for: \" + user_id + \"/\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsubnode + \"/\" + key, e);\n\t\t} \n\t}\n\n\t@Override\n\tpublic String getData(BareJID user_id, final String subnode, final String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getData(user_id, subnode, key, null);\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user_id, final String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getData(user_id, null, key, null);\n\t}\n\n\t@Override\n\tpublic String[] getDataList(BareJID user_id, final String subnode, final String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\n\t\t// String[] cache_res = (String[])cache.get(user_id+\"/\"+subnode+\"/\"+key);\n\t\t// if (cache_res != null) {\n\t\t// return cache_res;\n\t\t// } // end of if (result != null)\n\n\t\ttry {\n\t\t\tlong nid = getNodeNID(null, user_id, subnode);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Loading data for key: {0}, user: {1}, node: {2}, found nid: {3}\",\n\t\t\t\t\t\t\t\tnew Object[] { key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t user_id, subnode, nid });\n\t\t\t}\n\n\t\t\tif (nid > 0) {\n\t\t\t\tResultSet rs = null;\n\t\t\t\t\n\t\t\t\tPreparedStatement data_for_node_st = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\tDATA_FOR_NODE_QUERY);\n\n\t\t\t\tsynchronized (data_for_node_st) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tList<String> results = new ArrayList<String>();\n\n\t\t\t\t\t\tdata_for_node_st.setLong(1, nid);\n\t\t\t\t\t\tdata_for_node_st.setString(2, key);\n\t\t\t\t\t\trs = data_for_node_st.executeQuery();\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tresults.add(rs.getString(1));\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Found data: {0}\", rs.getString(1));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString[] result = (results.size() == 0)\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: results.toArray(new String[results.size()]);\n\n\t\t\t\t\t\t// cache.put(user_id+\"/\"+subnode+\"/\"+key, result);\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}    // end of if (nid > 0) else\t\t\t\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting data list for: \" + user_id + \"/\"\n\t\t\t\t\t+ subnode + \"/\" + key, e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user_id, final String subnode)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\n\t\ttry {\n\t\t\tlong nid = getNodeNID(null, user_id, subnode);\n\n\t\t\tif (nid > 0) {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tList<String> results               = new ArrayList<String>();\n\t\t\t\tPreparedStatement keys_for_node_st = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t KEYS_FOR_NODE_QUERY);\n\n\t\t\t\tsynchronized (keys_for_node_st) {\n\t\t\t\t\ttry {\n\t\t\t\t\tkeys_for_node_st.setLong(1, nid);\n\t\t\t\t\trs = keys_for_node_st.executeQuery();\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tresults.add(rs.getString(1));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (results.size() == 0)\n\t\t\t\t\t\t\t\t ? null\n\t\t\t\t\t\t\t\t : results.toArray(new String[results.size()]);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}    // end of if (nid > 0) else\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting subnodes list.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user_id)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getKeys(user_id, null);\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn data_repo.getResourceUri();\n\t}\n\n\tprotected DataRepository getRepository() {\n\t\treturn data_repo;\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user_id, final String subnode)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tlong nid = getNodeNID(null, user_id, subnode);\n\t\t\tif (nid > 0) {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement nodes_for_node_st = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\tNODES_FOR_NODE_QUERY);\n\n\t\t\t\tsynchronized (nodes_for_node_st) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tList<String> results = new ArrayList<String>();\n\n\t\t\t\t\t\tnodes_for_node_st.setLong(1, nid);\n\t\t\t\t\t\trs = nodes_for_node_st.executeQuery();\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tresults.add(rs.getString(2));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (results.size() == 0)\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: results.toArray(new String[results.size()]);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}    // end of if (nid > 0) else\n\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting subnodes list.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user_id)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getSubnodes(user_id, null);\n\t}\n\n\t@Override\n\tpublic long getUserUID(BareJID user_id) throws TigaseDBException {\n\t\tLong cache_res = (Long) cache.get(user_id.toString());\n\n\t\tif (cache_res != null) {\n\t\t\treturn cache_res.longValue();\n\t\t}    // end of if (result != null)\n\n\t\tlong result = -1;\n\n\t\ttry {\n\t\t\tresult = getUserUID(null, user_id);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error retrieving user UID from repository: \", e);\n\t\t}\n\t\tcache.put(user_id.toString(), Long.valueOf(result));\n\n\t\treturn result;\n\t}\n\n\tpublic long getUserUID(DataRepository repo, BareJID user_id) throws SQLException {\n\t\tlong result  = -1;\n\n\t\tResultSet rs = null;\n\t\tPreparedStatement uid_sp = null;\n\n\t\tif (repo == null) {\n\t\t\tuid_sp = data_repo.getPreparedStatement(user_id, GET_USER_DB_UID_QUERY);\n\t\t} else {\n\t\t\tuid_sp = repo.getPreparedStatement(user_id, GET_USER_DB_UID_QUERY);\n\t\t}\n\t\tsynchronized (uid_sp) {\n\t\t\ttry {\n\t\t\t\tuid_sp.setString(1, user_id.toString());\n\t\t\t\trs = uid_sp.executeQuery();\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\tresult = rs.getLong(1);\n\t\t\t\t} else {\n\t\t\t\t\tresult = -1;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic List<BareJID> getUsers() throws TigaseDBException {\n\t\tResultSet rs = null;\n\t\tList<BareJID> users = null;\n\n\t\ttry {\n\t\t\tPreparedStatement all_users_sp = data_repo.getPreparedStatement(null,\n\t\t\t\t\tget_users_query);\n\n\t\t\tsynchronized (all_users_sp) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user ids from database\n\t\t\t\t\trs = all_users_sp.executeQuery();\n\t\t\t\t\tusers = new ArrayList<BareJID>(1000);\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tusers.add(BareJID.bareJIDInstanceNS(rs.getString(1)));\n\t\t\t\t\t}    // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\t\t\t\t}\n\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t\treturn users;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tlong users = -1;\n\t\t\tPreparedStatement users_count_sp = data_repo.getPreparedStatement(null,\n\t\t\t\t\tGET_USERS_COUNT_QUERY);\n\n\t\t\tsynchronized (users_count_sp) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\trs = users_count_sp.executeQuery();\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t}    // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\n\t\t\t\t}\n\n\t\t\t\treturn users;\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new\n\t\t\t// TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tlong users = -1;\n\t\t\tPreparedStatement users_domain_count_st = data_repo.getPreparedStatement(null,\n\t\t\t\t\tCOUNT_USERS_FOR_DOMAIN_QUERY);\n\n\t\t\tsynchronized (users_domain_count_st) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\tusers_domain_count_st.setString(1, \"%@\" + domain);\n\t\t\t\t\trs = users_domain_count_st.executeQuery();\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t}    // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new\n\t\t\t// TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(final String connection_str, Map<String, String> params)\n\t\t\t\t\tthrows DBInitException {\n\t\ttry {\n\t\t\tdata_repo  = RepositoryFactory.getDataRepository(null, connection_str, params);\n\t\t\tcheckDBSchema();\n\t\t\tif (connection_str.contains(\"autoCreateUser=true\")) {\n\t\t\t\tautoCreateUser = true;\n\t\t\t}    // end of if (db_conn.contains())\n\t\t\tif (connection_str.contains(\"cacheRepo=off\")) {\n\t\t\t\tlog.fine(\"Disabling cache.\");\n\t\t\t\tcache = Collections.synchronizedMap(new RepoCache(0, -1000));\n\t\t\t} else {\n\t\t\t\tcache = Collections.synchronizedMap(new RepoCache(10000, 60 * 1000));\n\t\t\t}\n\t\t\tdata_repo.initPreparedStatement(GET_USER_DB_UID_QUERY, GET_USER_DB_UID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_USERS_COUNT_QUERY, GET_USERS_COUNT_QUERY);\n\t\t\tif (connection_str.startsWith(\"jdbc:postgresql\")) {\n\t\t\t\tget_users_query = PGSQL_GET_USERS_QUERY;\n\t\t\t} else {\n\t\t\t\tget_users_query = DEF_GET_USERS_QUERY;\n\t\t\t}\n\t\t\tdata_repo.initPreparedStatement(get_users_query, get_users_query);\n\t\t\tdata_repo.initPreparedStatement(ADD_USER_PLAIN_PW_QUERY, ADD_USER_PLAIN_PW_QUERY);\n\t\t\tdata_repo.initPreparedStatement(REMOVE_USER_QUERY, REMOVE_USER_QUERY);\n\t\t\tdata_repo.initPreparedStatement(ADD_NODE_QUERY, ADD_NODE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(COUNT_USERS_FOR_DOMAIN_QUERY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCOUNT_USERS_FOR_DOMAIN_QUERY);\n\t\t\tdata_repo.initPreparedStatement(DATA_FOR_NODE_QUERY, DATA_FOR_NODE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(KEYS_FOR_NODE_QUERY, KEYS_FOR_NODE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(NODES_FOR_NODE_QUERY, NODES_FOR_NODE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(INSERT_KEY_VAL_QUERY, INSERT_KEY_VAL_QUERY);\n\t\t\tdata_repo.initPreparedStatement(REMOVE_KEY_DATA_QUERY, REMOVE_KEY_DATA_QUERY);\n\t\t\tdata_repo.initPreparedStatement(UPDATE_PAIRS_QUERY, UPDATE_PAIRS_QUERY);\n\t\t\tauth = new AuthRepositoryImpl(this);\n\n\t\t\t// initRepo();\n\t\t\tlog.log(Level.INFO, \"Initialized database connection: {0}\", connection_str);\n\t\t} catch (Exception e) {\n\t\t\tdata_repo = null;\n\n\t\t\tthrow new DBInitException(\"Problem initializing jdbc connection: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconnection_str, e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tauth.logout(user);\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(final Map<String, Object> props)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.otherAuth(props);\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, final String password)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.plainAuth(user, password);\n\t}\n\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) {\n\t\tauth.queryAuth(authProps);\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user_id, final String subnode, final String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tremoveData(null, user_id, subnode, key);\n\t}\n\n\tprivate void removeData(DataRepository repo, BareJID user_id, final String subnode,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\n\t\t// cache.remove(user_id+\"/\"+subnode+\"/\"+key);\n\t\ttry {\n\t\t\tlong nid = getNodeNID(repo, user_id, subnode);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Removing data, user_id: {0}, subnode: {1}, key: {2}, nid: {3}\",\n\t\t\t\t\t\t\t\tnew Object[] { user_id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t subnode, key, nid });\n\t\t\t}\n\n\t\t\tPreparedStatement remove_key_data_st = null;\n\n\t\t\tif (repo == null) {\n\t\t\t\tremove_key_data_st = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\t\t\tREMOVE_KEY_DATA_QUERY);\n\t\t\t} else {\n\t\t\t\tremove_key_data_st = repo.getPreparedStatement(user_id, REMOVE_KEY_DATA_QUERY);\n\t\t\t}\n\t\t\tif (nid > 0) {\n\t\t\t\tsynchronized (remove_key_data_st) {\n\t\t\t\t\tremove_key_data_st.setLong(1, nid);\n\t\t\t\t\tremove_key_data_st.setString(2, key);\n\t\t\t\t\tremove_key_data_st.executeUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting subnodes list.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user_id, final String key)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tremoveData(user_id, null, key);\n\t}\n\n\t@Override\n\tpublic void removeSubnode(BareJID user_id, final String subnode)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tif (subnode == null) {\n\t\t\treturn;\n\t\t}    // end of if (subnode == null)\n\t\ttry {\n\t\t\tString[] subnodes = getSubnodes( user_id, subnode );\n\t\t\tif (subnodes != null && subnodes.length > 0 ) {\n\t\t\t\tfor ( String innerSubNode : subnodes) {\n\t\t\t\t\tremoveSubnode( user_id, subnode + \"/\" + innerSubNode);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlong nid = getNodeNID(null, user_id, subnode);\n\n\t\t\tif (nid > 0) {\n\t\t\t\tdeleteSubnode(null, nid);\n\t\t\t\tcache.remove(user_id + \"/\" + subnode);\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error getting subnodes list.\", e);\n\t\t}\n\t}\n\n\t/**\n\t * <code>removeUser</code> method is thread safe. It uses local variable for\n\t * storing <code>Statement</code>.\n\t *\n\t * @param user_id\n\t *          a <code>String</code> value the user Jabber ID.\n\t *\n\t * @throws TigaseDBException\n\t * @exception UserNotFoundException\n\t *              if an error occurs\n\t */\n\t@Override\n\tpublic void removeUser(BareJID user_id)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tStatement stmt = null;\n\t\tString query   = null;\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Removing user: {0}\", user_id);\n\t\t}\n\t\ttry {\n\t\t\tstmt = data_repo.createStatement(user_id);\n\n\t\t\t// Get user account uid\n\t\t\tlong uid = getUserUID(null, user_id, autoCreateUser);\n\n\t\t\t// Remove all user enrties from pairs table\n\t\t\tquery = \"delete from \" + DEF_PAIRS_TBL + \" where uid = \" + uid;\n\t\t\tstmt.executeUpdate(query);\n\n\t\t\t// Remove all user entries from nodes table\n\t\t\tquery = \"delete from \" + DEF_NODES_TBL + \" where uid = \" + uid;\n\t\t\tstmt.executeUpdate(query);\n\n\t\t\tPreparedStatement user_del_sp = data_repo.getPreparedStatement(user_id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tREMOVE_USER_QUERY);\n\n\t\t\t// Remove user account from users table\n\t\t\tsynchronized (user_del_sp) {\n\t\t\t\tuser_del_sp.setString(1, user_id.toString());\n\t\t\t\tuser_del_sp.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Error removing user from repository: \" + query, e);\n\t\t} finally {\n\t\t\tdata_repo.release(stmt, null);\n\t\t\tstmt = null;\n\t\t\tcache.remove(user_id.toString());\n\n\t\t\t// cache.clear();\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setData(BareJID user_id, final String subnode, final String key,\n\t\t\t\t\t\t\t\t\t\t\tfinal String value)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlong uid            = -2;\n\t\tlong nid            = -2;\n\t\tDataRepository repo = data_repo.takeRepoHandle(user_id);\n\n\t\tsynchronized (repo) {\n\t\t\ttry {\n\t\t\t\tuid = getUserUID(repo, user_id, autoCreateUser);\n\t\t\t\tnid = getNodeNID(repo, uid, subnode);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"Saving data setting data, user_id: {0}, subnode: {1}, key: {2}, \" +\n\t\t\t\t\t\t\t\t\t\"uid: {3}, nid: {4}, value: {5}\", new Object[] {\n\t\t\t\t\t\tuser_id, subnode, key, uid, nid, value\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (nid < 0) {\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// OK\n\t\t\t\t\t\tnid = createNodePath(repo, user_id, subnode);\n\t\t\t\t\t} catch (SQLException e) {\n\n\t\t\t\t\t\t// This may happen in cluster node, when 2 nodes at the same\n\t\t\t\t\t\t// time write data to the same location, like offline messages....\n\t\t\t\t\t\t// Let's try to get the nid again.\n\t\t\t\t\t\t// OK\n\t\t\t\t\t\tnid = getNodeNID(repo, uid, subnode);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tPreparedStatement update_pairs_sp = repo.getPreparedStatement(user_id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tUPDATE_PAIRS_QUERY);\n\n\t\t\t\tupdate_pairs_sp.setLong(1, nid);\n\t\t\t\tupdate_pairs_sp.setLong(2, uid);\n\t\t\t\tupdate_pairs_sp.setString(3, key);\n\t\t\t\tswitch ( data_repo.getDatabaseType() ) {\n\t\t\t\t\tcase derby:\n\t\t\t\t\t\tClob c = update_pairs_sp.getConnection().createClob();\n\t\t\t\t\t\tc.setString( 1, value);\n\t\t\t\t\t\tupdate_pairs_sp.setClob( 4, c);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tupdate_pairs_sp.setString( 4, value );\n\t\t\t\t}\n\t\t\t\tupdate_pairs_sp.executeUpdate();\n\t\t\t} catch ( SQLException e ) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Error setting data , user_id: \" + user_id + \", subnode: \" + subnode +\n\t\t\t\t\t\t\t\t\", key: \" + key + \", uid: \" + uid + \", nid: \" + nid + \", value: \" +\n\t\t\t\t\t\t\t\tvalue, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setData(BareJID user_id, final String key, final String value)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tsetData(user_id, null, key, value);\n\t}\n\n\t@Override\n\tpublic void setDataList(BareJID user_id, final String subnode, final String key,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] list)\n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\n\t\t// Transactions may not yet work properly but at least let's make sure\n\t\t// both calls below are executed exclusively on the same DB connection\n\t\tDataRepository repo = data_repo.takeRepoHandle(user_id);\n\n\t\tsynchronized (repo) {\n\t\t\ttry {\n\t\t\t\tremoveData(repo, user_id, subnode, key);\n\t\t\t\ttry {\n\t\t\t\t\taddDataList(repo, user_id, subnode, key, list);\n\t\t\t\t} catch (SQLException ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Problem adding data to DB, user_id: \" + user_id +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\", subnode: \" + subnode + \", key: \" + key +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\", list: \" + Arrays.toString(list), ex);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdata_repo.releaseRepoHandle(repo);\n\t\t\t}\n\t\t}\n\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void updatePassword(BareJID user, final String password)\n\t\t\t\t\tthrows TigaseDBException {\n\t\tauth.updatePassword(user, password);\n\t}\n\n\t@Override\n\tpublic boolean userExists(BareJID user) {\n\t\ttry {\n\t\t\tgetUserUID(null, user, false);\n\n\t\t\treturn true;\n\t\t} catch (Exception e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate long addNode(DataRepository repo, long uid, long parent_nid, String node_name)\n\t\t\t\t\tthrows SQLException {\n\t\tResultSet rs                  = null;\n\t\tPreparedStatement node_add_sp = null;\n\n\t\tif (repo == null) {\n\t\t\tnode_add_sp = data_repo.getPreparedStatement(null, ADD_NODE_QUERY);\n\t\t} else {\n\t\t\tnode_add_sp = repo.getPreparedStatement(null, ADD_NODE_QUERY);\n\t\t}\n\t\tsynchronized (node_add_sp) {\n\t\t\ttry {\n\t\t\t\tif (parent_nid < 0) {\n\t\t\t\t\tnode_add_sp.setNull(1, Types.BIGINT);\n\t\t\t\t} else {\n\t\t\t\t\tnode_add_sp.setLong(1, parent_nid);\n\t\t\t\t}    // end of else\n\t\t\t\tnode_add_sp.setLong(2, uid);\n\t\t\t\tnode_add_sp.setString(3, node_name);\n\n\t\t\t\tswitch ( data_repo.getDatabaseType() ) {\n//\t\t\t\t\tcase sqlserver:\n//\t\t\t\t\t\tnode_add_sp.executeUpdate();\n//\t\t\t\t\t\trs = node_add_sp.getGeneratedKeys();\n//\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\trs = node_add_sp.executeQuery();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\treturn rs.getLong(1);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Missing NID after adding new node...\");\n\n\t\t\t\t\treturn -1;\n\n\t\t\t\t\t// throw new TigaseDBException(\"Propeblem adding new node. \"\n\t\t\t\t\t// + \"The SP should return nid or fail\");\n\t\t\t\t}    // end of if (isnext) else\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\n\t\t// return new_nid;\n\t}\n\n\t/**\n\t * <code>addUserRepo</code> method is thread safe. It uses local variable for\n\t * storing <code>Statement</code>.\n\t *\n\t * @param user_id\n\t *          a <code>String</code> value of the user ID.\n\t * @return a <code>long</code> value of <code>uid</code> database user ID.\n\t * @exception SQLException if an error occurs\n\t * @exception UserExistsException if the user already exists in repository\n\t */\n\tprivate long addUserRepo( DataRepository repo, BareJID user_id )\n\t\t\tthrows SQLException, UserExistsException {\n\t\tResultSet rs                  = null;\n\t\tlong uid                      = -1;\n\t\tPreparedStatement user_add_sp = null;\n\n\t\tif (repo == null) {\n\t\t\tuser_add_sp = data_repo.getPreparedStatement(user_id, ADD_USER_PLAIN_PW_QUERY);\n\t\t} else {\n\t\t\tuser_add_sp = repo.getPreparedStatement(user_id, ADD_USER_PLAIN_PW_QUERY);\n\t\t}\n\t\tsynchronized (user_add_sp) {\n\t\t\ttry {\n\t\t\t\tuser_add_sp.setString(1, user_id.toString());\n\t\t\t\tuser_add_sp.setNull(2, Types.VARCHAR);\n\n\t\t\t\tlog.log(Level.FINEST, \"Adding non existing user to user-repository: \" + user_id.toString() );\n\n\t\t\t\tswitch ( data_repo.getDatabaseType() ) {\n\t\t\t\t\tdefault:\n\t\t\t\t\t\trs = user_add_sp.executeQuery();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (rs != null && rs.next()) {\n\t\t\t\t\tuid = rs.getLong(1);\n\n\t\t\t\t\t// addNode(uid, -1, root_node);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Missing UID after adding new user...\");\n\t\t\t\t}    // end of if (isnext) else\n\t\t\t} catch ( SQLException ex ) {\n\t\t\t\tif ( isExceptionKeyViolation( ex ) ){\n\t\t\t\t\tthrow new UserExistsException(user_id, \"User already exist in the database\", ex );\n\t\t\t\t} else {\n\t\t\t\t\tthrow ex;\n\t\t\t\t}\n\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\t\tcache.put(user_id.toString(), Long.valueOf(uid));\n\n\t\treturn uid;\n\t}\n\n\tprotected boolean isExceptionKeyViolation( SQLException ex ) {\n\t\tString sqlState = ex.getSQLState();\n\t\tboolean keyViolation = false;\n\t\tswitch ( data_repo.getDatabaseType() ) {\n\n\t\t\tcase derby:\n\t\t\t\tkeyViolation = (sqlState.equals( \"X0Y78\" ));\n\t\t\t\tbreak;\n\t\t\tcase postgresql:\n\t\t\t\tkeyViolation = (sqlState.equals( \"23505\" ) || sqlState.equals( \"23000\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tkeyViolation = sqlState.equals( \"23000\");\n\t\t\t\tbreak;\n\t\t}\n\t\treturn keyViolation;\n\t}\n\n\tprivate String buildNodeQuery(long uid, String node_path) {\n\t\tString query = \"select nid as nid1 from \" + DEF_NODES_TBL + \" where (uid = \" + uid +\n\t\t\t\t\t\t\t\t\t \")\" + \" AND (parent_nid is null)\" + \" AND (node = '\" + DEF_ROOT_NODE +\n\t\t\t\t\t\t\t\t\t \"')\";\n\n\t\tif (node_path == null) {\n\t\t\treturn query;\n\t\t} else {\n\t\t\tStringTokenizer strtok = new StringTokenizer(node_path, \"/\", false);\n\t\t\tint cnt                = 1;\n\t\t\tString subquery        = query;\n\n\t\t\twhile (strtok.hasMoreTokens()) {\n\t\t\t\tString token = strtok.nextToken();\n\n\t\t\t\t++cnt;\n\t\t\t\tsubquery = \"select nid as nid\" + cnt + \", node as node\" + cnt + \" from \" +\n\t\t\t\t\t\t\t\t\t DEF_NODES_TBL + \", (\" + subquery + \") nodes\" + (cnt - 1) +\n\t\t\t\t\t\t\t\t\t \" where (parent_nid = nid\" + (cnt - 1) + \")\" + \" AND (node = '\" +\n\t\t\t\t\t\t\t\t\t token + \"')\";\n\t\t\t}    // end of while (strtok.hasMoreTokens())\n\n\t\t\treturn subquery;\n\t\t}      // end of else\n\t}\n\n\t// Implementation of tigase.db.UserRepository\n\tprivate void checkDBSchema() throws SQLException {\n\t\tString schema_version = \"1.0\";\n\t\tString query = null;\n\n\t\tswitch ( data_repo.getDatabaseType() ) {\n\t\t\tcase derby:\n\t\t\t\tquery = DERBY_GETSCHEMAVER_QUERY;\n\t\t\t\tbreak;\n\t\t\tcase jtds:\n\t\t\tcase sqlserver:\n\t\t\t\tquery = SQLSERVER_GETSCHEMAVER_QUERY;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tquery = JDBC_GETSCHEMAVER_QUERY;\n\t\t\t\tbreak;\n\t\t}\n\t\tStatement stmt        = data_repo.createStatement(null);\n\t\tResultSet rs          = stmt.executeQuery(query);\n\n\t\ttry {\n\t\t\tif (rs.next()) {\n\t\t\t\tschema_version = rs.getString(1);\n\t\t\t\tif (false == CURRENT_DB_SCHEMA_VER.equals(schema_version)) {\n\t\t\t\t\tSystem.err.println(\"\\n\\nPlease upgrade database schema now.\");\n\t\t\t\t\tSystem.err.println(\"Current scheme version is: \" + schema_version +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \", expected: \" + CURRENT_DB_SCHEMA_VER);\n\t\t\t\t\tSystem.err.println(\"Check the schema upgrade guide at the address:\");\n\t\t\t\t\tSystem.err.println(SCHEMA_UPGRADE_LINK);\n\t\t\t\t\tSystem.err.println(\"----\");\n\t\t\t\t\tSystem.err.println(\"If you have upgraded your schema and you are still\");\n\t\t\t\t\tSystem.err.println(\"experiencing this problem please contact support at\");\n\t\t\t\t\tSystem.err.println(\"e-mail address: support@tigase.org\");\n\n\t\t\t\t\t// e.printStackTrace();\n\t\t\t\t\tSystem.exit(100);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tdata_repo.release(stmt, rs);\n\t\t}    // end of try-catch\n\t}\n\n\tprivate long createNodePath(DataRepository repo, BareJID user_id, String node_path)\n\t\t\t\t\tthrows SQLException, UserNotFoundException {\n\t\tif (node_path == null) {\n\n\t\t\t// Or should I throw NullPointerException?\n\t\t\t// OK\n\t\t\treturn getNodeNID(repo, user_id, null);\n\t\t}    // end of if (node_path == null)\n\n\t\t// OK\n\t\tlong uid = getUserUID(repo, user_id, autoCreateUser);\n\n\t\t// OK\n\t\tlong nid                 = getNodeNID(repo, uid, null);\n\t\tStringTokenizer strtok   = new StringTokenizer(node_path, \"/\", false);\n\t\tStringBuilder built_path = new StringBuilder();\n\n\t\twhile (strtok.hasMoreTokens()) {\n\t\t\tString token = strtok.nextToken();\n\n\t\t\tbuilt_path.append(\"/\").append(token);\n\n\t\t\t// OK\n\t\t\tlong cur_nid = getNodeNID(repo, uid, built_path.toString());\n\n\t\t\tif (cur_nid > 0) {\n\t\t\t\tnid = cur_nid;\n\t\t\t} else {\n\n\t\t\t\t// OK\n\t\t\t\tnid = addNode(repo, uid, nid, token);\n\t\t\t}    // end of if (cur_nid > 0) else\n\t\t}      // end of while (strtok.hasMoreTokens())\n\n\t\treturn nid;\n\t}\n\n\tprivate void deleteSubnode(DataRepository repo, long nid) throws SQLException {\n\t\tStatement stmt = null;\n\t\tResultSet rs   = null;\n\t\tString query   = null;\n\n\t\ttry {\n\t\t\tif (repo == null) {\n\t\t\t\tstmt = data_repo.createStatement(null);\n\t\t\t} else {\n\t\t\t\tstmt = repo.createStatement(null);\n\t\t\t}\n\t\t\tquery = \"delete from \" + DEF_PAIRS_TBL + \" where nid = \" + nid;\n\t\t\tstmt.executeUpdate(query);\n\t\t\tquery = \"delete from \" + DEF_NODES_TBL + \" where nid = \" + nid;\n\t\t\tstmt.executeUpdate(query);\n\t\t} finally {\n\t\t\tdata_repo.release(stmt, rs);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate long getNodeNID(DataRepository repo, long uid, String node_path)\n\t\t\t\t\tthrows SQLException, UserNotFoundException {\n\t\tString query = buildNodeQuery(uid, node_path);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(query);\n\t\t}\n\n\t\tStatement stmt = null;\n\t\tResultSet rs   = null;\n\t\tlong nid       = -1;\n\n\t\ttry {\n\t\t\tif (repo == null) {\n\t\t\t\tstmt = data_repo.createStatement(null);\n\t\t\t} else {\n\t\t\t\tstmt = repo.createStatement(null);\n\t\t\t}\n\t\t\trs = stmt.executeQuery(query);\n\t\t\tif (rs.next()) {\n\t\t\t\tnid = rs.getLong(1);\n\t\t\t} else {\n\t\t\t\tnid = -1;\n\t\t\t}    // end of if (isnext) else\n\t\t\tif (nid <= 0) {\n\t\t\t\tif (node_path == null) {\n\t\t\t\t\tlog.info(\n\t\t\t\t\t\t\t\"Missing root node, database upgrade or bug in the code? Adding missing \" +\n\t\t\t\t\t\t\t\"root node now.\");\n\n\t\t\t\t\t// OK\n\t\t\t\t\tnid = addNode(repo, uid, -1, \"root\");\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Missing nid for node path: {0} and uid: {1}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { node_path,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t uid });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nid;\n\t\t} finally {\n\t\t\tdata_repo.release(stmt, rs);\n\t\t\tstmt = null;\n\t\t\trs   = null;\n\t\t}\n\t}\n\n\tprivate long getNodeNID(DataRepository repo, BareJID user_id, String node_path)\n\t\t\t\t\tthrows SQLException, UserNotFoundException {\n\t\tLong cache_res = (Long) cache.get(user_id + \"/\" + node_path);\n\n\t\tif (cache_res != null) {\n\t\t\treturn cache_res.longValue();\n\t\t}    // end of if (result != null)\n\n\t\t// OK\n\t\tlong uid = getUserUID(repo, user_id, autoCreateUser);\n\n\t\t// OK\n\t\tlong result = getNodeNID(repo, uid, node_path);\n\n\t\tif (result > 0) {\n\t\t\tcache.put(user_id + \"/\" + node_path, Long.valueOf(result));\n\t\t}    // end of if (result > 0)\n\n\t\treturn result;\n\t}\n\n\tprivate long getUserUID(DataRepository repo, BareJID user_id, boolean autoCreate)\n\t\t\t\t\tthrows SQLException, UserNotFoundException {\n\n\t\t// OK\n\t\tlong result = getUserUID(repo, user_id);\n\n\t\tif (result <= 0) {\n\t\t\tif (autoCreate) {\n\n\t\t\t\t// OK\n\t\t\t\ttry {\n\t\t\t\t\tresult = addUserRepo(repo, user_id);\n\t\t\t\t} catch (UserExistsException ex) {\n\t\t\t\t\t// there was unique key violation which indicates that the user\n\t\t\t\t\t// already exists in the database therefore we can retrieve it's UID\n\t\t\t\t\tresult = getUserUID( repo, user_id );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user_id);\n\t\t\t}    // end of if (autoCreate) else\n\t\t}      // end of if (isnext) else\n\n\t\treturn result;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\t// ~--- inner classes --------------------------------------------------------\n\tprivate class RepoCache\n\t\t\t\t\textends SimpleCache<String, Object> {\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param maxsize\n\t\t * @param cache_time\n\t\t */\n\t\tpublic RepoCache(int maxsize, long cache_time) {\n\t\t\tsuper(maxsize, cache_time);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic Object remove(Object key) {\n\t\t\tif (cache_off) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tObject val          = super.remove(key);\n\t\t\tString strk         = key.toString();\n\t\t\tIterator<String> ks = keySet().iterator();\n\n\t\t\twhile (ks.hasNext()) {\n\t\t\t\tString k = ks.next().toString();\n\n\t\t\t\tif (k.startsWith(strk)) {\n\t\t\t\t\tks.remove();\n\t\t\t\t}    // end of if (k.startsWith(strk))\n\t\t\t}      // end of while (ks.hasNext())\n\n\t\t\treturn val;\n\t\t}\n\t}\t\n\t\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\t\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\treturn auth.isUserDisabled(user);\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {\n\t\tauth.setUserDisabled(user, value);\n\t}\t\n}    // JDBCRepository\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/TigaseAuth.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db.jdbc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthorizationException;\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.AuthRepository;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.util.Base64;\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xmpp.BareJID;\n\nimport static tigase.db.AuthRepository.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLIntegrityConstraintViolationException;\nimport java.sql.Statement;\n\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class TigaseAuth here.\n *\n *\n * Created: Sat Nov 11 22:22:04 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Meta( supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class TigaseAuth implements AuthRepository {\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.db.jdbc.TigaseAuth\");\n\tprivate static final String[] non_sasl_mechs = { \"password\" };\n\tprivate static final String[] sasl_mechs = { \"PLAIN\" };\n\tprivate static final String INIT_DB_QUERY = \"{ call TigInitdb() }\";\n\tprivate static final String ADD_USER_PLAIN_PW_QUERY = \"{ call TigAddUserPlainPw(?, ?) }\";\n\tprivate static final String REMOVE_USER_QUERY = \"{ call TigRemoveUser(?) }\";\n\tprivate static final String GET_PASSWORD_QUERY = \"{ call TigGetPassword(?) }\";\n\tprivate static final String UPDATE_PASSWORD_PLAIN_PW_QUERY =\n\t\t\"{ call TigUpdatePasswordPlainPw(?, ?) }\";\n\tprivate static final String USER_LOGIN_PLAIN_PW_QUERY = \"{ call TigUserLoginPlainPw(?, ?) }\";\n\tprivate static final String USER_LOGOUT_QUERY = \"{ call TigUserLogout(?) }\";\n\tprivate static final String USERS_COUNT_QUERY = \"{ call TigAllUsersCount() }\";\n\tprivate static final String USERS_DOMAIN_COUNT_QUERY =\n\t\t\"select count(*) from tig_users where user_id like ?\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addUser(BareJID user, final String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tPreparedStatement add_user_plain_pw_sp =\n\t\t\t\tdata_repo.getPreparedStatement(user, ADD_USER_PLAIN_PW_QUERY);\n\n\t\t\tsynchronized (add_user_plain_pw_sp) {\n\t\t\t\ttry {\n\t\t\t\t\tadd_user_plain_pw_sp.setString(1, user.toString());\n\t\t\t\t\tadd_user_plain_pw_sp.setString(2, password);\n\t\t\t\t\trs = add_user_plain_pw_sp.executeQuery();\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLIntegrityConstraintViolationException e) {\n\t\t\tthrow new UserExistsException(\"Error while adding user to repository, user exists?\", e);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, final String digest, final String id, final String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tthrow new AuthorizationException(\"Not supported.\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn data_repo.getResourceUri();\n\t}\n\n\t/**\n\t * <code>getUsersCount</code> method is thread safe. It uses local variable\n\t * for storing <code>Statement</code>.\n\t *\n\t * @return a <code>long</code> number of user accounts in database.\n\t */\n\t@Override\n\tpublic long getUsersCount() {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tlong users = -1;\n\t\t\tPreparedStatement users_count_sp = data_repo.getPreparedStatement(null, USERS_COUNT_QUERY);\n\n\t\t\tsynchronized (users_count_sp) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\trs = users_count_sp.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t}    // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tlong users = -1;\n\t\t\tPreparedStatement users_domain_count_st =\n\t\t\t\tdata_repo.getPreparedStatement(null, USERS_DOMAIN_COUNT_QUERY);\n\n\t\t\tsynchronized (users_domain_count_st) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\tusers_domain_count_st.setString(1, \"%@\" + domain);\n\t\t\t\t\trs = users_domain_count_st.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t}    // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(final String connection_str, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, connection_str, params);\n\t\t\tdata_repo.initPreparedStatement(INIT_DB_QUERY, INIT_DB_QUERY);\n\t\t\tdata_repo.initPreparedStatement(ADD_USER_PLAIN_PW_QUERY, ADD_USER_PLAIN_PW_QUERY);\n\t\t\tdata_repo.initPreparedStatement(REMOVE_USER_QUERY, REMOVE_USER_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_PASSWORD_QUERY, GET_PASSWORD_QUERY);\n\t\t\tdata_repo.initPreparedStatement(UPDATE_PASSWORD_PLAIN_PW_QUERY,\n\t\t\t\t\tUPDATE_PASSWORD_PLAIN_PW_QUERY);\n\t\t\tdata_repo.initPreparedStatement(USER_LOGIN_PLAIN_PW_QUERY, USER_LOGIN_PLAIN_PW_QUERY);\n\t\t\tdata_repo.initPreparedStatement(USER_LOGOUT_QUERY, USER_LOGOUT_QUERY);\n\t\t\tdata_repo.initPreparedStatement(USERS_COUNT_QUERY, USERS_COUNT_QUERY);\n\t\t\tdata_repo.initPreparedStatement(USERS_DOMAIN_COUNT_QUERY, USERS_DOMAIN_COUNT_QUERY);\n\n\t\t\tif ((params != null) && (params.get(\"init-db\") != null)) {\n\t\t\t\tdata_repo.getPreparedStatement(null, INIT_DB_QUERY).executeQuery();\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tdata_repo = null;\n\n\t\t\tthrow new DBInitException(\"Problem initializing jdbc connection: \" + connection_str, e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tPreparedStatement user_logout_sp = data_repo.getPreparedStatement(user, USER_LOGOUT_QUERY);\n\n\t\t\tsynchronized (user_logout_sp) {\n\t\t\t\tuser_logout_sp.setString(1, user.toString());\n\t\t\t\tuser_logout_sp.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(final Map<String, Object> props)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tString proto = (String) props.get(PROTOCOL_KEY);\n\n\t\tif (proto.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tString mech = (String) props.get(MACHANISM_KEY);\n\n\t\t\tif (mech.equals(\"PLAIN\")) {\n\t\t\t\ttry {\n\t\t\t\t\treturn saslAuth(props);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tthrow new AuthorizationException(\"Stringprep failed for: \" + props, ex);\n\t\t\t\t}\n\t\t\t}    // end of if (mech.equals(\"PLAIN\"))\n\n\t\t\tthrow new AuthorizationException(\"Mechanism is not supported: \" + mech);\n\t\t}      // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tif (proto.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tString password = (String) props.get(PASSWORD_KEY);\n\t\t\tBareJID user_id = (BareJID) props.get(USER_ID_KEY);\n\t\t\t\tif (password != null) {\n\t\t\t\t\treturn plainAuth(user_id, password);\n\t\t\t\t}\n\t\t\t\tString digest = (String) props.get(DIGEST_KEY);\n\t\t\t\tif (digest != null) {\n\t\t\t\t\tString digest_id = (String) props.get(DIGEST_ID_KEY);\n\t\t\t\t\treturn digestAuth(user_id, digest, digest_id, \"SHA\");\n\t\t\t\t}\n\t\t} // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tthrow new AuthorizationException(\"Protocol is not supported: \" + proto);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tResultSet rs = null;\n\t\tString res_string = null;\n\n\t\ttry {\n\t\t\tPreparedStatement user_login_plain_pw_sp\n\t\t\t\t\t= data_repo.getPreparedStatement(user, USER_LOGIN_PLAIN_PW_QUERY);\n\n\t\t\tsynchronized (user_login_plain_pw_sp) {\n\t\t\t\ttry {\n\t\t\t\t\tuser_login_plain_pw_sp.setString(1, user.toString());\n\t\t\t\t\tuser_login_plain_pw_sp.setString(2, password);\n\t\t\t\t\tswitch (data_repo.getDatabaseType()) {\n\t\t\t\t\t\tcase jtds:\n\t\t\t\t\t\tcase sqlserver:\n\t\t\t\t\t\t\tuser_login_plain_pw_sp.executeUpdate();\n\t\t\t\t\t\t\trs = user_login_plain_pw_sp.getGeneratedKeys();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\trs = user_login_plain_pw_sp.executeQuery();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean auth_result_ok = false;\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tres_string = rs.getString(1);\n\n\t\t\t\t\t\tif (res_string != null) {\n\t\t\t\t\t\t\tBareJID result = BareJID.bareJIDInstance(res_string);\n\n\t\t\t\t\t\t\tauth_result_ok = user.equals(result);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (auth_result_ok) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\t\"Login failed, for user: ''{0}\" + \"''\" + \", password: ''\" + \"{1}\" + \"''\"\n\t\t\t\t\t\t\t\t\t\t+ \", from DB got: \" + \"{2}\", new Object[]{user,\n\t\t\t\t\t\t\t\t\t\t\tpassword, res_string});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user);\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new AuthorizationException(\"Stringprep failed for: \" + res_string, ex);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}    // end of catch\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\tpublic void queryAuth(final Map<String, Object> authProps) {\n\t\tString protocol = (String) authProps.get(PROTOCOL_KEY);\n\n\t\tif (protocol.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tauthProps.put(RESULT_KEY, non_sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\n\t\tif (protocol.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tauthProps.put(RESULT_KEY, sasl_mechs);\n\t\t}    // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tPreparedStatement remove_user_sp = data_repo.getPreparedStatement(user, REMOVE_USER_QUERY);\n\n\t\t\tsynchronized (remove_user_sp) {\n\t\t\t\tremove_user_sp.setString(1, user.toString());\n\t\t\t\tremove_user_sp.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tPreparedStatement update_pass_plain_pw_sp =\n\t\t\t\tdata_repo.getPreparedStatement(user, UPDATE_PASSWORD_PLAIN_PW_QUERY);\n\n\t\t\tsynchronized (update_pass_plain_pw_sp) {\n\t\t\t\tupdate_pass_plain_pw_sp.setString(1, user.toString());\n\t\t\t\tupdate_pass_plain_pw_sp.setString(2, password);\n\t\t\t\tupdate_pass_plain_pw_sp.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tPreparedStatement get_pass_sp = data_repo.getPreparedStatement(user, GET_PASSWORD_QUERY);\n\n\t\t\tsynchronized (get_pass_sp) {\n\t\t\t\ttry {\n\t\t\t\t\tget_pass_sp.setString(1, user.toString());\n\t\t\t\t\trs = get_pass_sp.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\treturn rs.getString(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user);\n\t\t\t\t\t}    // end of if (isnext) else\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem with retrieving user password.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Feature not supported\");\t\n\t}\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate boolean saslAuth(final Map<String, Object> props)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException,\n\t\t\tTigaseStringprepException {\n\t\tString data_str = (String) props.get(DATA_KEY);\n\t\tString domain = (String) props.get(REALM_KEY);\n\n\t\tprops.put(RESULT_KEY, null);\n\n\t\tbyte[] in_data = ((data_str != null) ? Base64.decode(data_str) : new byte[0]);\n\t\tint auth_idx = 0;\n\n\t\twhile ((in_data[auth_idx] != 0) && (auth_idx < in_data.length)) {\n\t\t\t++auth_idx;\n\t\t}\n\n\t\tString authoriz = new String(in_data, 0, auth_idx);\n\t\tint user_idx = ++auth_idx;\n\n\t\twhile ((in_data[user_idx] != 0) && (user_idx < in_data.length)) {\n\t\t\t++user_idx;\n\t\t}\n\n\t\tString user_name = new String(in_data, auth_idx, user_idx - auth_idx);\n\n\t\t++user_idx;\n\n\t\tBareJID jid = null;\n\n\t\tif (BareJID.parseJID(user_name)[0] == null) {\n\t\t\tjid = BareJID.bareJIDInstance(user_name, domain);\n\t\t} else {\n\t\t\tjid = BareJID.bareJIDInstance(user_name);\n\t\t}\n\n\t\tprops.put(USER_ID_KEY, jid);\n\n\t\tString passwd = new String(in_data, user_idx, in_data.length - user_idx);\n\n\t\treturn plainAuth(jid, passwd);\n\t}\n}    // TigaseAuth\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/TigaseCustomAuth.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.db.jdbc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthRepository;\nimport tigase.db.AuthorizationException;\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.util.Algorithms;\nimport tigase.util.Base64;\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xmpp.BareJID;\n\nimport static tigase.db.AuthRepository.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLIntegrityConstraintViolationException;\n\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.RealmCallback;\nimport javax.security.sasl.Sasl;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * The user authentication connector allows for customized SQL queries to be\n * used. Queries are defined in the configuration file and they can be either\n * plain SQL queries or stored procedures.\n *\n * If the query starts with characters: <code>{ call</code> then the server\n * assumes this is a stored procedure call, otherwise it is executed as a plain\n * SQL query. Each configuration value is stripped from white characters on both\n * ends before processing.\n *\n * Please don't use semicolon <code>';'</code> at the end of the query as many\n * JDBC drivers get confused and the query may not work for unknown obvious\n * reason.\n *\n * Some queries take arguments. Arguments are marked by question marks\n * <code>'?'</code> in the query. Refer to the configuration parameters\n * description for more details about what parameters are expected in each\n * query.\n *\n * Example configuration.\n *\n * The first example shows how to put a stored procedure as a query with 2\n * required parameters.\n *\n * <pre>\n * add-user-query={ call TigAddUserPlainPw(?, ?) }\n * </pre>\n *\n * The same query with plain SQL parameters instead:\n *\n * <pre>\n * add-user-query=insert into users (user_id, password) values (?, ?)\n * </pre>\n *\n * Created: Sat Nov 11 22:22:04 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Meta( isDefault=true, supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class TigaseCustomAuth implements AuthRepository {\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(TigaseCustomAuth.class.getName());\n\n\t/**\n\t * Query executing periodically to ensure active connection with the database.\n\t *\n\t * Takes no arguments.\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * select 1\n\t * </pre>\n\t */\n\tpublic static final String DEF_CONNVALID_KEY = \"conn-valid-query\";\n\n\t/**\n\t * Database initialization query which is run after the server is started.\n\t *\n\t * Takes no arguments.\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * update tig_users set online_status = 0\n\t * </pre>\n\t */\n\tpublic static final String DEF_INITDB_KEY = \"init-db-query\";\n\n\t/**\n\t * Query adding a new user to the database.\n\t *\n\t * Takes 2 arguments: <code>(user_id (JID), password)</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * insert into tig_users (user_id, user_pw) values (?, ?)\n\t * </pre>\n\t */\n\tpublic static final String DEF_ADDUSER_KEY = \"add-user-query\";\n\n\t/**\n\t * Removes a user from the database.\n\t *\n\t * Takes 1 argument: <code>(user_id (JID))</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * delete from tig_users where user_id = ?\n\t * </pre>\n\t */\n\tpublic static final String DEF_DELUSER_KEY = \"del-user-query\";\n\n\t/**\n\t * Retrieves user password from the database for given user_id (JID).\n\t *\n\t * Takes 1 argument: <code>(user_id (JID))</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * select user_pw from tig_users where user_id = ?\n\t * </pre>\n\t */\n\tpublic static final String DEF_GETPASSWORD_KEY = \"get-password-query\";\n\n\t/**\n\t * Updates (changes) password for a given user_id (JID).\n\t *\n\t * Takes 2 arguments: <code>(password, user_id (JID))</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * update tig_users set user_pw = ? where user_id = ?\n\t * </pre>\n\t */\n\tpublic static final String DEF_UPDATEPASSWORD_KEY = \"update-password-query\";\n\n\t/**\n\t * Performs user login. Normally used when there is a special SP used for this\n\t * purpose. This is an alternative way to a method requiring retrieving user\n\t * password. Therefore at least one of those queries must be defined:\n\t * <code>user-login-query</code> or <code>get-password-query</code>.\n\t *\n\t * If both queries are defined then <code>user-login-query</code> is used.\n\t * Normally this method should be only used with plain text password\n\t * authentication or sasl-plain.\n\t *\n\t * The Tigase server expects a result set with user_id to be returned from the\n\t * query if login is successful and empty results set if the login is\n\t * unsuccessful.\n\t *\n\t * Takes 2 arguments: <code>(user_id (JID), password)</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * select user_id from tig_users where (user_id = ?) AND (user_pw = ?)\n\t * </pre>\n\t */\n\tpublic static final String DEF_USERLOGIN_KEY = \"user-login-query\";\n\n\t/**\n\t * This query is called when user logs out or disconnects. It can record that\n\t * event in the database.\n\t *\n\t * Takes 1 argument: <code>(user_id (JID))</code>\n\t *\n\t * Example query:\n\t *\n\t * <pre>\n\t * update tig_users, set online_status = online_status - 1 where user_id = ?\n\t * </pre>\n\t */\n\tpublic static final String DEF_USERLOGOUT_KEY = \"user-logout-query\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERS_COUNT_KEY = \"users-count-query\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERS_DOMAIN_COUNT_KEY = \"\" + \"users-domain-count-query\";\n\n\tpublic static final String DEF_LISTDISABLEDACCOUNTS_KEY= \"users-list-disabled-accounts-query\";\n\t\n\tpublic static final String DEF_DISABLEACCOUNT_KEY = \"user-disable-account-query\";\n\t\n\tpublic static final String DEF_ENABLEACCOUNT_KEY = \"user-enable-account-query\";\t\n\t\n\t/**\n\t * Comma separated list of NON-SASL authentication mechanisms. Possible\n\t * mechanisms are: <code>password</code> and <code>digest</code>.\n\t * <code>digest</code> mechanism can work only with\n\t * <code>get-password-query</code> active and only when password are stored in\n\t * plain text format in the database.\n\t */\n\tpublic static final String DEF_NONSASL_MECHS_KEY = \"non-sasl-mechs\";\n\n\t/**\n\t * Comma separated list of SASL authentication mechanisms. Possible mechanisms\n\t * are all mechanisms supported by Java implementation. The most common are:\n\t * <code>PLAIN</code>, <code>DIGEST-MD5</code>, <code>CRAM-MD5</code>.\n\t *\n\t * \"Non-PLAIN\" mechanisms will work only with the\n\t * <code>get-password-query</code> active and only when passwords are stored\n\t * in plain text format in the database.\n\t */\n\tpublic static final String DEF_SASL_MECHS_KEY = \"sasl-mechs\";\n\n\tpublic static final String NO_QUERY = \"none\";\n\n\t/** Field description */\n\tpublic static final String DEF_INITDB_QUERY = \"{ call TigInitdb() }\";\n\n\t/** Field description */\n\tpublic static final String DEF_ADDUSER_QUERY = \"{ call TigAddUserPlainPw(?, ?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_DELUSER_QUERY = \"{ call TigRemoveUser(?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_GETPASSWORD_QUERY = \"{ call TigGetPassword(?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_UPDATEPASSWORD_QUERY =\n\t\t\t\"{ call TigUpdatePasswordPlainPwRev(?, ?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERLOGIN_QUERY = \"{ call TigUserLoginPlainPw(?, ?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERLOGOUT_QUERY = \"{ call TigUserLogout(?) }\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERS_COUNT_QUERY = \"{ call TigAllUsersCount() }\";\n\n\t/** Field description */\n\tpublic static final String DEF_USERS_DOMAIN_COUNT_QUERY = \"\"\n\t\t\t+ \"select count(*) from tig_users where user_id like ?\";\n\n\tpublic static final String DEF_LISTDISABLEDACCOUNTS_QUERY = \"{ call TigDisabledAccounts() }\";\n\t\n\tpublic static final String DEF_DISABLEACCOUNT_QUERY = \"{ call TigDisableAccount(?) }\";\n\t\n\tpublic static final String DEF_ENABLEACCOUNT_QUERY = \"{ call TigEnableAccount(?) }\";\t\n\t\n\t/** Field description */\n\tpublic static final String DEF_NONSASL_MECHS = \"password\";\n\n\t/** Field description */\n\tpublic static final String DEF_SASL_MECHS = \"PLAIN\";\n\n\t/** Field description */\n\tpublic static final String SP_STARTS_WITH = \"{ call\";\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\tprivate String initdb_query = DEF_INITDB_QUERY;\n\tprivate String getpassword_query = DEF_GETPASSWORD_QUERY;\n\tprivate String deluser_query = DEF_DELUSER_QUERY;\n\tprivate String adduser_query = DEF_ADDUSER_QUERY;\n\tprivate String updatepassword_query = DEF_UPDATEPASSWORD_QUERY;\n\tprivate String userlogin_query = DEF_USERLOGIN_QUERY;\n\tprivate String userdomaincount_query = DEF_USERS_DOMAIN_COUNT_QUERY;\n\tprivate String listdisabledaccounts_query = DEF_LISTDISABLEDACCOUNTS_QUERY;\n\tprivate String disableaccount_query = DEF_DISABLEACCOUNT_QUERY;\n\tprivate String enableaccount_query = DEF_ENABLEACCOUNT_QUERY;\n\t\n\n\t// It is better just to not call the query if it is not defined by the user\n\t// By default it is null then and not called.\n\tprivate String userlogout_query = null;\n\tprivate String userscount_query = DEF_USERS_COUNT_QUERY;\n\tprivate boolean userlogin_active = false;\n\n\t// private String userlogout_query = DEF_USERLOGOUT_QUERY;\n\tprivate String[] sasl_mechs = DEF_SASL_MECHS.split(\",\");\n\tprivate String[] nonsasl_mechs = DEF_NONSASL_MECHS.split(\",\");\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addUser(BareJID user, final String password) throws UserExistsException,\n\t\t\tTigaseDBException {\n\t\tif (adduser_query == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement add_user = data_repo.getPreparedStatement(user, adduser_query);\n\n\t\t\tsynchronized (add_user) {\n\t\t\t\ttry {\n\t\t\t\t\tadd_user.setString(1, user.toString());\n\t\t\t\t\tadd_user.setString(2, password);\n\n\t\t\t\t\tboolean is_result = add_user.execute();\n\n\t\t\t\t\tif (is_result) {\n\t\t\t\t\t\trs = add_user.getResultSet();\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLIntegrityConstraintViolationException e) {\n\t\t\tthrow new UserExistsException(\n\t\t\t\t\t\"Error while adding user to repository, user possibly exists: \" + user, e);\n\t\t} catch (SQLException e) {\n\t\t\tif (e.getMessage() != null \n\t\t\t\t\t&& (e.getMessage().contains(\"Violation of UNIQUE KEY\") || e.getMessage().contains(\"violates unique constraint \\\"user_id\\\"\"))) {\n\t\t\t\t// This is a workaround SQL Server which just throws SLQ Exception\n\t\t\t\tthrow new UserExistsException(\n\t\t\t\t\t\t\"Error while adding user to repository, user possibly exists: \" + user, e);\n\t\t\t} else {\n\t\t\t\tthrow new TigaseDBException(\"Problem accessing repository for user: \" + user, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, final String digest, final String id,\n\t\t\tfinal String alg) throws UserNotFoundException, TigaseDBException,\n\t\t\tAuthorizationException {\n\t\tif (userlogin_active) {\n\t\t\tthrow new AuthorizationException(\"Not supported.\");\n\t\t} else {\n\t\t\tfinal String db_password = getPassword(user);\n\n\t\t\ttry {\n\t\t\t\tfinal String digest_db_pass = Algorithms.hexDigest(id, db_password, alg);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Comparing passwords, given: {0}, db: {1}\", new Object[] {\n\t\t\t\t\t\t\tdigest, digest_db_pass });\n\t\t\t\t}\n\n\t\t\t\treturn digest.equals(digest_db_pass);\n\t\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\t\tthrow new AuthorizationException(\"No such algorithm.\", e);\n\t\t\t} // end of try-catch\n\t\t}\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn data_repo.getResourceUri();\n\t}\n\n\t/**\n\t * <code>getUsersCount</code> method is thread safe. It uses local variable\n\t * for storing <code>Statement</code>.\n\t *\n\t * @return a <code>long</code> number of user accounts in database.\n\t */\n\t@Override\n\tpublic long getUsersCount() {\n\t\tif (userscount_query == null) {\n\t\t\treturn -1;\n\t\t}\n\n\t\ttry {\n\t\t\tlong users = -1;\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement users_count =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, userscount_query);\n\n\t\t\tsynchronized (users_count) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\trs = users_count.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t} // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new\n\t\t\t// TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\tif (userdomaincount_query == null) {\n\t\t\treturn -1;\n\t\t}\n\n\t\ttry {\n\t\t\tlong users = -1;\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement users_domain_count =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, userdomaincount_query);\n\n\t\t\tsynchronized (users_domain_count) {\n\t\t\t\ttry {\n\t\t\t\t\t// Load all user count from database\n\t\t\t\t\tusers_domain_count.setString(1, \"%@\" + domain);\n\t\t\t\t\trs = users_domain_count.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tusers = rs.getLong(1);\n\t\t\t\t\t} // end of while (rs.next())\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\trs = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (SQLException e) {\n\t\t\treturn -1;\n\n\t\t\t// throw new\n\t\t\t// TigaseDBException(\"Problem loading user list from repository\", e);\n\t\t}\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(final String connection_str, Map<String, String> params)\n\t\t\tthrows DBInitException {\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, connection_str, params);\n\t\t\tinitdb_query = getParamWithDef(params, DEF_INITDB_KEY, DEF_INITDB_QUERY);\n\n\t\t\tif (initdb_query != null) {\n\t\t\t\tdata_repo.initPreparedStatement(initdb_query, initdb_query);\n\t\t\t}\n\n\t\t\tadduser_query = getParamWithDef(params, DEF_ADDUSER_KEY, DEF_ADDUSER_QUERY);\n\n\t\t\tif ((adduser_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(adduser_query, adduser_query);\n\t\t\t}\n\n\t\t\tdeluser_query = getParamWithDef(params, DEF_DELUSER_KEY, DEF_DELUSER_QUERY);\n\n\t\t\tif ((deluser_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(deluser_query, deluser_query);\n\t\t\t}\n\n\t\t\tgetpassword_query = getParamWithDef(params, DEF_GETPASSWORD_KEY, DEF_GETPASSWORD_QUERY);\n\n\t\t\tif ((getpassword_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(getpassword_query, getpassword_query);\n\t\t\t}\n\n\t\t\tupdatepassword_query =\n\t\t\t\t\tgetParamWithDef(params, DEF_UPDATEPASSWORD_KEY, DEF_UPDATEPASSWORD_QUERY);\n\n\t\t\tif ((updatepassword_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(updatepassword_query, updatepassword_query);\n\t\t\t}\n\n\t\t\tuserlogin_query = getParamWithDef(params, DEF_USERLOGIN_KEY, DEF_USERLOGIN_QUERY);\n\t\t\tif (userlogin_query  != null) {\n\t\t\t\tdata_repo.initPreparedStatement(userlogin_query, userlogin_query);\n\t\t\t\tuserlogin_active = true;\n\t\t\t}\n\n\t\t\tuserlogout_query =\n\t\t\t\t\tgetParamWithDef(params, DEF_USERLOGOUT_KEY, DEF_USERLOGOUT_QUERY);\n\n\t\t\tif ((userlogout_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(userlogout_query, userlogout_query);\n\t\t\t}\n\n\t\t\tuserscount_query =\n\t\t\t\t\tgetParamWithDef(params, DEF_USERS_COUNT_KEY, DEF_USERS_COUNT_QUERY);\n\n\t\t\tif ((userscount_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(userscount_query, userscount_query);\n\t\t\t}\n\n\t\t\tuserdomaincount_query =\n\t\t\t\t\tgetParamWithDef(params, DEF_USERS_DOMAIN_COUNT_KEY,\n\t\t\t\t\t\t\tDEF_USERS_DOMAIN_COUNT_QUERY);\n\n\t\t\tif ((userdomaincount_query != null)) {\n\t\t\t\tdata_repo.initPreparedStatement(userdomaincount_query, userdomaincount_query);\n\t\t\t}\n\t\t\t\n\t\t\tlistdisabledaccounts_query = getParamWithDef(params, DEF_LISTDISABLEDACCOUNTS_KEY, \n\t\t\t\t\tDEF_LISTDISABLEDACCOUNTS_QUERY);\n\t\t\tif (listdisabledaccounts_query != null) {\n\t\t\t\tdata_repo.initPreparedStatement(listdisabledaccounts_query, listdisabledaccounts_query);\n\t\t\t}\n\n\t\t\tdisableaccount_query = getParamWithDef(params, DEF_DISABLEACCOUNT_KEY, \n\t\t\t\t\tDEF_DISABLEACCOUNT_QUERY);\n\t\t\tif (disableaccount_query != null) {\n\t\t\t\tdata_repo.initPreparedStatement(disableaccount_query, disableaccount_query);\n\t\t\t}\n\t\t\t\n\t\t\tenableaccount_query = getParamWithDef(params, DEF_ENABLEACCOUNT_KEY, \n\t\t\t\t\tDEF_ENABLEACCOUNT_QUERY);\n\t\t\tif (enableaccount_query != null) {\n\t\t\t\tdata_repo.initPreparedStatement(enableaccount_query, enableaccount_query);\n\t\t\t}\n\t\t\t\n\t\t\tnonsasl_mechs =\n\t\t\t\t\tgetParamWithDef(params, DEF_NONSASL_MECHS_KEY, DEF_NONSASL_MECHS).split(\",\");\n\t\t\tsasl_mechs = getParamWithDef(params, DEF_SASL_MECHS_KEY, DEF_SASL_MECHS).split(\",\");\n\n\t\t\tif ((params != null) && (params.get(\"init-db\") != null)) {\n\t\t\t\tinitDb();\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tdata_repo = null;\n\n\t\t\tthrow new DBInitException(\n\t\t\t\t\t\"Problem initializing jdbc connection: \" + connection_str, e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tif (userlogout_query == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tPreparedStatement user_logout =\n\t\t\t\t\tdata_repo.getPreparedStatement(user, userlogout_query);\n\n\t\t\tif (user_logout != null) {\n\t\t\t\tsynchronized (user_logout) {\n\t\t\t\t\tuser_logout.setString(1, user.toString());\n\t\t\t\t\tuser_logout.execute();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(final Map<String, Object> props) throws UserNotFoundException,\n\t\t\tTigaseDBException, AuthorizationException {\n\t\tString proto = (String) props.get(PROTOCOL_KEY);\n\n\t\tif (proto.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tString mech = (String) props.get(MACHANISM_KEY);\n\n\t\t\tif (mech.equals(\"PLAIN\")) {\n\t\t\t\ttry {\n\t\t\t\t\tif (saslPlainAuth(props)) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new AuthorizationException(\"Authentication failed.\");\n\t\t\t\t\t}\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tthrow new AuthorizationException(\"Stringprep failed for: \" + props, ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn saslAuth(props);\n\t\t\t}\n\t\t} // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tif (proto.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tString password = (String) props.get(PASSWORD_KEY);\n\t\t\tBareJID user_id = (BareJID) props.get(USER_ID_KEY);\n\t\t\tif (password != null) {\n\t\t\t\treturn plainAuth(user_id, password);\n\t\t\t}\n\t\t\tString digest = (String) props.get(DIGEST_KEY);\n\t\t\tif (digest != null) {\n\t\t\t\tString digest_id = (String) props.get(DIGEST_ID_KEY);\n\t\t\t\treturn digestAuth(user_id, digest, digest_id, \"SHA\");\n\t\t\t}\n\t\t} // end of if (proto.equals(PROTOCOL_VAL_SASL))\n\n\t\tthrow new AuthorizationException(\"Protocol is not supported.\");\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tif (userlogin_active) {\n\t\t\treturn userLoginAuth(user, password);\n\t\t} else {\n\t\t\tString db_password = getPassword(user);\n\n\t\t\treturn (password != null) && (db_password != null) && db_password.equals(password);\n\t\t}\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\tpublic void queryAuth(final Map<String, Object> authProps) {\n\t\tString protocol = (String) authProps.get(PROTOCOL_KEY);\n\n\t\tif (protocol.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tauthProps.put(RESULT_KEY, nonsasl_mechs);\n\t\t} // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\n\t\tif (protocol.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tauthProps.put(RESULT_KEY, sasl_mechs);\n\t\t} // end of if (protocol.equals(PROTOCOL_VAL_NONSASL))\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tif (deluser_query == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tPreparedStatement remove_user = data_repo.getPreparedStatement(user, deluser_query);\n\n\t\t\tsynchronized (remove_user) {\n\t\t\t\tremove_user.setString(1, user.toString());\n\t\t\t\tremove_user.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tif (updatepassword_query == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tPreparedStatement update_pass =\n\t\t\t\t\tdata_repo.getPreparedStatement(user, updatepassword_query);\n\n\t\t\tsynchronized (update_pass) {\n\t\t\t\tupdate_pass.setString(1, password);\n\t\t\t\tupdate_pass.setString(2, user.toString());\n\t\t\t\tupdate_pass.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t}\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\tprotected String getParamWithDef(Map<String, String> params, String key, String def) {\n\t\tif (params == null) {\n\t\t\treturn def;\n\t\t}\n\n\t\tString result = params.get(key);\n\n\t\tif (result != null) {\n\t\t\tlog.log(Level.CONFIG, \"Custom query loaded for ''{0}'': ''{1}''\", new Object[] {\n\t\t\t\t\tkey, result });\n\t\t} else {\n\t\t\tresult = def;\n\t\t\tlog.log(Level.CONFIG, \"Default query loaded for ''{0}'': ''{1}''\", new Object[] {\n\t\t\t\t\tkey, def });\n\t\t}\n\n\t\tif (result != null) {\n\t\t\tresult = result.trim();\n\n\t\t\tif (result.isEmpty() || result.equals(NO_QUERY)) {\n\t\t\t\tresult = null;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException  {\n\t\tif (getpassword_query == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement get_pass =\n\t\t\t\t\tdata_repo.getPreparedStatement(user, getpassword_query);\n\n\t\t\tsynchronized (get_pass) {\n\t\t\t\ttry {\n\t\t\t\t\tget_pass.setString(1, user.toString());\n\t\t\t\t\trs = get_pass.executeQuery();\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\treturn rs.getString(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user);\n\t\t\t\t\t} // end of if (isnext) else\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem with retrieving user password.\", e);\n\t\t}\n\t}\n\n\t\t@Override\n\tpublic boolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement list_disabledaccounts\n\t\t\t\t\t= data_repo.getPreparedStatement(user, listdisabledaccounts_query);\n\n\t\t\tsynchronized (list_disabledaccounts) {\n\t\t\t\ttry {\n\t\t\t\t\trs = list_disabledaccounts.executeQuery();\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tString accountJid = rs.getString(1);\n\t\t\t\t\t\tif (user.toString().equals(accountJid)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem with checking if user account is disabled\", e);\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tString query = (value == null || !value)\n\t\t\t\t\t? enableaccount_query : disableaccount_query;\n\t\t\tPreparedStatement changeState = data_repo.getPreparedStatement(user, query);\n\t\t\t\n\t\t\tsynchronized (changeState) {\n\t\t\t\tchangeState.setString(1, user.toString());\n\t\t\t\tchangeState.execute();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new TigaseDBException(\"Problem with changing user account state\", e);\n\t\t}\n\t}\n\t// ~--- methods --------------------------------------------------------------\n\n\tprivate void initDb() throws SQLException {\n\t\tif (initdb_query == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tPreparedStatement init_db = data_repo.getPreparedStatement(null, initdb_query);\n\n\t\tsynchronized (init_db) {\n\t\t\tinit_db.executeUpdate();\n\t\t}\n\t}\n\n\tprivate boolean saslAuth(final Map<String, Object> props) throws AuthorizationException {\n\t\ttry {\n\t\t\tSaslServer ss = (SaslServer) props.get(\"SaslServer\");\n\n\t\t\tif (ss == null) {\n\t\t\t\tMap<String, String> sasl_props = new TreeMap<String, String>();\n\n\t\t\t\tsasl_props.put(Sasl.QOP, \"auth\");\n\t\t\t\tss =\n\t\t\t\t\t\tSasl.createSaslServer((String) props.get(MACHANISM_KEY), \"xmpp\",\n\t\t\t\t\t\t\t\t(String) props.get(SERVER_NAME_KEY), sasl_props, new SaslCallbackHandler(\n\t\t\t\t\t\t\t\t\t\tprops));\n\t\t\t\tprops.put(\"SaslServer\", ss);\n\t\t\t} // end of if (ss == null)\n\n\t\t\tString data_str = (String) props.get(DATA_KEY);\n\t\t\tbyte[] in_data = ((data_str != null) ? Base64.decode(data_str) : new byte[0]);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"response: {0}\", new String(in_data));\n\t\t\t}\n\n\t\t\tbyte[] challenge = ss.evaluateResponse(in_data);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"challenge: {0}\", ((challenge != null) ? new String(\n\t\t\t\t\t\tchallenge) : \"null\"));\n\t\t\t}\n\n\t\t\tString challenge_str =\n\t\t\t\t\t(((challenge != null) && (challenge.length > 0)) ? Base64.encode(challenge)\n\t\t\t\t\t\t\t: null);\n\n\t\t\tprops.put(RESULT_KEY, challenge_str);\n\n\t\t\tif (ss.isComplete()) {\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t} // end of if (ss.isComplete()) else\n\t\t} catch (SaslException e) {\n\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t} // end of try-catch\n\t}\n\n\tprivate boolean saslPlainAuth(final Map<String, Object> props)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException,\n\t\t\tTigaseStringprepException {\n\t\tString data_str = (String) props.get(DATA_KEY);\n\t\tString domain = (String) props.get(REALM_KEY);\n\n\t\tprops.put(RESULT_KEY, null);\n\n\t\tbyte[] in_data = ((data_str != null) ? Base64.decode(data_str) : new byte[0]);\n\t\tint auth_idx = 0;\n\n\t\twhile ((in_data[auth_idx] != 0) && (auth_idx < in_data.length)) {\n\t\t\t++auth_idx;\n\t\t}\n\n\t\tString authoriz = new String(in_data, 0, auth_idx);\n\t\tint user_idx = ++auth_idx;\n\n\t\twhile ((in_data[user_idx] != 0) && (user_idx < in_data.length)) {\n\t\t\t++user_idx;\n\t\t}\n\n\t\tString user_name = new String(in_data, auth_idx, user_idx - auth_idx);\n\n\t\t++user_idx;\n\n\t\tBareJID jid = null;\n\n\t\tif (BareJID.parseJID(user_name)[0] == null) {\n\t\t\tjid = BareJID.bareJIDInstance(user_name, domain);\n\t\t} else {\n\t\t\tjid = BareJID.bareJIDInstance(user_name);\n\t\t}\n\n\t\tprops.put(USER_ID_KEY, jid);\n\n\t\tString passwd = new String(in_data, user_idx, in_data.length - user_idx);\n\n\t\treturn plainAuth(jid, passwd);\n\t}\n\n\tprivate boolean userLoginAuth(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tif (userlogin_query == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tString res_string = null;\n\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement user_login = data_repo.getPreparedStatement(user, userlogin_query);\n\n\t\t\tsynchronized (user_login) {\n\t\t\t\ttry {\n\t\t\t\t\tuser_login.setString(1, user.toString());\n\t\t\t\t\tuser_login.setString(2, password);\n\n\t\t\t\t\tswitch (data_repo.getDatabaseType()) {\n\t\t\t\t\t\tcase sqlserver:\n\t\t\t\t\t\t\tuser_login.executeUpdate();\n\t\t\t\t\t\t\trs = user_login.getGeneratedKeys();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\trs = user_login.executeQuery();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean auth_result_ok = false;\n\n\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\tres_string = rs.getString(1);\n\n\t\t\t\t\t\tif (res_string != null) {\n\t\t\t\t\t\t\tBareJID result = BareJID.bareJIDInstance(res_string);\n\n\t\t\t\t\t\t\tauth_result_ok = user.equals(result);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (auth_result_ok) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINE, \"Login failed, for user: ''{0}\" + \"''\"\n\t\t\t\t\t\t\t\t\t\t+ \", password: ''\" + \"{1}\" + \"''\" + \", from DB got: \" + \"{2}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[]{user, password, res_string});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t\tthrow new UserNotFoundException(\"User does not exist: \" + user\n\t\t\t\t\t\t+ \", in database: \" + getResourceUri());\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new AuthorizationException(\"Stringprep failed for: \" + res_string, ex);\n\t\t} catch (SQLException e) {\n\t\t\tthrow new TigaseDBException(\"Problem accessing repository.\", e);\n\t\t} // end of catch\n\t}\n\n\t// ~--- inner classes --------------------------------------------------------\n\n\tprivate class SaslCallbackHandler implements CallbackHandler {\n\t\tprivate Map<String, Object> options = null;\n\n\t\t// ~--- constructors -------------------------------------------------------\n\n\t\tprivate SaslCallbackHandler(final Map<String, Object> options) {\n\t\t\tthis.options = options;\n\t\t}\n\n\t\t// ~--- methods ------------------------------------------------------------\n\n\t\t// Implementation of javax.security.auth.callback.CallbackHandler\n\n\t\t@Override\n\t\tpublic void handle(final Callback[] callbacks) throws IOException,\n\t\t\t\tUnsupportedCallbackException {\n\t\t\tBareJID jid = null;\n\n\t\t\tfor (int i = 0; i < callbacks.length; i++) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Callback: {0}\", callbacks[i].getClass().getSimpleName());\n\t\t\t\t}\n\n\t\t\t\tif (callbacks[i] instanceof RealmCallback) {\n\t\t\t\t\tRealmCallback rc = (RealmCallback) callbacks[i];\n\t\t\t\t\tString realm = (String) options.get(REALM_KEY);\n\n\t\t\t\t\tif (realm != null) {\n\t\t\t\t\t\trc.setText(realm);\n\t\t\t\t\t} // end of if (realm == null)\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"RealmCallback: {0}\", realm);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (callbacks[i] instanceof NameCallback) {\n\t\t\t\t\t\tNameCallback nc = (NameCallback) callbacks[i];\n\t\t\t\t\t\tString user_name = nc.getName();\n\n\t\t\t\t\t\tif (user_name == null) {\n\t\t\t\t\t\t\tuser_name = nc.getDefaultName();\n\t\t\t\t\t\t} // end of if (name == null)\n\n\t\t\t\t\t\tjid = BareJID.bareJIDInstanceNS(user_name, (String) options.get(REALM_KEY));\n\t\t\t\t\t\toptions.put(USER_ID_KEY, jid);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"NameCallback: {0}\", user_name);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (callbacks[i] instanceof PasswordCallback) {\n\t\t\t\t\t\t\tPasswordCallback pc = (PasswordCallback) callbacks[i];\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tString passwd = getPassword(jid);\n\n\t\t\t\t\t\t\t\tpc.setPassword(passwd.toCharArray());\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"PasswordCallback: {0}\", passwd);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tthrow new IOException(\"Password retrieving problem.\", e);\n\t\t\t\t\t\t\t} // end of try-catch\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (callbacks[i] instanceof AuthorizeCallback) {\n\t\t\t\t\t\t\t\tAuthorizeCallback authCallback = ((AuthorizeCallback) callbacks[i]);\n\t\t\t\t\t\t\t\tString authenId = authCallback.getAuthenticationID();\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authenId: {0}\", authenId);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tString authorId = authCallback.getAuthorizationID();\n\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"AuthorizeCallback: authorId: {0}\", authorId);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (authenId.equals(authorId)) {\n\t\t\t\t\t\t\t\t\tauthCallback.setAuthorized(true);\n\t\t\t\t\t\t\t\t} // end of if (authenId.equals(authorId))\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedCallbackException(callbacks[i],\n\t\t\t\t\t\t\t\t\t\t\"Unrecognized Callback\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} // TigaseCustomAuth\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/jdbc/TigaseSPAuth.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.db.jdbc;\n\nimport java.security.InvalidKeyException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.SecureRandom;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\nimport tigase.db.AuthorizationException;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\n\n/**\n * Tigase Salted Password Auth.\n * \n */\npublic class TigaseSPAuth extends TigaseCustomAuth {\n\n\tprivate static final Logger log = Logger.getLogger(TigaseSPAuth.class.getName());\n\n\tprivate static final SecureRandom random = new SecureRandom();\n\n\tprivate static final String encode(String pwd) throws InvalidKeyException, NoSuchAlgorithmException {\n\t\tbyte[] salt = new byte[20];\n\t\trandom.nextBytes(salt);\n\t\treturn encode(pwd, salt);\n\t}\n\n\tprivate static final String encode(final String pwd, final byte[] salt) throws InvalidKeyException,\n\t\t\tNoSuchAlgorithmException {\n\t\tbyte[] saltedPassword = AbstractSaslSCRAM.hi(\"SHA1\", AbstractSaslSCRAM.normalize(pwd), salt, 4096);\n\t\tbyte[] result = new byte[salt.length + saltedPassword.length];\n\n\t\tSystem.arraycopy(salt, 0, result, 0, salt.length);\n\t\tSystem.arraycopy(saltedPassword, 0, result, salt.length, saltedPassword.length);\n\n\t\treturn Base64.encode(result);\n\t}\n\n\t@Override\n\tpublic void addUser(BareJID user, String password) throws UserExistsException, TigaseDBException {\n\t\ttry {\n\t\t\tsuper.addUser(user, encode(password));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't add user \" + user, e);\n\t\t}\n\t}\n\n\tprivate String encodeWithUserSalt(final BareJID user, final String password) throws UserNotFoundException,\n\t\t\tTigaseDBException, InvalidKeyException, NoSuchAlgorithmException {\n\t\tString pwd = getPassword(user);\n\t\tif (pwd == null)\n\t\t\tthrow new UserNotFoundException(\"User \" + user + \" not found.\");\n\t\tbyte[] buffer = Base64.decode(pwd);\n\t\tbyte[] salt = new byte[20];\n\t\tSystem.arraycopy(buffer, 0, salt, 0, salt.length);\n\n\t\treturn encode(password, salt);\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tprivate boolean isPasswordValid(final BareJID user, final String password) throws UserNotFoundException, TigaseDBException,\n\t\t\tInvalidKeyException, NoSuchAlgorithmException {\n\n\t\t// String saltedPassword = getPassword(user);\n\t\tString pwd = getPassword(user);\n\t\tif (pwd == null)\n\t\t\tthrow new UserNotFoundException(\"User \" + user + \" not found.\");\n\t\tbyte[] buffer = Base64.decode(pwd);\n\t\tbyte[] salt = new byte[20];\n\t\tbyte[] saltedPassword = new byte[20];\n\t\tSystem.arraycopy(buffer, 0, salt, 0, salt.length);\n\t\tSystem.arraycopy(buffer, salt.length, saltedPassword, 0, saltedPassword.length);\n\n\t\tbyte[] np = AbstractSaslSCRAM.hi(\"SHA1\", AbstractSaslSCRAM.normalize(password), salt, 4096);\n\n\t\treturn Arrays.equals(saltedPassword, np);\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(Map<String, Object> props) throws UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tString password = (String) props.get(PASSWORD_KEY);\n\t\tBareJID user_id = (BareJID) props.get(USER_ID_KEY);\n\n\t\ttry {\n\t\t\tprops.put(PASSWORD_KEY, encodeWithUserSalt(user_id, password));\n\t\t\treturn super.otherAuth(props);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't salt user password\", e);\n\t\t\tthrow new AuthorizationException(\"Can't salt user password\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, String password) throws UserNotFoundException, TigaseDBException {\n\t\ttry {\n\t\t\tsuper.updatePassword(user, encode(password));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't update password for user \" + user, e);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/ldap/LdapAuthProvider.java",
    "content": "package tigase.db.ldap;\n\nimport java.util.Hashtable;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.naming.Context;\nimport javax.naming.directory.DirContext;\nimport javax.naming.directory.InitialDirContext;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\nimport tigase.db.AuthRepository;\nimport tigase.db.AuthorizationException;\nimport tigase.db.DBInitException;\nimport tigase.db.Repository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\nimport tigase.util.Base64;\nimport tigase.xmpp.BareJID;\n\n@Repository.Meta( supportedUris = { \"ldaps?:.*\" } )\npublic class LdapAuthProvider implements AuthRepository {\n\n\tprivate class SaslPLAINLdap implements SaslServer {\n\n\t\tprivate boolean authOk = false;\n\n\t\tprivate final String serverName;\n\n\t\tprivate BareJID userId;\n\n\t\tpublic SaslPLAINLdap(String serverName) {\n\t\t\tthis.serverName = serverName;\n\t\t}\n\n\t\t@Override\n\t\tpublic void dispose() throws SaslException {\n\t\t}\n\n\t\t@Override\n\t\tpublic byte[] evaluateResponse(byte[] byteArray) throws SaslException {\n\t\t\tint auth_idx = 0;\n\n\t\t\twhile ((byteArray[auth_idx] != 0) && (auth_idx < byteArray.length)) {\n\t\t\t\t++auth_idx;\n\t\t\t}\n\n\t\t\tint user_idx = ++auth_idx;\n\n\t\t\twhile ((byteArray[user_idx] != 0) && (user_idx < byteArray.length)) {\n\t\t\t\t++user_idx;\n\t\t\t}\n\n\t\t\tfinal String user_id = new String(byteArray, auth_idx, user_idx - auth_idx);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"SASL userId: \" + user_id);\n\t\t\t}\n\n\t\t\t++user_idx;\n\n\t\t\tfinal String passwd = new String(byteArray, user_idx, byteArray.length - user_idx);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"SASL password: \" + passwd);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tuserId = BareJID.bareJIDInstance(user_id, serverName);\n\t\t\t\tauthOk = doBindAuthentication(userId, passwd);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't authenticate user\", e);\n\t\t\t\tauthOk = false;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getAuthorizationID() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getMechanismName() {\n\t\t\treturn \"PLAIN\";\n\t\t}\n\n\t\t@Override\n\t\tpublic Object getNegotiatedProperty(String propName) {\n\t\t\treturn null;\n\t\t}\n\n\t\tpublic BareJID getUser_id() {\n\t\t\treturn userId;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isComplete() {\n\t\t\treturn authOk;\n\t\t}\n\n\t\t@Override\n\t\tpublic byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\tprivate static final Logger log = Logger.getLogger(LdapAuthProvider.class.getName());\n\n\tprotected static final String[] non_sasl_mechs = { \"password\" };\n\n\tprotected static final String[] sasl_mechs = { \"PLAIN\" };\n\n\t/**\n\t * Example: <code>uid=%s,ou=people,dc=xmpp-test,dc=org</code>\n\t */\n\tpublic static final String USER_DN_PATTERN_KEY = \"user-dn-pattern\";\n\n\tprivate String providerUrl;\n\n\tprivate String userDnPattern;\n\n\t@Override\n\tpublic void addUser(BareJID user, String password) throws UserExistsException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Not available\");\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean digestAuth(BareJID user, String digest, String id, String alg) throws UserNotFoundException,\n\t\t\tTigaseDBException, AuthorizationException {\n\t\tthrow new AuthorizationException(\"Not supported.\");\n\t}\n\n\tprivate boolean doBindAuthentication(BareJID userId, final String password) throws UserNotFoundException,\n\t\t\tTigaseDBException, AuthorizationException {\n\t\ttry {\n\t\t\tHashtable<Object, Object> env = new Hashtable<Object, Object>();\n\t\t\tenv.put(Context.INITIAL_CONTEXT_FACTORY, \"com.sun.jndi.ldap.LdapCtxFactory\");\n\t\t\tenv.put(Context.PROVIDER_URL, this.providerUrl);\n\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"Authenticating user '\" + userId + \"' with password ******\");\n\n\t\t\tfinal String dn = String.format(this.userDnPattern, userId.getLocalpart(), userId.getDomain(), userId.toString());\n\n\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\tlog.finer(\"Using DN:\" + dn);\n\n\t\t\tenv.put(Context.SECURITY_AUTHENTICATION, \"simple\");\n\t\t\tenv.put(Context.SECURITY_PRINCIPAL, dn);\n\t\t\tenv.put(Context.SECURITY_CREDENTIALS, password);\n\n\t\t\t// Create the initial context\n\t\t\tDirContext ctx = new InitialDirContext(env);\n\t\t\tctx.close();\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"User \" + userId + \" authenticated.\");\n\t\t\treturn true;\n\t\t} catch (javax.naming.AuthenticationException e) {\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.log(Level.FINE, \"Authentication error: \" + e.getMessage());\n\t\t\treturn false;\n\t\t} catch (Exception e) {\n\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\tlog.log(Level.WARNING, \"Can't authenticate user\", e);\n\t\t\treturn false;\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn providerUrl;\n\t}\n\n\t@Override\n\tpublic long getUsersCount() {\n\t\treturn -1;\n\t};\n\n\t@Override\n\tpublic long getUsersCount(String domain) {\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\tthis.userDnPattern = params.get(USER_DN_PATTERN_KEY);\n\t\tthis.providerUrl = resource_uri;\n\t\tif (log.isLoggable(Level.CONFIG)) {\n\t\t\tlog.config(\"User DN Pattern: \" + this.userDnPattern);\n\t\t\tlog.config(\"LDAP URL: \" + this.providerUrl);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void logout(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t}\n\n\t@Override\n\tpublic boolean otherAuth(Map<String, Object> props) throws UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\tString proto = (String) props.get(PROTOCOL_KEY);\n\n\t\tif (proto.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tif (props.get(MACHANISM_KEY).equals(\"PLAIN\")) {\n\t\t\t\treturn saslAuth(props);\n\t\t\t}\n\t\t} else if (proto.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tString password = (String) props.get(PASSWORD_KEY);\n\t\t\tBareJID user_id = (BareJID) props.get(USER_ID_KEY);\n\t\t\tboolean auth = doBindAuthentication(user_id, password);\n\t\t\tif (auth) {\n\t\t\t\tprops.put(USER_ID_KEY, user_id);\n\t\t\t}\n\t\t\treturn auth;\n\t\t}\n\n\t\tthrow new AuthorizationException(\"Protocol is not supported.\");\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean plainAuth(BareJID user, String password) throws UserNotFoundException, TigaseDBException,\n\t\t\tAuthorizationException {\n\t\tthrow new AuthorizationException(\"Not supported.\");\n\t}\n\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) {\n\t\tString protocol = (String) authProps.get(PROTOCOL_KEY);\n\n\t\tif (protocol.equals(PROTOCOL_VAL_NONSASL)) {\n\t\t\tauthProps.put(RESULT_KEY, non_sasl_mechs);\n\t\t}\n\n\t\tif (protocol.equals(PROTOCOL_VAL_SASL)) {\n\t\t\tauthProps.put(RESULT_KEY, sasl_mechs);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeUser(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Not available\");\n\t}\n\n\tprivate boolean saslAuth(final Map<String, Object> props) throws AuthorizationException {\n\t\ttry {\n\t\t\tSaslPLAINLdap ss = new SaslPLAINLdap((String) props.get(SERVER_NAME_KEY));\n\n\t\t\tString data_str = (String) props.get(DATA_KEY);\n\t\t\tbyte[] in_data = ((data_str != null) ? Base64.decode(data_str) : new byte[0]);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"response: \" + new String(in_data));\n\t\t\t}\n\n\t\t\tbyte[] challenge = ss.evaluateResponse(in_data);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"challenge: \" + ((challenge != null) ? new String(challenge) : \"null\"));\n\t\t\t}\n\n\t\t\tString challenge_str = (((challenge != null) && (challenge.length > 0)) ? Base64.encode(challenge) : null);\n\n\t\t\tprops.put(RESULT_KEY, challenge_str);\n\n\t\t\tif (ss.isComplete()) {\n\t\t\t\tprops.put(USER_ID_KEY, ss.getUser_id());\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t} // end of if (ss.isComplete()) else\n\t\t} catch (SaslException e) {\n\t\t\tthrow new AuthorizationException(\"Sasl exception.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updatePassword(BareJID user, String password) throws UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Not available\");\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Not available\");\n\t}\n\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Feature not supported\");\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/db/xml/XMLRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\npackage tigase.db.xml;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthRepository;\nimport tigase.db.AuthRepositoryImpl;\nimport tigase.db.AuthorizationException;\nimport tigase.db.Repository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\nimport tigase.db.UserRepository;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.xml.db.NodeExistsException;\nimport tigase.xml.db.NodeNotFoundException;\nimport tigase.xml.db.XMLDB;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Class <code>XMLRepository</code> is a <em>XML</em> implementation of\n * <code>UserRepository</code>.\n * It uses <code>tigase.xml.db</code> package as repository backend and uses\n * <em>Bridge</em> design pattern to translate <code>XMLDB</code> calls to\n * <code>UserRepository</code> functions.\n *\n * <p>\n * Created: Tue Oct 26 15:27:33 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\n@Repository.Meta( supportedUris = { \"dummy\" } )\npublic class XMLRepository implements AuthRepository, UserRepository {\n\n\t/** Log filed */\n\tprivate static final String USER_STR = \"User: \";\n\n\t/** Log filed */\n\tprivate static final String NOT_FOUND_STR = \" has not been found in repository.\";\n\n\t/** Logger instance */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.db.xml.XMLRepository\");\n\n\t/** AuthRepository filed */\n\tprivate AuthRepository auth = null;\n\n\t/** XML database filed */\n\tprivate XMLDB xmldb = null;\n\n\t/** autoCreateUser filed */\n\tprivate boolean autoCreateUser = false;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic synchronized void addDataList(BareJID user, final String subnode, final String key,\n\t\t\tfinal String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Adding data list, user: {0}, subnode: {1}, key: {2}, list: {3}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key, Arrays.asList( list ) } );\n\n\t\ttry {\n\t\t\tString[] old_data = getDataList(user, subnode, key);\n\t\t\tString[] all = null;\n\n\t\t\tif (old_data != null) {\n\t\t\t\tall = new String[old_data.length + list.length];\n\t\t\t\tSystem.arraycopy(old_data, 0, all, 0, old_data.length);\n\t\t\t\tSystem.arraycopy(list, 0, all, old_data.length, list.length);\n\t\t\t\txmldb.setData(user.toString(), subnode, key, all);\n\t\t\t} else {\n\t\t\t\txmldb.setData(user.toString(), subnode, key, list);\n\t\t\t}    // end of else\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t}      // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized void addUser(BareJID user) throws UserExistsException {\n\t\tlog.log( Level.FINEST, \"adding new user, user: {0}\",\n\t\t\t\t\t\t new Object[] { user } );\n\t\ttry {\n\t\t\txmldb.addNode1(user.toString());\n\t\t} catch (NodeExistsException e) {\n\t\t\tthrow new UserExistsException(USER_STR + user + \" already exists.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized void addUser(BareJID user, final String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tauth.addUser(user, password);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic synchronized boolean digestAuth(BareJID user, final String digest, final String id,\n\t\t\tfinal String alg)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.digestAuth(user, digest, id, alg);\n\t}\n\n\t@Override\n\tpublic synchronized String getData(BareJID user, final String subnode, final String key,\n\t\t\tfinal String def)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Getting data, user: {0}, subnode: {1}, key: {2}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key } );\n\n\t\ttry {\n\t\t\treturn (String) xmldb.getData(user.toString(), subnode, key, def);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\n\t\t\t\t\treturn (String) xmldb.getData(user.toString(), subnode, key, def);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, final String subnode, final String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getData(user, subnode, key, null);\n\t}\n\n\t@Override\n\tpublic String getData(BareJID user, final String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn getData(user, null, key, null);\n\t}\n\n\t@Override\n\tpublic synchronized String[] getDataList(BareJID user, final String subnode,\n\t\t\tfinal String key)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Getting data list, user: {0}, subnode: {1}, key: {2}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key } );\n\n\t\ttry {\n\t\t\treturn xmldb.getDataList(user.toString(), subnode, key);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\n\t\t\t\t\treturn xmldb.getDataList(user.toString(), subnode, key);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized String[] getKeys(BareJID user, final String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Getting keys, user: {0}, subnode: {1}\",\n\t\t\t\t\t\t new Object[] { user, subnode } );\n\n\t\ttry {\n\t\t\treturn xmldb.getKeys(user.toString(), subnode);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\n\t\t\t\t\treturn xmldb.getKeys(user.toString(), subnode);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[] getKeys(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\treturn getKeys(user, null);\n\t}\n\n\t@Override\n\tpublic String getResourceUri() {\n\t\treturn xmldb.getDBFileName();\n\t}\n\n\t@Override\n\tpublic synchronized String[] getSubnodes(BareJID user, final String subnode)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Getting subnodes, user: {0}, subnode: {1}\",\n\t\t\t\t\t\t new Object[] { user, subnode } );\n\n\t\ttry {\n\t\t\treturn xmldb.getSubnodes(user.toString(), subnode);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\n\t\t\t\t\treturn xmldb.getSubnodes(user.toString(), subnode);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[] getSubnodes(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\treturn getSubnodes(user, null);\n\t}\n\n\t@Override\n\tpublic long getUserUID(BareJID user) throws TigaseDBException {\n\t\treturn Math.abs(user.hashCode());\n\t}\n\n\t@Override\n\tpublic synchronized List<BareJID> getUsers() {\n\t\tList<String> users = xmldb.getAllNode1s();\n\t\tlog.log( Level.FINEST, \"Getting users, users: {0}, xmldb: {1}\",\n\t\t\t\t\t\t new Object[] { users, xmldb } );\n\n\n\t\tList<BareJID> result = new ArrayList<BareJID>();\n\n\t\tfor (String usr : users) {\n\t\t\tresult.add(BareJID.bareJIDInstanceNS(usr));\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic synchronized long getUsersCount(String domain) {\n\t\tlong res = 0;\n\t\tList<BareJID> jids = getUsers();\n\n\t\tfor (BareJID jid : jids) {\n\t\t\tif (jid.getDomain().equals(domain)) {\n\t\t\t\t++res;\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\t@Override\n\tpublic synchronized long getUsersCount() {\n\t\treturn xmldb.getAllNode1sCount();\n\t}\n\n\t@Override\n\tpublic synchronized void initRepository(String file, Map<String, String> params) {\n\t\tString file_name = file;\n\n\t\tlog.log( Level.FINEST, \"Initializing repository, file: {0}, params: {1}\",\n\t\t\t\t\t\t new Object[] { file, params } );\n\n\t\ttry {\n\t\t\tint idx = file.indexOf(\"?\");\n\n\t\t\tif (idx > 0) {\n\t\t\t\tfile_name = file.substring(0, idx);\n\t\t\t}\n\n\t\t\tif (file.contains(\"autoCreateUser=true\")) {\n\t\t\t\tautoCreateUser = true;\n\t\t\t}    // end of if (db_conn.contains())\n\n\t\t\tauth = new AuthRepositoryImpl(this);\n\t\t\txmldb = new XMLDB(file_name);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"Can not open existing user repository file, creating new one, \" + e);\n\t\t\txmldb = XMLDB.createDB(file_name, \"users\", \"user\");\n\t\t}      // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized void logout(BareJID user)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tauth.logout(user);\n\t}\n\n\t@Override\n\tpublic synchronized boolean otherAuth(final Map<String, Object> props)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.otherAuth(props);\n\t}\n\n\t// Implementation of tigase.db.AuthRepository\n\n\t@Override\n\t@Deprecated\n\tpublic synchronized boolean plainAuth(BareJID user, final String password)\n\t\t\tthrows UserNotFoundException, TigaseDBException, AuthorizationException {\n\t\treturn auth.plainAuth(user, password);\n\t}\n\n\t@Override\n\tpublic synchronized void queryAuth(Map<String, Object> authProps) {\n\t\tauth.queryAuth(authProps);\n\t}\n\n\t@Override\n\tpublic synchronized void removeData(BareJID user, final String subnode, final String key)\n\t\t\tthrows UserNotFoundException {\n\t\tlog.log( Level.FINEST, \"Removing data, user: {0}, subnode: {1}, key: {2}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key } );\n\n\t\ttry {\n\t\t\txmldb.removeData(user.toString(), subnode, key);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif ( !autoCreateUser) {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic void removeData(BareJID user, final String key) throws UserNotFoundException {\n\t\tremoveData(user, null, key);\n\t}\n\n\t@Override\n\tpublic synchronized void removeSubnode(BareJID user, final String subnode)\n\t\t\tthrows UserNotFoundException {\n\t\tlog.log( Level.FINEST, \"Removing subnode, user: {0}, subnode: {1}\",\n\t\t\t\t\t\t new Object[] { user, subnode } );\n\n\t\ttry {\n\t\t\txmldb.removeSubnode(user.toString(), subnode);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif ( !autoCreateUser) {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized void removeUser(BareJID user) throws UserNotFoundException {\n\t\ttry {\n\t\tlog.log( Level.FINEST, \"Removing user: {0}\",\n\t\t\t\t\t\t new Object[] { user } );\n\n\t\t\txmldb.removeNode1(user.toString());\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t}    // end of try-catch\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic synchronized void setData( BareJID user, final String subnode, final String key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String value )\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Setting data, user: {0}, subnode: {1}, key: {2}, value: {3}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key, value } );\n\t\ttry {\n\t\t\txmldb.setData(user.toString(), subnode, key, value);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\t\t\t\t\txmldb.setData(user.toString(), subnode, key, value);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic void setData(BareJID user, final String key, final String value)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tsetData(user, null, key, value);\n\t}\n\n\t@Override\n\tpublic synchronized void setDataList(BareJID user, final String subnode, final String key,\n\t\t\tfinal String[] list)\n\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tlog.log( Level.FINEST, \"Setting data list, user: {0}, subnode: {1}, key: {2}, value: {3}\",\n\t\t\t\t\t\t new Object[] { user, subnode, key, Arrays.asList( list ) } );\n\t\ttry {\n\t\t\txmldb.setData(user.toString(), subnode, key, list);\n\t\t} catch (NodeNotFoundException e) {\n\t\t\tif (autoCreateUser) {\n\t\t\t\ttry {\n\t\t\t\t\taddUser(user);\n\t\t\t\t\txmldb.setData(user.toString(), subnode, key, list);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tthrow new TigaseDBException(\"Unknown repository problem: \", ex);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new UserNotFoundException(USER_STR + user + NOT_FOUND_STR, e);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic synchronized void updatePassword(BareJID user, final String password)\n\t\t\tthrows UserExistsException, TigaseDBException {\n\t\tauth.updatePassword(user, password);\n\t}\n\n\t@Override\n\tpublic synchronized boolean userExists(BareJID user) {\n\t\treturn xmldb.findNode1(user.toString()) != null;\n\t}\n\n\t@Override\n\tpublic String getPassword(BareJID user) throws UserNotFoundException, TigaseDBException {\n\t\treturn auth.getPassword(user);\n\t}\n\t\n\t@Override\n\tpublic boolean isUserDisabled(BareJID user) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic void setUserDisabled(BareJID user, Boolean value) \n\t\t\t\t\tthrows UserNotFoundException, TigaseDBException {\n\t\tthrow new TigaseDBException(\"Feature not supported\");\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disco/ServiceEntity.java",
    "content": "/*\n * ServiceEntity.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.disco;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Set;\n\n/**\n * Describe class ServiceEntity here.\n *\n *\n * Created: Sat Feb 10 13:11:34 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ServiceEntity {\n\tprivate static Logger log = Logger.getLogger(ServiceEntity.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Set<String>           features   = null;\n\tprivate List<ServiceIdentity> identities = null;\n\tprivate Set<ServiceEntity>    items      = null;\n\tprivate String                jid        = null;\n\tprivate String                name       = null;\n\tprivate String                node       = null;\n\tprivate boolean               adminOnly  = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>ServiceEntity</code> instance.\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param name\n\t */\n\tpublic ServiceEntity(String jid, String node, String name) {\n\t\tthis.jid  = jid;\n\t\tthis.node = node;\n\t\tthis.name = name;\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param name\n\t * @param adminOnly\n\t */\n\tpublic ServiceEntity(String jid, String node, String name, boolean adminOnly) {\n\t\tthis.jid       = jid;\n\t\tthis.node      = node;\n\t\tthis.name      = name;\n\t\tthis.adminOnly = adminOnly;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Describe <code>addFeatures</code> method here.\n\t *\n\t *\n\t * @param features\n\t */\n\tpublic void addFeatures(String... features) {\n\t\tif (this.features == null) {\n\t\t\tthis.features = new LinkedHashSet<String>();\n\t\t}\n\t\tCollections.addAll(this.features, features);\n\t}\n\n\t/**\n\t * Describe <code>addIdentities</code> method here.\n\t *\n\t *\n\t * @param identities\n\t */\n\tpublic void addIdentities(ServiceIdentity... identities) {\n\t\tif (this.identities == null) {\n\t\t\tthis.identities = new ArrayList<ServiceIdentity>();\n\t\t}\n\t\tCollections.addAll(this.identities, identities);\n\t}\n\n\t/**\n\t * Describe <code>addItems</code> method here.\n\t *\n\t *\n\t * @param items\n\t */\n\tpublic void addItems(ServiceEntity... items) {\n\t\tif (this.items == null) {\n\t\t\tthis.items = new LinkedHashSet<ServiceEntity>();\n\t\t}\n\n\t\t// It may look very strange but look at equals() method....\n\t\t// So some items which might be the same from the Set point of\n\t\t// view are not really the same. They may have different name.\n\t\t// This is to allow \"update\" the service discovery with some changed\n\t\t// info.... So in particular the \"name\" may contain some additional\n\t\t// information which can change at runtime\n\t\tfor (ServiceEntity item : items) {\n\t\t\tif (this.items.contains(item)) {\n\t\t\t\tthis.items.remove(item);\n\t\t\t}\n\t\t\tthis.items.add(item);\n\t\t}\n\t}\n\n\t/**\n\t * 2 ServiceEntities are equal of JIDs are equal and NODEs are equal.\n\t *\n\t * @param obj an <code>Object</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (obj instanceof ServiceEntity) {\n\t\t\tServiceEntity se = (ServiceEntity) obj;\n\n\t\t\t// Assuming here that jid can never be NULL\n\t\t\t// Node can be NULL so we need to do more calculation on it\n\t\t\treturn ((se == null)\n\t\t\t\t\t? false\n\t\t\t\t\t: jid.equals(se.jid)) && ((node == se.node) || ((node != null)\n\t\t\t\t\t? node.equals(se.node)\n\t\t\t\t\t: se.node.equals(node)));\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Describe <code>findNode</code> method here.\n\t *\n\t * @param node a <code>String</code> value\n\t * @return a <code>ServiceEntity</code> value\n\t */\n\tpublic ServiceEntity findNode(String node) {\n\n\t\t// System.out.println(\"Looking for a node: \" + node);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Looking for a node: \" + node);\n\t\t}\n\t\tif ((this.node != null) && this.node.equals(node)) {\n\n\t\t\t// System.out.println(\"Looking for a node: \" + node);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Found myself: \" + toString());\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t\tif (items == null) {\n\t\t\treturn null;\n\t\t}\n\t\tfor (ServiceEntity item : items) {\n\t\t\tString n = item.getNode();\n\n\t\t\tif ((n != null) && node.equals(n)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Found child item: \" + item.toString());\n\t\t\t\t}\n\n\t\t\t\treturn item;\n\t\t\t}\n\t\t}\n\n\t\tint idx = node.indexOf('/');\n\n\t\tif (idx >= 0) {\n\t\t\tString        top     = node.substring(0, idx);\n\t\t\tServiceEntity current = findNode(top);\n\n\t\t\tif (current != null) {\n\t\t\t\tString rest = node.substring(idx + 1);\n\n\t\t\t\treturn current.findNode(rest);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Describe <code>hashCode</code> method here.\n\t *\n\t * @return an <code>int</code> value\n\t */\n\tpublic int hashCode() {\n\t\treturn ((jid != null)\n\t\t\t\t? jid.hashCode()\n\t\t\t\t: 0) + ((node != null)\n\t\t\t\t? node.hashCode()\n\t\t\t\t: 0);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param items is a <code>ServiceEntity</code>\n\t */\n\tpublic void removeItems(ServiceEntity... items) {\n\t\tif (this.items == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (ServiceEntity item : items) {\n\t\t\tthis.items.remove(item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getDiscoItem(null, null).toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t *\n\t * @return a value of <code>Element[]</code>\n\t */\n\tpublic Element[] getDiscoFeatures(String node) {\n\t\tArrayList<Element> elFeatures = new ArrayList<Element>();\n\n\t\tif (features != null) {\n\t\t\tfor (String feature : features) {\n\t\t\t\telFeatures.add(new Element(\"feature\", new String[] { \"var\" }, new String[] {\n\t\t\t\t\t\tfeature }));\n\t\t\t}\n\t\t}\n\n\t\treturn (elFeatures.size() > 0)\n\t\t\t\t? elFeatures.toArray(new Element[elFeatures.size()])\n\t\t\t\t: null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t *\n\t * @return a value of <code>Element</code>\n\t */\n\tpublic Element getDiscoInfo(String node) {\n\t\treturn getDiscoInfo(node, true);\n\t}\n\n\t/**\n\t * Describe <code>getDiscoInfo</code> method here.\n\t *\n\t * @param node a <code>String</code> value\n\t * @param admin is a <code>boolean</code>\n\t * @return an <code>Element</code> value\n\t */\n\tpublic Element getDiscoInfo(String node, boolean admin) {\n\n\t\t// System.out.println(\"Node: \" + node);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Node: \" + node);\n\t\t}\n\n\t\tElement query = null;\n\n\t\tif (node == null) {\n\n\t\t\t// If the node is for admins only and this is not admin return null\n\t\t\tif (adminOnly &&!admin) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"It's me: \" + toString());\n\t\t\t}\n\t\t\tquery = new Element(\"query\", new String[] { \"xmlns\" }, new String[] {\n\t\t\t\t\t\"http://jabber.org/protocol/disco#info\" });\n\t\t\tif (identities != null) {\n\t\t\t\tfor (ServiceIdentity ident : identities) {\n\t\t\t\t\tquery.addChild(ident.getElement());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (features != null) {\n\t\t\t\tfor (String feature : features) {\n\t\t\t\t\tquery.addChild(new Element(\"feature\", new String[] { \"var\" }, new String[] {\n\t\t\t\t\t\t\tfeature }));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tServiceEntity entity = findNode(node);\n\n\t\t\t// If the entity is for admins only and this is not admin return null\n\t\t\tif ((entity != null) && entity.adminOnly &&!admin) {\n\t\t\t\tentity = null;\n\t\t\t}\n\t\t\tif (entity != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Found child node: \" + entity.toString());\n\t\t\t\t}\n\t\t\t\tquery = entity.getDiscoInfo(null);\n\t\t\t\tquery.setAttribute(\"node\", node);\n\t\t\t}\n\t\t}\n\n\t\treturn query;\n\t}\n\n\t/**\n\t * Describe <code>getDiscoItem</code> method here.\n\t *\n\t * @param node a <code>String</code> value\n\t * @param jid a <code>String</code> value\n\t * @return an <code>Element</code> value\n\t */\n\tpublic Element getDiscoItem(String node, String jid) {\n\t\tElement item = new Element(\"item\");\n\n\t\tif (jid != null) {\n\t\t\titem.setAttribute(\"jid\", jid);\n\t\t} else {\n\t\t\tif (this.jid != null) {\n\t\t\t\titem.setAttribute(\"jid\", this.jid);\n\t\t\t}\n\t\t}\n\t\tif (node != null) {\n\t\t\titem.setAttribute(\"node\", node + ((this.node != null)\n\t\t\t\t\t? \"/\" + this.node\n\t\t\t\t\t: \"\"));\n\t\t} else {\n\t\t\tif (this.node != null) {\n\t\t\t\titem.setAttribute(\"node\", this.node);\n\t\t\t}\n\t\t}\n\t\tif (name != null) {\n\t\t\titem.setAttribute(\"name\", name);\n\t\t}\n\n\t\treturn item;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t * @param jid is a <code>String</code>\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\tpublic List<Element> getDiscoItems(String node, String jid) {\n\t\treturn getDiscoItems(node, jid, true);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t * @param jid is a <code>String</code>\n\t * @param admin is a <code>boolean</code>\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\tpublic List<Element> getDiscoItems(String node, String jid, boolean admin) {\n\n\t\t// System.out.println(\"node: \" + node + \", jid: \" + jid);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"node: \" + node + \", jid: \" + jid);\n\t\t}\n\n\t\tList<Element> result = null;\n\n\t\tif (node == null) {\n\t\t\tresult = getItems(null, jid, admin);\n\t\t} else {\n\t\t\tServiceEntity entity = findNode(node);\n\n\t\t\tif ((entity != null) && entity.adminOnly &&!admin) {\n\t\t\t\tentity = null;\n\t\t\t}\n\n\t\t\t// System.out.println(\"Found disco entity: \" + entity.toString());\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Found disco entity: \" + ((entity != null)\n\t\t\t\t\t\t? entity.toString()\n\t\t\t\t\t\t: null));\n\t\t\t}\n\t\t\tif (entity != null) {\n\t\t\t\tresult = entity.getItems(node, jid, admin);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t * @param jid is a <code>String</code>\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\tpublic List<Element> getItems(String node, String jid) {\n\t\treturn getItems(node, jid, true);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node is a <code>String</code>\n\t * @param jid is a <code>String</code>\n\t * @param admin is a <code>boolean</code>\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\tpublic List<Element> getItems(String node, String jid, boolean admin) {\n\t\tList<Element> result = null;\n\n\t\tif (items != null) {\n\t\t\tresult = new ArrayList<Element>();\n\t\t\tfor (ServiceEntity item : items) {\n\t\t\t\tif (item.adminOnly &&!admin) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresult.add(item.getDiscoItem(node, jid));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Describe <code>getJID</code> method here.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tpublic String getJID() {\n\t\treturn jid;\n\t}\n\n\t/**\n\t * Describe <code>getName</code> method here.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * Describe <code>getNode</code> method here.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tpublic String getNode() {\n\t\treturn node;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isAdminOnly() {\n\t\treturn adminOnly;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param adminOnly is a <code>boolean</code>\n\t */\n\tpublic void setAdminOnly(boolean adminOnly) {\n\t\tthis.adminOnly = adminOnly;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param description is a <code>String</code>\n\t */\n\tpublic void setDescription(String description) {\n\t\tthis.name = description;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param features is a <code>String</code>\n\t */\n\tpublic void setFeatures(String... features) {\n\t\tthis.features = null;\n\t\taddFeatures(features);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param identities is a <code>ServiceIdentity</code>\n\t */\n\tpublic void setIdentities(ServiceIdentity... identities) {\n\t\tthis.identities = new ArrayList<ServiceIdentity>();\n\t\tCollections.addAll(this.identities, identities);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/10/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disco/ServiceIdentity.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.disco;\n\nimport tigase.xml.Element;\n\n/**\n * Describe class ServiceIdentity here.\n *\n *\n * Created: Sat Feb 10 13:34:54 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ServiceIdentity {\n\n\tprivate String category = null;\n\tprivate String type = null;\n\tprivate String name = null;\n\n\t/**\n\t * Creates a new <code>ServiceIdentity</code> instance.\n\t *\n\t */\n\tpublic ServiceIdentity(String category, String type, String name) {\n\t\tthis.category = category;\n\t\tthis.type = type;\n\t\tthis.name = name;\n\t}\n\n\tpublic String getCategory() {\n\t\treturn category;\n\t}\n\n\tpublic String getType() {\n\t\treturn type;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic Element getElement() {\n\t\treturn new Element(\"identity\",\n\t\t\tnew String[] {\"category\", \"type\", \"name\"},\n\t\t\tnew String[] {category, type, name});\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disco/XMPPService.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.disco;\n\nimport java.util.List;\nimport tigase.xml.Element;\nimport tigase.server.ServerComponent;\nimport tigase.xmpp.JID;\n\n/**\n * Interface XMPPService\n *\n * Objects which implement this interface can respond to \"ServiceDiscovery\"\n * requests. All such requests are managed by MessageRouter instance.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPService extends ServerComponent {\n\n\t/**\n\t * A convenience constant with service discovery info xmlns string.\n\t */\n\tpublic static final String INFO_XMLNS =\n\t\t\t\"http://jabber.org/protocol/disco#info\";\n\t/**\n\t * A convenience constant with service discovery items xmlns string.\n\t */\n\tpublic static final String ITEMS_XMLNS =\n\t\t\t\"http://jabber.org/protocol/disco#items\";\n\t/**\n\t * A convenience constant with all stream features for service discovery.\n\t */\n\tpublic static final String[] DEF_FEATURES = {INFO_XMLNS, ITEMS_XMLNS};\n\t/**\n\t * A convenience constant with component features related to ad-hoc commands.\n\t */\n\tpublic static final String[] CMD_FEATURES =\n {\n\t\t\"http://jabber.org/protocol/commands\", \"jabber:x:data\"};\n\n\t/**\n\t * Returns service discovery info for the component. If the jid is null then this is\n\t * info for the top level request. SM may return disco info on the top level. Other\n\t * components should not.\n\t *\n\t * @param node is service discovery node for which the request is made. Is\n\t * normally null for the component top level request.\n\t * @param jid is the jid to which the request has been made.\n\t * @param from is the request sender address. Some service discovery information\n\t * is only meant for administrators.\n\t * @return returns an XML Element with service discovery data.\n\t */\n\tElement getDiscoInfo(String node, JID jid, JID from);\n\n\t/**\n\t * Returns service discovery items for the component. If the JID is null then this is\n\t * request for the top level request. SM may return disco items on the top level, other\n\t * components should just return it's top level service discovery item for null node.\n\t * @param node is a service discovery node for which the request has been made.\n\t * @param jid is the jid to which the request has been made.\n\t * @param from is the request sender address. Some service discovery information\n\t * is only meant for administrators.\n\t * @return a list of service discovery items for this component or the component\n\t * itself disco item for the top level request.\n\t */\n\tList<Element> getDiscoItems(String node, JID jid, JID from);\n\n\t/**\n\t * Returns features for top level disco info\n\t *\n\t * @param from a request sender address. Some service disco elements are meant\n\t * to be available only to system administrarors. The component is responsible to\n\t * check whether the sender is the component administrator and return results\n\t * appropriate.\n\t * @return a list of elements with service discovery features.\n\t */\n\tList<Element> getDiscoFeatures(JID from);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disco/XMPPServiceCollector.java",
    "content": "/*\n * XMPPServiceCollector.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.disco;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractComponentRegistrator;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.ServerComponent;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.logging.Logger;\nimport java.util.Queue;\n\n/**\n * Class XMPPServiceCollector\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class XMPPServiceCollector\n\t\t\t\textends AbstractComponentRegistrator<XMPPService> {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\t@SuppressWarnings(\"unused\")\n\tprivate static final Logger log =\n\t\tLogger.getLogger(XMPPServiceCollector.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate ServiceEntity serviceEntity = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic XMPPServiceCollector() {\n\t\tserviceEntity = new ServiceEntity(\"Tigase\", \"server\", \"Session manager\");\n\t\tserviceEntity.addIdentities(new ServiceIdentity[] {\n\t\t\tnew ServiceIdentity(\"server\", \"im\",\n\t\t\t\t\t\t\t\t\t\t\t\t\ttigase.server.XMPPServer.NAME + \" ver. \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\ttigase.server.XMPPServer.getImplementationVersion()) });\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param component\n\t */\n\t@Override\n\tpublic void componentAdded(XMPPService component) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param component\n\t */\n\t@Override\n\tpublic void componentRemoved(XMPPService component) {}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isCorrectType(ServerComponent component) {\n\t\treturn component instanceof XMPPService;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(final Packet packet, final Queue<Packet> results) {\n\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, INFO_XMLNS) ||\n\t\t\t\tpacket.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, ITEMS_XMLNS)) {\n\t\t\tJID jid       = packet.getStanzaTo();\n\t\t\tJID from      = packet.getStanzaFrom();\n\t\t\tString node   = packet.getAttributeStaticStr(Iq.IQ_QUERY_PATH, \"node\");\n\t\t\tElement query = packet.getElement().getChild(\"query\").clone();\n\n\t\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, INFO_XMLNS)) {\n\t\t\t\tfor (XMPPService comp : components.values()) {\n\t\t\t\t\tElement resp = comp.getDiscoInfo(node, jid, from);\n\n\t\t\t\t\tif (resp != null) {\n\t\t\t\t\t\tquery = resp;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}      // end of for ()\n\t\t\t}\n\t\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, ITEMS_XMLNS)) {\n\t\t\t\tfor (XMPPService comp : components.values()) {\n\t\t\t\t\tList<Element> items = comp.getDiscoItems(node, jid, from);\n\n\t\t\t\t\tif ((items != null) && (items.size() > 0)) {\n\t\t\t\t\t\tquery.addChildren(items);\n\t\t\t\t\t}    // end of if (stats != null && stats.count() > 0)\n\t\t\t\t}      // end of for ()\n\t\t\t}\n\t\t\tresults.offer(packet.okResult(query, 0));\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/DistEventBusException.java",
    "content": "package tigase.disteventbus;\n\npublic class DistEventBusException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic DistEventBusException() {\n\t\tsuper();\n\t}\n\n\tpublic DistEventBusException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic DistEventBusException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n\n\tpublic DistEventBusException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {\n\t\tsuper(message, cause, enableSuppression, writableStackTrace);\n\t}\n\n\tpublic DistEventBusException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/EventBus.java",
    "content": "package tigase.disteventbus;\n\nimport tigase.xml.Element;\n\npublic interface EventBus {\n\n\t/**\n\t * Registers handler to receive events with given name and namespace.\n\t * \n\t * @param name\n\t *            name of events. Can be {@code null}, then handler will be\n\t *            received all events with given {@code xmlns}.\n\t * @param xmlns\n\t *            namespace of events.\n\t * @param handler\n\t *            event handler.\n\t */\n\tpublic void addHandler(final String name, final String xmlns, final EventHandler handler);\n\n\tpublic void fire(final Element event);\n\n\tpublic void removeHandler(final String name, final String xmlns, final EventHandler handler);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/EventBusFactory.java",
    "content": "package tigase.disteventbus;\n\nimport tigase.disteventbus.impl.LocalEventBus;\n\npublic class EventBusFactory {\n\n\tprivate final static LocalEventBus eventBus = new LocalEventBus();\n\n\tprivate EventBusFactory() {\n\t}\n\n\tpublic static EventBus getInstance() {\n\t\treturn eventBus;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/EventHandler.java",
    "content": "package tigase.disteventbus;\n\nimport tigase.xml.Element;\n\npublic interface EventHandler {\n\n\tvoid onEvent(String name, String xmlns, Element event);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/FireEventException.java",
    "content": "package tigase.disteventbus;\n\nimport java.util.Collection;\n\npublic class FireEventException extends DistEventBusException {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected static String createMessage(Collection<Throwable> causes) {\n\t\tif (causes.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tStringBuilder b = new StringBuilder();\n\n\t\tint c = causes.size();\n\t\tif (c == 1) {\n\t\t\tb.append(\"Exception caught: \");\n\t\t} else {\n\t\t\tb.append(c).append(\" exceptions caught: \");\n\t\t}\n\n\t\tboolean first = true;\n\t\tfor (Throwable t : causes) {\n\t\t\tif (first) {\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tb.append(\"; \");\n\t\t\t}\n\t\t\tb.append(t.getMessage());\n\t\t}\n\n\t\treturn b.toString();\n\t}\n\n\tprotected static Throwable createThrowable(Collection<Throwable> causes) {\n\t\tif (causes.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\treturn causes.iterator().next();\n\t}\n\n\tprivate final Collection<Throwable> causes;\n\n\tpublic FireEventException(Collection<Throwable> causes) {\n\t\tsuper(createMessage(causes), createThrowable(causes));\n\t\tthis.causes = causes;\n\t}\n\n\t/**\n\t * Returns collection of all Exceptions throwed by handlers or listeners.\n\t * \n\t * @return collection of Exceptions.\n\t */\n\tpublic Collection<Throwable> getCauses() {\n\t\treturn causes;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/AbstractEventBusModule.java",
    "content": "package tigase.disteventbus.component;\n\nimport tigase.component.modules.AbstractModule;\nimport tigase.xmpp.JID;\n\npublic abstract class AbstractEventBusModule extends AbstractModule<EventBusContext> {\n\n\tprivate static long id = 0;\n\n\tprotected boolean isClusteredEventBus(final JID jid) {\n\t\treturn jid.getLocalpart().equals(\"eventbus\") && context.getConnectedNodes().contains(jid);\n\t}\n\n\tprotected String nextStanzaID() {\n\n\t\tString prefix = context.getComponentID().getDomain();\n\n\t\tsynchronized (this) {\n\t\t\treturn prefix + \"-\" + (++id);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/AddListenerScriptCommand.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class AddListenerScriptCommand implements AdHocCommand {\n\n\tprivate ListenerScriptRegistrar registrar;\n\n\tprivate ScriptEngineManager scriptEngineManager;\n\n\tpublic AddListenerScriptCommand(ScriptEngineManager scriptEngineManager, ListenerScriptRegistrar registrar) {\n\t\tthis.scriptEngineManager = scriptEngineManager;\n\t\tthis.registrar = registrar;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tForm form = new Form(\"form\", \"Add listener script\", null);\n\n\t\t\t\tList<ScriptEngineFactory> sef = scriptEngineManager.getEngineFactories();\n\t\t\t\tArrayList<String> labels = new ArrayList<String>();\n\t\t\t\tArrayList<String> values = new ArrayList<String>();\n\t\t\t\tfor (ScriptEngineFactory scriptEngineFactory : sef) {\n\t\t\t\t\tlabels.add(scriptEngineFactory.getLanguageName());\n\t\t\t\t\tvalues.add(scriptEngineFactory.getExtensions().get(0));\n\t\t\t\t}\n\n\t\t\t\tform.addField(Field.fieldTextSingle(\"scriptName\", \"\", \"Script name\"));\n\t\t\t\tform.addField(Field.fieldListSingle(\"scriptExtension\", \"\", \"Script engine\", labels.toArray(new String[] {}),\n\t\t\t\t\t\tvalues.toArray(new String[] {})));\n\n\t\t\t\tField f = Field.fieldTextSingle(\"eventName\", \"\", \"Event name\");\n\t\t\t\tf.setRequired(false);\n\t\t\t\tform.addField(f);\n\n\t\t\t\tf = Field.fieldTextSingle(\"eventXMLNS\", \"\", \"Event namespace\");\n\t\t\t\tf.setRequired(true);\n\t\t\t\tform.addField(f);\n\n\t\t\t\tform.addField(Field.fieldTextMulti(\"scriptContent\", \"\", \"Script\"));\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tString scriptName = form.getAsString(\"scriptName\");\n\t\t\t\t\tString scriptExtension = form.getAsString(\"scriptExtension\");\n\t\t\t\t\tString scriptContent = form.getAsString(\"scriptContent\");\n\n\t\t\t\t\tString eventName = form.getAsString(\"eventName\");\n\t\t\t\t\tString eventXMLNS = form.getAsString(\"eventXMLNS\");\n\n\t\t\t\t\tregistrar.registerScript(scriptName, scriptExtension, scriptContent,\n\t\t\t\t\t\t\teventName == null || eventName.isEmpty() ? null : eventName, eventXMLNS);\n\t\t\t\t}\n\n\t\t\t\tresponse.completeSession();\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Add listener script\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn \"add-listener-script\";\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/ElemPathCriteria.java",
    "content": "package tigase.disteventbus.component;\n\nimport tigase.criteria.Criteria;\nimport tigase.xml.Element;\n\npublic class ElemPathCriteria implements Criteria {\n\n\tpublic static void main(String[] args) {\n\t\t// ElemPathCriteria c = new ElemPathCriteria(new String[] { \"iq\",\n\t\t// \"pubsub\", \"subscribe\" }, new String[] { null,\n\t\t// \"http://jabber.org/protocol/pubsub\", null });\n\n\t\tElemPathCriteria c = new ElemPathCriteria(new String[] { \"iq\", \"pubsub\", \"subscribe\" }, new String[] { null,\n\t\t\t\t\"http://jabber.org/protocol/pubsub\", null });\n\n\t\tElement e = new Element(\"iq\");\n\t\tElement x = new Element(\"pubsub\", new String[] { \"xmlns\" }, new String[] { \"http://jabber.org/protocol/pubsub\" });\n\t\tx.addChild(new Element(\"subscribe\"));\n\t\te.addChild(x);\n\n\t\tSystem.out.println(e.getChildrenStaticStr(new String[] { \"iq\", \"pubsub\" }));\n\n\t\tSystem.out.println(c.match(e));\n\n\t}\n\n\tprivate final String[] names;\n\n\tprivate final String[] xmlns;\n\n\tpublic ElemPathCriteria(String[] elemNames, String[] namespaces) {\n\t\tthis.names = elemNames;\n\t\tthis.xmlns = namespaces;\n\t}\n\n\t@Override\n\tpublic Criteria add(Criteria criteria) {\n\t\tthrow new RuntimeException(\"UNSUPPORTED!\");\n\t}\n\n\t@Override\n\tpublic boolean match(Element element) {\n\n\t\tboolean match = element.getName().equals(names[0]);\n\t\tif (match && xmlns[0] != null)\n\t\t\tmatch &= xmlns[0].equals(element.getXMLNS());\n\n\t\tElement child = element;\n\t\tint i = 1;\n\t\tfor (; i < names.length; i++) {\n\t\t\tString n = names[i];\n\t\t\tString x = xmlns[i];\n\n\t\t\tchild = child.getChildStaticStr(n, x);\n\n\t\t\tmatch &= child != null;\n\n\t\t\tif (!match)\n\t\t\t\treturn match;\n\n\t\t}\n\n\t\t// TODO Auto-generated method stub\n\t\treturn match;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/EventBusComponent.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\n\nimport javax.script.ScriptEngineManager;\n\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.component.AbstractComponent;\nimport tigase.component.AbstractContext;\nimport tigase.component.modules.Module;\nimport tigase.component.modules.impl.AdHocCommandModule;\nimport tigase.component.modules.impl.DiscoveryModule;\nimport tigase.component.modules.impl.JabberVersionModule;\nimport tigase.component.modules.impl.XmppPingModule;\nimport tigase.conf.ConfigurationException;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.disteventbus.component.stores.Affiliation;\nimport tigase.disteventbus.component.stores.AffiliationStore;\nimport tigase.disteventbus.component.stores.SubscriptionStore;\nimport tigase.disteventbus.impl.LocalEventBus;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.JID;\n\npublic class EventBusComponent extends AbstractComponent<EventBusContext>implements ClusteredComponentIfc {\n\n\tpublic static final String COMPONENT_EVENTS_XMLNS = \"tigase:eventbus\";\n\tprivate static final String THREADS_KEY = \"threads\";\n\tprivate static long counter = 0;\n\tprivate final AffiliationStore affiliationStore = new AffiliationStore();\n\tprivate final Map<String, ListenerScript> listenersScripts = new ConcurrentHashMap<String, ListenerScript>();\n\t/**\n\t * For cluster nodes.\n\t */\n\tprivate final SubscriptionStore subscriptionStore = new SubscriptionStore();\n\tprivate ScriptEngineManager scriptEngineManager = new ScriptEngineManager();\n\n\tprivate ListenerScriptRegistrar scriptsRegistrar;\n\n\tpublic EventBusComponent() {\n\t}\n\n\t@Override\n\tprotected EventBusContext createContext() {\n\t\treturn new EventBusContextImpl(this);\n\t}\n\n\t@Override\n\tpublic String getComponentVersion() {\n\t\tString version = this.getClass().getPackage().getImplementationVersion();\n\t\treturn version == null ? \"0.0.0\" : version;\n\t}\n\n\t@Override\n\tprotected Map<String, Class<? extends Module>> getDefaultModulesList() {\n\t\tfinal Map<String, Class<? extends Module>> result = new HashMap<String, Class<? extends Module>>();\n\n\t\tresult.put(SubscribeModule.ID, SubscribeModule.class);\n\t\tresult.put(UnsubscribeModule.ID, UnsubscribeModule.class);\n\t\tresult.put(EventReceiverModule.ID, EventReceiverModule.class);\n\t\tresult.put(EventPublisherModule.ID, EventPublisherModule.class);\n\n\t\tresult.put(XmppPingModule.ID, XmppPingModule.class);\n\t\tresult.put(JabberVersionModule.ID, JabberVersionModule.class);\n\t\tresult.put(AdHocCommandModule.ID, AdHocCommandModule.class);\n\t\tresult.put(DiscoveryModule.ID, DiscoveryModule.class);\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategory() {\n\t\treturn \"component\";\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"generic\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Distributed EventBus\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t}\n\n\t@Override\n\tpublic boolean isDiscoNonAdmin() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isSubdomain() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tprotected void onNodeConnected(JID jid) {\n\t\tsuper.onNodeConnected(jid);\n\n\t\tif (log.isLoggable(Level.FINE))\n\t\t\tlog.fine(\"Cluster node \" + jid + \" added to Affiliation Store\");\n\n\t\tcontext.getAffiliationStore().putAffiliation(jid, Affiliation.owner);\n\n\t\tModule module = modulesManager.getModule(SubscribeModule.ID);\n\t\tif (module != null && module instanceof SubscribeModule) {\n\t\t\t((SubscribeModule) module).clusterNodeConnected(jid);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onNodeDisconnected(JID jid) {\n\t\tsuper.onNodeDisconnected(jid);\n\n\t\tModule module = modulesManager.getModule(SubscribeModule.ID);\n\t\tif (module != null && module instanceof SubscribeModule) {\n\t\t\t((SubscribeModule) module).clusterNodeDisconnected(jid);\n\t\t}\n\t\tcontext.getAffiliationStore().removeAffiliation(jid);\n\t}\n\n\t@Override\n\tpublic void processPacket(tigase.server.Packet packet) {\n\t\tsuper.processPacket(packet);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\n\t\tscriptsRegistrar = new ListenerScriptRegistrar(listenersScripts, context, scriptEngineManager);\n\n\t\tAdHocCommandModule<?> adHocCommandModule = getModuleProvider().getModule(AdHocCommandModule.ID);\n\t\tif (adHocCommandModule != null) {\n\t\t\tadHocCommandModule.register(new AddListenerScriptCommand(scriptEngineManager, scriptsRegistrar));\n\t\t\tadHocCommandModule.register(new RemoveListenerScriptCommand(listenersScripts, scriptsRegistrar));\n\t\t}\n\n\t\tif (props.containsKey(\"allowed-subscribers\")) {\n\t\t\tString t = (String) props.get(\"allowed-subscribers\");\n\t\t\tString[] x = t.split(\",\");\n\t\t\tfor (String string : x) {\n\t\t\t\tcontext.getAffiliationStore().putAffiliation(JID.jidInstanceNS(string), Affiliation.member);\n\t\t\t}\n\t\t}\n\n\t\tif (props.containsKey(THREADS_KEY)) {\n\t\t\tInteger threads = (Integer) props.get(THREADS_KEY);\n\t\t\tcontext.getEventBusInstance().setThreadPool(threads);\n\t\t}\n\t\tscriptsRegistrar.load();\n\t}\n\n\tprivate class EventBusContextImpl extends AbstractContext implements EventBusContext {\n\n\t\tprivate final LocalEventBus eventBusInstance;\n\n\t\tpublic EventBusContextImpl(AbstractComponent<?> component) {\n\t\t\tsuper(component);\n\t\t\tthis.eventBusInstance = (LocalEventBus) EventBusFactory.getInstance();\n\t\t}\n\n\t\t@Override\n\t\tpublic AffiliationStore getAffiliationStore() {\n\t\t\treturn affiliationStore;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<JID> getConnectedNodes() {\n\t\t\treturn Collections.unmodifiableCollection(getNodesConnected());\n\t\t}\n\n\t\t@Override\n\t\tpublic LocalEventBus getEventBusInstance() {\n\t\t\treturn eventBusInstance;\n\t\t}\n\n\t\t@Override\n\t\tpublic SubscriptionStore getSubscriptionStore() {\n\t\t\treturn subscriptionStore;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/EventBusContext.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.Collection;\n\nimport tigase.component.Context;\nimport tigase.disteventbus.component.stores.AffiliationStore;\nimport tigase.disteventbus.component.stores.SubscriptionStore;\nimport tigase.disteventbus.impl.LocalEventBus;\nimport tigase.xmpp.JID;\n\npublic interface EventBusContext extends Context {\n\n\tAffiliationStore getAffiliationStore();\n\n\tCollection<JID> getConnectedNodes();\n\n\tLocalEventBus getEventBusInstance();\n\n\tSubscriptionStore getSubscriptionStore();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/EventPublisherModule.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.Collection;\nimport java.util.logging.Level;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.criteria.Criteria;\nimport tigase.disteventbus.EventHandler;\nimport tigase.disteventbus.component.stores.Subscription;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\npublic class EventPublisherModule extends AbstractEventBusModule {\n\n\tpublic final static String ID = \"publisher\";\n\n\tprivate final EventHandler eventBusEventFiredHandler = new EventHandler() {\n\t\t@Override\n\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\tpublishEvent(name, xmlns, event);\n\t\t}\n\t};\n\n\t@Override\n\tpublic void afterRegistration() {\n\t\tsuper.afterRegistration();\n\n\t\tcontext.getEventBusInstance().addHandler(null, null, eventBusEventFiredHandler);\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException, TigaseStringprepException {\n\t}\n\n\tpublic void publishEvent(Element event) {\n\t\tpublishEvent(event.getName(), event.getXMLNS(), event);\n\t}\n\n\tprivate void publishEvent(Element pubsubEventElem, String from, JID toJID) throws TigaseStringprepException {\n\t\tPacket message = Packet.packetInstance(new Element(\"message\", new String[] { \"to\", \"from\", \"id\" },\n\t\t\t\tnew String[] { toJID.toString(), from, nextStanzaID() }));\n\t\tmessage.getElement().addChild(pubsubEventElem);\n\t\tmessage.setXMLNS(Packet.CLIENT_XMLNS);\n\n\t\tmessage.setPermissions(Permissions.ADMIN);\n\n\t\twrite(message);\n\t}\n\n\tpublic void publishEvent(final String name, final String xmlns, Element event) {\n\t\tfinal String isRemote = event.getAttributeStaticStr(\"remote\");\n\t\tif (isRemote != null && (\"true\".equals(isRemote) || \"1\".equals(isRemote))) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Remote event. No need to redistribute this way. \" + event.toString());\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tfinal String isLocal = event.getAttributeStaticStr(\"local\");\n\t\tif (isLocal != null && (\"true\".equals(isLocal) || \"1\".equals(isLocal))) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Event for local subscribers only. Skipping. \" + event.toString());\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tfinal Collection<Subscription> subscribers = context.getSubscriptionStore().getSubscribersJIDs(name, xmlns);\n\t\tpublishEvent(name, xmlns, event, subscribers);\n\t}\n\n\tpublic void publishEvent(String name, String xmlns, Element event, Collection<Subscription> subscribers) {\n\t\ttry {\n\t\t\tfinal Element eventElem = new Element(\"event\", new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { \"http://jabber.org/protocol/pubsub#event\" });\n\t\t\tfinal Element itemsElem = new Element(\"items\", new String[] { \"node\" },\n\t\t\t\t\tnew String[] { NodeNameUtil.createNodeName(name, xmlns) });\n\t\t\teventElem.addChild(itemsElem);\n\t\t\tfinal Element itemElem = new Element(\"item\");\n\t\t\titemElem.addChild(event);\n\t\t\titemsElem.addChild(itemElem);\n\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Sending event ({0}, {1}, {2}) to {3}\", new Object[] { name, xmlns, event, subscribers });\n\t\t\t}\n\n\t\t\tfor (Subscription subscriber : subscribers) {\n\n\t\t\t\tString from;\n\t\t\t\tif (subscriber.getServiceJID() == null) {\n\t\t\t\t\tfrom = context.getComponentID().toString();\n\t\t\t\t} else {\n\t\t\t\t\tfrom = subscriber.getServiceJID().toString();\n\t\t\t\t}\n\t\t\t\tJID toJID = subscriber.getJid();\n\n\t\t\t\tpublishEvent(eventElem, from, toJID);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void unregisterModule() {\n\t\tcontext.getEventBusInstance().removeHandler(null, null, eventBusEventFiredHandler);\n\t\tsuper.unregisterModule();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/EventReceiverModule.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.logging.Level;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.criteria.Criteria;\nimport tigase.disteventbus.component.stores.Affiliation;\nimport tigase.disteventbus.component.stores.Subscription;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\n\npublic class EventReceiverModule extends AbstractEventBusModule {\n\n\tpublic final static String ID = \"receiver\";\n\tprivate static final Criteria CRIT = new ElemPathCriteria(new String[] { \"message\", \"event\" },\n\t\t\tnew String[] { null, \"http://jabber.org/protocol/pubsub#event\" });\n\tprivate EventPublisherModule eventPublisherModule;\n\n\t@Override\n\tpublic void afterRegistration() {\n\t\tsuper.afterRegistration();\n\n\t\teventPublisherModule = context.getModuleProvider().getModule(EventPublisherModule.ID);\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException, TigaseStringprepException {\n\t\tfinal Affiliation affiliation = context.getAffiliationStore().getAffiliation(packet.getStanzaFrom());\n\t\tif (!affiliation.isPublishItem())\n\t\t\tthrow new ComponentException(Authorization.FORBIDDEN);\n\n\t\tfinal String type = packet.getElement().getAttributeStaticStr(\"type\");\n\n\t\tif (type != null && type.equals(\"error\")) {\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"Ignoring error message! \" + packet);\n\t\t\treturn;\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINER))\n\t\t\tlog.finer(\"Received event stanza: \" + packet.toStringFull());\n\n\t\tElement eventElem = packet.getElement().getChild(\"event\", \"http://jabber.org/protocol/pubsub#event\");\n\t\tElement itemsElem = eventElem.getChild(\"items\");\n\n\t\tfor (Element item : itemsElem.getChildren()) {\n\t\t\tif (!\"item\".equals(item.getName()))\n\t\t\t\tcontinue;\n\t\t\tfor (Element event : item.getChildren()) {\n\t\t\t\tString eventName = event.getName();\n\t\t\t\tString eventXmlns = event.getXMLNS();\n\n\t\t\t\tevent.setAttribute(\"remote\", \"true\");\n\n\t\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\t\tlog.finer(\"Received event (\" + eventName + \", \" + eventXmlns + \"): \" + event);\n\n\t\t\t\tcontext.getEventBusInstance().doFire(eventName, eventXmlns, event);\n\n\t\t\t\t// forwarding event to _non cluster_ subscribers.\n\t\t\t\tfinal Collection<Subscription> subscribers = context.getSubscriptionStore().getSubscribersJIDs(eventName,\n\t\t\t\t\t\teventXmlns);\n\t\t\t\tIterator<Subscription> it = subscribers.iterator();\n\t\t\t\twhile (it.hasNext()) {\n\t\t\t\t\tSubscription subscription = it.next();\n\t\t\t\t\tif (subscription.isInClusterSubscription())\n\t\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t\teventPublisherModule.publishEvent(eventName, eventXmlns, event, subscribers);\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/ListenerScript.java",
    "content": "package tigase.disteventbus.component;\n\nimport javax.script.Bindings;\nimport javax.script.Compilable;\nimport javax.script.CompiledScript;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\n\nimport tigase.disteventbus.EventHandler;\nimport tigase.xml.Element;\n\npublic class ListenerScript implements EventHandler {\n\n\tprivate CompiledScript compiledScript;\n\n\tprivate EventBusContext context;\n\n\tprivate ScriptEngine engine;\n\n\tprivate String eventName;\n\n\tprivate String eventXMLNS;\n\n\tprivate String scriptContent;\n\n\t@Override\n\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\ttry {\n\t\t\tBindings bindings = engine.createBindings();\n\t\t\tbindings.put(\"event\", event);\n\t\t\tbindings.put(\"eventName\", name);\n\t\t\tbindings.put(\"eventXMLNS\", xmlns);\n\t\t\tbindings.put(\"context\", context);\n\n\t\t\tif (this.compiledScript != null) {\n\t\t\t\tthis.compiledScript.eval(bindings);\n\t\t\t} else {\n\t\t\t\tthis.engine.eval(scriptContent, bindings);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic void run(EventBusContext context, ScriptEngineManager scriptEngineManager, String scriptName,\n\t\t\tString scriptExtension, String scriptContent, String eventName, String eventXMLNS) throws ScriptException {\n\t\tthis.context = context;\n\t\tthis.eventName = eventName;\n\t\tthis.eventXMLNS = eventXMLNS;\n\t\tthis.engine = scriptEngineManager.getEngineByExtension(scriptExtension);\n\t\tthis.scriptContent = scriptContent;\n\t\tif (engine instanceof Compilable) {\n\t\t\tthis.compiledScript = ((Compilable) engine).compile(scriptContent);\n\t\t} else {\n\t\t\tthis.compiledScript = null;\n\t\t}\n\n\t\tcontext.getEventBus().addHandler(this.eventName, this.eventXMLNS, this);\n\t}\n\n\tpublic void unregister() {\n\t\tcontext.getEventBus().removeHandler(this.eventName, this.eventXMLNS, this);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/ListenerScriptRegistrar.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\n\nimport tigase.util.Algorithms;\nimport tigase.util.Base64;\n\npublic class ListenerScriptRegistrar {\n\n\tprivate EventBusContext context;\n\tprivate Map<String, ListenerScript> listenersScripts;\n\tprivate ScriptEngineManager scriptEngineManager;\n\tprivate String scriptPath = \"./listenerScripts\";\n\n\tpublic ListenerScriptRegistrar(Map<String, ListenerScript> listenersScripts, EventBusContext context,\n\t\t\tScriptEngineManager scriptEngineManager) {\n\t\tthis.context = context;\n\t\tthis.listenersScripts = listenersScripts;\n\t\tthis.scriptEngineManager = scriptEngineManager;\n\t}\n\n\tpublic void delete(String taskName) {\n\t\tFile par = new File(scriptPath);\n\t\tif (!par.exists())\n\t\t\treturn;\n\n\t\tFile f = new File(par, Algorithms.sha256(taskName) + \".script\");\n\t\tf.delete();\n\t}\n\n\tpublic void load() {\n\t\tFile par = new File(scriptPath);\n\n\t\tif (!par.exists() || !par.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (File f : par.listFiles()) {\n\t\t\tif (f.isFile() && f.getName().endsWith(\".script\")) {\n\t\t\t\tload(f);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate void load(final File f) {\n\t\ttry {\n\t\t\tFileReader reader = new FileReader(f);\n\t\t\tProperties p = new Properties();\n\t\t\tp.load(reader);\n\t\t\treader.close();\n\n\t\t\tString scriptName = p.getProperty(\"scriptName\");\n\t\t\tString scriptExtension = p.getProperty(\"scriptExtension\");\n\t\t\tString scriptContent = new String(Base64.decode(p.getProperty(\"scriptContent\")));\n\n\t\t\tString eventXMLNS = p.getProperty(\"eventXMLNS\");\n\t\t\tString eventName = p.getProperty(\"eventName\");\n\t\t\trunScriptTask(scriptName, scriptExtension, scriptContent, eventName, eventXMLNS);\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (ScriptException e) {\n\t\t\t// TODO Auto-generated catch block\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic void registerScript(String scriptName, String scriptExtension, String scriptContent, String eventName,\n\t\t\tString eventXMLNS) throws ScriptException {\n\t\tsaveScript(scriptName, scriptExtension, scriptContent, eventName, eventXMLNS);\n\t\trunScriptTask(scriptName, scriptExtension, scriptContent, eventName, eventXMLNS);\n\t}\n\n\tprivate void runScriptTask(String scriptName, String scriptExtension, String scriptContent, String eventName,\n\t\t\tString eventXMLNS) throws ScriptException {\n\t\tListenerScript ls = new ListenerScript();\n\t\tlistenersScripts.put(scriptName, ls);\n\t\tls.run(context, scriptEngineManager, scriptName, scriptExtension, scriptContent,\n\t\t\t\teventName == null || eventName.isEmpty() ? null : eventName, eventXMLNS);\n\t}\n\n\tprivate void saveScript(String scriptName, String scriptExtension, String scriptContent, String eventName, String eventXMLNS) {\n\t\tFile par = new File(scriptPath);\n\t\tif (!par.exists())\n\t\t\tpar.mkdirs();\n\n\t\tFile f = new File(par, Algorithms.sha256(scriptName) + \".script\");\n\n\t\tProperties p = new Properties();\n\t\tp.setProperty(\"scriptName\", scriptName);\n\t\tp.setProperty(\"scriptExtension\", scriptExtension);\n\t\tif (eventName != null)\n\t\t\tp.setProperty(\"eventName\", eventName);\n\t\tp.setProperty(\"eventXMLNS\", eventXMLNS);\n\t\tp.setProperty(\"scriptContent\", Base64.encode(scriptContent.getBytes()));\n\n\t\ttry {\n\t\t\tFileWriter writer = new FileWriter(f);\n\t\t\tp.store(writer, \"Script \" + scriptName + \".\" + scriptExtension);\n\t\t\twriter.close();\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/NodeNameUtil.java",
    "content": "package tigase.disteventbus.component;\n\nimport tigase.disteventbus.impl.EventName;\n\npublic class NodeNameUtil {\n\n\tprivate NodeNameUtil() {\n\t}\n\n\tpublic static String createNodeName(String eventName, String xmlns) {\n\t\treturn (eventName == null ? \"*\" : eventName) + \"|\" + (xmlns == null ? \"*\" : xmlns);\n\t}\n\n\tpublic static EventName parseNodeName(String nodeName) {\n\t\tint i = nodeName.indexOf('|');\n\t\tString n = nodeName.substring(0, i);\n\t\tString x = nodeName.substring(i + 1);\n\t\treturn new EventName(n.equals(\"*\") ? null : n, x.equals(\"*\") ? null : x);\n\t}\n\n\t// public static EventName parseNodeName(String nodeName) {\n\t// String[] x = nodeName.split(\"\\\\|\", 2);\n\t// return new EventName(x[0].equals(\"*\") ? null : x[0], x[1].equals(\"*\") ?\n\t// null : x[1]);\n\t// }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/RemoveListenerScriptCommand.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.Collection;\nimport java.util.Map;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class RemoveListenerScriptCommand implements AdHocCommand {\n\n\tprivate ListenerScriptRegistrar listenerScriptRegistrar;\n\tprivate Map<String, ListenerScript> listenersScripts;\n\n\tpublic RemoveListenerScriptCommand(Map<String, ListenerScript> listenersScripts,\n\t\t\tListenerScriptRegistrar listenerScriptRegistrar) {\n\t\tthis.listenersScripts = listenersScripts;\n\t\tthis.listenerScriptRegistrar = listenerScriptRegistrar;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tForm form = new Form(\"form\", \"Delete listener script\", null);\n\n\t\t\t\tCollection<String> scriptNames = listenersScripts.keySet();\n\n\t\t\t\tform.addField(Field.fieldListSingle(\"delete_script\", \"\", \"Script to delete\",\n\t\t\t\t\t\tscriptNames.toArray(new String[] {}), scriptNames.toArray(new String[] {})));\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tString scriptName = form.getAsString(\"delete_script\");\n\n\t\t\t\t\tlistenerScriptRegistrar.delete(scriptName);\n\t\t\t\t\tListenerScript i = listenersScripts.remove(scriptName);\n\t\t\t\t\tif (i != null) {\n\t\t\t\t\t\ti.unregister();\n\t\t\t\t\t} else\n\t\t\t\t\t\tthrow new RuntimeException(\"Are you kidding me?\");\n\t\t\t\t}\n\n\t\t\t\tresponse.completeSession();\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Remove listener script\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn \"remove-listener-script\";\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/SubscribeModule.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.*;\nimport java.util.logging.Level;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.responses.AsyncCallback;\nimport tigase.criteria.Criteria;\nimport tigase.disteventbus.EventHandler;\nimport tigase.disteventbus.component.stores.Affiliation;\nimport tigase.disteventbus.component.stores.Subscription;\nimport tigase.disteventbus.impl.EventName;\nimport tigase.disteventbus.impl.LocalEventBus;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\npublic class SubscribeModule extends AbstractEventBusModule {\n\n\tpublic final static String ID = \"subscribe\";\n\tprivate static final Criteria CRIT = new ElemPathCriteria(new String[] { \"iq\", \"pubsub\", \"subscribe\" },\n\t\t\tnew String[] { null, \"http://jabber.org/protocol/pubsub\", null });\n\n\tprivate final EventHandler eventBusHandlerAddedHandler = new EventHandler() {\n\n\t\tprivate final String[] NAME_PATH = new String[] { LocalEventBus.HANDLER_ADDED_EVENT_NAME, \"name\" };\n\t\tprivate final String[] XMLNS_PATH = new String[] { LocalEventBus.HANDLER_ADDED_EVENT_NAME, \"xmlns\" };\n\n\t\t@Override\n\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\tString n = event.getCData(NAME_PATH);\n\t\t\tString x = event.getCData(XMLNS_PATH);\n\t\t\tif (x == null || !x.equals(LocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS))\n\t\t\t\tSubscribeModule.this.onAddHandler(n, x);\n\t\t}\n\t};\n\n\t@Override\n\tpublic void afterRegistration() {\n\t\tsuper.afterRegistration();\n\t\tcontext.getEventBusInstance().addHandler(LocalEventBus.HANDLER_ADDED_EVENT_NAME,\n\t\t\t\tLocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS, eventBusHandlerAddedHandler);\n\t}\n\n\tpublic void clusterNodeConnected(JID node) {\n\t\tif (context.getComponentID().equals(node))\n\t\t\treturn;\n\t\t// context.getSubscriptionStore().addSubscription(null,\n\t\t// \"tigase:eventbus\", JID.jidInstanceNS(\"eventbus\", node, null));\n\n\t\tif (log.isLoggable(Level.FINER))\n\t\t\tlog.finer(\"Node \" + node + \" is connected. Preparing subscribe request.\");\n\n\t\tSet<Element> pubsubNodes = new HashSet<>();\n\t\tfor (EventName eventName : context.getEventBusInstance().getAllListenedEvents()) {\n\t\t\tpubsubNodes.add(prepareSubscribeElement(eventName, context.getComponentID(), null));\n\t\t}\n\n\t\tfor (EventName eventName : context.getSubscriptionStore().getSubscribedEvents()) {\n\t\t\tCollection<Subscription> subscriptions = context.getSubscriptionStore().getSubscribersJIDs(eventName.getName(),\n\t\t\t\t\teventName.getXmlns());\n\t\t\tfor (Subscription subscription : subscriptions) {\n\t\t\t\tif (subscription.getServiceJID() != null)\n\t\t\t\t\tpubsubNodes.add(\n\t\t\t\t\t\t\tprepareSubscribeElement(eventName, subscription.getJid(), subscription.getServiceJID().toString()));\n\t\t\t}\n\t\t}\n\n\t\tif (!pubsubNodes.isEmpty())\n\t\t\tsendSubscribeRequest(\"eventbus@\" + node.getDomain(), pubsubNodes);\n\t}\n\n\tpublic void clusterNodeDisconnected(JID node) {\n\t\tif (context.getComponentID().equals(node))\n\t\t\treturn;\n\n\t\tif (log.isLoggable(Level.FINER))\n\t\t\tlog.finer(\"Node \" + node + \" is disconnected.\");\n\t\tcontext.getSubscriptionStore().remove(new Subscription(JID.jidInstanceNS(\"eventbus\", node.getDomain(), null)));\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn new String[] { \"http://jabber.org/protocol/pubsub#subscribe\" };\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\tprotected void onAddHandler(String eventName, String eventXmlns) {\n\t\tfor (JID node : context.getConnectedNodes()) {\n\t\t\tif (context.getComponentID().equals(node))\n\t\t\t\tcontinue;\n\n\t\t\tElement se = prepareSubscribeElement(new EventName(eventName, eventXmlns), context.getComponentID(), null);\n\t\t\tsendSubscribeRequest(\"eventbus@\" + node.getDomain(), Collections.singleton(se));\n\t\t}\n\t}\n\n\tprivate Element prepareSubscribeElement(EventName event, JID jid, String service) {\n\t\tElement subscribeElem = new Element(\"subscribe\");\n\t\tsubscribeElem.addAttribute(\"node\", event.toEventBusNode());\n\t\tsubscribeElem.addAttribute(\"jid\", jid.toString());\n\n\t\tif (service != null) {\n\t\t\tsubscribeElem.addChild(new Element(\"service\", service));\n\t\t}\n\n\t\treturn subscribeElem;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException, TigaseStringprepException {\n\t\tif (packet.getType() == StanzaType.set) {\n\t\t\tprocessSet(packet);\n\t\t} else\n\t\t\tthrow new ComponentException(Authorization.NOT_ALLOWED, \"Only type set is allowed.\");\n\t}\n\n\tprotected Element processClusterSubscription(final Packet packet) throws TigaseStringprepException {\n\t\t// subscription from cluster node\n\t\tlog.finest(\"Processing cluster subscription request from \" + packet.getStanzaFrom());\n\t\tList<Element> subscribeElements = packet.getElemChildrenStaticStr(new String[] { \"iq\", \"pubsub\" });\n\n\t\tfor (Element subscribe : subscribeElements) {\n\t\t\tElement serviceItem = subscribe.getChild(\"service\");\n\n\t\t\tfinal EventName parsedName = NodeNameUtil.parseNodeName(subscribe.getAttributeStaticStr(\"node\"));\n\t\t\tfinal JID jid = JID.jidInstance(subscribe.getAttributeStaticStr(\"jid\"));\n\t\t\tfinal String service;\n\n\t\t\tif (serviceItem != null && serviceItem.getCData() != null) {\n\t\t\t\tservice = serviceItem.getCData();\n\t\t\t} else {\n\t\t\t\tservice = null;\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"Node \" + jid + \" subscribed for events \" + parsedName);\n\n\t\t\tSubscription subscription = new Subscription(jid);\n\t\t\tsubscription.setInClusterSubscription(true);\n\t\t\tsubscription.setServiceJID(JID.jidInstanceNS(service));\n\n\t\t\tcontext.getSubscriptionStore().addSubscription(parsedName.getName(), parsedName.getXmlns(), subscription);\n\n\t\t}\n\t\treturn null;\n\t}\n\n\tprotected Element processNonClusterSubscription(final Packet packet) throws TigaseStringprepException, ComponentException {\n\t\t// subscription from something out of cluster\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.finest(\"Processing noncluster subscription request from \" + packet.getStanzaFrom());\n\n\t\tfinal Affiliation affiliation = context.getAffiliationStore().getAffiliation(packet.getStanzaFrom());\n\n\t\tif (!affiliation.isSubscribe()) {\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\n\t\t\t\t\t\t\"Subscription rejected. Subscriber \" + packet.getStanzaFrom() + \" has bad affiliation: \" + affiliation);\n\t\t\tthrow new ComponentException(Authorization.FORBIDDEN, \"Bad affiliation: \" + affiliation);\n\t\t}\n\n\t\tList<Element> subscribeElements = packet.getElemChildrenStaticStr(new String[] { \"iq\", \"pubsub\" });\n\t\tElement response = new Element(\"pubsub\", new String[] { \"xmlns\" },\n\t\t\t\tnew String[] { \"http://jabber.org/protocol/pubsub\" });\n\n\t\tfinal Set<Element> subscribedNodes = new HashSet<>();\n\t\tfor (Element subscribe : subscribeElements) {\n\t\t\tEventName parsedName = NodeNameUtil.parseNodeName(subscribe.getAttributeStaticStr(\"node\"));\n\t\t\tJID jid = JID.jidInstance(subscribe.getAttributeStaticStr(\"jid\"));\n\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"Entity \" + jid + \" subscribed for events \" + parsedName);\n\n\t\t\tSubscription subscription = new Subscription(jid, packet.getStanzaTo());\n\t\t\tsubscription.setInClusterSubscription(false);\n\n\t\t\tcontext.getSubscriptionStore().addSubscription(parsedName.getName(), parsedName.getXmlns(), subscription);\n\n\t\t\tsubscribedNodes.add(prepareSubscribeElement(parsedName, jid, packet.getStanzaTo().toString()));\n\n\t\t\tresponse.addChild(new Element(\"subscription\", new String[] { \"node\", \"jid\", \"subscription\" },\n\t\t\t\t\tnew String[] { parsedName.toEventBusNode(), jid.toString(), \"subscribed\" }));\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINER))\n\t\t\tlog.finer(\"Forwarding subscription request to: \" + context.getConnectedNodes());\n\n\t\tfor (JID node : context.getConnectedNodes()) {\n\t\t\tif (context.getComponentID().equals(node))\n\t\t\t\tcontinue;\n\t\t\tsendSubscribeRequest(\"eventbus@\" + node.getDomain(), subscribedNodes);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\tprivate void processSet(final Packet packet) throws TigaseStringprepException, ComponentException {\n\t\tElement subscriptionResponse;\n\t\tif (isClusteredEventBus(packet.getStanzaFrom())) {\n\t\t\tsubscriptionResponse = processClusterSubscription(packet);\n\t\t} else {\n\t\t\tsubscriptionResponse = processNonClusterSubscription(packet);\n\t\t}\n\n\t\tPacket response = packet.okResult(subscriptionResponse, 0);\n\t\tresponse.setPermissions(Permissions.ADMIN);\n\t\twrite(response);\n\t}\n\n\tprotected void sendSubscribeRequest(final String to, Collection<Element> subscriptionElements) {\n\t\ttry {\n\t\t\tfinal String id = nextStanzaID();\n\t\t\tElement iq = new Element(\"iq\", new String[] { \"from\", \"to\", \"type\", \"id\" },\n\t\t\t\t\tnew String[] { context.getComponentID().toString(), to, \"set\", id });\n\n\t\t\tElement pubsubElem = new Element(\"pubsub\", new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { \"http://jabber.org/protocol/pubsub\" });\n\t\t\tiq.addChild(pubsubElem);\n\n\t\t\tsubscriptionElements.forEach(pubsubElem::addChild);\n\n\t\t\tfinal Packet packet = Packet.packetInstance(iq);\n\t\t\tpacket.setPermissions(Permissions.ADMIN);\n\t\t\tpacket.setXMLNS(Packet.CLIENT_XMLNS);\n\n\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\tlog.finer(\"Sending subscribe request (id=\" + id + \") to node \" + to);\n\n\t\t\twrite(packet, new AsyncCallback() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onError(Packet responseStanza, String errorCondition) {\n\t\t\t\t\t// TODO Auto-generated method stub\n\t\t\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\t\t\tlog.fine(\"Subscription request was cancelled by node \" + to + \" with error \" + errorCondition);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onSuccess(Packet responseStanza) {\n\t\t\t\t\t// TODO Auto-generated method stub\n\t\t\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\t\t\tlog.fine(\"Subscription request was accepted by node \" + to + \".\");\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onTimeout() {\n\t\t\t\t\t// TODO Auto-generated method stub\n\t\t\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\t\t\tlog.fine(\"Subscription request timeout. Node \" + to + \" not answered.\");\n\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Why? Oh Why?\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void unregisterModule() {\n\t\tcontext.getEventBusInstance().removeHandler(LocalEventBus.HANDLER_ADDED_EVENT_NAME,\n\t\t\t\tLocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS, eventBusHandlerAddedHandler);\n\t\tsuper.unregisterModule();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/UnsubscribeModule.java",
    "content": "package tigase.disteventbus.component;\n\nimport java.util.*;\nimport java.util.logging.Level;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.responses.AsyncCallback;\nimport tigase.criteria.Criteria;\nimport tigase.disteventbus.EventHandler;\nimport tigase.disteventbus.component.stores.Subscription;\nimport tigase.disteventbus.impl.EventName;\nimport tigase.disteventbus.impl.LocalEventBus;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\npublic class UnsubscribeModule extends AbstractEventBusModule {\n\n\tpublic final static String ID = \"unsubscribe\";\n\tprivate static final Criteria CRIT = new ElemPathCriteria(new String[] { \"iq\", \"pubsub\", \"unsubscribe\" },\n\t\t\tnew String[] { null, \"http://jabber.org/protocol/pubsub\", null });\n\tprivate final EventHandler eventBusHandlerRemovedHandler = new EventHandler() {\n\n\t\tprivate final String[] NAME_PATH = new String[] { LocalEventBus.HANDLER_REMOVED_EVENT_NAME, \"name\" };\n\t\tprivate final String[] XMLNS_PATH = new String[] { LocalEventBus.HANDLER_REMOVED_EVENT_NAME, \"xmlns\" };\n\n\t\t@Override\n\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\tString n = event.getCData(NAME_PATH);\n\t\t\tString x = event.getCData(XMLNS_PATH);\n\t\t\tif (x == null || !x.equals(LocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS))\n\t\t\t\tUnsubscribeModule.this.onRemoveHandler(n, x);\n\t\t}\n\t};\n\n\t@Override\n\tpublic void afterRegistration() {\n\t\tsuper.afterRegistration();\n\n\t\tcontext.getEventBusInstance().addHandler(LocalEventBus.HANDLER_REMOVED_EVENT_NAME,\n\t\t\t\tLocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS, eventBusHandlerRemovedHandler);\n\n\t}\n\n\t@Override\n\tpublic String[] getFeatures() {\n\t\treturn new String[] { \"http://jabber.org/protocol/pubsub#subscribe\" };\n\t}\n\n\t@Override\n\tpublic Criteria getModuleCriteria() {\n\t\treturn CRIT;\n\t}\n\n\tprotected void onRemoveHandler(String eventName, String eventXmlns) {\n\t\tboolean listenedByHandlers = context.getEventBusInstance().hasHandlers(eventName, eventXmlns);\n\n\t\tif (!listenedByHandlers) {\n\t\t\tfor (JID node : context.getConnectedNodes()) {\n\t\t\t\tElement se = prepareUnsubscribeElement(new EventName(eventName, eventXmlns), context.getComponentID(), null);\n\t\t\t\tsendUnsubscribeRequest(\"eventbus@\" + node.getDomain(), Collections.singleton(se));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Element prepareUnsubscribeElement(EventName event, JID jid, String service) {\n\t\tElement subscribeElem = new Element(\"unsubscribe\");\n\t\tsubscribeElem.addAttribute(\"node\", event.toEventBusNode());\n\t\tsubscribeElem.addAttribute(\"jid\", jid.toString());\n\n\t\tif (service != null) {\n\t\t\tsubscribeElem.addChild(new Element(\"service\", service));\n\t\t}\n\n\t\treturn subscribeElem;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException, TigaseStringprepException {\n\t\tif (packet.getType() == StanzaType.set) {\n\t\t\tprocessSet(packet);\n\t\t} else\n\t\t\tthrow new ComponentException(Authorization.NOT_ALLOWED);\n\t}\n\n\tprivate void processSet(final Packet packet) throws TigaseStringprepException {\n\t\tList<Element> unsubscribeElements = packet.getElemChildrenStaticStr(new String[] { \"iq\", \"pubsub\" });\n\n\t\tif (isClusteredEventBus(packet.getStanzaFrom())) {\n\t\t\t// request from cluster node\n\t\t\tfor (Element unsubscribe : unsubscribeElements) {\n\t\t\t\tEventName parsedName = NodeNameUtil.parseNodeName(unsubscribe.getAttributeStaticStr(\"node\"));\n\t\t\t\tJID jid = JID.jidInstance(unsubscribe.getAttributeStaticStr(\"jid\"));\n\n\t\t\t\tcontext.getSubscriptionStore().removeSubscription(parsedName.getName(), parsedName.getXmlns(),\n\t\t\t\t\t\tnew Subscription(jid));\n\t\t\t}\n\t\t} else {\n\t\t\t// request from something out of cluster\n\t\t\tfinal Set<Element> subscribedNodes = new HashSet<>();\n\t\t\tfor (Element subscribe : unsubscribeElements) {\n\t\t\t\tEventName parsedName = NodeNameUtil.parseNodeName(subscribe.getAttributeStaticStr(\"node\"));\n\t\t\t\tJID jid = JID.jidInstance(subscribe.getAttributeStaticStr(\"jid\"));\n\n\t\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\t\tlog.finer(\"Entity \" + jid + \" subscribed for events \" + parsedName);\n\n\t\t\t\tcontext.getSubscriptionStore().removeSubscription(parsedName.getName(), parsedName.getXmlns(),\n\t\t\t\t\t\tnew Subscription(jid, packet.getStanzaTo()));\n\n\t\t\t\tsubscribedNodes.add(prepareUnsubscribeElement(parsedName, jid, packet.getStanzaTo().toString()));\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\tlog.finer(\"Forwarding unsubcribe to: \" + context.getConnectedNodes());\n\n\t\t\tfor (JID node : context.getConnectedNodes()) {\n\t\t\t\tsendUnsubscribeRequest(\"eventbus@\" + node.getDomain(), subscribedNodes);\n\t\t\t}\n\t\t}\n\t\tPacket response = packet.okResult((Element) null, 0);\n\t\tresponse.setPermissions(Permissions.ADMIN);\n\t\twrite(response);\n\t}\n\n\tprotected void sendUnsubscribeRequest(String to, Collection<Element> subscriptionElement) {\n\t\ttry {\n\t\t\tElement iq = new Element(\"iq\", new String[] { \"from\", \"to\", \"type\", \"id\" },\n\t\t\t\t\tnew String[] { context.getComponentID().toString(), to, \"set\", nextStanzaID() });\n\n\t\t\tElement pubsubElem = new Element(\"pubsub\", new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { \"http://jabber.org/protocol/pubsub\" });\n\t\t\tiq.addChild(pubsubElem);\n\n\t\t\tfor (Element node : subscriptionElement) {\n\t\t\t\tpubsubElem.addChild(node);\n\t\t\t}\n\n\t\t\tfinal Packet packet = Packet.packetInstance(iq);\n\t\t\tpacket.setPermissions(Permissions.ADMIN);\n\t\t\tpacket.setXMLNS(Packet.CLIENT_XMLNS);\n\n\t\t\twrite(packet, new AsyncCallback() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onError(Packet responseStanza, String errorCondition) {\n\t\t\t\t\t// TODO Auto-generated method stub\n\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onSuccess(Packet responseStanza) {\n\t\t\t\t\t// TODO Auto-generated method stub\n\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onTimeout() {\n\t\t\t\t\t// TODO Auto-generated method stub\n\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void unregisterModule() {\n\t\tcontext.getEventBusInstance().removeHandler(LocalEventBus.HANDLER_REMOVED_EVENT_NAME,\n\t\t\t\tLocalEventBus.EVENTBUS_INTERNAL_EVENTS_XMLNS, eventBusHandlerRemovedHandler);\n\t\tsuper.unregisterModule();\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/stores/Affiliation.java",
    "content": "package tigase.disteventbus.component.stores;\n\npublic enum Affiliation {\n\t/** */\n\tmember(2, true, true, false, false, false, false, false),\n\t/** */\n\tnone(1, true, false, false, false, false, false, false),\n\t/** An entity that is disallowed from subscribing or publishing to a node. */\n\toutcast(0, false, false, false, false, false, false, false),\n\t/**\n\t * The manager of a node, of which there may be more than one; often but not\n\t * necessarily the node creator.\n\t */\n\towner(4, true, true, true, true, true, true, true),\n\t/** An entity that is allowed to publish items to a node. */\n\tpublisher(3, true, true, true, true, false, false, false);\n\n\tprivate final boolean configureNode;\n\n\tprivate final boolean deleteItem;\n\n\tprivate final boolean deleteNode;\n\n\tprivate final boolean publishItem;\n\n\tprivate final boolean purgeNode;\n\n\tprivate final boolean retrieveItem;\n\n\tprivate final boolean subscribe;\n\n\tprivate final int weight;\n\n\tprivate Affiliation(int weight, boolean subscribe, boolean retrieveItem, boolean publishItem, boolean deleteItem,\n\t\t\tboolean configureNode, boolean deleteNode, boolean purgeNode) {\n\t\tthis.subscribe = subscribe;\n\t\tthis.weight = weight;\n\t\tthis.retrieveItem = retrieveItem;\n\t\tthis.publishItem = publishItem;\n\t\tthis.deleteItem = deleteItem;\n\t\tthis.configureNode = configureNode;\n\t\tthis.deleteNode = deleteNode;\n\t\tthis.purgeNode = purgeNode;\n\t}\n\n\tpublic int getWeight() {\n\t\treturn weight;\n\t}\n\n\tpublic boolean isConfigureNode() {\n\t\treturn configureNode;\n\t}\n\n\tpublic boolean isDeleteItem() {\n\t\treturn deleteItem;\n\t}\n\n\tpublic boolean isDeleteNode() {\n\t\treturn deleteNode;\n\t}\n\n\tpublic boolean isPublishItem() {\n\t\treturn publishItem;\n\t}\n\n\tpublic boolean isPurgeNode() {\n\t\treturn purgeNode;\n\t}\n\n\tpublic boolean isRetrieveItem() {\n\t\treturn retrieveItem;\n\t}\n\n\tpublic boolean isSubscribe() {\n\t\treturn subscribe;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/stores/AffiliationStore.java",
    "content": "package tigase.disteventbus.component.stores;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport tigase.xmpp.JID;\n\npublic class AffiliationStore {\n\n\tprivate final Map<JID, Affiliation> affiliations = new ConcurrentHashMap<JID, Affiliation>();\n\n\tpublic Affiliation getAffiliation(final JID jid) {\n\t\tAffiliation a = affiliations.get(jid);\n\t\treturn a == null ? Affiliation.none : a;\n\t}\n\n\tpublic void putAffiliation(JID jid, Affiliation affiliation) {\n\t\tthis.affiliations.put(jid, affiliation);\n\t}\n\n\tpublic void removeAffiliation(JID jid) {\n\t\tthis.affiliations.remove(jid);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/stores/Subscription.java",
    "content": "package tigase.disteventbus.component.stores;\n\nimport tigase.xmpp.JID;\n\npublic class Subscription {\n\n\tprivate final JID jid;\n\n\tprivate JID serviceJID;\n\n\tprivate boolean inClusterSubscription;\n\n\tpublic Subscription(JID jid) {\n\t\tsuper();\n\t\tthis.jid = jid;\n\t}\n\n\tpublic Subscription(JID jid, JID serviceJID) {\n\t\tsuper();\n\t\tthis.jid = jid;\n\t\tthis.serviceJID = serviceJID;\n\t}\n\n\tpublic boolean isInClusterSubscription() {\n\t\treturn inClusterSubscription;\n\t}\n\n\tpublic void setInClusterSubscription(boolean inClusterSubscription) {\n\t\tthis.inClusterSubscription = inClusterSubscription;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj)\n\t\t\treturn true;\n\t\tif (obj == null)\n\t\t\treturn false;\n\t\tif (getClass() != obj.getClass())\n\t\t\treturn false;\n\t\tSubscription other = (Subscription) obj;\n\t\tif (jid == null) {\n\t\t\tif (other.jid != null)\n\t\t\t\treturn false;\n\t\t} else if (!jid.equals(other.jid))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tpublic JID getJid() {\n\t\treturn jid;\n\t}\n\n\tpublic JID getServiceJID() {\n\t\treturn serviceJID;\n\t}\n\n\tpublic void setServiceJID(JID serviceJID) {\n\t\tthis.serviceJID = serviceJID;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tfinal int prime = 31;\n\t\tint result = 1;\n\t\tresult = prime * result + ((jid == null) ? 0 : jid.hashCode());\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Subscription{\" + \"jid=\" + jid + \", serviceJID=\" + serviceJID + '}';\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/component/stores/SubscriptionStore.java",
    "content": "package tigase.disteventbus.component.stores;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.logging.Logger;\n\nimport tigase.disteventbus.impl.EventName;\nimport tigase.disteventbus.impl.EventsNameMap;\n\npublic class SubscriptionStore {\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\tprivate final EventsNameMap<Subscription> subscribers = new EventsNameMap<Subscription>();\n\n\tpublic void addSubscription(String name, String xmlns, Subscription subscription) {\n\t\tsubscribers.put(name, xmlns, subscription);\n\t}\n\n\tpublic Collection<Subscription> getAllData() {\n\t\treturn subscribers.getAllData();\n\t}\n\n\tpublic Set<EventName> getSubscribedEvents() {\n\t\treturn subscribers.getAllListenedEvents();\n\t}\n\n\tpublic Collection<Subscription> getSubscribersJIDs(String name, String xmlns) {\n\t\tfinal HashSet<Subscription> handlers = new HashSet<Subscription>();\n\t\thandlers.addAll(subscribers.get(name, xmlns));\n\t\thandlers.addAll(subscribers.get(null, xmlns));\n\t\treturn handlers;\n\t}\n\n\tpublic boolean hasSubscriber(String eventName, String eventXmlns) {\n\t\treturn subscribers.hasData(eventName, eventXmlns);\n\t}\n\n\tpublic void remove(Subscription jid) {\n\t\tsubscribers.delete(jid);\n\t}\n\n\tpublic void removeSubscription(String eventName, String eventXmlns, Subscription jidInstanceNS) {\n\t\tsubscribers.delete(eventName, eventXmlns, jidInstanceNS);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/impl/EventName.java",
    "content": "package tigase.disteventbus.impl;\n\nimport tigase.disteventbus.component.NodeNameUtil;\n\npublic class EventName {\n\n\tprivate final String name;\n\n\tprivate final String xmlns;\n\n\tpublic EventName(String name, String xmlns) {\n\t\tsuper();\n\t\tthis.name = name;\n\t\tthis.xmlns = xmlns;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj)\n\t\t\treturn true;\n\t\tif (obj == null)\n\t\t\treturn false;\n\t\tif (getClass() != obj.getClass())\n\t\t\treturn false;\n\t\tEventName other = (EventName) obj;\n\t\tif (name == null) {\n\t\t\tif (other.name != null)\n\t\t\t\treturn false;\n\t\t} else if (!name.equals(other.name))\n\t\t\treturn false;\n\t\tif (xmlns == null) {\n\t\t\tif (other.xmlns != null)\n\t\t\t\treturn false;\n\t\t} else if (!xmlns.equals(other.xmlns))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic String getXmlns() {\n\t\treturn xmlns;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tfinal int prime = 31;\n\t\tint result = 1;\n\t\tresult = prime * result + ((name == null) ? 0 : name.hashCode());\n\t\tresult = prime * result + ((xmlns == null) ? 0 : xmlns.hashCode());\n\t\treturn result;\n\t}\n\n\tpublic String toEventBusNode() {\n\t\treturn NodeNameUtil.createNodeName(name, xmlns);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"(\" + name + \", \" + xmlns + \")\";\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/impl/EventsNameMap.java",
    "content": "package tigase.disteventbus.impl;\n\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class EventsNameMap<M> {\n\n\tprivate final static String NULL_NAME = new String(new byte[] { 0 });\n\n\tprivate final Map<String, Map<String, Collection<M>>> dataMap = createMainDataMap();\n\n\tprotected Collection<M> createDataList() {\n\t\treturn new HashSet<M>();\n\t}\n\n\tprotected Map<String, Map<String, Collection<M>>> createMainDataMap() {\n\t\treturn new ConcurrentHashMap<String, Map<String, Collection<M>>>();\n\t}\n\n\tprotected Map<String, Collection<M>> createNamesDataMap() {\n\t\treturn new ConcurrentHashMap<String, Collection<M>>();\n\t}\n\n\tpublic void delete(M data) {\n\t\tIterator<Entry<String, Map<String, Collection<M>>>> namesIt = dataMap.entrySet().iterator();\n\t\twhile (namesIt.hasNext()) {\n\t\t\tMap<String, Collection<M>> datas = namesIt.next().getValue();\n\t\t\tIterator<Entry<String, Collection<M>>> dataIt = datas.entrySet().iterator();\n\t\t\twhile (dataIt.hasNext()) {\n\t\t\t\tCollection<M> d = dataIt.next().getValue();\n\t\t\t\td.remove(data);\n\n\t\t\t\tif (d.isEmpty()) {\n\t\t\t\t\tdataIt.remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tpublic void delete(String name, String xmlns, M data) {\n\t\tfinal String eventName = name == null ? NULL_NAME : name;\n\t\tfinal String eventXmlns = xmlns == null ? NULL_NAME : xmlns;\n\n\t\tMap<String, Collection<M>> namesData = dataMap.get(eventXmlns);\n\t\tif (namesData == null)\n\t\t\treturn;\n\n\t\tCollection<M> dataCollection = namesData.get(eventName);\n\t\tif (dataCollection == null)\n\t\t\treturn;\n\n\t\tdataCollection.remove(data);\n\n\t\tif (dataCollection.isEmpty()) {\n\t\t\tnamesData.remove(eventName);\n\t\t}\n\n\t\tif (namesData.isEmpty()) {\n\t\t\tdataMap.remove(eventXmlns);\n\t\t}\n\t}\n\n\tpublic Collection<M> get(String name, String xmlns) {\n\t\tfinal String eventName = name == null ? NULL_NAME : name;\n\t\tfinal String eventXmlns = xmlns == null ? NULL_NAME : xmlns;\n\n\t\tMap<String, Collection<M>> namesData = dataMap.get(eventXmlns);\n\t\tif (namesData == null)\n\t\t\treturn Collections.emptyList();\n\n\t\tCollection<M> dataList = namesData.get(eventName);\n\t\tif (dataList == null)\n\t\t\treturn Collections.emptyList();\n\n\t\treturn dataList;\n\t}\n\n\tpublic Collection<M> getAllData() {\n\t\tHashSet<M> result = new HashSet<M>();\n\t\tfor (Map<String, Collection<M>> c1 : dataMap.values()) {\n\t\t\tfor (Collection<M> c2 : c1.values()) {\n\t\t\t\tresult.addAll(c2);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic Set<EventName> getAllListenedEvents() {\n\t\tHashSet<EventName> result = new HashSet<EventName>();\n\t\tIterator<Entry<String, Map<String, Collection<M>>>> xmlnsIt = dataMap.entrySet().iterator();\n\n\t\twhile (xmlnsIt.hasNext()) {\n\t\t\tEntry<String, Map<String, Collection<M>>> e = xmlnsIt.next();\n\t\t\tfinal String xmlns = e.getKey();\n\n\t\t\tIterator<String> namesIt = e.getValue().keySet().iterator();\n\t\t\twhile (namesIt.hasNext()) {\n\t\t\t\tString n = namesIt.next();\n\t\t\t\tresult.add(new EventName(n == NULL_NAME ? null : n, xmlns == NULL_NAME ? null : xmlns));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic boolean hasData(String name, String xmlns) {\n\t\tfinal String eventName = name == null ? NULL_NAME : name;\n\t\tfinal String eventXmlns = xmlns == null ? NULL_NAME : xmlns;\n\n\t\tMap<String, Collection<M>> namesData = dataMap.get(eventXmlns);\n\t\tif (namesData == null || namesData.isEmpty())\n\t\t\treturn false;\n\n\t\tCollection<M> dataList = namesData.get(eventName);\n\t\treturn !(dataList == null || dataList.isEmpty());\n\t}\n\n\tpublic void put(String name, String xmlns, M data) {\n\t\tfinal String eventName = name == null ? NULL_NAME : name;\n\t\tfinal String eventXmlns = xmlns == null ? NULL_NAME : xmlns;\n\n\t\tMap<String, Collection<M>> namesData = dataMap.get(eventXmlns);\n\t\tif (namesData == null) {\n\t\t\tnamesData = createNamesDataMap();\n\t\t\tdataMap.put(eventXmlns, namesData);\n\t\t}\n\n\t\tCollection<M> dataList = namesData.get(eventName);\n\t\tif (dataList == null) {\n\t\t\tdataList = createDataList();\n\t\t\tnamesData.put(eventName, dataList);\n\t\t}\n\n\t\tdataList.add(data);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/disteventbus/impl/LocalEventBus.java",
    "content": "package tigase.disteventbus.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Set;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventHandler;\nimport tigase.xml.Element;\n\npublic class LocalEventBus implements EventBus {\n\n\tpublic static final String EVENTBUS_INTERNAL_EVENTS_XMLNS = \"tigase:eventbus:internal:events:0\";\n\tpublic static final String HANDLER_ADDED_EVENT_NAME = \"HandlerAdded\";\n\tpublic static final String HANDLER_REMOVED_EVENT_NAME = \"HandlerRemoved\";\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\tprivate final EventsNameMap<EventHandler> handlers;\n\tprivate Executor executor;\n\n\tpublic LocalEventBus() {\n\t\tsetThreadPool(4);\n\t\thandlers = createHandlersMap();\n\t}\n\n\tpublic Executor getExecutor() {\n\t\treturn executor;\n\t}\n\n\tpublic void setExecutor(Executor executor) {\n\t\tthis.executor = executor;\n\t}\n\n\t@Override\n\tpublic void addHandler(final String name, final String xmlns, final EventHandler handler) {\n\t\tif (name != null && xmlns == null)\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"Illegal handler registration. If name is specified, then xmlns must also be specified.\");\n\t\tthis.handlers.put(name, xmlns, handler);\n\t\tfireOnAddHandler(name, xmlns, handler);\n\t}\n\n\tprotected EventsNameMap<EventHandler> createHandlersMap() {\n\t\treturn new EventsNameMap<>();\n\t}\n\n\tpublic void doFire(final String name, final String xmlns, final Element event) {\n\t\tif (event == null) {\n\t\t\tthrow new NullPointerException(\"Cannot fire null event\");\n\t\t}\n\n\t\tfinal ArrayList<EventHandler> handlers = new ArrayList<>();\n\t\tsynchronized (this.handlers) {\n\t\t\thandlers.addAll(getHandlersList(name, xmlns));\n\t\t\thandlers.addAll(getHandlersList(null, xmlns));\n\t\t\thandlers.addAll(getHandlersList(null, null));\n\t\t}\n\t\tdoFireThreadPerHandler(name, xmlns, event, handlers);\n\t}\n\n\tprivate void doFireThreadPerHandler(final String name, final String xmlns, final Element event,\n\t\t\tArrayList<EventHandler> handlersList) {\n\t\tfor (EventHandler eventHandler : handlersList) {\n\t\t\tRunnable task = () -> {\n\t\t\t\ttry {\n\t\t\t\t\teventHandler.onEvent(name, xmlns, event);\n\t\t\t\t} catch (Throwable e) {\n\t\t\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem during handling event name=\" + name + \", xmlns=\" + xmlns\n\t\t\t\t\t\t\t\t+ \" in handler \" + eventHandler, e);\n\t\t\t\t}\n\t\t\t};\n\t\t\texecutor.execute(task);\n\t\t}\n\t}\n\n\tprivate void doFireThreadPerEvent(final String name, final String xmlns, final Element event,\n\t\t\tArrayList<EventHandler> handlersList) {\n\t\tRunnable task = () -> {\n\t\t\tfor (EventHandler eventHandler : handlersList) {\n\t\t\t\ttry {\n\t\t\t\t\teventHandler.onEvent(name, xmlns, event);\n\t\t\t\t} catch (Throwable e) {\n\t\t\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem during handling event name=\" + name + \", xmlns=\" + xmlns\n\t\t\t\t\t\t\t\t+ \" in handler \" + eventHandler, e);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\texecutor.execute(task);\n\t}\n\n\t@Override\n\tpublic void fire(final Element event) {\n\t\tfinal String name = event.getName();\n\t\tfinal String xmlns = event.getXMLNS();\n\n\t\tdoFire(name, xmlns, event);\n\t}\n\n\tprivate void fireOnAddHandler(final String name, final String xmlns, final EventHandler handler) {\n\t\tElement event = new Element(HANDLER_ADDED_EVENT_NAME);\n\t\tevent.setAttribute(\"local\", \"true\");\n\t\tevent.setXMLNS(EVENTBUS_INTERNAL_EVENTS_XMLNS);\n\n\t\tevent.addChild(new Element(\"name\", name));\n\t\tevent.addChild(new Element(\"xmlns\", xmlns));\n\n\t\tfire(event);\n\t}\n\n\tprivate void fireOnRemoveHandler(final String name, final String xmlns, final EventHandler handler) {\n\t\tElement event = new Element(HANDLER_REMOVED_EVENT_NAME);\n\t\tevent.setAttribute(\"local\", \"true\");\n\t\tevent.setXMLNS(EVENTBUS_INTERNAL_EVENTS_XMLNS);\n\n\t\tevent.addChild(new Element(\"name\", name));\n\t\tevent.addChild(new Element(\"xmlns\", xmlns));\n\n\t\tfire(event);\n\t}\n\n\tpublic Set<EventName> getAllListenedEvents() {\n\t\treturn handlers.getAllListenedEvents();\n\t}\n\n\tprotected Collection<EventHandler> getHandlersList(final String name, final String xmlns) {\n\t\treturn handlers.get(name, xmlns);\n\t}\n\n\tpublic boolean hasHandlers(String name, String xmlns) {\n\t\treturn handlers.hasData(name, xmlns);\n\t}\n\n\t@Override\n\tpublic void removeHandler(final String name, final String xmlns, final EventHandler handler) {\n\t\thandlers.delete(name, xmlns, handler);\n\t\tfireOnRemoveHandler(name, xmlns, handler);\n\t}\n\n\tpublic void setThreadPool(int pool) {\n\t\tthis.executor = Executors.newFixedThreadPool(pool);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/BufferUnderflowException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.io;\n\nimport java.io.IOException;\n\n/**\n * Describe class BufferUnderflowException here.\n *\n *\n * Created: Sun Sep 24 22:32:37 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BufferUnderflowException extends IOException {\n  private static final long serialVersionUID = 1L;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/CertFilesTrustManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: kobit $\n * $Date:  $\n */\n\npackage tigase.io;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.InputStream;\nimport java.security.InvalidAlgorithmParameterException;\nimport java.security.cert.CertPath;\nimport java.security.cert.CertPathValidator;\nimport java.security.cert.CertPathValidatorException;\nimport java.security.cert.CertPathValidatorResult;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.CertificateParsingException;\nimport java.security.cert.PKIXParameters;\nimport java.security.cert.TrustAnchor;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport javax.net.ssl.X509TrustManager;\n\n/**\n * Class CertFilesTrustManager\n *\n * @author <a href=\"mailto:bartosz.malkowski@tigase.org\">Bartosz Malkowski</a>\n * @version $Rev: $\n */\npublic class CertFilesTrustManager implements X509TrustManager {\n\n\tprivate static CertificateFactory certificateFactory;\n\n\tpublic static CertFilesTrustManager getInstance(String pathToCertsFiles) throws Exception {\n\t\tcertificateFactory = CertificateFactory.getInstance(\"X.509\");\n\t\tSet<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();\n\n\t\tFile[] files = new File(pathToCertsFiles).listFiles();\n\n\t\tfor (File file : files) {\n\t\t\tif (!file.isFile()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tX509Certificate cert = loadCertificate(file);\n\t\t\t\tTrustAnchor ta = new TrustAnchor(cert, null);\n\t\t\t\ttrustAnchors.add(ta);\n\t\t\t} catch (CertificateParsingException e) {}\n\t\t}\n\n\t\tCertPathValidator val = CertPathValidator.getInstance(CertPathValidator.getDefaultType());\n\n\t\tPKIXParameters cpp = new PKIXParameters(trustAnchors);\n\t\tcpp.setRevocationEnabled(false);\n\t\tCertFilesTrustManager tm = new CertFilesTrustManager(val, cpp);\n\t\treturn tm;\n\t}\n\n\tprivate static X509Certificate loadCertificate(File certFile) throws Exception {\n\t\tInputStream inStream = null;\n\t\ttry {\n\t\t\tinStream = new FileInputStream(certFile);\n\t\t\tX509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(inStream);\n\t\t\treturn cert;\n\t\t} finally {\n\t\t\tif (inStream != null) inStream.close();\n\t\t}\n\t}\n\n\tprivate PKIXParameters parameters;\n\n\tprivate CertPathValidator validator;\n\n\tprivate CertFilesTrustManager(CertPathValidator val, PKIXParameters cpp) {\n\t\tthis.validator = val;\n\t\tthis.parameters = cpp;\n\t}\n\n\t@Override\n\tpublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n\t\tcheckServerTrusted(chain, authType);\n\t}\n\n\t@Override\n\tpublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n\t\t// TODO Auto-generated method stub\n\t\tList<X509Certificate> certs = new ArrayList<X509Certificate>();\n\t\tfor (X509Certificate certificate : chain) {\n\t\t\tcertificate.checkValidity();\n\t\t\tcerts.add(certificate);\n\t\t}\n\t\tCertPath cp = CertificateFactory.getInstance(\"X.509\").generateCertPath(certs);\n\t\ttry {\n\t\t\tCertPathValidatorResult result = validator.validate(cp, parameters);\n\t\t\tSystem.out.println(result);\n\t\t} catch (CertPathValidatorException e) {\n\t\t\t// e.printStackTrace();\n\t\t\tthrow new CertificateException(e);\n\t\t} catch (InvalidAlgorithmParameterException e) {\n\t\t\t// e.printStackTrace();\n\t\t\tthrow new CertificateException(e);\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic X509Certificate[] getAcceptedIssuers() {\n\t\treturn parameters.getTrustAnchors().toArray(new X509Certificate[] {});\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/IOInterface.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.IOListener;\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SocketChannel;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface IOInterface here.\n *\n *\n * Created: Sat May 14 08:07:38 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface IOInterface {\n\tint bytesRead();\n\n\tboolean checkCapabilities(String caps);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tint getInputPacketSize() throws IOException;\n\n\tSocketChannel getSocketChannel();\n\n\tvoid getStatistics(StatisticsList list, boolean reset);\n\n\tlong getBytesSent(boolean reset);\n\n\tlong getTotalBytesSent();\n\n\tlong getBytesReceived(boolean reset);\n\n\tlong getTotalBytesReceived();\n\n\tlong getBuffOverflow(boolean reset);\n\n\tlong getTotalBuffOverflow();\n\t\n\tboolean isConnected();\n\n\tboolean isRemoteAddress(String addr);\n\n\t//~--- methods --------------------------------------------------------------\n\n\tByteBuffer read(final ByteBuffer buff) throws IOException;\n\n\tvoid stop() throws IOException;\n\n\tboolean waitingToSend();\n\n\tint waitingToSendSize();\n\n\tint write(final ByteBuffer buff) throws IOException;\n\t\n\tvoid setLogId(String logId);\n\t\n}    // IOInterface\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/SSLContextContainer.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.io.CharArrayReader;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.security.KeyPair;\nimport java.security.KeyStore;\nimport java.security.KeyStoreException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.SecureRandom;\nimport java.security.UnrecoverableKeyException;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateParsingException;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.net.ssl.KeyManager;\nimport javax.net.ssl.KeyManagerFactory;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509KeyManager;\nimport javax.net.ssl.X509TrustManager;\nimport tigase.cert.CertificateEntry;\nimport tigase.cert.CertificateUtil;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 15, 2010 2:40:49 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SSLContextContainer implements SSLContextContainerIfc {\n\n\tprivate static class FakeTrustManager implements X509TrustManager {\n\t\tprivate X509Certificate[] issuers = null;\n\n\t\t// ~--- constructors\n\t\t// -------------------------------------------------------\n\n\t\t/**\n\t\t * Constructs ...\n\t\t * \n\t\t */\n\t\tFakeTrustManager() {\n\t\t\tthis(new X509Certificate[0]);\n\t\t}\n\n\t\t/**\n\t\t * Constructs ...\n\t\t * \n\t\t * \n\t\t * @param ai\n\t\t */\n\t\tFakeTrustManager(X509Certificate[] ai) {\n\t\t\tissuers = ai;\n\t\t}\n\n\t\t// ~--- methods\n\n\t\t// Implementation of javax.net.ssl.X509TrustManager\n\n\t\t@Override\n\t\tpublic void checkClientTrusted(final X509Certificate[] x509CertificateArray, final String string)\n\t\t\t\tthrows CertificateException {\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkServerTrusted(final X509Certificate[] x509CertificateArray, final String string)\n\t\t\t\tthrows CertificateException {\n\t\t}\n\n\t\t// ~--- get methods\n\n\t\t@Override\n\t\tpublic X509Certificate[] getAcceptedIssuers() {\n\t\t\treturn issuers;\n\t\t}\n\t}\n\n\t// ~--- fields\n\n\tprivate class PEMFileFilter implements FileFilter {\n\n\t\t@Override\n\t\tpublic boolean accept(File pathname) {\n\t\t\tif (pathname.isFile()\n\t\t\t\t\t&& (pathname.getName().endsWith(\".pem\") || pathname.getName().endsWith(\".PEM\")\n\t\t\t\t\t\t\t|| pathname.getName().endsWith(\".crt\") || pathname.getName().endsWith(\".CRT\")\n\t\t\t\t\t\t\t|| pathname.getName().endsWith(\".cer\") || pathname.getName().endsWith(\".CER\"))) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tprivate static final Logger log = Logger.getLogger(SSLContextContainer.class.getName());\n\tpublic final static String PER_DOMAIN_CERTIFICATE_KEY = \"virt-hosts-cert-\";\n\tprivate ArrayList<X509Certificate> acceptedIssuers = new ArrayList<X509Certificate>(200);\n\tprivate File[] certsDirs = null;\n\tprotected String def_cert_alias = DEFAULT_DOMAIN_CERT_VAL;\n\tprivate String email = \"admin@tigase.org\";\n\tprivate char[] emptyPass = new char[0];\n\tprotected Map<String, KeyManagerFactory> kmfs = new ConcurrentSkipListMap<String, KeyManagerFactory>();\n\tprivate String o = \"Tigase.org\";\n\tprivate String ou = \"XMPP Service\";\n\tprivate SecureRandom secureRandom = new SecureRandom();\n\n\t// ~--- methods\n\t// --------------------------------------------------------------\n\n\tprotected Map<String, SSLContextsHolder> sslContexts = new ConcurrentSkipListMap<>();\n\n\t// ~--- get methods\n\t// ----------------------------------------------------------\n\n\tprivate X509TrustManager[] tms = new X509TrustManager[] { new FakeTrustManager() };\n\tprotected X509KeyManager[] kms = null;\n\n\tprivate KeyStore trustKeyStore = null;\n\n\t// ~--- methods\n\t// --------------------------------------------------------------\n\n\tprivate KeyManagerFactory addCertificateEntry(CertificateEntry entry, String alias, boolean store)\n\t\t\tthrows KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {\n\t\tKeyStore keys = KeyStore.getInstance(\"JKS\");\n\n\t\tkeys.load(null, emptyPass);\n\t\tkeys.setKeyEntry(alias, entry.getPrivateKey(), emptyPass, CertificateUtil.sort(entry.getCertChain()));\n\n\t\t\n\t\tKeyManagerFactory kmf = KeyManagerFactory.getInstance(\"SunX509\");\n\n\t\tkmf.init(keys, emptyPass);\n\t\tkmfs.put(alias, kmf);\n\n\t\tif (store) {\n\t\t\tCertificateUtil.storeCertificate(new File(certsDirs[0], alias + \".pem\").toString(), entry);\n\t\t}\n\n\t\treturn kmf;\n\t}\n\n\t@Override\n\tpublic void addCertificates(Map<String, String> params) throws CertificateParsingException {\n\t\tString pemCert = params.get(PEM_CERTIFICATE_KEY);\n\t\tString saveToDiskVal = params.get(CERT_SAVE_TO_DISK_KEY);\n\t\tboolean saveToDisk = (saveToDiskVal != null) && saveToDiskVal.equalsIgnoreCase(\"true\");\n\t\tfinal String alias = params.get(CERT_ALIAS_KEY);\n\n\t\tif (alias == null) {\n\t\t\tthrow new RuntimeException(\"Certificate alias must be specified\");\n\t\t}\n\n\t\tif (pemCert != null) {\n\t\t\ttry {\n\t\t\t\tCertificateEntry entry = CertificateUtil.parseCertificate(new CharArrayReader(pemCert.toCharArray()));\n\n\t\t\t\taddCertificateEntry(entry, alias, saveToDisk);\n\t\t\t\tsslContexts.remove(alias);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tthrow new CertificateParsingException(\"Problem adding a new certificate.\", ex);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ~--- get methods\n\t// ----------------------------------------------------------\n\n\tprivate Map<String, File> findPredefinedCertificates(Map<String, Object> params) {\n\t\tfinal Map<String, File> result = new HashMap<String, File>();\n\t\tif (params == null)\n\t\t\treturn result;\n\n\t\tIterator<String> it = params.keySet().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tString t = it.next();\n\t\t\tif (t.startsWith(PER_DOMAIN_CERTIFICATE_KEY)) {\n\t\t\t\tString domainName = t.substring(PER_DOMAIN_CERTIFICATE_KEY.length());\n\t\t\t\tFile f = new File(params.get(t).toString());\n\n\t\t\t\tresult.put(domainName, f);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n\t// ~--- inner classes\n\t// --------------------------------------------------------\n\n\tpublic SSLContext getSSLContext(String protocol, String hostname, boolean clientMode) {\n\t\treturn getSSLContext(protocol, hostname, clientMode, tms);\n\t}\n\t\n\tpublic static <T> T find(Map<String, T> data, String key) {\n\t\tif (data.containsKey(key)) {\n\t\t\treturn data.get(key);\n\t\t}\n\n\t\t// should be faster than code commented below\n\t\t// in case when there is no value at all\n\t\tint idx = key.indexOf(\".\");\n\t\tif (idx >= 0) {\n\t\t\tString asteriskKey = \"*\" + key.substring(idx);\n\t\t\tT value = data.get(asteriskKey);\n\t\t\tif (value != null) {\n\t\t\t\tdata.put(key, value);\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n//\t\tfor (Entry<String, T> entry : data.entrySet()) {\n//\t\t\tfinal String k = entry.getKey();\n//\t\t\tif (k.startsWith(\"*\") && key.endsWith(k.substring(1))) {\n//\t\t\t\tdata.put(key, entry.getValue());\n//\t\t\t\treturn entry.getValue();\n//\t\t\t}\n//\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate class SSLContextsHolder {\n\t\tprivate final Map<TrustManager[],SSLContext> sslContexts = new ConcurrentHashMap<>(4);\n\t\t\n\t\tpublic SSLContext getSSLContext(TrustManager[] tms) {\n\t\t\treturn sslContexts.get(tms);\n\t\t}\n\t\t\n\t\tpublic void putSSLContext(TrustManager[] tms, SSLContext sslContext) {\n\t\t\tsslContexts.put(tms, sslContext);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic SSLContext getSSLContext(String protocol, String hostname, boolean clientMode, TrustManager... tms) {\n\t\tSSLContext sslContext = null;\n\n\t\tString alias = hostname;\n\n\t\ttry {\n\n\t\t\t// in client mode we need SSLContext initialized with certificate for proper domain\n\t\t\t// as in other case we would not be able to authenticate to other endpoint by\n\t\t\t// providing proper client certificate for domain\n//\t\t\tif (clientMode) {\n//\t\t\t\tsslContext = SSLContext.getInstance(protocol);\n//\t\t\t\tsslContext.init(null, tms, secureRandom);\n//\t\t\t\treturn sslContext;\n//\t\t\t}\n\n\n\t\t\tif (alias == null) {\n\t\t\t\talias = def_cert_alias;\n\t\t\t} // end of if (hostname == null)\n\n\t\t\tSSLContextsHolder sslContextsHolder = find(sslContexts, alias);\n\t\t\tif (sslContextsHolder != null)\n\t\t\t\tsslContext = sslContextsHolder.getSSLContext(tms);\n\t\t\t\n\t\t\tif (sslContext == null) {\n\t\t\t\tKeyManagerFactory kmf = find(kmfs, alias);\n\n\t\t\t\tif (kmf == null) {\n\t\t\t\t\t// if there is no KeyManagerFactory for domain then we can create\n\t\t\t\t\t// new empty context as we have no certificate for this domain\n\t\t\t\t\tif (clientMode) {\n\t\t\t\t\t\tsslContext = SSLContext.getInstance(protocol);\n\t\t\t\t\t\tsslContext.init(null, tms, secureRandom);\n\t\t\t\t\t\treturn sslContext;\n\t\t\t\t\t}\n\n\t\t\t\t\tKeyPair keyPair = CertificateUtil.createKeyPair(1024, \"secret\");\n\t\t\t\t\tX509Certificate cert = CertificateUtil.createSelfSignedCertificate(email, alias, ou, o, null, null, null,\n\t\t\t\t\t\t\tkeyPair);\n\t\t\t\t\tCertificateEntry entry = new CertificateEntry();\n\n\t\t\t\t\tentry.setPrivateKey(keyPair.getPrivate());\n\t\t\t\t\tentry.setCertChain(new Certificate[]{cert});\n\t\t\t\t\tkmf = addCertificateEntry(entry, alias, true);\n\t\t\t\t\tlog.log(Level.WARNING, \"Auto-generated certificate for domain: {0}\", alias);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tsslContext = SSLContext.getInstance(protocol);\n\t\t\t\tsslContext.init((hostname == null && kms != null) ? kms : kmf.getKeyManagers(), tms, secureRandom);\n\t\t\t\tsslContextsHolder = new SSLContextsHolder();\n\t\t\t\tsslContextsHolder = sslContexts.putIfAbsent(alias, sslContextsHolder);\n\t\t\t\tif (sslContextsHolder == null)\n\t\t\t\t\tsslContextsHolder = sslContexts.get(alias);\n\t\t\t\tsslContextsHolder.putSSLContext(tms, sslContext);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not initialize SSLContext for domain: \" + alias + \", protocol: \" + protocol, e);\n\t\t\tsslContext = null;\n\t\t}\n                \n\t\treturn sslContext;\n\t}\n\n\t@Override\n\tpublic KeyStore getTrustStore() {\n\t\treturn trustKeyStore;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> params) {\n\t\ttry {\n\t\t\tdef_cert_alias = (String) params.get(DEFAULT_DOMAIN_CERT_KEY);\n\n\t\t\tif (def_cert_alias == null) {\n\t\t\t\tdef_cert_alias = DEFAULT_DOMAIN_CERT_VAL;\n\t\t\t}\n\n\t\t\tString pemD = (String) params.get(SERVER_CERTS_LOCATION_KEY);\n\n\t\t\tif (pemD == null) {\n\t\t\t\tpemD = SERVER_CERTS_LOCATION_VAL;\n\t\t\t}\n\n\t\t\tString[] pemDirs = pemD.split(\",\");\n\n\t\t\tcertsDirs = new File[pemDirs.length];\n\n\t\t\tint certsDirsIdx = -1;\n\n\t\t\tMap<String, File> predefined = findPredefinedCertificates(params);\n\t\t\tlog.log(Level.CONFIG, \"Loading predefined server certificates\");\n\t\t\tfor (final Entry<String, File> entry : predefined.entrySet()) {\n\t\t\t\ttry {\n\t\t\t\t\tCertificateEntry certEntry = CertificateUtil.loadCertificate(entry.getValue());\n\t\t\t\t\tString alias = entry.getKey();\n\t\t\t\t\taddCertificateEntry(certEntry, alias, false);\n\t\t\t\t\tlog.log(Level.CONFIG, \"Loaded server certificate for domain: {0} from file: {1}\", new Object[] { alias,\n\t\t\t\t\t\t\tentry.getValue() });\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Cannot load certficate from file: \" + entry.getValue(), ex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (String pemDir : pemDirs) {\n\t\t\t\tlog.log(Level.CONFIG, \"Loading server certificates from PEM directory: {0}\", pemDir);\n\t\t\t\tcertsDirs[++certsDirsIdx] = new File(pemDir);\n\n\t\t\t\tfor (File file : certsDirs[certsDirsIdx].listFiles(new PEMFileFilter())) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tCertificateEntry certEntry = CertificateUtil.loadCertificate(file);\n\t\t\t\t\t\tString alias = file.getName();\n\t\t\t\t\t\tif (alias.endsWith(\".pem\"))\n\t\t\t\t\t\t\talias = alias.substring(0, alias.length() - 4);\n\n\t\t\t\t\t\taddCertificateEntry(certEntry, alias, false);\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Loaded server certificate for domain: {0} from file: {1}\", new Object[] { alias,\n\t\t\t\t\t\t\t\tfile });\n\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Cannot load certficate from file: \" + file, ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"There was a problem initializing SSL certificates.\", ex);\n\t\t}\n\n\t\tString trustLoc = (String) params.get(TRUSTED_CERTS_DIR_KEY);\n\n\t\tif (trustLoc == null) {\n\t\t\ttrustLoc = TRUSTED_CERTS_DIR_VAL;\n\t\t}\n\n\t\tfinal String[] trustLocations = trustLoc.split(\",\");\n\n\t\t// It may take a while, let's do it in background\n\t\tnew Thread() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tloadTrustedCerts(trustLocations);\n\t\t\t}\n\t\t}.start();\n\t}\n\n\tprivate void loadTrustedCerts(String[] trustLocations) {\n\t\tint counter = 0;\n\t\tlong start = System.currentTimeMillis();\n\n\t\ttry {\n\t\t\ttrustKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());\n\t\t\ttrustKeyStore.load(null, emptyPass);\n\n\t\t\tfinal File trustStoreFile = new File(System.getProperty(\"java.home\")\n\t\t\t\t\t+ \"/lib/security/cacerts\".replace('/', File.separatorChar));\n\t\t\tfinal File userStoreFile = new File(\"~/.keystore\");\n\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.log(Level.FINE, \"Looking for trusted certs in: {0}\", trustStoreFile);\n\n\t\t\tif (trustStoreFile.exists()) {\n\t\t\t\tlog.log(Level.CONFIG, \"Loading trustKeyStore from location: {0}\", trustStoreFile);\n\t\t\t\tInputStream in = new FileInputStream(trustStoreFile);\n\t\t\t\ttrustKeyStore.load(in, null);\n\t\t\t\tin.close();\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.log(Level.FINE, \"Looking for trusted certs in: {0}\", userStoreFile);\n\n\t\t\tif (userStoreFile.exists()) {\n\t\t\t\tlog.log(Level.CONFIG, \"Loading trustKeyStore from location: {0}\", userStoreFile);\n\t\t\t\tInputStream in = new FileInputStream(userStoreFile);\n\t\t\t\ttrustKeyStore.load(in, null);\n\t\t\t\tin.close();\n\t\t\t}\n\n\t\t\tlog.log(Level.CONFIG, \"Loading trustKeyStore from locations: {0}\", Arrays.toString(trustLocations));\n\t\t\tfor (String location : trustLocations) {\n\t\t\t\tFile root = new File(location);\n\t\t\t\tFile[] files = root.listFiles(new PEMFileFilter());\n\n\t\t\t\tif (files != null) {\n\t\t\t\t\tfor (File file : files) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tCertificateEntry certEntry = CertificateUtil.loadCertificate(file);\n\t\t\t\t\t\t\tCertificate[] chain = certEntry.getCertChain();\n\n\t\t\t\t\t\t\tif (chain != null) {\n\t\t\t\t\t\t\t\tfor (Certificate cert : chain) {\n\t\t\t\t\t\t\t\t\tif (cert instanceof X509Certificate) {\n\t\t\t\t\t\t\t\t\t\tX509Certificate crt = (X509Certificate) cert;\n\t\t\t\t\t\t\t\t\t\tString alias = crt.getSubjectX500Principal().getName();\n\n\t\t\t\t\t\t\t\t\t\ttrustKeyStore.setCertificateEntry(alias, crt);\n\t\t\t\t\t\t\t\t\t\tacceptedIssuers.add(crt);\n\t\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Imported certificate: {0}\", alias);\n\t\t\t\t\t\t\t\t\t\t++counter;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem loading certificate from file: {0}\", file);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"An error loading trusted certificates\", ex);\n\t\t}\n\n\t\ttry {\n\t\t\tif (!trustKeyStore.aliases().hasMoreElements()) {\n\t\t\t\tlog.log(Level.CONFIG, \"No Trusted Anchors!!! Creating temporary trusted CA cert!\");\n\t\t\t\tKeyPair keyPair = CertificateUtil.createKeyPair(1024, \"secret\");\n\t\t\t\tX509Certificate cert = CertificateUtil.createSelfSignedCertificate(\"fake_local@tigase\", \"fake one\", \"none\",\n\t\t\t\t\t\t\"none\", \"none\", \"none\", \"US\", keyPair);\n\t\t\t\ttrustKeyStore.setCertificateEntry(\"generated fake CA\", cert);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't generate fake trusted CA certificate\", e);\n\t\t}\n\n\t\ttms = new X509TrustManager[] { new FakeTrustManager(\n\t\t\t\tacceptedIssuers.toArray(new X509Certificate[acceptedIssuers.size()])) };\n\n\t\tlong seconds = (System.currentTimeMillis() - start) / 1000;\n\n\t\tlog.log(Level.CONFIG, \"Loaded {0} trust certificates, it took {1} seconds.\", new Object[] { counter, seconds });\n\t}\t\n}\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/SSLContextContainerIfc.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.File;\nimport java.security.KeyStore;\nimport java.security.cert.CertificateParsingException;\nimport java.util.Map;\n\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509TrustManager;\nimport tigase.io.jdk18.SNISSLContextContainer;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface SSLContextContainerIfc here.\n * \n * \n * Created: Tue Nov 20 11:43:32 2007\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface SSLContextContainerIfc {\n\n\t/**\n\t * Constant <code>ALLOW_INVALID_CERTS_KEY</code> is a key pointing to a\n\t * configuration parameters specyfying if invalid certificates are\n\t * acceptable by the server. Invalid certificates are expired ones or\n\t * certificates issued for a different domain. This should be really set to\n\t * <code>false</code> in any real deployment and can be set ot\n\t * <code>true</code> in development invironment.\n\t */\n\tpublic static final String ALLOW_INVALID_CERTS_KEY = \"allow-invalid-certs\";\n\n\t/**\n\t * Constant <code>ALLOW_INVALID_CERTS_VAL</code> is a default configuration\n\t * parameter specifying if invalid certificates are acceptable by the\n\t * server.\n\t * \n\t */\n\tpublic static final String ALLOW_INVALID_CERTS_VAL = \"false\";\n\n\t/**\n\t * Constant <code>ALLOW_SELF_SIGNED_CERTS_KEY</code> is a key pointing to a\n\t * configuration parameter specifying if self-signed certificates are\n\t * acceptable for the server.\n\t */\n\tpublic static final String ALLOW_SELF_SIGNED_CERTS_KEY = \"allow-self-signed-certs\";\n\n\t/**\n\t * Constant <code>ALLOW_SELF_SIGNED_CERTS_VAL</code> is a default\n\t * configuration value specifying if self-signed certificates are allowed by\n\t * the server.\n\t */\n\tpublic static final String ALLOW_SELF_SIGNED_CERTS_VAL = \"true\";\n\n\t/** Field description */\n\tpublic static final String CERT_ALIAS_KEY = \"cert-alias\";\n\n\t/** Field description */\n\tpublic static final String CERT_SAVE_TO_DISK_KEY = \"cert-save-to-disk\";\n\n\t/**\n\t * Constant <code>DEFAULT_DOMAIN_CERT_KEY</code> is a key pointing to the\n\t * domain with default certificate.\n\t */\n\tpublic static final String DEFAULT_DOMAIN_CERT_KEY = \"ssl-def-cert-domain\";\n\n\t/**\n\t * Constant <code>DEFAULT_DOMAIN_CERT_VAL</code> keeps default value for a\n\t * domain with default certificate.\n\t */\n\tpublic static final String DEFAULT_DOMAIN_CERT_VAL = \"default\";\n\n\t/**\n\t * Constant <code>JKS_KEYSTORE_FILE_KEY</code> is a key pointing to a JKS\n\t * keystore file.\n\t */\n\tpublic static final String JKS_KEYSTORE_FILE_KEY = \"keys-store\";\n\n\t/**\n\t * Constant <code>JKS_KEYSTORE_FILE_VAL</code> keeps default value for a JKS\n\t * keystore file.\n\t */\n\tpublic static final String JKS_KEYSTORE_FILE_VAL = \"certs\" + File.separator + \"rsa-keystore\";\n\n\t/**\n\t * Constant <code>JKS_KEYSTORE_PWD_KEY</code> is a key pointing to a private\n\t * key password,\n\t */\n\tpublic static final String JKS_KEYSTORE_PWD_KEY = \"keys-store-password\";\n\n\t/**\n\t * Constant <code>JKS_KEYSTORE_PWD_VAL</code> is a default private key\n\t * password.\n\t */\n\tpublic static final String JKS_KEYSTORE_PWD_VAL = \"keystore\";\n\n\t/** Field description */\n\tpublic static final String PEM_CERTIFICATE_KEY = \"pem-certificate\";\n\n\t/**\n\t * Constant <code>SERVER_CERTS_DIR_KEY</code> is a key pointing to a\n\t * configuration parameter with directory names where all server\n\t * certificates are stored. This can be a comma separated list of\n\t * directories, instead of a single directory name. Certificates are stored\n\t * in <code>*.pem</code> files where the first part of the file name is a\n\t * domain name i.e.: <code>yourdomain.com.pem</code>. There is one exception\n\t * though. The file named <code>default.pem</code> stores a certificate\n\t * which is a default certificate for the server if certificate for specific\n\t * domain is missing.\n\t */\n\tpublic static final String SERVER_CERTS_LOCATION_KEY = \"ssl-certs-location\";\n\n\t/**\n\t * Constant <code>SERVER_CERTS_DIR_VAL</code> is a default directory name\n\t * where all certificate files are stored.\n\t * \n\t */\n\tpublic static final String SERVER_CERTS_LOCATION_VAL = \"certs/\";\n\n\t/**\n\t * Constant <code>SSL_CONTAINER_CLASS_KEY</code> is a key pointing to a\n\t * container implementation class. The class is loaded at startup time and\n\t * initialized using configuration parameters. Some container\n\t * implementations may accept different parameters set. Please refer to the\n\t * implementation for more details.\n\t */\n\tpublic static final String SSL_CONTAINER_CLASS_KEY = \"ssl-container-class\";\n\n\t/**\n\t * Constant <code>SSL_CONTAINER_CLASS_VAL</code> keeps default container\n\t * implementation class loaded if none is specified in configuration file.\n\t */\n\tpublic static final String SSL_CONTAINER_CLASS_VAL = SNISSLContextContainer.class.getName();\n\n\t/**\n\t * Constant <code>TRUSTED_CERTS_DIR_KEY</code> is a key pointing to a\n\t * configuration parameter where all trusted certificates are stored. This\n\t * can be a comma separated list of directories.\n\t */\n\tpublic static final String TRUSTED_CERTS_DIR_KEY = \"trusted-certs-dir\";\n\n\t/**\n\t * Constant <code>TRUSTED_CERTS_DIR_VAL</code> is a default directory name\n\t * where all trusted certificates are stored.\n\t */\n\tpublic static final String TRUSTED_CERTS_DIR_VAL = \"/etc/ssl/certs\";\n\n\t/**\n\t * Constant <code>TRUSTSTORE_FILE_KEY</code> is a key pointing to a trust\n\t * store file.\n\t */\n\tpublic static final String TRUSTSTORE_FILE_KEY = \"trusts-store\";\n\n\t/**\n\t * Constant <code>TRUSTSTORE_FILE_VAL</code> is a default truststore file.\n\t */\n\tpublic static final String TRUSTSTORE_FILE_VAL = \"certs\" + File.separator + \"truststore\";\n\n\t/**\n\t * Constant <code>TRUSTSTORE_PWD_KEY</code> is a key pointing to a trustore\n\t * file password.\n\t */\n\tpublic static final String TRUSTSTORE_PWD_KEY = \"trusts-store-password\";\n\n\t/**\n\t * Constant <code>TRUSTSTORE_PWD_VAL</code> is a default password for\n\t * truststore file.\n\t */\n\tpublic static final String TRUSTSTORE_PWD_VAL = \"truststore\";\n\n\t// ~--- methods\n\t// --------------------------------------------------------------\n\n\t/**\n\t * Method <code>addCertificates</code> allows to add more certificates at\n\t * run time after the container has bee already initialized. This is to\n\t * avoid server restart if there are certificates updates or new\n\t * certificates for new virtual domain. The method should add new\n\t * certificates or replace existing one if there is already a certificate\n\t * for a domain.\n\t * \n\t * @param params\n\t *            a <code>Map</code> value with configuration parameters.\n\t * @throws CertificateParsingException\n\t */\n\tvoid addCertificates(Map<String, String> params) throws CertificateParsingException;\n\n\t// ~--- get methods\n\t// ----------------------------------------------------------\n\n\t/**\n\t * Method <code>getSSLContext</code> creates and returns new SSLContext for\n\t * a given domain (hostname). For creation of the SSLContext a certificate\n\t * associated with this domain (hostname) should be used. If there is no\n\t * specific certificate for a given domain then default certificate should\n\t * be used.\n\t * \n\t * @param protocol\n\t *            a <code>String</code> is either 'SSL' or 'TLS' value.\n\t * @param hostname\n\t *            a <code>String</code> value keeps a hostname or domain for\n\t *            SSLContext.\n\t * @return a <code>SSLContext</code> value\n\t */\n\tSSLContext getSSLContext(String protocol, String hostname, boolean clientMode);\n\n\t SSLContext getSSLContext(String protocol, String hostname, boolean clientMode, TrustManager... tms);\n\t\n\t/**\n\t * Returns a trust store with all trusted certificates.\n\t * \n\t * @return a KeyStore with all trusted certificates, the KeyStore can be\n\t *         empty but cannot be null.\n\t */\n\tKeyStore getTrustStore();\n\n\t// ~--- methods\n\t// --------------------------------------------------------------\n\n\t/**\n\t * Method <code>init</code> method initializes the container. If the\n\t * container has been already initialized then it should clear all the data\n\t * and re-initialize the container with the \"fresh\" data. If there is only\n\t * one certificate loaded it is a default one as well. Otherwise the\n\t * certificate from <code>default.pem</code> file should be used as a\n\t * default one. Default certificate can be also set through the settings in\n\t * the <code>Map</code> given as a parameter.\n\t * <code>DEFAULT_DOMAIN_CERT_KEY</code> points to the domain which holds\n\t * default certificate.\n\t * \n\t * @param params\n\t *            a <code>Map</code> value\n\t */\n\tvoid init(Map<String, Object> params);\n}\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/SampleSocketThread.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.io;\n\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.Selector;\nimport java.nio.channels.ServerSocketChannel;\nimport java.nio.channels.SocketChannel;\nimport java.util.Iterator;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Describe class SampleSocketThread here.\n *\n *\n * Created: Sun Aug  6 22:34:40 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SampleSocketThread extends Thread {\n\n  private static final Logger log =\n\t\tLogger.getLogger(\"tigase.io.SampleSocketThread\");\n\n  private boolean stopping = false;\n\n  private final ConcurrentLinkedQueue<IOInterface> waiting =\n    new ConcurrentLinkedQueue<IOInterface>();\n\tprivate final ConcurrentLinkedQueue<InetSocketAddress> waiting_accept =\n    new ConcurrentLinkedQueue<InetSocketAddress>();\n  private final ConcurrentLinkedQueue<IOInterface> for_removal =\n    new ConcurrentLinkedQueue<IOInterface>();\n\n  private Selector clientSel = null;\n\tprivate SocketHandler handler = null;\n\n\t/**\n\t * Creates a new <code>SampleSocketThread</code> instance.\n\t *\n\t *\n\t * @param handler\n\t * @throws IOException\n\t */\n\tpublic SampleSocketThread(SocketHandler handler) throws IOException {\n\t\tthis.handler = handler;\n\t\tclientSel = Selector.open();\n\t\tsetName(\"SampleSocketThread\");\n\t}\n\n\tpublic void addIOInterface(IOInterface s) {\n    waiting.offer(s);\n    clientSel.wakeup();\n\t}\n\n\tpublic void addForAccept(InetSocketAddress isa) {\n\t\twaiting_accept.offer(isa);\n\t\tclientSel.wakeup();\n\t}\n\n\tpublic void removeIOInterface(IOInterface s) {\n\t\tSelectionKey key = s.getSocketChannel().keyFor(clientSel);\n\t\tif (key != null && key.attachment() == s) {\n\t\t\tkey.cancel();\n\t\t} // end of if (key != null)\n\t}\n\n  private void addAllWaiting() throws IOException {\n    IOInterface s = null;\n    while ((s = waiting.poll()) != null) {\n      final SocketChannel sc = s.getSocketChannel();\n      try {\n        sc.register(clientSel, SelectionKey.OP_READ, s);\n\t\t\t} catch (Exception e) {\n        // Ignore such channel\n      } // end of try-catch\n    } // end of for ()\n\t\tInetSocketAddress isa = null;\n\t\twhile ((isa = waiting_accept.poll()) != null) {\n\t\t\tServerSocketChannel ssc = ServerSocketChannel.open();\n\t\t\tssc.configureBlocking(false);\n\t\t\tssc.socket().bind(isa);\n\t\t\tssc.register(clientSel, SelectionKey.OP_ACCEPT, null);\n\t\t} // end of while (isa = waiting_accept.poll() != null)\n  }\n\n\t// Implementation of java.lang.Runnable\n\n\t@Override\n\tpublic void run() {\n    while (!stopping) {\n      try {\n        clientSel.select();\n        for (Iterator i = clientSel.selectedKeys().iterator(); i.hasNext();) {\n\t\t\t\t\tSelectionKey sk = (SelectionKey)i.next();\n\t\t\t\t\ti.remove();\n\t\t\t\t\tif ((sk.readyOps() & SelectionKey.OP_ACCEPT) != 0) {\n\t\t\t\t\t\tServerSocketChannel nextReady = (ServerSocketChannel)sk.channel();\n\t\t\t\t\t\tSocketChannel sc = nextReady.accept();\n            \t\t\tif (log.isLoggable(Level.FINER)) {\n            \t\t\t\tlog.finer(\"Registered new client socket: \"+sc);\n                        }\n\t\t\t\t\t\thandler.handleSocketAccept(sc);\n\t\t\t\t\t}\n\t\t\t\t\tif ((sk.readyOps() & SelectionKey.OP_CONNECT) != 0) {\n\t\t\t\t\t\t// Not implemented yet\n\t\t\t\t\t}\n\t\t\t\t\tif ((sk.readyOps() & SelectionKey.OP_READ) != 0) {\n\t\t\t\t\t\tIOInterface s = (IOInterface)sk.attachment();\n\t\t\t\t\t\tsk.cancel();\n\t\t\t\t\t\thandler.handleIOInterface(s);\n\t\t\t\t\t}\n        }\n\t\t\t\t// Clean-up cancelled keys...\n        clientSel.selectNow();\n        addAllWaiting();\n      } catch (Exception e) {\n        log.log(Level.SEVERE,\n\t\t\t\t\t\"SampleSocketThread I/O error, can't continue my work.\", e);\n        stopping = true;\n      }\n    }\n    System.err.println(\"SampleSocketThread stopped!\");\n    System.exit(2);\n\t}\n\n\tpublic interface SocketHandler {\n\n\t\tvoid handleIOInterface(IOInterface ioIfc) throws IOException;\n\n\t\tvoid handleSocketAccept(SocketChannel sc) throws IOException;\n\n\t}\n\n} // SampleSocketThread\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/SocketIO.java",
    "content": "/*\n * SocketIO.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.net.ConnectionOpenListener;\n\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.EOFException;\nimport java.io.IOException;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SocketChannel;\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Queue;\nimport tigase.net.IOUtil;\n\n/**\n * Describe class SocketIO here.\n *\n *\n * Created: Sat May 14 07:18:30 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SocketIO\n\t\t\t\timplements IOInterface {\n\tprivate static final Logger log                          =\n\t\tLogger.getLogger(SocketIO.class.getName());\n\tprivate static final int MAX_USER_IO_QUEUE_SIZE_PROP_DEF = 1000;\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate static final String MAX_USER_IO_QUEUE_SIZE_PROP_KEY = \"max-user-io-queue-size\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long buffOverflow            = 0;\n\tprivate int bytesRead                = 0;\n\tprivate long bytesReceived           = 0;\n\tprivate long bytesSent               = 0;\n\tprivate SocketChannel channel        = null;\n\tprivate Queue<ByteBuffer> dataToSend = null;\n\tprivate String logId                 = null;\n\tprivate String remoteAddress         = null;\n\tprivate long totalBuffOverflow       = 0;\n\tprivate long totalBytesReceived      = 0;\n\tprivate long totalBytesSent          = 0;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>SocketIO</code> instance.\n\t *\n\t * @param sock\n\t * @throws IOException\n\t */\n\tpublic SocketIO(final SocketChannel sock) throws IOException {\n\t\tchannel = sock;\n\t\tchannel.configureBlocking(false);\n\t\tchannel.socket().setSoLinger(false, 0);\n\t\tchannel.socket().setReuseAddress(true);\n\t\tchannel.socket().setKeepAlive(true);\n\t\tremoteAddress = channel.socket().getInetAddress().getHostAddress();\n\t\tif (channel.socket().getTrafficClass() == ConnectionOpenListener.IPTOS_THROUGHPUT) {\n\t\t\tdataToSend = new LinkedBlockingQueue<ByteBuffer>(100000);\n\t\t} else {\n\t\t\tint queue_size = Integer.getInteger(MAX_USER_IO_QUEUE_SIZE_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t MAX_USER_IO_QUEUE_SIZE_PROP_DEF);\n\n\t\t\tdataToSend = new LinkedBlockingQueue<ByteBuffer>(queue_size);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int bytesRead() {\n\t\treturn bytesRead;\n\t}\n\n\t@Override\n\tpublic boolean checkCapabilities(String caps) {\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic int getInputPacketSize() throws IOException {\n\t\treturn channel.socket().getReceiveBufferSize();\n\t}\n\n\t@Override\n\tpublic SocketChannel getSocketChannel() {\n\t\treturn channel;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list, boolean reset) {\n\t\tlist.add(\"socketio\", \"Bytes sent\", bytesSent, Level.FINE);\n\t\tlist.add(\"socketio\", \"Bytes received\", bytesReceived, Level.FINE);\n\t\tlist.add(\"socketio\", \"Buffers overflow\", buffOverflow, Level.FINE);\n\t\tlist.add(\"socketio\", \"Total bytes sent\", totalBytesSent, Level.FINE);\n\t\tlist.add(\"socketio\", \"Total bytes received\", totalBytesReceived, Level.FINE);\n\t\tlist.add(\"socketio\", \"Ttoal buffers overflow\", totalBuffOverflow, Level.FINE);\n\t\tif (reset) {\n\t\t\tbytesSent     = 0;\n\t\t\tbytesReceived = 0;\n\t\t\tbuffOverflow  = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t * \n\t */\n\tpublic long getBytesSent(boolean reset) {\n\t\tlong tmp = bytesSent;\n\n\t\tif (reset) {\n\t\t\tbytesSent = 0;\n\t\t}\n\n\t\treturn tmp;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getTotalBytesSent() {\n\t\treturn totalBytesSent;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t * \n\t */\n\tpublic long getBytesReceived(boolean reset) {\n\t\tlong tmp = bytesReceived;\n\n\t\tif (reset) {\n\t\t\tbytesReceived = 0;\n\t\t}\n\n\t\treturn tmp;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getTotalBytesReceived() {\n\t\treturn totalBytesReceived;\n\t}\n\n\t@Override\n\tpublic long getBuffOverflow(boolean reset) {\n\t\tlong tmp = buffOverflow;\n\n\t\tif (reset) {\n\t\t\tbuffOverflow = 0;\n\t\t}\n\n\t\treturn tmp;\n\t}\n\n\t@Override\n\tpublic long getTotalBuffOverflow() {\n\t\treturn totalBuffOverflow;\n\t}\n\n\t@Override\n\tpublic boolean isConnected() {\n\n\t\t// More correct would be calling both methods, however in the Tigase\n\t\t// all SocketChannels are connected before SocketIO is created.\n\t\t// return channel.isOpen() && channel.isConnected();\n\t\treturn channel.isOpen();\n\t}\n\n\t@Override\n\tpublic boolean isRemoteAddress(String addr) {\n\t\treturn remoteAddress.equals(addr);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic ByteBuffer read(final ByteBuffer buff) throws IOException {\n\t\tByteBuffer tmp = IOUtil.getDirectBuffer(buff.remaining());\n\t\ttry {\n\t\t\tbytesRead = channel.read(tmp);\n\t\t\ttmp.flip();\n\t\t\tif (bytesRead > 0) {\n\t\t\t\tbuff.put(tmp);\n\t\t\t}\n\t\t} finally {\n\t\t\tIOUtil.returnDirectBuffer(tmp);\n\t\t}\n\t\t\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Read from channel {0} bytes, {1}\", new Object[] { bytesRead,\n\t\t\t\t\t\t\ttoString() });\n\t\t}\n\t\tif (bytesRead == -1) {\n\t\t\t// we need to close channel but we should not throw exception as\n\t\t\t// in other way we will lose data from higher level internal buffers\n\t\t\tchannel.close();\n//\t\t\tthrow new EOFException(\"Channel has been closed.\");\n\t\t}    // end of if (result == -1)\n\t\tif (bytesRead > 0) {\n\t\t\tbuff.flip();\n\t\t\tbytesReceived      += bytesRead;\n\t\t\ttotalBytesReceived += bytesRead;\n\t\t}\n\n\t\treturn buff;\n\t}\n\n\t@Override\n\tpublic void stop() throws IOException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Stop called \" + toString());\n\t\t}\n\n\t\t// if (isRemoteAddress(\"81.142.228.219\")) {\n\t\t// log.warning(\"Stop called.\");\n\t\t// }\n\t\tchannel.close();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn logId + ((channel == null)\n\t\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t\t: channel.socket());\n\t}\n\n\t@Override\n\tpublic boolean waitingToSend() {\n\t\treturn isConnected() && (dataToSend.size() > 0);\n\t}\n\n\t@Override\n\tpublic int waitingToSendSize() {\n\t\treturn dataToSend.size();\n\t}\n\n\t@Override\n\tpublic int write(final ByteBuffer buff) throws IOException {\n\n\t\t// int result = 0;\n\t\t// while (buff.hasRemaining()) {\n\t\t// final int res = channel.write(buff);\n\t\t// if (res == -1) {\n\t\t// throw new EOFException(\"Channel has been closed.\");\n\t\t// } // end of if (res == -1)\n\t\t// result += res;\n\t\t// } // end of while (out.hasRemaining())\n\t\t// log.finer(\"Wrote to channel \" + result + \" bytes.\");\n\t\t// return result;\n\t\tif ((buff != null) && buff.hasRemaining()) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"SOCKET - Writing data, remaining: {0}, {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { buff.remaining(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t toString() });\n\t\t\t}\n\t\t\tif (!dataToSend.offer(buff)) {\n\t\t\t\t++buffOverflow;\n\t\t\t\t++totalBuffOverflow;\n\t\t\t}\n\t\t}\n\n\t\tint result            = 0;\n\t\tByteBuffer dataBuffer = null;\n\t\t\n\t\t// we are processing all buffers one by one to reduce need for direct \n\t\t// memory, and we use our own cache of DirectByteBuffers as cache from JDK\n\t\t// may keep up to 1024 buffers for single thread!!\n\t\twhile ((dataBuffer = dataToSend.peek()) != null) {\n\t\t\tint pos = dataBuffer.position();\n\t\t\tint lim = dataBuffer.limit();\n\t\t\tint rem = (pos <= lim ? lim - pos : 0);\n\t\t\tint res = 0;\n\t\t\t\n\t\t\tByteBuffer tmp = IOUtil.getDirectBuffer(rem);\n\t\t\ttry {\n\t\t\t\ttmp.put(dataBuffer);\n\t\t\t\ttmp.flip();\n\t\t\t\tdataBuffer.position(pos);\n\t\t\t\tres = channel.write(tmp);\n\t\t\t\tif (res > 0) {\n\t\t\t\t\tdataBuffer.position(pos + res);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tIOUtil.returnDirectBuffer(tmp);\n\t\t\t}\n\t\t\t\n\t\t\tif (res == -1) {\n\t\t\t\tthrow new EOFException(\"Channel has been closed.\");\n\t\t\t} else {\n\t\t\t\tresult += res;\n\t\t\t}\n\t\t\t\n\t\t\tif (!dataBuffer.hasRemaining()) {\n\t\t\t\tdataToSend.poll();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Wrote to channel {0} bytes, {1}\", new Object[] { result,\n\t\t\t\t\t\t\ttoString() });\n\t\t}\n\n\t\t// if (isRemoteAddress(\"81.142.228.219\")) {\n\t\t// log.warning(\"Wrote to channel \" + result + \" bytes.\");\n\t\t// }\n\t\tbytesSent      += result;\n\t\ttotalBytesSent += result;\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setLogId(String logId) {\n\t\tthis.logId = logId + \" \";\n\t}\t\t\n}    // SocketIO\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TLSEventHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface TLSEventHandler here.\n *\n *\n * Created: Wed Feb  7 23:20:14 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface TLSEventHandler {\n\tvoid handshakeCompleted(TLSWrapper wrapper);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TLSIO.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.EOFException;\nimport java.io.IOException;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.channels.SocketChannel;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.net.ssl.SSLEngineResult;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class TLSIO here.\n * \n * \n * Created: Sat May 14 07:43:30 2005\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TLSIO implements IOInterface {\n\n\t/** Field description */\n\tpublic static final String TLS_CAPS = \"tls-caps\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(TLSIO.class.getName());\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\tprivate IOInterface io = null;\n\t\n\t/**\n\t * <code>tlsInput</code> buffer keeps data decoded from tlsWrapper.\n\t */\n\tprivate ByteBuffer tlsInput = null;\n\n\t/**\n\t * <code>tlsWrapper</code> is a TLS wrapper for connections requiring TLS\n\t * protocol.\n\t */\n\tprivate TLSWrapper tlsWrapper = null;\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\t// /**\n\t// * Creates a new <code>TLSIO</code> instance.\n\t// *\n\t// */\n\t// public TLSIO(final SocketChannel sock) {\n\t// io = new SocketIO(sock);\n\t// tlsWrapper = new TLSWrapper(\"TLS\");\n\t// tlsInput = ByteBuffer.allocate(tlsWrapper.getAppBuffSize());\n\t// }\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param ioi\n\t * @param wrapper\n\t *\n\t * @throws IOException\n\t */\n\tpublic TLSIO(final IOInterface ioi, final TLSWrapper wrapper, final ByteOrder order) throws IOException {\n\t\tio = ioi;\n\t\ttlsWrapper = wrapper;\n\t\ttlsWrapper.setDebugId(toString());\n\t\ttlsInput = ByteBuffer.allocate(tlsWrapper.getAppBuffSize());\n                tlsInput.order(order);\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"TLS Socket created: {0}\", io.toString());\n\t\t}\n\n\t\tif (tlsWrapper.isClientMode()) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"TLS - client mode, starting handshaking now...\");\n\t\t\t}\n\n\t\t\twrite(ByteBuffer.allocate(0));\n\t\t} // end of if (tlsWrapper.isClientMode())\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int bytesRead() {\n\t\treturn io.bytesRead();\n\t}\n\n\t@Override\n\tpublic long getBytesSent(boolean reset) {\n\t\treturn io.getBytesSent(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBytesSent() {\n\t\treturn io.getTotalBytesSent();\n\t}\n\n\t@Override\n\tpublic long getBytesReceived(boolean reset) {\n\t\treturn io.getBytesReceived(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBytesReceived() {\n\t\treturn io.getTotalBytesReceived();\n\t}\n\n\t@Override\n\tpublic long getBuffOverflow(boolean reset) {\n\t\treturn io.getBuffOverflow(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBuffOverflow() {\n\t\treturn io.getTotalBuffOverflow();\n\t}\n\n\t@Override\n\tpublic boolean checkCapabilities(String caps) {\n\t\treturn caps.contains(TLS_CAPS) || io.checkCapabilities(caps);\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic int getInputPacketSize() throws IOException {\n\t\treturn tlsWrapper.getPacketBuffSize();\n\t}\n\n\t@Override\n\tpublic SocketChannel getSocketChannel() {\n\t\treturn io.getSocketChannel();\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list, boolean reset) {\n\t\tif (io != null) {\n\t\t\tio.getStatistics(list, reset);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isConnected() {\n\t\treturn io.isConnected();\n\t}\n\n\t@Override\n\tpublic boolean isRemoteAddress(String addr) {\n\t\treturn io.isRemoteAddress(addr);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic ByteBuffer read(ByteBuffer buff) throws IOException {\n\n\t\t// if (log.isLoggable(Level.FINER)) {\n\t\t// log.finer(\"input.capacity()=\" + buff.capacity());\n\t\t// log.finer(\"input.remaining()=\" + buff.remaining());\n\t\t// log.finer(\"input.limit()=\" + buff.limit());\n\t\t// log.finer(\"input.position()=\" + buff.position());\n\t\t// }\n\t\tByteBuffer tmpBuffer = io.read(buff);\n\n\t\tif (io.bytesRead() > 0) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Read bytes: {0}, {1}\", new Object[] { io.bytesRead(),\n\t\t\t\t\t\ttoString() });\n\t\t\t}\n\n\t\t\treturn decodeData(tmpBuffer);\n\t\t} else {\n\t\t\treturn null;\n\t\t} // end of else\n\t}\n\n\t@Override\n\tpublic void stop() throws IOException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Stop called...\" + toString());\n\n\t\t\t// Thread.dumpStack();\n\t\t}\n\n\t\tio.stop();\n\t\ttlsWrapper.close();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"TLS: \" + io.toString();\n\t}\n\n\t@Override\n\tpublic boolean waitingToSend() {\n\t\treturn io.waitingToSend();\n\t}\n\n\t@Override\n\tpublic int waitingToSendSize() {\n\t\treturn io.waitingToSendSize();\n\t}\n\n\t@Override\n\tpublic int write(ByteBuffer buff) throws IOException {\n\t\tTLSStatus stat = tlsWrapper.getStatus();\n\n\t\t// The loop below falls into infinite loop for some reason.\n\t\t// Let's try to detect it here and recover.\n\t\t// Looks like for some reason tlsWrapper.getStatus() sometimes starts to\n\t\t// return\n\t\t// NEED_READ status all the time and the loop never ends.\n\t\tint loop_cnt = 0;\n\t\tint max_loop_runs = 100000;\n\n\t\tboolean breakNow = true;\n\t\t\n\t\twhile (((stat == TLSStatus.NEED_WRITE) || (stat == TLSStatus.NEED_READ))\n\t\t\t\t&& (++loop_cnt < max_loop_runs)) {\n\t\t\tswitch (stat) {\n\t\t\t\tcase NEED_WRITE:\n\t\t\t\t\twriteBuff(ByteBuffer.allocate(0));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_READ:\n\t\t\t\t\t// We can get NEED_READ TLS status while there are data awaiting to be\n\t\t\t\t\t// sent thru network connection - we need to force sending data and to break\n\t\t\t\t\t// from this loop\n\t\t\t\t\tif (io.waitingToSend()) {\n\t\t\t\t\t\tio.write(null);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// it appears only during handshake so force break only in this case\n\t\t\t\t\t\tif (tlsWrapper.getTlsEngine().getHandshakeStatus() == \n\t\t\t\t\t\t\t\tSSLEngineResult.HandshakeStatus.NOT_HANDSHAKING \n\t\t\t\t\t\t\t\t&& (buff == null || !buff.hasRemaining())) {\n\t\t\t\t\t\t\tbreakNow = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// I wonder if some real data can be read from the socket here (and we\n\t\t\t\t\t// would\n\t\t\t\t\t// loose the data) or this is just TLS stuff here.....\n\t\t\t\t\tByteBuffer rbuff = read(ByteBuffer.allocate(tlsWrapper.getNetBuffSize()));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\t// case CLOSED:\n\t\t\t\t// if (tlsWrapper.getStatus() == TLSStatus.CLOSED) {\n\t\t\t\t// if (log.isLoggable(Level.FINER)) {\n\t\t\t\t// log.finer(\"TLS Socket closed...\");\n\t\t\t\t// }\n\t\t\t\t// throw new EOFException(\"Socket has been closed.\");\n\t\t\t\t// } // end of if (tlsWrapper.getStatus() == TLSStatus.CLOSED)\n\t\t\t\t// break;\n\t\t\t\tdefault:\n\t\t\t}\n\n\t\t\tstat = tlsWrapper.getStatus();\n\t\t\n\t\t\t// We can get NEED_READ TLS status while there are data awaiting to be\n\t\t\t// sent thru network connection - we need to force sending data and to break\n\t\t\t// from this loop\n\t\t\tif (breakNow) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (loop_cnt > (max_loop_runs / 2)) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Infinite loop detected in write(buff) TLS code, tlsWrapper.getStatus(): {0}, io: {1}\",\n\t\t\t\t\tnew Object[] {tlsWrapper.getStatus() , toString() }\n\t\t\t);\n\n\t\t\t// Let's close the connection now\n\t\t\tthrow new EOFException(\"Socket has been closed due to TLS problems.\");\n\t\t}\n\n\t\tif (tlsWrapper.getStatus() == TLSStatus.CLOSED) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"TLS Socket closed...\");\n\t\t\t}\n\n\t\t\tthrow new EOFException(\"Socket has been closed.\");\n\t\t} // end of if (tlsWrapper.getStatus() == TLSStatus.CLOSED)\n\n\t\tint result = -1;\n\n\t\tif (buff == null) {\n\t\t\tresult = io.write(null);\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"TLS - Writing data, remaining: {0}, {1}\", new Object[] {\n\t\t\t\t\t\tbuff.remaining(), toString() });\n\t\t\t}\n\n\t\t\tresult = writeBuff(buff);\n\t\t}\n\n\t\t// if (isRemoteAddress(\"81.142.228.219\")) {\n\t\t// log.warning(\"TLS - Writing data, remaining: \" + buff.remaining());\n\t\t// }\n\t\t// if (isRemoteAddress(\"81.142.228.219\")) {\n\t\t// log.warning(\"TLS - written: \" + result);\n\t\t// }\n\t\treturn result;\n\t}\n\n\tprivate ByteBuffer decodeData(ByteBuffer input) throws IOException {\n\t\tTLSStatus stat = null;\n\t\tboolean continueLoop = true;\n\n\t\t// input.flip();\n\t\t// do_loop:\n\t\tdo {\n\n\t\t\t// if (log.isLoggable(Level.FINER)) {\n\t\t\t// log.finer(\"Decoding data: \" + input.remaining());\n\t\t\t// log.finer(\"input.capacity()=\" + input.capacity());\n\t\t\t// log.finer(\"input.remaining()=\" + input.remaining());\n\t\t\t// log.finer(\"input.limit()=\" + input.limit());\n\t\t\t// log.finer(\"input.position()=\" + input.position());\n\t\t\t// log.finer(\"tlsInput.capacity()=\" + tlsInput.capacity());\n\t\t\t// log.finer(\"tlsInput.remaining()=\" + tlsInput.remaining());\n\t\t\t// log.finer(\"tlsInput.limit()=\" + tlsInput.limit());\n\t\t\t// log.finer(\"tlsInput.position()=\" + tlsInput.position());\n\t\t\t// }\n\t\t\ttlsInput = tlsWrapper.unwrap(input, tlsInput);\n\n\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t// int netSize = tlsWrapper.getPacketBuffSize();\n\t\t\t//\n\t\t\t// log.finer(\"tlsWrapper.getStatus() = \" + tlsWrapper.getStatus().name());\n\t\t\t// log.finer(\"PacketBuffSize=\" + netSize);\n\t\t\t// log.finer(\"input.capacity()=\" + input.capacity());\n\t\t\t// log.finer(\"input.remaining()=\" + input.remaining());\n\t\t\t// log.finer(\"input.limit()=\" + input.limit());\n\t\t\t// log.finer(\"input.position()=\" + input.position());\n\t\t\t// log.finer(\"tlsInput.capacity()=\" + tlsInput.capacity());\n\t\t\t// log.finer(\"tlsInput.remaining()=\" + tlsInput.remaining());\n\t\t\t// log.finer(\"tlsInput.limit()=\" + tlsInput.limit());\n\t\t\t// log.finer(\"tlsInput.position()=\" + tlsInput.position());\n\t\t\t// }\n\t\t\t// if (input.hasRemaining()) {\n\t\t\t// input.compact();\n\t\t\t// }// end of if (input.hasRemaining())\n\t\t\tswitch (tlsWrapper.getStatus()) {\n\t\t\t\tcase NEED_WRITE:\n\t\t\t\t\twriteBuff(ByteBuffer.allocate(0));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UNDERFLOW:\n\n\t\t\t\t\t// if (log.isLoggable(Level.FINER) && !log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t// int netSize = tlsWrapper.getPacketBuffSize();\n\t\t\t\t\t// log.finer(\"tlsWrapper.getStatus() = UNDERFLOW\");\n\t\t\t\t\t// log.finer(\"PacketBuffSize=\" + netSize);\n\t\t\t\t\t// log.finer(\"input.capacity()=\" + input.capacity());\n\t\t\t\t\t// log.finer(\"input.remaining()=\" + input.remaining());\n\t\t\t\t\t// log.finer(\"input.limit()=\" + input.limit());\n\t\t\t\t\t// log.finer(\"input.position()=\" + input.position());\n\t\t\t\t\t// log.finer(\"tlsInput.capacity()=\" + tlsInput.capacity());\n\t\t\t\t\t// log.finer(\"tlsInput.remaining()=\" + tlsInput.remaining());\n\t\t\t\t\t// log.finer(\"tlsInput.limit()=\" + tlsInput.limit());\n\t\t\t\t\t// log.finer(\"tlsInput.position()=\" + tlsInput.position());\n\t\t\t\t\t// }\n\t\t\t\t\t// Obtain more inbound network data for src,\n\t\t\t\t\t// then retry the operation.\n\t\t\t\t\t// If there is some data ready to read, let's try to read it before we\n\t\t\t\t\t// increase\n\t\t\t\t\t// the buffer size\n\t\t\t\t\t// throw new BufferUnderflowException();\n\t\t\t\t\tif (tlsInput.capacity() == tlsInput.remaining()) {\n\t\t\t\t\t\tthrow new BufferUnderflowException();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tinput.compact();\n\t\t\t\t\t\tcontinueLoop = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CLOSED:\n\n\t\t\t\t\t// if (tlsWrapper.getStatus() == TLSStatus.CLOSED) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(\"TLS Socket closed...\" + toString());\n\t\t\t\t\t}\n\n\t\t\t\t\t//throw new EOFException(\"Socket has been closed.\");\n\n\t\t\t\t\t// } // end of if (tlsWrapper.getStatus() == TLSStatus.CLOSED)\n\t\t\t\t\t// break do_loop;\n\t\t\t\t\t// break;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t} // end of switch (tlsWrapper.getStatus())\n\n\t\t\tstat = tlsWrapper.getStatus();\n\t\t} while (continueLoop && ((stat == TLSStatus.NEED_READ) || (stat == TLSStatus.OK))\n\t\t\t\t&& input.hasRemaining());\n\n\t\tif (continueLoop) {\n\t\t\tif (input.hasRemaining()) {\n\t\t\t\tinput.rewind();\n\t\t\t} else {\n\t\t\t\tinput.clear();\n\t\t\t}\n\t\t}\n\n\t\ttlsInput.flip();\n\n\t\treturn tlsInput;\n\t}\n\n\tprivate int writeBuff(ByteBuffer buff) throws IOException {\n\t\tint result = 0;\n\t\tint wr = 0;\n\n\t\t// The loop below falls into infinite loop for some reason.\n\t\t// Let's try to detect it here and recover.\n\t\t// -- After some tests....\n\t\t// Looks like the cause has been detected. Sometimes the loop\n\t\t// below is executed a few times for some reason. It happens that\n\t\t// the tlsWarpper.getStatus() returns NEED_READ and it doesn't\n\t\t// accept any more data from the input buffer.\n\t\t// The proper handling would need reading from the socket to\n\t\t// reset TLS to the correct state, but this involves another problems.\n\t\t// What to do with possible user data received in such a call?\n\t\t// It happens extremely rarely and is hard to diagnose. Let's leave it\n\t\t// as it is now which just causes such connections to be closed.\n\t\tint loop_cnt = 0;\n\t\tint max_loop_runs = 100000;\n\n\t\tdo {\n\t\t\tif (tlsWrapper.getStatus() == TLSStatus.NEED_READ) {\n\n\t\t\t\t// I wonder if some real data can be read from the socket here (and we\n\t\t\t\t// would\n\t\t\t\t// loose the data) or this is just TLS stuff here.....\n\t\t\t\tByteBuffer rbuff = read(ByteBuffer.allocate(tlsWrapper.getNetBuffSize()));\n\t\t\t}\n\n\t\t\tByteBuffer tlsOutput = ByteBuffer.allocate(tlsWrapper.getNetBuffSize());\n\n\t\t\t// Not sure if this is really needed, I guess not...\n\t\t\ttlsOutput.clear();\n\t\t\ttlsWrapper.wrap(buff, tlsOutput);\n\n\t\t\tif (tlsWrapper.getStatus() == TLSStatus.CLOSED) {\n\t\t\t\tthrow new EOFException(\"Socket has been closed.\");\n\t\t\t} // end of if (tlsWrapper.getStatus() == TLSStatus.CLOSED)\n\n\t\t\ttlsOutput.flip();\n\t\t\twr = io.write(tlsOutput);\n\t\t\tresult += wr;\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINER, \"TLS - Writing data, remaining: {0}, {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {buff.remaining(), toString() } );\n\t\t\t}\n\n\t\t} while (buff.hasRemaining() && (++loop_cnt < max_loop_runs));\n\n\t\tif (loop_cnt > (max_loop_runs / 2)) {\n\t\t\tlog.warning(\"Infinite loop detected in writeBuff(buff) TLS code, \"\n\t\t\t\t\t+ \"tlsWrapper.getStatus(): \" + tlsWrapper.getStatus()\n\t\t\t\t\t\t\t\t\t+ \", buff.remaining(): \" + buff.remaining() + \" io: \" + toString() );\n\n\t\t\t// Let's close the connection now\n\t\t\tthrow new EOFException(\"Socket has been closed due to TLS problems.\");\n\t\t}\n\n\t\tif (tlsWrapper.getStatus() == TLSStatus.NEED_WRITE) {\n\t\t\twriteBuff(ByteBuffer.allocate(0));\n\t\t} // end of if ()\n\n\t\treturn result;\n\t}\n\t\n\t@Override\n\tpublic void setLogId(String logId) {\n\t\tio.setLogId(logId);\n\t}\n} // TLSIO\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TLSStatus.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.io;\n\n/**\n * Describe class TLSStatus here.\n *\n *\n * Created: Sat Mar  5 09:28:45 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum TLSStatus {\n\n  NEED_WRITE,\n  NEED_READ,\n  UNDERFLOW,\n  CLOSED,\n  OK;\n\n} // TLSStatus\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TLSUtil.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.security.KeyStore;\nimport java.security.cert.CertificateParsingException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509TrustManager;\nimport static tigase.io.SSLContextContainerIfc.*;\nimport tigase.osgi.ModulesManagerImpl;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class TLSUtil here.\n *\n *\n * Created: Mon Jan 23 14:21:31 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class TLSUtil {\n\tprivate static final Logger log = Logger.getLogger(TLSUtil.class.getName());\n\n//private static Map<String, SSLContextContainerIfc> sslContexts =\n//  new HashMap<String, SSLContextContainerIfc>();\n\tprivate static SSLContextContainerIfc sslContextContainer = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param params\n\t *\n\t * @throws CertificateParsingException\n\t */\n\tpublic static void addCertificate(Map<String, String> params) throws CertificateParsingException {\n\t\tsslContextContainer.addCertificates(params);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param params\n\t */\n\tpublic static void configureSSLContext(Map<String, Object> params) {\n\t\tString sslCC_class = (String) params.get(SSL_CONTAINER_CLASS_KEY);\n\n\t\tif (sslCC_class == null) {\n\t\t\tsslCC_class = SSL_CONTAINER_CLASS_VAL;\n\t\t}\n\n\t\ttry {\n\t\t\tsslContextContainer = (SSLContextContainerIfc) ModulesManagerImpl.getInstance().forName(sslCC_class).newInstance();\n\t\t\t//sslContextContainer = (SSLContextContainerIfc) Class.forName(sslCC_class).newInstance();\n\t\t\tsslContextContainer.init(params);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not initialize SSL Container: \" + sslCC_class, e);\n\t\t\tsslContextContainer = null;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param protocol\n\t * @param hostname\n\t *\n\t * \n\t */\n\tpublic static SSLContext getSSLContext(String protocol, String hostname) {\n\t\treturn sslContextContainer.getSSLContext(protocol, hostname, false);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param protocol\n\t * @param hostname\n\t *\n\t * \n\t */\n\tpublic static SSLContext getSSLContext(String protocol, String hostname, boolean clientMode) {\n\t\treturn sslContextContainer.getSSLContext(protocol, hostname, clientMode);\n\t}\n\n\tpublic static SSLContext getSSLContext(String protocol, String hostname, boolean clientMode, TrustManager... tm) {\n\t\treturn sslContextContainer.getSSLContext(protocol, hostname, clientMode, tm);\n\t}\n\n        /**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static KeyStore getTrustStore() {\n\t\treturn sslContextContainer.getTrustStore();\n\t}\n}    // TLSUtil\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TLSWrapper.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\nimport java.security.NoSuchAlgorithmException;\nimport java.security.cert.Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLEngine;\nimport javax.net.ssl.SSLEngineResult;\nimport javax.net.ssl.SSLEngineResult.HandshakeStatus;\nimport javax.net.ssl.SSLEngineResult.Status;\nimport javax.net.ssl.SSLException;\nimport javax.net.ssl.SSLPeerUnverifiedException;\n\nimport tigase.cert.CertCheckResult;\nimport tigase.cert.CertificateUtil;\nimport tigase.server.XMPPServer;\n\nimport java.nio.ByteBuffer;\n\n/**\n * Describe class TLSWrapper here.\n * \n * \n * Created: Sat Mar 5 09:13:29 2005\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TLSWrapper {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(TLSWrapper.class.getName());\n\n\tprivate int appBuffSize = 0;\n\tprivate String debugId = null;\n\n\t// private String protocol = null;\n\tprivate TLSEventHandler eventHandler = null;\n\tprivate int netBuffSize = 0;\n\tprivate SSLEngine tlsEngine = null;\n\tprivate SSLEngineResult tlsEngineResult = null;\n\n\t// TLS/SSL issue with JDK and NSS - bug workaround\n\tprivate static final boolean tls_jdk_nss_workaround = System.getProperty(\"tls-jdk-nss-bug-workaround-active\") == null ? false\n\t\t\t: Boolean.getBoolean(\"tls-jdk-nss-bug-workaround-active\");\n\n\t// Workaround for TLS/SSL bug in new JDK used with new version of\n\t// nss library see also:\n\t// http://stackoverflow.com/q/10687200/427545\n\t// http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=b509d9cb5d8164d90e6731f5fc44?bug_id=6928796\n\tprivate static final String[] TLS_WORKAROUND_CIPHERS = new String[] { \"SSL_RSA_WITH_RC4_128_MD5\",\n\t\t\t\"SSL_RSA_WITH_RC4_128_SHA\", \"TLS_RSA_WITH_AES_128_CBC_SHA\", \"TLS_DHE_RSA_WITH_AES_128_CBC_SHA\",\n\t\t\t\"TLS_DHE_DSS_WITH_AES_128_CBC_SHA\", \"SSL_RSA_WITH_3DES_EDE_CBC_SHA\", \"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\",\n\t\t\t\"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA\", \"SSL_RSA_WITH_DES_CBC_SHA\", \"SSL_DHE_RSA_WITH_DES_CBC_SHA\",\n\t\t\t\"SSL_DHE_DSS_WITH_DES_CBC_SHA\", \"SSL_RSA_EXPORT_WITH_RC4_40_MD5\", \"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA\",\n\t\t\t\"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA\", \"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA\",\n\t\t\t\"TLS_EMPTY_RENEGOTIATION_INFO_SCSV\" };\n\n\tprivate static final String[] HARDENED_MODE_FORBIDDEN_SIPHERS = new String[] { \"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA\",\n\t\t\t\"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\", \"SSL_RSA_WITH_3DES_EDE_CBC_SHA\", \"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA\",\n\t\t\t\"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA\", \"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\", \"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA\",\n\t\t\t\"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA\", \"TLS_ECDHE_RSA_WITH_RC4_128_SHA\", \"SSL_RSA_WITH_RC4_128_SHA\",\n\t\t\t\"TLS_ECDH_ECDSA_WITH_RC4_128_SHA\", \"TLS_ECDH_RSA_WITH_RC4_128_SHA\", \"SSL_RSA_WITH_RC4_128_MD5\",\n\t\t\t\"SSL_RSA_EXPORT_WITH_RC4_40_MD5\", \"TLS_KRB5_WITH_RC4_128_SHA\", \"TLS_KRB5_WITH_RC4_128_MD5\",\n\t\t\t\"TLS_KRB5_EXPORT_WITH_RC4_40_SHA\", \"TLS_KRB5_EXPORT_WITH_RC4_40_MD5\" };\n\n\tprivate static String[] enabledProtocols;\n\n\tprivate static String[] enabledCiphers;\n\n\tprivate static String markEnabled(String[] enabled, String[] supported) {\n\t\tfinal List<String> en = enabled == null ? new ArrayList<String>() : Arrays.asList(enabled);\n\t\tString result = \"\";\n\n\t\tif (supported != null)\n\t\t\tfor (int i = 0; i < supported.length; i++) {\n\t\t\t\tString t = supported[i];\n\t\t\t\tresult += (en.contains(t) ? \"(+)\" : \"(-)\");\n\t\t\t\tresult += t;\n\t\t\t\tif (i + 1 < supported.length)\n\t\t\t\t\tresult += \",\";\n\t\t\t}\n\n\t\treturn result;\n\t}\n\n\tstatic {\n\t\tString[] allEnabledCiphers = null;\n\t\ttry {\n\t\t\tSSLEngine tmpE = SSLContext.getDefault().createSSLEngine();\n\t\t\tallEnabledCiphers = tmpE.getEnabledCipherSuites();\n\t\t\tlog.config(\"Supported protocols: \" + markEnabled(tmpE.getEnabledProtocols(), tmpE.getSupportedProtocols()));\n\t\t\tlog.config(\"Supported ciphers: \" + markEnabled(allEnabledCiphers, tmpE.getSupportedCipherSuites()));\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't determine supported protocols\", e);\n\t\t}\n\n\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\tlog.config(\"Hardened mode is \" + (XMPPServer.isHardenedModeEnabled() ? \"enabled\" : \"disabled\"));\n\n\t\tString enabledProtocolsProp = System.getProperty(\"tls-enabled-protocols\");\n\t\tif (enabledProtocolsProp != null) {\n\t\t\tenabledProtocols = enabledProtocolsProp.split(\",\");\n\t\t} else if (XMPPServer.isHardenedModeEnabled()) {\n\t\t\tenabledProtocols = new String[] { \"SSLv2Hello\", \"TLSv1\", \"TLSv1.1\", \"TLSv1.2\" };\n\t\t}\n\n\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\tlog.config(\"Enabled protocols: \" + (enabledProtocols == null ? \"default\" : Arrays.toString(enabledProtocols)));\n\n\t\tString enabledCiphersProp = System.getProperty(\"tls-enabled-ciphers\");\n\t\tif (enabledCiphersProp != null) {\n\t\t\tenabledCiphers = enabledCiphersProp.split(\",\");\n\t\t} else if (XMPPServer.isHardenedModeEnabled()) {\n\t\t\tSystem.setProperty(\"jdk.tls.ephemeralDHKeySize\", \"2048\");\n\t\t\tArrayList<String> ciphers = new ArrayList<String>(Arrays.asList(allEnabledCiphers));\n\t\t\tciphers.removeAll(Arrays.asList(HARDENED_MODE_FORBIDDEN_SIPHERS));\n\t\t\tenabledCiphers = ciphers.toArray(new String[] {});\n\t\t} else if (tls_jdk_nss_workaround) {\n\t\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\t\tlog.config(\"Workaround for TLS/SSL bug is enabled\");\n\t\t\tenabledCiphers = TLS_WORKAROUND_CIPHERS;\n\t\t}\n\n\t\tif (log.isLoggable(Level.CONFIG))\n\t\t\tlog.config(\"Enabled ciphers: \" + (enabledCiphers == null ? \"default\" : Arrays.toString(enabledCiphers)));\n\n\t}\n\n\tpublic TLSWrapper(SSLContext sslc, TLSEventHandler eventHandler, String hostname, int port, final boolean clientMode, final boolean wantClientAuth) {\n\t\tthis(sslc, eventHandler, hostname, port, clientMode, wantClientAuth, false);\n\t}\n\t\n\t/**\n\t * Creates a new <code>TLSWrapper</code> instance.\n\t * \n\t * \n\t * @param sslc\n\t * @param eventHandler\n\t * @param hostname\n\t * @param port\n\t * @param clientMode\n\t * @param wantClientAuth\n\t */\n\tpublic TLSWrapper(SSLContext sslc, TLSEventHandler eventHandler, String hostname, int port, final boolean clientMode, final boolean wantClientAuth, final boolean needClientAuth) {\n\t\tif (clientMode && hostname != null)\n\t\t\ttlsEngine = sslc.createSSLEngine(hostname, port);\n\t\telse\n\t\t\ttlsEngine = sslc.createSSLEngine();\n\t\ttlsEngine.setUseClientMode(clientMode);\n\n\t\tif (enabledCiphers != null) {\n\t\t\ttlsEngine.setEnabledCipherSuites(enabledCiphers);\n\t\t}\n\n\t\tif (enabledProtocols != null) {\n\t\t\ttlsEngine.setEnabledProtocols(enabledProtocols);\n\t\t}\n\n\t\tnetBuffSize = tlsEngine.getSession().getPacketBufferSize();\n\t\tappBuffSize = tlsEngine.getSession().getApplicationBufferSize();\n\t\tthis.eventHandler = eventHandler;\n\n\t\tif (!clientMode && wantClientAuth) {\n\t\t\ttlsEngine.setWantClientAuth(true);\n\t\t}\n\t\tif (!clientMode && needClientAuth) {\n\t\t\ttlsEngine.setNeedClientAuth(true);\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.finest(\"Created \"\n\t\t\t\t\t+ (clientMode ? \"client\" : \"server\")\n\t\t\t\t\t+ \" TLSWrapper. Protocols:\"\n\t\t\t\t\t+ (tlsEngine.getEnabledProtocols() == null ? \" default\" : Arrays.toString(tlsEngine.getEnabledProtocols()))\n\t\t\t\t\t+ \"; Ciphers:\"\n\t\t\t\t\t+ (tlsEngine.getEnabledCipherSuites() == null ? \" default\"\n\t\t\t\t\t\t\t: Arrays.toString(tlsEngine.getEnabledCipherSuites())));\n\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic int bytesConsumed() {\n\t\treturn tlsEngineResult.bytesConsumed();\n\t}\n\n\tpublic byte[] getSessionId(){\n\t\treturn tlsEngine.getSession().getId();\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @throws SSLException\n\t */\n\tpublic void close() throws SSLException {\n\t\ttlsEngine.closeOutbound();\n\t\ttlsEngine.getSession().invalidate();\n\t\t// tlsEngine.closeInbound();\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic int getAppBuffSize() {\n\t\treturn appBuffSize;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t * @param revocationEnabled\n\t * \n\t */\n\tpublic CertCheckResult getCertificateStatus(boolean revocationEnabled) {\n\t\tCertificate[] peerChain = null;\n\n\t\ttry {\n\t\t\tpeerChain = tlsEngine.getSession().getPeerCertificates();\n\t\t} catch (SSLPeerUnverifiedException ex) {\n\n\t\t\t// This normally happens when the peer is in a client mode and does\n\t\t\t// not\n\t\t\t// send any certificate, even though we set: setWantClientAuth(true)\n\t\t\treturn CertCheckResult.none;\n\t\t}\n\n\t\ttry {\n\t\t\treturn CertificateUtil.validateCertificate(peerChain, TLSUtil.getTrustStore(), revocationEnabled);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem validating certificate\", ex);\n\t\t}\n\n\t\treturn CertCheckResult.invalid;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic int getNetBuffSize() {\n\t\treturn netBuffSize;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic int getPacketBuffSize() {\n\t\treturn tlsEngine.getSession().getPacketBufferSize();\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic TLSStatus getStatus() {\n\t\tTLSStatus status = null;\n\n\t\tif ((tlsEngineResult != null) && (tlsEngineResult.getStatus() == Status.BUFFER_UNDERFLOW)) {\n\t\t\tstatus = TLSStatus.UNDERFLOW;\n\n\t\t\t// status = TLSStatus.NEED_READ;\n\t\t} // end of if (tlsEngine.getStatus() == Status.BUFFER_UNDERFLOW)\n\t\telse {\n\t\t\tif ((tlsEngineResult != null) && (tlsEngineResult.getStatus() == Status.CLOSED)) {\n\t\t\t\tstatus = TLSStatus.CLOSED;\n\t\t\t} // end of if (tlsEngine.getStatus() == Status.BUFFER_UNDERFLOW)\n\t\t\telse {\n\t\t\t\tswitch (tlsEngine.getHandshakeStatus()) {\n\t\t\t\tcase NEED_WRAP:\n\t\t\t\t\tstatus = TLSStatus.NEED_WRITE;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase NEED_UNWRAP:\n\t\t\t\t\tstatus = TLSStatus.NEED_READ;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tstatus = TLSStatus.OK;\n\n\t\t\t\t\tbreak;\n\t\t\t\t} // end of switch (tlsEngine.getHandshakeStatus())\n\t\t\t}\n\t\t} // end of else\n\n\t\treturn status;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic boolean isClientMode() {\n\t\treturn tlsEngine.getUseClientMode();\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param id\n\t */\n\tpublic void setDebugId(String id) {\n\t\tdebugId = id;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param net\n\t * @param app\n\t * \n\t * \n\t * \n\t * @throws SSLException\n\t */\n\tpublic ByteBuffer unwrap(ByteBuffer net, ByteBuffer app) throws SSLException {\n\t\tByteBuffer out = app;\n\n\t\tout.order(app.order());\n\t\ttlsEngineResult = tlsEngine.unwrap(net, out);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, unwrap() tlsEngineRsult.getStatus() = {1}, \"\n\t\t\t\t\t+ \"tlsEngineRsult.getHandshakeStatus() = {2}\", new Object[] { debugId, tlsEngineResult.getStatus(),\n\t\t\t\t\ttlsEngineResult.getHandshakeStatus() });\n\t\t}\n\n\t\tif (tlsEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {\n\t\t\tif (eventHandler != null) {\n\t\t\t\teventHandler.handshakeCompleted(this);\n\t\t\t}\n\t\t}\n\n\t\tif (tlsEngineResult.getStatus() == Status.BUFFER_OVERFLOW) {\n\t\t\tout = resizeApplicationBuffer(net, out);\n\t\t\ttlsEngineResult = tlsEngine.unwrap(net, out);\n\t\t}\n\n\t\tif (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {\n\t\t\tdoTasks();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"unwrap() doTasks(), handshake: {0}, {1}\", new Object[] { tlsEngine.getHandshakeStatus(),\n\t\t\t\t\t\tdebugId });\n\t\t\t}\n\t\t}\n\n\t\treturn out;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param app\n\t * @param net\n\t * \n\t * @throws SSLException\n\t */\n\tpublic void wrap(ByteBuffer app, ByteBuffer net) throws SSLException {\n\t\ttlsEngineResult = tlsEngine.wrap(app, net);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, tlsEngineRsult.getStatus() = {1}, tlsEngineRsult.getHandshakeStatus() = {2}\",\n\t\t\t\t\tnew Object[] { debugId, tlsEngineResult.getStatus(), tlsEngineResult.getHandshakeStatus() });\n\t\t}\n\n\t\tif (tlsEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {\n\t\t\tif (eventHandler != null) {\n\t\t\t\teventHandler.handshakeCompleted(this);\n\t\t\t}\n\t\t}\n\n\t\tif (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {\n\t\t\tdoTasks();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"doTasks(): {0}, {1}\", new Object[] { tlsEngine.getHandshakeStatus(), debugId });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void doTasks() {\n\t\tRunnable runnable = null;\n\n\t\twhile ((runnable = tlsEngine.getDelegatedTask()) != null) {\n\t\t\trunnable.run();\n\t\t} // end of while ((runnable = engine.getDelegatedTask()) != 0)\n\t}\n\n\t/**\n\t * Method <code>resizeApplicationBuffer</code> is used to perform\n\t */\n\tprivate ByteBuffer resizeApplicationBuffer(ByteBuffer net, ByteBuffer app) {\n\n\t\t// if (appBuffSize > app.remaining()) {\n\t\t// if (net.remaining() > app.remaining()) {\n\t\t// if (appBuffSize > app.capacity() - app.remaining()) {\n\t\t// if (log.isLoggable(Level.FINE)) {\n\t\t// log.fine(\"Resizing tlsInput to \" + (appBuffSize + app.capacity()) +\n\t\t// \" bytes.\");\n\t\t// }\n\t\t//\n\t\t// ByteBuffer bb = ByteBuffer.allocate(app.capacity() + appBuffSize);\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"Resizing tlsInput to {0} bytes, {1}\", new Object[] { (2048 + app.capacity()), debugId });\n\t\t}\n\n\t\tByteBuffer bb = ByteBuffer.allocate(app.capacity() + 2048);\n\n\t\t// bb.clear();\n\t\tbb.order(app.order());\n\t\tapp.flip();\n\t\tbb.put(app);\n\n\t\treturn bb;\n\n\t\t// } else {\n\t\t//\n\t\t// return app;\n\t\t// } // end of else\n\t}\n\n\tpublic SSLEngine getTlsEngine() {\n\t\treturn tlsEngine;\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TelnetClient.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport static tigase.io.SSLContextContainerIfc.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.ByteArrayInputStream;\nimport java.io.EOFException;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\n\nimport java.net.InetSocketAddress;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.CharBuffer;\nimport java.nio.channels.SocketChannel;\nimport java.nio.charset.Charset;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * This is sample class demonstrating how to use <code>tigase.io</code> library\n * for TLS/SSL client connection. This is simple telnet client class which\n * can connect to remote server using plain connection or SSL.\n *\n *\n * Created: Sun Aug  6 15:14:49 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TelnetClient implements SampleSocketThread.SocketHandler {\n\tprivate static final Logger log = Logger.getLogger(\"tigase.io.TelnetClient\");\n\tprivate static final Charset coder = Charset.forName(\"UTF-8\");\n\tprivate static int port = 7777;\n\tprivate static String hostname = \"localhost\";\n\tprivate static boolean debug = false;\n\tprivate static String file = null;\n\tprivate static boolean continuous = false;\n\tprivate static long delay = 100;\n\tprivate static boolean ssl = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate IOInterface iosock = null;\n\tprivate SampleSocketThread reader = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>TelnetClient</code> instance.\n\t *\n\t *\n\t * @param hostname\n\t * @param port\n\t *\n\t * @throws Exception\n\t */\n\tpublic TelnetClient(String hostname, int port) throws Exception {\n\t\treader = new SampleSocketThread(this);\n\t\treader.start();\n\n\t\tSocketChannel sc = SocketChannel.open(new InetSocketAddress(hostname, port));\n\n\t\t// Basic channel configuration\n\t\tiosock = new SocketIO(sc);\n\n\t\tif (ssl) {\n\t\t\tiosock = new TLSIO(iosock, new TLSWrapper(TLSUtil.getSSLContext(\"SSL\", null), null, null, 0, true, false), ByteOrder.BIG_ENDIAN);\n\t\t}    // end of if (ssl)\n\n\t\treader.addIOInterface(iosock);\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Registered new client socket: \" + sc);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String help() {\n\t\treturn \"\\n\" + \"Parameters:\\n\" + \" -?                this help message\\n\"\n\t\t\t\t+ \" -h hostname       host name\\n\" + \" -p port           port number\\n\"\n\t\t\t\t\t+ \" -ssl              turn SSL on for all connections\\n\"\n\t\t\t\t\t\t+ \" -f file           file with content to send to remote host\\n\"\n\t\t\t\t\t\t\t+ \" -c                continuous sending file content\\n\"\n\t\t\t\t\t\t\t\t+ \" -t millis         delay between sending file content\\n\"\n\t\t\t\t\t\t\t\t\t+ \" -v                prints server version info\\n\"\n\t\t\t\t\t\t\t\t\t\t+ \" -d [true|false]   turn on|off debug mode\\n\"\n\t\t;\n\t}\n\n\t/**\n\t * Describe <code>main</code> method here.\n\t *\n\t * @param args a <code>String[]</code> value\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void main(final String[] args) throws Exception {\n\t\tparseParams(args);\n\n\t\tif (debug) {\n\t\t\tturnDebugOn();\n\t\t}    // end of if (debug)\n\n\t\tif (ssl) {\n\t\t\tMap<String, Object> tls_params = new LinkedHashMap<String, Object>();\n\n\t\t\ttls_params.put(JKS_KEYSTORE_FILE_KEY, \"certs/keystore\");\n\t\t\ttls_params.put(JKS_KEYSTORE_PWD_KEY, \"keystore\");\n\t\t\tTLSUtil.configureSSLContext(tls_params);\n\t\t}    // end of if (ssl)\n\n\t\tTelnetClient client = new TelnetClient(hostname, port);\n\t\tInputStreamReader str_reader = new InputStreamReader(System.in);\n\n\t\tif (file != null) {\n\t\t\tFileReader fr = new FileReader(file);\n\t\t\tchar[] file_buff = new char[64 * 1024];\n\t\t\tint res = -1;\n\n\t\t\twhile ((res = fr.read(file_buff)) != -1) {\n\t\t\t\tclient.writeData(new String(file_buff, 0, res));\n\t\t\t}    // end of while ((res = fr.read(buff)) != -1)\n\n\t\t\tfr.close();\n\t\t}      // end of if (file != null)\n\n\t\tchar[] buff = new char[1024];\n\n\t\tfor (;;) {\n\t\t\tint res = str_reader.read(buff);\n\n\t\t\tclient.writeData(new String(buff, 0, res));\n\t\t}    // end of for (;;)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void parseParams(final String[] args) throws Exception {\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tif (args[i].equals(\"-?\")) {\n\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-v\")) {\n\t\t\t\t\tSystem.out.print(version());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-f\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\tfile = args[++i];\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-h\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\thostname = args[++i];\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-p\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\tport = Integer.decode(args[++i]);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-d\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tdebug = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tdebug = (args[i].charAt(0) != '-') && (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-d\"))\n\n\t\t\t\tif (args[i].equals(\"-c\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tcontinuous = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tcontinuous = (args[i].charAt(0) != '-')\n\t\t\t\t\t\t\t\t&& (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-c\"))\n\n\t\t\t\tif (args[i].equals(\"-ssl\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tssl = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tssl = (args[i].charAt(0) != '-') && (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-ssl\"))\n\t\t\t}        // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic static void turnDebugOn() {\n\t\tMap<String, String> properties = new HashMap<String, String>();\n\n\t\tproperties.put(\".level\", \"ALL\");\n\t\tproperties.put(\"handlers\", \"java.util.logging.ConsoleHandler\");\n\t\tproperties.put(\"java.util.logging.ConsoleHandler.formatter\", \"tigase.util.LogFormatter\");\n\t\tproperties.put(\"java.util.logging.ConsoleHandler.level\", \"ALL\");\n\n\t\tSet<Map.Entry<String, String>> entries = properties.entrySet();\n\t\tStringBuilder buff = new StringBuilder();\n\n\t\tfor (Map.Entry<String, String> entry : entries) {\n\t\t\tbuff.append(entry.getKey() + \"=\" + entry.getValue() + \"\\n\");\n\t\t}\n\n\t\ttry {\n\t\t\tfinal ByteArrayInputStream bis = new ByteArrayInputStream(buff.toString().getBytes());\n\n\t\t\tLogManager.getLogManager().readConfiguration(bis);\n\t\t\tbis.close();\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not configure logManager\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String version() {\n\t\treturn \"\\n\" + \"-- \\n\" + \"Tigase XMPP Telnet, version: \"\n\t\t\t\t+ TelnetClient.class.getPackage().getImplementationVersion() + \"\\n\"\n\t\t\t\t\t+ \"Author:  Artur Hefczyc <artur.hefczyc@tigase.org>\\n\" + \"-- \\n\"\n\t\t;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ioifc\n\t *\n\t * @throws IOException\n\t */\n\tpublic void handleIOInterface(IOInterface ioifc) throws IOException {\n\t\tByteBuffer socketInput =\n\t\t\tByteBuffer.allocate(ioifc.getSocketChannel().socket().getReceiveBufferSize());\n\t\tByteBuffer tmpBuffer = ioifc.read(socketInput);\n\n\t\tif (ioifc.bytesRead() > 0) {\n\t\t\ttmpBuffer.flip();\n\n\t\t\tCharBuffer cb = coder.decode(tmpBuffer);\n\n\t\t\ttmpBuffer.clear();\n\n\t\t\tif (cb != null) {\n\t\t\t\tSystem.out.print(new String(cb.array()));\n\t\t\t}    // end of if (cb != null)\n\t\t}      // end of if (socketIO.bytesRead() > 0)\n\n\t\tif (!ioifc.isConnected())\n\t\t\tthrow new EOFException(\"Channel has been closed.\");\t\t\n\t\t\n\t\treader.addIOInterface(ioifc);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sc\n\t */\n\tpublic void handleSocketAccept(SocketChannel sc) {\n\n\t\t// Empty, not needed any implementation for that\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws IOException\n\t */\n\tpublic void writeData(String data) throws IOException {\n\t\tByteBuffer dataBuffer = null;\n\n\t\tif ((data != null) && (data.length() > 0)) {\n\t\t\tdataBuffer = coder.encode(CharBuffer.wrap(data));\n\t\t\tiosock.write(dataBuffer);\n\t\t}    // end of if (data == null || data.equals(\"\")) else\n\t}\n}    // TelnetClient\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/TelnetServer.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport static tigase.io.SSLContextContainerIfc.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.ByteArrayInputStream;\nimport java.io.EOFException;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\n\nimport java.net.InetSocketAddress;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.CharBuffer;\nimport java.nio.channels.SocketChannel;\nimport java.nio.charset.Charset;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * This is sample class demonstrating how to use <code>tigase.io</code> library\n * for TLS/SSL server connection. This is simple telnet server class which can\n * be run to receive plain connections or SSL connections.\n *\n *\n * Created: Sun Aug  6 22:27:13 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TelnetServer implements SampleSocketThread.SocketHandler {\n\tprivate static final Logger log = Logger.getLogger(\"tigase.io.TelnetServer\");\n\tprivate static final Charset coder = Charset.forName(\"UTF-8\");\n\tprivate static int port = 7777;\n\tprivate static String hostname = \"localhost\";\n\tprivate static boolean debug = false;\n\tprivate static String file = null;\n\tprivate static boolean continuous = false;\n\tprivate static long delay = 100;\n\tprivate static boolean ssl = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate IOInterface iosock = null;\n\tprivate SampleSocketThread reader = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>TelnetServer</code> instance.\n\t *\n\t *\n\t * @param port\n\t *\n\t * @throws IOException\n\t */\n\tpublic TelnetServer(int port) throws IOException {\n\t\treader = new SampleSocketThread(this);\n\t\treader.start();\n\t\treader.addForAccept(new InetSocketAddress(port));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String help() {\n\t\treturn \"\\n\" + \"Parameters:\\n\" + \" -?                this help message\\n\"\n\t\t\t\t+ \" -h hostname       host name\\n\" + \" -p port           port number\\n\"\n\t\t\t\t\t+ \" -ssl              turn SSL on for all connections\\n\"\n\t\t\t\t\t\t+ \" -f file           file with content to send to remote host\\n\"\n\t\t\t\t\t\t\t+ \" -c                continuous sending file content\\n\"\n\t\t\t\t\t\t\t\t+ \" -t millis         delay between sending file content\\n\"\n\t\t\t\t\t\t\t\t\t+ \" -v                prints server version info\\n\"\n\t\t\t\t\t\t\t\t\t\t+ \" -d [true|false]   turn on|off debug mode\\n\"\n\t\t;\n\t}\n\n\t/**\n\t * Describe <code>main</code> method here.\n\t *\n\t * @param args a <code>String[]</code> value\n\t * @throws Exception\n\t */\n\tpublic static void main(final String[] args) throws Exception {\n\t\tparseParams(args);\n\n\t\tif (debug) {\n\t\t\tturnDebugOn();\n\t\t}    // end of if (debug)\n\n\t\tif (ssl) {\n\t\t\tMap<String, Object> tls_params = new LinkedHashMap<String, Object>();\n\n\t\t\ttls_params.put(JKS_KEYSTORE_FILE_KEY, \"certs/keystore\");\n\t\t\ttls_params.put(JKS_KEYSTORE_PWD_KEY, \"keystore\");\n\t\t\ttls_params.put(TRUSTSTORE_FILE_KEY, \"certs/truststore\");\n\t\t\ttls_params.put(TRUSTSTORE_PWD_KEY, \"truststore\");\n\t\t\tTLSUtil.configureSSLContext(tls_params);\n\t\t}    // end of if (ssl)\n\n\t\tTelnetServer server = new TelnetServer(port);\n\n\t\tserver.run();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void parseParams(final String[] args) throws Exception {\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tif (args[i].equals(\"-?\")) {\n\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-v\")) {\n\t\t\t\t\tSystem.out.print(version());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-f\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\tfile = args[++i];\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-h\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\thostname = args[++i];\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-p\")) {\n\t\t\t\t\tif (i + 1 == args.length) {\n\t\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\t\tSystem.exit(1);\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\tport = Integer.decode(args[++i]);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-d\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tdebug = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tdebug = (args[i].charAt(0) != '-') && (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-d\"))\n\n\t\t\t\tif (args[i].equals(\"-c\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tcontinuous = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tcontinuous = (args[i].charAt(0) != '-')\n\t\t\t\t\t\t\t\t&& (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-c\"))\n\n\t\t\t\tif (args[i].equals(\"-ssl\")) {\n\t\t\t\t\tif ((i + 1 == args.length) || args[i + 1].startsWith(\"-\")) {\n\t\t\t\t\t\tssl = true;\n\t\t\t\t\t}    // end of if (i+1 == args.length)\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t++i;\n\t\t\t\t\t\tssl = (args[i].charAt(0) != '-') && (args[i].equals(\"true\") || args[i].equals(\"yes\"));\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-ssl\"))\n\t\t\t}        // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic static void turnDebugOn() {\n\t\tMap<String, String> properties = new HashMap<String, String>();\n\n\t\tproperties.put(\".level\", \"ALL\");\n\t\tproperties.put(\"handlers\", \"java.util.logging.ConsoleHandler\");\n\t\tproperties.put(\"java.util.logging.ConsoleHandler.formatter\", \"tigase.util.LogFormatter\");\n\t\tproperties.put(\"java.util.logging.ConsoleHandler.level\", \"ALL\");\n\n\t\tSet<Map.Entry<String, String>> entries = properties.entrySet();\n\t\tStringBuilder buff = new StringBuilder();\n\n\t\tfor (Map.Entry<String, String> entry : entries) {\n\t\t\tbuff.append(entry.getKey() + \"=\" + entry.getValue() + \"\\n\");\n\t\t}\n\n\t\ttry {\n\t\t\tfinal ByteArrayInputStream bis = new ByteArrayInputStream(buff.toString().getBytes());\n\n\t\t\tLogManager.getLogManager().readConfiguration(bis);\n\t\t\tbis.close();\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not configure logManager\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String version() {\n\t\treturn \"\\n\" + \"-- \\n\" + \"Tigase XMPP Telnet, version: \"\n\t\t\t\t+ TelnetServer.class.getPackage().getImplementationVersion() + \"\\n\"\n\t\t\t\t\t+ \"Author:  Artur Hefczyc <artur.hefczyc@tigase.org>\\n\" + \"-- \\n\"\n\t\t;\n\t}\n\n\t@Override\n\tpublic void handleIOInterface(IOInterface ioifc) throws IOException {\n\t\tByteBuffer socketInput =\n\t\t\tByteBuffer.allocate(ioifc.getSocketChannel().socket().getReceiveBufferSize());\n\t\tByteBuffer tmpBuffer = ioifc.read(socketInput);\n\n\t\tif (ioifc.bytesRead() > 0) {\n\t\t\ttmpBuffer.flip();\n\n\t\t\tCharBuffer cb = coder.decode(tmpBuffer);\n\n\t\t\ttmpBuffer.clear();\n\n\t\t\tif (cb != null) {\n\t\t\t\tSystem.out.print(new String(cb.array()));\n\t\t\t}    // end of if (cb != null)\n\t\t}      // end of if (socketIO.bytesRead() > 0)\n\n\t\tif (!ioifc.isConnected())\n\t\t\tthrow new EOFException(\"Channel has been closed.\");\n\t\t\n\t\treader.addIOInterface(ioifc);\n\t}\n\n\t@Override\n\tpublic void handleSocketAccept(SocketChannel sc) throws IOException {\n\t\tiosock = new SocketIO(sc);\n\n\t\tif (ssl) {\n\t\t\tiosock = new TLSIO(iosock, new TLSWrapper(TLSUtil.getSSLContext(\"SSL\", null), null, null, 0, false, false), ByteOrder.BIG_ENDIAN);\n\t\t}    // end of if (ssl)\n\n\t\treader.addIOInterface(iosock);\n\n\t\tif (file != null) {\n\t\t\tFileReader fr = new FileReader(file);\n\t\t\tchar[] file_buff = new char[64 * 1024];\n\t\t\tint res = -1;\n\n\t\t\twhile ((res = fr.read(file_buff)) != -1) {\n\t\t\t\tByteBuffer dataBuffer = coder.encode(CharBuffer.wrap(file_buff, 0, res));\n\n\t\t\t\tiosock.write(dataBuffer);\n\t\t\t}    // end of while ((res = fr.read(buff)) != -1)\n\n\t\t\tfr.close();\n\t\t}      // end of if (file != null)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws IOException\n\t */\n\tpublic void run() throws IOException {\n\t\tInputStreamReader isr = new InputStreamReader(System.in);\n\t\tchar[] buff = new char[1024];\n\n\t\tfor (;;) {\n\t\t\tint res = isr.read(buff);\n\n\t\t\tif (iosock != null) {\n\t\t\t\tByteBuffer dataBuffer = coder.encode(CharBuffer.wrap(buff, 0, res));\n\n\t\t\t\tiosock.write(dataBuffer);\n\t\t\t}    // end of if (ioscok != null)\n\t\t\t\t\telse {\n\t\t\t\tSystem.err.println(\"Can't write to socket, no open socket.\");\n\t\t\t}    // end of if (ioscok != null) else\n\t\t}      // end of for (;;)\n\t}\n}    // Telnetserver\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/ZLibIO.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.io;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.IOListener;\nimport tigase.stats.StatisticsList;\n\nimport tigase.util.ZLibWrapper;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SocketChannel;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jul 29, 2009 11:58:02 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ZLibIO implements IOInterface {\n\n\t/** Field description */\n\tpublic static final String ZLIB_CAPS = \"zlib-caps\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static Logger log = Logger.getLogger(ZLibIO.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate IOInterface io = null;\n\tprivate ZLibWrapper zlib = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param ioi\n\t * @param level\n\t */\n\tpublic ZLibIO(final IOInterface ioi, final int level) {\n\t\tthis.io = ioi;\n\t\tzlib = new ZLibWrapper();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int bytesRead() {\n\t\treturn io.bytesRead();\n\t}\n\n\t@Override\n\tpublic long getBytesSent(boolean reset) {\n\t\treturn io.getBytesSent(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBytesSent() {\n\t\treturn io.getTotalBytesSent();\n\t}\n\n\t@Override\n\tpublic long getBytesReceived(boolean reset) {\n\t\treturn io.getBytesReceived(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBytesReceived() {\n\t\treturn io.getTotalBytesReceived();\n\t}\n\n\t@Override\n\tpublic long getBuffOverflow(boolean reset) {\n\t\treturn io.getBuffOverflow(reset);\n\t}\n\n\t@Override\n\tpublic long getTotalBuffOverflow() {\n\t\treturn io.getTotalBuffOverflow();\n\t}\n\n\t@Override\n\tpublic boolean checkCapabilities(String caps) {\n\t\treturn caps.contains(ZLIB_CAPS) || io.checkCapabilities(caps);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic int getInputPacketSize() throws IOException {\n\t\treturn io.getInputPacketSize();\n\t}\n\n\t@Override\n\tpublic SocketChannel getSocketChannel() {\n\t\treturn io.getSocketChannel();\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list, boolean reset) {\n\t\tif (io != null) {\n\t\t\tio.getStatistics(list, reset);\n\t\t}\n\n\t\tif (zlib != null) {\n\t\t\tlist.add(\"zlibio\", \"Average compression rate\", zlib.averageCompressionRate(), Level.FINE);\n\t\t\tlist.add(\"zlibio\", \"Average decompression rate\", zlib.averageDecompressionRate(), Level.FINE);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isConnected() {\n\t\treturn io.isConnected();\n\t}\n\n\t@Override\n\tpublic boolean isRemoteAddress(String addr) {\n\t\treturn io.isRemoteAddress(addr);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic ByteBuffer read(ByteBuffer buff) throws IOException {\n\t\tByteBuffer tmpBuffer = io.read(buff);\n\n\t\tif (io.bytesRead() > 0) {\n\t\t\tByteBuffer decompressed_buff = zlib.decompress(tmpBuffer);\n\n\t\t\t// The buffer is reused to it needs to be cleared before it can be\n\t\t\t// used again.\n\t\t\ttmpBuffer.clear();\n\n\t\t\t// System.out.println(\"Decompression rate: \" + zlib.lastDecompressionRate());\n\t\t\treturn decompressed_buff;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void stop() throws IOException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Stop called...\" + toString());\n\t\t}\n\n\t\tio.stop();\n\t\tzlib.end();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"ZLIB: \" + io.toString();\n\t}\n\n\t@Override\n\tpublic boolean waitingToSend() {\n\t\treturn io.waitingToSend();\n\t}\n\n\t@Override\n\tpublic int waitingToSendSize() {\n\t\treturn io.waitingToSendSize();\n\t}\n\n\t@Override\n\tpublic int write(ByteBuffer buff) throws IOException {\n\t\tif (buff == null) {\n\t\t\treturn io.write(null);\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"ZLIB - Writing data, remaining: {0}\", buff.remaining());\n\t\t}\n\n\t\tByteBuffer compressed_buff = zlib.compress(buff);\n\n\t\t// System.out.println(\"Compression rate: \" + zlib.lastCompressionRate());\n\t\treturn io.write(compressed_buff);\n\t}\n\n\t@Override\n\tpublic void setLogId(String logId) {\n\t\tio.setLogId(logId);\n\t}\n\t\n\tpublic void setIOListener(IOListener listener) {\n\t\tzlib.setIOListener(listener);\n\t}\t\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/io/jdk18/SNISSLContextContainer.java",
    "content": "/*\n * SNISSLContextContainer.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.io.jdk18;\n\nimport java.net.Socket;\nimport java.security.Principal;\nimport java.security.PrivateKey;\nimport java.security.cert.X509Certificate;\nimport java.util.Set;\nimport javax.net.ssl.ExtendedSSLSession;\nimport javax.net.ssl.KeyManagerFactory;\nimport javax.net.ssl.SNIHostName;\nimport javax.net.ssl.SNIServerName;\nimport javax.net.ssl.SSLEngine;\nimport javax.net.ssl.SSLSocket;\nimport javax.net.ssl.StandardConstants;\nimport javax.net.ssl.X509ExtendedKeyManager;\nimport javax.net.ssl.X509KeyManager;\nimport tigase.io.SSLContextContainer;\nimport static tigase.io.SSLContextContainer.find;\n\n/**\n * Implementation of SSLContextContainer which may be used since JDK 1.8 to\n * provide support for Server Name Indication (SNI) extension of SSL/TLS protocol\n * which indicates server name the client is attempting to connect during \n * handshaking. This implementation searches for proper SSL certificate for \n * passed server name and uses this certificate if it is available, if not it\n * falls back to use of default certificate.\n *\n * @author andrzej\n */\npublic class SNISSLContextContainer extends SSLContextContainer {\n\t\n\tprivate class SniKeyManager extends X509ExtendedKeyManager {\n\n\t\t@Override\n\t\tpublic String[] getClientAliases(String string, Principal[] prncpls) {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic String chooseClientAlias(String[] strings, Principal[] prncpls, Socket socket) {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic String[] getServerAliases(String string, Principal[] prncpls) {\n\t\t\tSet<String> aliases = sslContexts.keySet();\n\t\t\treturn aliases.toArray(new String[aliases.size()]);\n\t\t}\n\n\t\t@Override\n\t\tpublic String chooseServerAlias(String string, Principal[] prncpls, Socket socket) {\n\t\t\tif (socket instanceof SSLSocket) {\n\t\t\t\tExtendedSSLSession session = (ExtendedSSLSession) ((SSLSocket) socket).getSession();\n\t\t\t\t\n\t\t\t\treturn chooseServerAlias(session);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {\n\t\t\tExtendedSSLSession session = (ExtendedSSLSession) engine.getHandshakeSession();\n\n\t\t\treturn chooseServerAlias(session);\n\t\t}\n\n\t\t/**\n\t\t * Method retrieves requested server name from ExtendedSSLSession and\n\t\t * uses it to return proper alias for server certificate\n\t\t * \n\t\t * @param session\n\t\t * @return \n\t\t */\n\t\tprivate String chooseServerAlias(ExtendedSSLSession session) {\n\t\t\t// Pick first SNIHostName in the list of SNI names.\n\t\t\tString hostname = null;\n\t\t\tfor (SNIServerName name : session.getRequestedServerNames()) {\n\t\t\t\tif (name.getType() == StandardConstants.SNI_HOST_NAME) {\n\t\t\t\t\thostname = ((SNIHostName) name).getAsciiName();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we got given a hostname over SNI, check if we have a cert and \n\t\t\t// key for that hostname. If so, we use it.\n\t\t\t// Otherwise, we fall back to the default certificate.\n\t\t\tif (hostname != null && (getCertificateChain(hostname) != null \n\t\t\t\t\t&& getPrivateKey(hostname) != null)) {\n\t\t\t\treturn hostname;\n\t\t\t} else {\n\t\t\t\treturn def_cert_alias;\n\t\t\t}\t\t\t\n\t\t}\n\n\t\t/**\n\t\t * Using passed alias method searches for proper KeyManagerFactory to\n\t\t * return proper certificate chain for alias\n\t\t * \n\t\t * @param alias\n\t\t * @return \n\t\t */\n\t\t@Override\n\t\tpublic X509Certificate[] getCertificateChain(String alias) {\n\t\t\tif (alias == null) \n\t\t\t\talias = def_cert_alias;\n\t\t\tKeyManagerFactory kmf = find( kmfs, alias );\n\t\t\tif ( kmf == null ){\n\t\t\t\talias = def_cert_alias;\n\t\t\t\tkmf = SSLContextContainer.find( kmfs, alias );\n\t\t\t}\n\n\t\t\treturn ((X509KeyManager) kmf.getKeyManagers()[0]).getCertificateChain(alias);\n\t\t}\n\n\t\t/**\n\t\t * Using passed alias method searches for proper KeyManagerFactory to\n\t\t * return proper private key for alias\n\t\t * \n\t\t * @param alias\n\t\t * @return \n\t\t */\n\t\t@Override\n\t\tpublic PrivateKey getPrivateKey(String alias) {\n\t\t\tif (alias == null) \n\t\t\t\talias = def_cert_alias;\t\t\t\n\t\t\tKeyManagerFactory kmf = find(kmfs, alias);\n\t\t\tif ( kmf == null ){\n\t\t\t\talias = def_cert_alias;\n\t\t\t\tkmf = SSLContextContainer.find( kmfs, alias );\n\t\t\t}\n\n\t\t\treturn ((X509KeyManager) kmf.getKeyManagers()[0]).getPrivateKey(alias);\n\t\t}\n\t\t\n\t}\n\n\tpublic SNISSLContextContainer() {\n\t\tkms = new X509KeyManager[] { new SniKeyManager() };\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/jdk18/Activator.java",
    "content": "/*\n * Activator.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.jdk18;\n\nimport java.util.logging.Logger;\nimport org.osgi.framework.BundleActivator;\nimport org.osgi.framework.BundleContext;\nimport org.osgi.framework.ServiceEvent;\nimport org.osgi.framework.ServiceListener;\nimport org.osgi.framework.ServiceReference;\nimport tigase.io.jdk18.SNISSLContextContainer;\nimport tigase.osgi.ModulesManager;\n\n/**\n *\n * @author andrzej\n */\npublic class Activator implements BundleActivator, ServiceListener {\n\n\tprivate static final Logger log = Logger.getLogger(Activator.class.getCanonicalName());\n\tprivate BundleContext context = null;\n\tprivate Class<SNISSLContextContainer> sslContextContainerCls = null;\n\tprivate ServiceReference serviceReference = null;\n\tprivate ModulesManager serviceManager = null;\n\n\t@Override\n\tpublic void start(BundleContext bc) throws Exception {\n\t\tsynchronized (this) {\n\t\t\tcontext = bc;\n\t\t\tbc.addServiceListener(this, \"(&(objectClass=\" + ModulesManager.class.getName() + \"))\");\n\t\t\tserviceReference = bc.getServiceReference(ModulesManager.class.getName());\n\t\t\tsslContextContainerCls = SNISSLContextContainer.class;\n\t\t\tif (serviceReference != null) {\n\t\t\t\tserviceManager = (ModulesManager) bc.getService(serviceReference);\n\t\t\t\tregisterAddons();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stop(BundleContext bc) throws Exception {\n\t\tsynchronized (this) {\n\t\t\tif (serviceManager != null) {\n\t\t\t\tunregisterAddons();\n\t\t\t\tcontext.ungetService(serviceReference);\n\t\t\t\tserviceManager = null;\n\t\t\t\tserviceReference = null;\n\t\t\t}\n\t\t\tsslContextContainerCls = null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void serviceChanged(ServiceEvent event) {\n\t\tif (event.getType() == ServiceEvent.REGISTERED) {\n\t\t\tif (serviceReference == null) {\n\t\t\t\tserviceReference = event.getServiceReference();\n\t\t\t\tserviceManager = (ModulesManager) context.getService(serviceReference);\n\t\t\t\tregisterAddons();\n\t\t\t}\n\t\t} else if (event.getType() == ServiceEvent.UNREGISTERING) {\n\t\t\tif (serviceReference == event.getServiceReference()) {\n\t\t\t\tunregisterAddons();\n\t\t\t\tcontext.ungetService(serviceReference);\n\t\t\t\tserviceManager = null;\n\t\t\t\tserviceReference = null;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void registerAddons() {\n\t\tif (serviceManager != null) {\n\t\t\tserviceManager.registerClass(sslContextContainerCls);\n\t\t\tserviceManager.update();\n\t\t}\n\t}\n\n\tprivate void unregisterAddons() {\n\t\tif (serviceManager != null) {\n\t\t\tserviceManager.unregisterClass(sslContextContainerCls);\n\t\t\tserviceManager.update();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/AnnotationConfigurator.java",
    "content": "package tigase.kernel;\n\nimport java.io.IOException;\nimport java.util.Set;\n\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.core.Kernel;\nimport tigase.util.ClassUtil;\n\npublic class AnnotationConfigurator {\n\n\t@Inject\n\tprivate Kernel kernel;\n\n\tpublic void registerBeans() {\n\t\ttry {\n\t\t\tSet<Class<?>> cls = ClassUtil.getClassesFromClassPath();\n\t\t\tfor (Class<?> class1 : cls) {\n\t\t\t\tBean bean = class1.getAnnotation(Bean.class);\n\t\t\t\tif (bean != null) {\n\t\t\t\t\tkernel.registerBean(class1);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (ClassNotFoundException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/BeanUtils.java",
    "content": "package tigase.kernel;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class BeanUtils {\n\n\tpublic static Method[] getAllMethods(Class<?> klass) {\n\t\tList<Method> fields = new ArrayList<Method>();\n\t\tfields.addAll(Arrays.asList(klass.getDeclaredMethods()));\n\t\tif (klass.getSuperclass() != null) {\n\t\t\tfields.addAll(Arrays.asList(getAllMethods(klass.getSuperclass())));\n\t\t}\n\t\treturn fields.toArray(new Method[] {});\n\t}\n\n\tpublic static Object getValue(Object fromBean, Field field) throws IllegalAccessException, IllegalArgumentException,\n\t\t\tInvocationTargetException {\n\t\tMethod setter = BeanUtils.prepareGetterMethod(field);\n\t\tif (setter != null) {\n\t\t\treturn setter.invoke(fromBean);\n\t\t} else {\n\t\t\tfield.setAccessible(true);\n\t\t\treturn field.get(fromBean);\n\t\t}\n\n\t}\n\n\tpublic static String prepareAccessorMainPartName(final String fieldName) {\n\t\tif (fieldName.length() == 1) {\n\t\t\treturn fieldName.toUpperCase();\n\t\t}\n\n\t\tString r;\n\t\tif (Character.isUpperCase(fieldName.charAt(1))) {\n\t\t\tr = fieldName.substring(0, 1);\n\t\t} else {\n\t\t\tr = fieldName.substring(0, 1).toUpperCase();\n\t\t}\n\n\t\tr += fieldName.substring(1);\n\n\t\treturn r;\n\t}\n\n\tpublic static Method prepareGetterMethod(Field f) {\n\t\tString t = prepareAccessorMainPartName(f.getName());\n\t\t@SuppressWarnings(\"unused\")\n\t\tString sm;\n\t\tString gm;\n\t\tif (f.getType().isPrimitive() && f.getType().equals(boolean.class)) {\n\t\t\tsm = \"set\" + t;\n\t\t\tgm = \"is\" + t;\n\t\t} else {\n\t\t\tsm = \"set\" + t;\n\t\t\tgm = \"get\" + t;\n\t\t}\n\n\t\ttry {\n\t\t\tMethod m = f.getDeclaringClass().getMethod(gm);\n\t\t\treturn m;\n\t\t} catch (NoSuchMethodException e) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic static Method prepareSetterMethod(Field f) {\n\t\tString t = prepareAccessorMainPartName(f.getName());\n\t\tString sm;\n\t\t@SuppressWarnings(\"unused\")\n\t\tString gm;\n\t\tif (f.getType().isPrimitive() && f.getType().equals(boolean.class)) {\n\t\t\tsm = \"set\" + t;\n\t\t\tgm = \"is\" + t;\n\t\t} else {\n\t\t\tsm = \"set\" + t;\n\t\t\tgm = \"get\" + t;\n\t\t}\n\n\t\ttry {\n\t\t\tMethod m = f.getDeclaringClass().getMethod(sm, f.getType());\n\t\t\treturn m;\n\t\t} catch (NoSuchMethodException e) {\n\t\t\treturn null;\n\t\t\t// throw new KernelException(\"Class \" +\n\t\t\t// f.getDeclaringClass().getName() + \" has no setter of field \" +\n\t\t\t// f.getName(), e);\n\t\t}\n\t}\n\n\tpublic static ArrayList<Method> prepareSetterMethods(Class<?> destination, String fieldName) {\n\t\tString t = prepareAccessorMainPartName(fieldName);\n\t\tArrayList<Method> result = new ArrayList<Method>();\n\t\ttry {\n\t\t\tfor (Method m : getAllMethods(destination)) {\n\t\t\t\tif (m.getName().equals(\"set\" + t)) {\n\t\t\t\t\tresult.add(m);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t} catch (Exception e) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic static void setValue(Object toBean, Field field, Object valueToSet) throws IllegalAccessException,\n\t\t\tIllegalArgumentException, InvocationTargetException {\n\t\tMethod setter = BeanUtils.prepareSetterMethod(field);\n\t\tif (setter != null) {\n\t\t\tsetter.invoke(toBean, valueToSet);\n\t\t} else {\n\t\t\tfield.setAccessible(true);\n\t\t\tfield.set(toBean, valueToSet);\n\t\t}\n\t}\n\n\tpublic static void setValue(Object toBean, String fieldName, Object valueToSet) throws IllegalAccessException,\n\t\t\tIllegalArgumentException, InvocationTargetException, NoSuchMethodException {\n\t\tArrayList<Method> setters = BeanUtils.prepareSetterMethods(toBean.getClass(), fieldName);\n\n\t\tif (setters == null || setters.isEmpty()) {\n\t\t\tthrow new NoSuchMethodException(\"No setter for property '\" + fieldName + \"'.\");\n\t\t}\n\n\t\tfor (final Method s : setters) {\n\t\t\ttry {\n\t\t\t\ts.invoke(toBean, valueToSet);\n\t\t\t\treturn;\n\t\t\t} catch (Exception e) {\n\t\t\t}\n\t\t}\n\n\t\tthrow new IllegalArgumentException(\"Cannot set value type \" + valueToSet.getClass().getName() + \" to property '\"\n\t\t\t\t+ fieldName + \"'.\");\n\t}\n\n\tprivate BeanUtils() {\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/KernelException.java",
    "content": "package tigase.kernel;\n\npublic class KernelException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic KernelException() {\n\t\tsuper();\n\t}\n\n\tpublic KernelException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic KernelException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n\n\tpublic KernelException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {\n\t\tsuper(message, cause, enableSuppression, writableStackTrace);\n\t}\n\n\tpublic KernelException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/Registrar.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.core.Kernel;\n\npublic interface Registrar {\n\n\tvoid register(Kernel kernel);\n\n\tvoid start(Kernel krnl);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/Bean.java",
    "content": "package tigase.kernel.beans;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target({ ElementType.TYPE })\n@Retention(RetentionPolicy.RUNTIME)\n@Inherited\n@Documented\npublic @interface Bean {\n\n\tString name();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/BeanFactory.java",
    "content": "package tigase.kernel.beans;\n\nimport tigase.kernel.KernelException;\n\npublic interface BeanFactory<T> {\n\n\tT createInstance() throws KernelException;\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/Initializable.java",
    "content": "package tigase.kernel.beans;\n\npublic interface Initializable {\n\n\tvoid initialize();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/Inject.java",
    "content": "package tigase.kernel.beans;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target({ ElementType.FIELD })\n@Retention(RetentionPolicy.RUNTIME)\n@Inherited\n@Documented\npublic @interface Inject {\n\n\tpublic static final class EMPTY {\n\t\tprivate EMPTY() {\n\t\t}\n\t}\n\n\tString bean() default \"\";\n\n\tboolean nullAllowed() default true;\n\n\tClass<?> type() default EMPTY.class;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/UnregisterAware.java",
    "content": "package tigase.kernel.beans;\n\npublic interface UnregisterAware {\n\n\tvoid beforeUnregister();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/config/AbstractBeanConfigurator.java",
    "content": "package tigase.kernel.beans.config;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport tigase.kernel.BeanUtils;\nimport tigase.kernel.KernelException;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.core.BeanConfig;\nimport tigase.kernel.core.DependencyManager;\nimport tigase.kernel.core.Kernel;\n\npublic abstract class AbstractBeanConfigurator implements BeanConfigurator {\n\n\tprivate final ConcurrentHashMap<BeanConfig, HashMap<Field, Object>> defaultFieldValues = new ConcurrentHashMap<BeanConfig, HashMap<Field, Object>>();\n\n\t@Inject(nullAllowed = false)\n\tprivate Kernel kernel;\n\n\t@Override\n\tpublic void configure(BeanConfig beanConfig, Object bean) throws KernelException {\n\t\ttry {\n\t\t\tMap<String, Object> ccc = getConfiguration(beanConfig);\n\n\t\t\tHashMap<Field, Object> defaultConfig = defaultFieldValues.get(beanConfig);\n\t\t\tif (defaultConfig == null) {\n\t\t\t\tdefaultConfig = new HashMap<Field, Object>();\n\t\t\t\tdefaultFieldValues.put(beanConfig, defaultConfig);\n\t\t\t}\n\n\t\t\tfinal Field[] fields = DependencyManager.getAllFields(beanConfig.getClazz());\n\t\t\tfor (Field field : fields) {\n\n\t\t\t\tConfigField configField = field.getAnnotation(ConfigField.class);\n\n\t\t\t\tif (configField == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tObject currentValue = BeanUtils.getValue(bean, field);\n\t\t\t\t\tif (!defaultFieldValues.contains(field)) {\n\t\t\t\t\t\tdefaultConfig.put(field, currentValue);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!ccc.containsKey(field.getName()))\n\t\t\t\t\tcontinue;\n\n\t\t\t\tObject valueToSet = ccc.get(field.getName());\n\n\t\t\t\tMethod setter = BeanUtils.prepareSetterMethod(field);\n\t\t\t\tif (setter != null) {\n\t\t\t\t\tsetter.invoke(bean, valueToSet);\n\t\t\t\t} else {\n\t\t\t\t\tfield.setAccessible(true);\n\t\t\t\t\tfield.set(bean, valueToSet);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tthrow new KernelException(\"Cannot inject configuration to bean \" + beanConfig.getBeanName(), e);\n\t\t}\n\t}\n\n\tprotected abstract Map<String, Object> getConfiguration(BeanConfig beanConfig);\n\n\tpublic Kernel getKernel() {\n\t\treturn kernel;\n\t}\n\n\tpublic void restoreDefaults(String beanName) {\n\t\tBeanConfig beanConfig = kernel.getDependencyManager().getBeanConfig(beanName);\n\t\tObject bean = kernel.getInstance(beanName);\n\n\t\ttry {\n\t\t\tHashMap<Field, Object> defaultConfig = defaultFieldValues.get(beanConfig);\n\t\t\tif (defaultConfig == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfinal Field[] fields = DependencyManager.getAllFields(beanConfig.getClazz());\n\t\t\tfor (Field field : fields) {\n\n\t\t\t\tConfigField configField = field.getAnnotation(ConfigField.class);\n\n\t\t\t\tif (configField == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!defaultConfig.containsKey(field))\n\t\t\t\t\tcontinue;\n\n\t\t\t\tObject valueToSet = defaultConfig.get(field);\n\n\t\t\t\tMethod setter = BeanUtils.prepareSetterMethod(field);\n\t\t\t\tif (setter != null) {\n\t\t\t\t\tsetter.invoke(bean, valueToSet);\n\t\t\t\t} else {\n\t\t\t\t\tfield.setAccessible(true);\n\t\t\t\t\tfield.set(bean, valueToSet);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tthrow new KernelException(\"Cannot inject configuration to bean \" + beanConfig.getBeanName(), e);\n\t\t}\n\n\t}\n\n\tpublic void setKernel(Kernel kernel) {\n\t\tthis.kernel = kernel;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/config/BeanConfigurator.java",
    "content": "package tigase.kernel.beans.config;\n\nimport tigase.kernel.core.BeanConfig;\n\npublic interface BeanConfigurator {\n\n\tpublic static final String DEFAULT_CONFIGURATOR_NAME = \"defaultBeanConfigurator\";\n\n\tvoid configure(BeanConfig beanConfig, Object bean);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/beans/config/ConfigField.java",
    "content": "package tigase.kernel.beans.config;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target({ ElementType.FIELD })\n@Retention(RetentionPolicy.RUNTIME)\n@Inherited\n@Documented\npublic @interface ConfigField {\n\n\tString desc();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/BeanConfig.java",
    "content": "package tigase.kernel.core;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class BeanConfig {\n\n\tpublic enum State {\n\t\tinitialized,\n\t\tinstanceCreated,\n\t\tregistered;\n\t}\n\n\tprivate final String beanName;\n\n\tprivate final Class<?> clazz;\n\n\tprivate boolean exportable;\n\n\tprivate BeanConfig factory;\n\n\tprivate final Map<Field, Dependency> fieldDependencies = new HashMap<Field, Dependency>();\n\n\tprivate Kernel kernel;\n\n\tprivate State state;\n\n\tBeanConfig(String id, Class<?> clazz) {\n\t\tsuper();\n\t\tthis.beanName = id;\n\t\tthis.clazz = clazz;\n\t};\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj)\n\t\t\treturn true;\n\t\tif (obj == null)\n\t\t\treturn false;\n\t\tif (getClass() != obj.getClass())\n\t\t\treturn false;\n\t\tBeanConfig other = (BeanConfig) obj;\n\t\tif (beanName == null) {\n\t\t\tif (other.beanName != null)\n\t\t\t\treturn false;\n\t\t} else if (!beanName.equals(other.beanName))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tpublic String getBeanName() {\n\t\treturn beanName;\n\t}\n\n\tpublic Class<?> getClazz() {\n\t\treturn clazz;\n\t}\n\n\tpublic BeanConfig getFactory() {\n\t\treturn factory;\n\t}\n\n\tpublic Map<Field, Dependency> getFieldDependencies() {\n\t\treturn fieldDependencies;\n\t}\n\n\tpublic Kernel getKernel() {\n\t\treturn kernel;\n\t}\n\n\tpublic State getState() {\n\t\treturn state;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tfinal int prime = 31;\n\t\tint result = 1;\n\t\tresult = prime * result + ((beanName == null) ? 0 : beanName.hashCode());\n\t\treturn result;\n\t}\n\n\tpublic boolean isExportable() {\n\t\treturn exportable;\n\t}\n\n\tvoid setExportable(boolean value) {\n\t\tthis.exportable = value;\n\t}\n\n\tvoid setFactory(final BeanConfig bfc) {\n\t\tthis.factory = bfc;\n\t}\n\n\tvoid setKernel(Kernel kernel) {\n\t\tthis.kernel = kernel;\n\t}\n\n\tvoid setState(State state) {\n\t\tthis.state = state;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn beanName + \":\" + clazz.getName();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/BeanConfigBuilder.java",
    "content": "package tigase.kernel.core;\n\nimport java.util.logging.Logger;\n\nimport tigase.kernel.KernelException;\nimport tigase.kernel.Registrar;\n\npublic class BeanConfigBuilder {\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\tprivate final String beanName;\n\tprivate final DependencyManager dependencyManager;\n\tprivate final Kernel kernel;\n\tprivate BeanConfig beanConfig;\n\tprivate Object beanInstance;\n\tprivate BeanConfig factoryBeanConfig;\n\tprivate Class<?> clazz;\n\n\tBeanConfigBuilder(Kernel kernel, DependencyManager dependencyManager, String beanName) {\n\t\tthis.kernel = kernel;\n\t\tthis.dependencyManager = dependencyManager;\n\t\tthis.beanName = beanName;\n\t}\n\n\tpublic BeanConfigBuilder asClass(Class<?> cls) {\n\t\tthis.clazz = cls;\n\t\tif (this.beanConfig != null)\n\t\t\tthrowException(new KernelException(\"Class or instance is already defined for bean '\" + beanName + \"'\"));\n\n\t\tthis.beanConfig = dependencyManager.createBeanConfig(kernel, beanName, cls);\n\t\treturn this;\n\t}\n\n\tpublic BeanConfigBuilder asInstance(Object bean) {\n\t\tif (this.beanConfig != null)\n\t\t\tthrowException(new KernelException(\"Class or instance is already defined for bean '\" + beanName + \"'\"));\n\n\t\tthis.beanConfig = dependencyManager.createBeanConfig(kernel, beanName, bean.getClass());\n\t\tthis.beanInstance = bean;\n\t\treturn this;\n\t}\n\n\tpublic void exec() {\n\t\tif (beanConfig == null) {\n\t\t\tlog.warning(\"Bean \" + clazz + \" cannot be registered, because Kernel cannot create configuration for this bean.\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (factoryBeanConfig != null) {\n\t\t\tkernel.unregisterInt(factoryBeanConfig.getBeanName());\n\t\t\tdependencyManager.register(factoryBeanConfig);\n\t\t}\n\t\tkernel.unregisterInt(beanConfig.getBeanName());\n\t\tdependencyManager.register(beanConfig);\n\n\t\tif (beanInstance != null) {\n\t\t\tkernel.putBeanInstance(beanConfig, beanInstance);\n\t\t}\n\n\t\tkernel.currentlyUsedConfigBuilder = null;\n\t\tkernel.injectIfRequired(beanConfig);\n\n\t\tfor (BeanConfig rbc : kernel.getDependencyManager().getBeanConfigs(Registrar.class)) {\n\t\t\tkernel.getInstance(rbc.getBeanName());\n\t\t}\n\t}\n\n\tpublic BeanConfigBuilder exportable() {\n\t\tbeanConfig.setExportable(true);\n\t\treturn this;\n\t}\n\n\tpublic String getBeanName() {\n\t\treturn beanName;\n\t}\n\n\tprotected void throwException(KernelException e) {\n\t\tkernel.currentlyUsedConfigBuilder = null;\n\t\tthrow e;\n\t}\n\n\tpublic BeanConfigBuilder withFactory(Class<?> beanFactoryClass) {\n\t\tif (beanInstance != null)\n\t\t\tthrowException(new KernelException(\"Cannot register factory to bean '\" + beanName + \"' registered as instance.\"));\n\t\tif (factoryBeanConfig != null)\n\t\t\tthrowException(new KernelException(\"Factory for bean '\" + beanName + \"' is already registered.\"));\n\n\t\tthis.factoryBeanConfig = dependencyManager.createBeanConfig(kernel, beanName + \"#FACTORY\", beanFactoryClass);\n\t\tbeanConfig.setFactory(factoryBeanConfig);\n\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/Dependency.java",
    "content": "package tigase.kernel.core;\n\nimport java.lang.reflect.Field;\n\npublic class Dependency {\n\n\tprivate BeanConfig beanConfig;\n\n\tprivate String beanName;\n\n\tprivate Field field;\n\n\tprivate boolean nullAllowed;\n\n\tprivate Class<?> type;\n\n\tpublic Dependency(BeanConfig beanConfig) {\n\t\tthis.beanConfig = beanConfig;\n\t}\n\n\tpublic BeanConfig getBeanConfig() {\n\t\treturn beanConfig;\n\t}\n\n\tpublic String getBeanName() {\n\t\treturn beanName;\n\t}\n\n\tpublic Field getField() {\n\t\treturn field;\n\t}\n\n\tpublic Class<?> getType() {\n\t\treturn type;\n\t}\n\n\tpublic boolean isNullAllowed() {\n\t\treturn nullAllowed;\n\t}\n\n\tpublic void setBeanName(String beanId) {\n\t\tthis.beanName = beanId;\n\t}\n\n\tpublic void setField(Field field) {\n\t\tthis.field = field;\n\t}\n\n\tpublic void setNullAllowed(boolean nullAllowed) {\n\t\tthis.nullAllowed = nullAllowed;\n\t}\n\n\tpublic void setType(Class<?> type) {\n\t\tthis.type = type;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tif (beanName != null)\n\t\t\treturn \"bean:\" + beanName;\n\t\telse\n\t\t\treturn \"type:\" + type.getName();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/DependencyGrapher.java",
    "content": "package tigase.kernel.core;\n\nimport tigase.kernel.core.Kernel.DelegatedBeanConfig;\n\nimport java.util.HashSet;\n\npublic class DependencyGrapher {\n\n    private Kernel kernel;\n\n    public DependencyGrapher() {\n    }\n\n    public DependencyGrapher(Kernel krnl) {\n        setKernel(krnl);\n    }\n\n    private void drawContext(StringBuilder structureSB, HashSet<String> connections, Kernel kernel) {\n\n        final DependencyManager dependencyManager = kernel.getDependencyManager();\n        structureSB.append(\"subgraph \").append(\" {\\n\");\n\n        for (BeanConfig bc : dependencyManager.getBeanConfigs()) {\n            if (bc.getClazz().equals(Kernel.class))\n                continue;\n            structureSB.append('\"').append(bc.getKernel().getName() + \".\" + bc.getBeanName()).append('\"').append(\"[\");\n\n            if (bc instanceof DelegatedBeanConfig) {\n                structureSB.append(\"label=\\\"\");\n                structureSB.append(bc.getBeanName());\n                structureSB.append(\"\\\"\");\n                structureSB.append(\"shape=oval\");\n            } else {\n                structureSB.append(\"label=\\\"{\");\n                structureSB.append(bc.getBeanName()).append(\"\\\\n\").append(\"(\").append(bc.getClazz().getName()).append(\")\");\n                structureSB.append(\"}\\\"\");\n            }\n            structureSB.append(\"];\\n\");\n        }\n        structureSB.append(\"}\\n\");\n\n        int c = 0;\n        for (final BeanConfig bc : dependencyManager.getBeanConfigs()) {\n            ++c;\n\n\n            if (bc.getFactory() != null) {\n                BeanConfig dBean = bc.getFactory();\n                StringBuilder sbi = new StringBuilder();\n                sbi.append('\"').append(bc.getKernel().getName() + \".\" + bc.getBeanName()).append('\"');\n                // sb.append(':').append(dp.getField().getName());\n                sbi.append(\"->\");\n\n                sbi.append('\"').append(dBean.getKernel().getName() + \".\" + dBean.getBeanName()).append('\"').append(\n                        \"[style=\\\"dashed\\\"]\");\n\n                connections.add(sbi.toString());\n            }\n\n            if (bc instanceof DelegatedBeanConfig) {\n                final BeanConfig oryginal = ((DelegatedBeanConfig) bc).getOriginal();\n                StringBuilder sbi = new StringBuilder();\n                sbi.append('\"').append(oryginal.getKernel().getName() + \".\" + oryginal.getBeanName()).append('\"');\n                sbi.append(\"->\");\n                sbi.append('\"').append(bc.getKernel().getName() + \".\" + bc.getBeanName()).append('\"').append(\n                        \"[style=dotted,arrowtail=none,arrowhead=none]\");\n                connections.add(sbi.toString());\n                continue;\n            }\n\n            for (Dependency dp : bc.getFieldDependencies().values()) {\n\n                BeanConfig[] dBeans = dependencyManager.getBeanConfig(dp);\n                for (BeanConfig dBean : dBeans) {\n                    BeanConfig fromBC = bc;\n                    StringBuilder sbi = new StringBuilder();\n                    if (dBean != null && dBean.getKernel() != bc.getKernel()) {\n                        sbi.append(\"/* inne kernele */ \");\n                        fromBC = findDelegateIn(bc, dBean.getKernel().getDependencyManager());\n                    }\n\n\n                    if (dBean == null) {\n                        sbi.append('\"').append(fromBC.getKernel().getName() + \".\" + fromBC.getBeanName()).append('\"');\n                        sbi.append(\"->\");\n                        sbi.append(\"{UNKNOWN_\").append(c).append(\"[label=\\\"\").append(dp).append(\n                                \"\\\", fillcolor=red, style=filled, shape=box]}\");\n                    } else {\n                        sbi.append('\"').append(fromBC.getKernel().getName() + \".\" + fromBC.getBeanName()).append('\"');\n                        sbi.append(\"->\");\n                        sbi.append('\"').append(dBean.getKernel().getName() + \".\" + dBean.getBeanName()).append('\"');\n                    }\n                    connections.add(sbi.toString());\n\n                }\n            }\n        }\n\n        for (BeanConfig kc : dependencyManager.getBeanConfigs(Kernel.class)) {\n            Kernel ki = kernel.getInstance(kc.getBeanName());\n            structureSB.append(\"subgraph \").append(\"cluster_\").append(ki.hashCode()).append(\" {\\n\");\n            structureSB.append(\"label=\").append(\"\\\"\").append(ki.getName()).append(\"\\\"\\n\");\n            if (ki != kernel)\n                drawContext(structureSB, connections, ki);\n            structureSB.append(\"}\\n\");\n        }\n\n    }\n\n    private BeanConfig findDelegateIn(BeanConfig dBean, DependencyManager dependencyManager) {\n        for (BeanConfig bc : dependencyManager.getBeanConfigs()) {\n            if (bc instanceof DelegatedBeanConfig) {\n                BeanConfig orig = ((DelegatedBeanConfig) bc).getOriginal();\n                if (orig == dBean)\n                    return bc;\n            }\n        }\n        return dBean;\n    }\n\n    public String getDependencyGraph() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"digraph \").append(\"Context\").append(\" {\\n\");\n        sb.append(\"label=\").append(\"\\\"\").append(kernel.getName()).append(\"\\\"\\n\");\n        sb.append(\"node[shape=record,style=filled,fillcolor=khaki1, color=brown]\\n\");\n        sb.append(\"edge[color=brown]\\n\");\n\n        // sb.append(\"rank=same\\n\");\n\n        HashSet<String> connections = new HashSet<String>();\n        drawContext(sb, connections, kernel);\n\n        for (String string : connections) {\n            sb.append(string).append('\\n');\n        }\n        sb.append(\"}\\n\");\n        return sb.toString();\n    }\n\n    public Kernel getKernel() {\n        return kernel;\n    }\n\n    public void setKernel(Kernel kernel) {\n        this.kernel = kernel;\n    }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/DependencyManager.java",
    "content": "package tigase.kernel.core;\n\nimport java.lang.reflect.Field;\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.core.BeanConfig.State;\n\npublic class DependencyManager {\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\tprivate final Map<String, BeanConfig> beanConfigs = new HashMap<String, BeanConfig>();\n\tprivate DependencyManager parent;\n\t/**\n\t * if <code>true</code> then DependencyManager will throw exception if it\n\t * can't create beanConfig. If <code>false</code> then\n\t * {@link DependencyManager#createBeanConfig(Kernel, String, Class)} will\n\t * return null instead of BeanConfig.\n\t */\n\tprivate boolean throwExceptionIfCannotCreate = false;\n\n\tpublic static Field[] getAllFields(Class<?> klass) {\n\t\tList<Field> fields = new ArrayList<Field>();\n\t\tfields.addAll(Arrays.asList(klass.getDeclaredFields()));\n\t\tif (klass.getSuperclass() != null) {\n\t\t\tfields.addAll(Arrays.asList(getAllFields(klass.getSuperclass())));\n\t\t}\n\t\treturn fields.toArray(new Field[] {});\n\t}\n\n\tpublic static boolean match(Dependency dependency, BeanConfig beanConfig) {\n\t\tif (dependency.getBeanName() != null) {\n\t\t\treturn beanConfig.getBeanName().equals(dependency.getBeanName());\n\t\t} else if (dependency.getType() != null) {\n\t\t\treturn dependency.getType().isAssignableFrom(beanConfig.getClazz());\n\t\t} else\n\t\t\tthrow new RuntimeException(\"Unsupported dependecy type.\");\n\t}\n\n\tprotected BeanConfig createBeanConfig(final Kernel kernel, final String beanName, final Class<?> beanClass) {\n\t\ttry {\n\t\t\tBeanConfig result = new BeanConfig(beanName, beanClass);\n\t\t\tresult.setKernel(kernel);\n\t\t\tprepareDependencies(result);\n\t\t\treturn result;\n\t\t} catch (java.lang.NoClassDefFoundError e) {\n\t\t\tlog.log(Level.WARNING, \"Cannot create bean config '\" + beanName + \"', type=\" + beanClass.getName()\n\t\t\t\t\t+ \". Bean requires unknown class \" + e.getMessage());\n\n\t\t\tif (throwExceptionIfCannotCreate) {\n\t\t\t\tthrow e;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Map<Field, Inject> createFieldsDependencyList(final Class<?> cls) {\n\t\tMap<Field, Inject> deps = new HashMap<Field, Inject>();\n\t\tfor (Field field : getAllFields(cls)) {\n\t\t\tInject injectAnnotation = field.getAnnotation(Inject.class);\n\t\t\tif (injectAnnotation != null) {\n\t\t\t\tdeps.put(field, injectAnnotation);\n\t\t\t}\n\t\t}\n\t\treturn deps;\n\t}\n\n\tpublic BeanConfig[] getBeanConfig(Dependency dependency) {\n\t\tArrayList<BeanConfig> bcs = new ArrayList<BeanConfig>();\n\t\tif (this.parent != null && this.parent != this) {\n\t\t\tBeanConfig[] pds = this.parent.getBeanConfig(dependency);\n\t\t\tfor (BeanConfig beanConfig : pds) {\n\t\t\t\tif (beanConfig != null && beanConfig.isExportable())\n\t\t\t\t\tbcs.add(beanConfig);\n\t\t\t}\n\t\t}\n\t\tif (dependency.getBeanName() != null) {\n\t\t\tBeanConfig b = beanConfigs.get(dependency.getBeanName());\n\t\t\tif (b != null)\n\t\t\t\tbcs.add(b);\n\t\t\tif (bcs.isEmpty())\n\t\t\t\tbcs.add(null);\n\t\t} else if (dependency.getType() != null) {\n\t\t\tbcs.addAll(getBeanConfigs(dependency.getType()));\n\t\t} else\n\t\t\tthrow new RuntimeException(\"Unsupported dependecy type.\");\n\t\treturn bcs.toArray(new BeanConfig[] {});\n\t}\n\n\tpublic BeanConfig getBeanConfig(String beanName) {\n\t\treturn this.beanConfigs.get(beanName);\n\t}\n\n\tpublic Collection<BeanConfig> getBeanConfigs() {\n\t\treturn Collections.unmodifiableCollection(beanConfigs.values());\n\t}\n\n\tpublic List<BeanConfig> getBeanConfigs(Class<?> type) {\n\t\treturn getBeanConfigs(type, true);\n\t}\n\n\tpublic List<BeanConfig> getBeanConfigs(final Class<?> type, final boolean allowNonExportable) {\n\t\tArrayList<BeanConfig> result = new ArrayList<BeanConfig>();\n\t\tfor (BeanConfig bc : beanConfigs.values()) {\n\t\t\tif (type.isAssignableFrom(bc.getClazz()) && (allowNonExportable || bc.isExportable())) {\n\t\t\t\tresult.add(bc);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic Collection<Dependency> getDependenciesTo(BeanConfig destination) {\n\t\tHashSet<Dependency> result = new HashSet<Dependency>();\n\t\tfor (BeanConfig candidate : beanConfigs.values()) {\n\t\t\tfor (Dependency dp : candidate.getFieldDependencies().values()) {\n\t\t\t\tList<BeanConfig> bcs = Arrays.asList(getBeanConfig(dp));\n\t\t\t\tif (bcs.contains(destination)) {\n\t\t\t\t\tresult.add(dp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic HashSet<BeanConfig> getDependentBeans(final BeanConfig beanConfig) {\n\t\tHashSet<BeanConfig> result = new HashSet<BeanConfig>();\n\t\tfor (BeanConfig candidate : beanConfigs.values()) {\n\t\t\tfor (Dependency dp : candidate.getFieldDependencies().values()) {\n\t\t\t\tList<BeanConfig> bcs = Arrays.asList(getBeanConfig(dp));\n\t\t\t\tif (bcs.contains(beanConfig)) {\n\t\t\t\t\tresult.add(candidate);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tDependencyManager getParent() {\n\t\treturn parent;\n\t}\n\n\tvoid setParent(DependencyManager parent) {\n\t\tthis.parent = parent;\n\t}\n\n\tpublic boolean isBeanClassRegistered(String beanName) {\n\t\treturn beanConfigs.containsKey(beanName);\n\t}\n\n\tpublic boolean isThrowExceptionIfCannotCreate() {\n\t\treturn throwExceptionIfCannotCreate;\n\t}\n\n\tpublic void setThrowExceptionIfCannotCreate(boolean throwExceptionIfCannotCreate) {\n\t\tthis.throwExceptionIfCannotCreate = throwExceptionIfCannotCreate;\n\t}\n\n\tprotected void prepareDependencies(BeanConfig beanConfig) {\n\t\tfinal String id = beanConfig.getBeanName();\n\t\tfinal Class<?> cls = beanConfig.getClazz();\n\n\t\tMap<Field, Inject> deps = createFieldsDependencyList(cls);\n\t\tfor (Entry<Field, Inject> e : deps.entrySet()) {\n\t\t\tDependency d = new Dependency(beanConfig);\n\t\t\td.setField(e.getKey());\n\t\t\td.setNullAllowed(e.getValue().nullAllowed());\n\t\t\tif (!e.getValue().bean().isEmpty()) {\n\t\t\t\td.setBeanName(e.getValue().bean());\n\t\t\t} else if (e.getValue().type() != Inject.EMPTY.class) {\n\t\t\t\td.setType(e.getValue().type());\n\t\t\t} else if (e.getKey().getType().isArray()) {\n\t\t\t\td.setType(e.getKey().getType().getComponentType());\n\t\t\t} else {\n\t\t\t\td.setType(e.getKey().getType());\n\t\t\t}\n\n\t\t\tbeanConfig.getFieldDependencies().put(e.getKey(), d);\n\t\t}\n\t}\n\n\tvoid register(BeanConfig factoryBeanConfig) {\n\t\tbeanConfigs.put(factoryBeanConfig.getBeanName(), factoryBeanConfig);\n\t\tfactoryBeanConfig.setState(State.registered);\n\n\t}\n\n\tpublic BeanConfig unregister(String beanName) {\n\t\treturn beanConfigs.remove(beanName);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/Kernel.java",
    "content": "package tigase.kernel.core;\n\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.kernel.BeanUtils;\nimport tigase.kernel.KernelException;\nimport tigase.kernel.Registrar;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.BeanFactory;\nimport tigase.kernel.beans.Initializable;\nimport tigase.kernel.beans.UnregisterAware;\nimport tigase.kernel.beans.config.BeanConfigurator;\nimport tigase.kernel.core.BeanConfig.State;\n\npublic class Kernel {\n\n    static class DelegatedBeanConfig extends BeanConfig {\n\n        private final BeanConfig original;\n\n        DelegatedBeanConfig(String localName, BeanConfig src) {\n            super(localName, src.getClazz());\n            original = src;\n        }\n\n        @Override\n        public Class<?> getClazz() {\n            return original.getClazz();\n        }\n\n        @Override\n        public BeanConfig getFactory() {\n            return original.getFactory();\n        }\n\n        @Override\n        public Map<Field, Dependency> getFieldDependencies() {\n            return original.getFieldDependencies();\n        }\n\n        @Override\n        public Kernel getKernel() {\n            return original.getKernel();\n        }\n\n        public BeanConfig getOriginal() {\n            return original;\n        }\n\n        @Override\n        public State getState() {\n            return original.getState();\n        }\n\n        @Override\n        public boolean isExportable() {\n            return original.isExportable();\n        }\n\n        @Override\n        public String toString() {\n            return original.toString();\n        }\n    }\n\n    private final Map<BeanConfig, Object> beanInstances = new HashMap<BeanConfig, Object>();\n\n    BeanConfigBuilder currentlyUsedConfigBuilder;\n\n    private final DependencyManager dependencyManager = new DependencyManager();\n\n    protected final Logger log = Logger.getLogger(this.getClass().getName());\n\n    private String name;\n\n    private Kernel parent;\n\n    public Kernel() {\n        this(\"<unknown>\");\n    }\n\n    public Kernel(String name) {\n        this.name = name;\n\n        BeanConfig bc = dependencyManager.createBeanConfig(this, \"kernel\", Kernel.class);\n        dependencyManager.register(bc);\n        registerBean(\"kernel\").asInstance(this).exec();\n\n        putBeanInstance(bc, this);\n    }\n\n    private Object createNewInstance(BeanConfig beanConfig) {\n        try {\n            if (beanConfig.getFactory() != null) {\n                BeanFactory<?> factory = (BeanFactory<?>) beanConfig.getKernel().getInstance(beanConfig.getFactory());\n                return factory.createInstance();\n            } else {\n                if (log.isLoggable(Level.FINER))\n                    log.finer(\"[\" + getName() + \"] Creating instance of bean \" + beanConfig.getBeanName());\n                Class<?> clz = beanConfig.getClazz();\n\n                return clz.newInstance();\n            }\n        } catch (Exception e) {\n            throw new KernelException(\"Can't create instance of bean '\" + beanConfig.getBeanName() + \"'\", e);\n        }\n    }\n\n    public DependencyManager getDependencyManager() {\n        return dependencyManager;\n    }\n\n    public <T> T getInstance(BeanConfig beanConfig) {\n        if (beanConfig instanceof DelegatedBeanConfig) {\n            BeanConfig b = ((DelegatedBeanConfig) beanConfig).original;\n            return (T) beanConfig.getKernel().beanInstances.get(b);\n        } else {\n            return (T) beanConfig.getKernel().beanInstances.get(beanConfig);\n        }\n    }\n\n    public <T> T getInstance(Class<T> beanClass) {\n        return getInstance(beanClass, true);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    protected <T> T getInstance(Class<T> beanClass, boolean allowNonExportable) {\n        final List<BeanConfig> bcs = dependencyManager.getBeanConfigs(beanClass, allowNonExportable);\n\n        if (bcs.size() > 1)\n            throw new KernelException(\"Too many beans implemented class \" + beanClass);\n        else if (bcs.isEmpty() && this.parent != null && this.parent != this) {\n            return this.parent.getInstance(beanClass, false);\n        }\n\n        if (bcs.isEmpty())\n            throw new KernelException(\"Can't find bean implementing \" + beanClass);\n\n        BeanConfig bc = bcs.get(0);\n\n        if (bc.getState() != State.initialized) {\n            try {\n                initBean(bc, new HashSet<BeanConfig>(), 0);\n            } catch (Exception e) {\n                e.printStackTrace();\n                throw new KernelException(e);\n            }\n        }\n\n        Object result = bc.getKernel().getInstance(bc);\n\n        return (T) result;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T getInstance(String beanName) {\n        BeanConfig bc = dependencyManager.getBeanConfig(beanName);\n\n        if (bc == null && parent != null && parent.getDependencyManager().isBeanClassRegistered(beanName)) {\n            return parent.getInstance(beanName);\n        }\n\n        if (bc == null)\n            throw new KernelException(\"Unknown bean '\" + beanName + \"'.\");\n\n        if (bc.getState() != State.initialized) {\n            try {\n                bc.getKernel().initBean(bc, new HashSet<BeanConfig>(), 0);\n            } catch (Exception e) {\n                e.printStackTrace();\n                throw new KernelException(e);\n            }\n        }\n\n        Object result = bc.getKernel().getInstance(bc);\n\n        return (T) result;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public Collection<String> getNamesOf(Class<?> beanType) {\n        ArrayList<String> result = new ArrayList<String>();\n        List<BeanConfig> bcs = dependencyManager.getBeanConfigs(beanType);\n        for (BeanConfig beanConfig : bcs) {\n            result.add(beanConfig.getBeanName());\n        }\n        return Collections.unmodifiableCollection(result);\n    }\n\n    public Kernel getParent() {\n        return parent;\n    }\n\n    public void initAll() {\n        try {\n            for (BeanConfig bc : dependencyManager.getBeanConfigs()) {\n                if (bc.getState() != State.initialized) {\n                    initBean(bc, new HashSet<BeanConfig>(), 0);\n                }\n            }\n        } catch (Exception e) {\n            throw new KernelException(\"Can't initialize all beans\", e);\n        }\n    }\n\n    protected void initBean(BeanConfig tmpBC, Set<BeanConfig> createdBeansConfig, int deep) throws IllegalAccessException,\n            IllegalArgumentException, InvocationTargetException, InstantiationException {\n        final BeanConfig beanConfig = tmpBC instanceof DelegatedBeanConfig ? ((DelegatedBeanConfig) tmpBC).original : tmpBC;\n\n        if (beanConfig.getState() == State.initialized)\n            return;\n\n        Object bean;\n        if (beanConfig.getState() == State.registered) {\n            beanConfig.setState(State.instanceCreated);\n            if (beanConfig.getFactory() != null && beanConfig.getFactory().getState() != State.initialized) {\n                initBean(beanConfig.getFactory(), new HashSet<BeanConfig>(), 0);\n            }\n            bean = createNewInstance(beanConfig);\n            beanConfig.getKernel().putBeanInstance(beanConfig, bean);\n            createdBeansConfig.add(beanConfig);\n        } else {\n            bean = beanConfig.getKernel().getInstance(beanConfig);\n        }\n\n        for (final Dependency dep : beanConfig.getFieldDependencies().values()) {\n            injectDependencies(bean, dep, createdBeansConfig, deep);\n        }\n\n        BeanConfigurator beanConfigurator;\n        try {\n            if (isBeanClassRegistered(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME) && !beanConfig.getBeanName().equals(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME))\n                beanConfigurator = getInstance(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME);\n            else\n                beanConfigurator = null;\n        } catch (KernelException e) {\n            beanConfigurator = null;\n        }\n\n        if (beanConfigurator != null) {\n            beanConfigurator.configure(beanConfig, bean);\n        }\n\n        if (deep == 0) {\n            for (BeanConfig bc : createdBeansConfig) {\n                Object bi = bc.getKernel().getInstance(bc);\n                bc.setState(State.initialized);\n                if (bi instanceof Initializable) {\n                    ((Initializable) bi).initialize();\n                }\n            }\n\n            if (Registrar.class.isAssignableFrom(beanConfig.getClazz())) {\n                RegistrarKernel k = new RegistrarKernel();\n                k.setName(beanConfig.getBeanName());\n                registerBean(beanConfig.getBeanName() + \"#KERNEL\").asInstance(k).exec();\n                ((Registrar) bean).register(k);\n                // ((Registrar) bean).start(k);\n            }\n        }\n    }\n\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    private void inject(Object[] data, Dependency dependency, Object toBean) throws IllegalAccessException,\n            IllegalArgumentException, InvocationTargetException, InstantiationException {\n\n        if (!dependency.isNullAllowed() && data == null)\n            throw new KernelException(\"Can't inject <null> to field \" + dependency.getField());\n\n        Object valueToSet;\n        if (data == null) {\n            valueToSet = null;\n        } else if (Collection.class.isAssignableFrom(dependency.getField().getType())) {\n            Collection o;\n\n            if (!dependency.getField().getType().isInterface()) {\n                o = (Collection) dependency.getField().getType().newInstance();\n            } else if (dependency.getField().getType().isAssignableFrom(Set.class)) {\n                o = new HashSet();\n            } else {\n                o = new ArrayList();\n            }\n\n            o.addAll(Arrays.asList(data));\n\n            valueToSet = o;\n        } else {\n            Object o;\n            if (data != null && dependency.getField().getType().equals(data.getClass())) {\n                o = data;\n            } else {\n                int l = Array.getLength(data);\n                if (l > 1)\n                    throw new KernelException(\"Can't put many objects to single field \" + dependency.getField());\n                if (l == 0)\n                    o = null;\n                else\n                    o = Array.get(data, 0);\n            }\n\n            valueToSet = o;\n        }\n\n        BeanUtils.setValue(toBean, dependency.getField(), valueToSet);\n    }\n\n    private void injectDependencies(Object bean, Dependency dep, Set<BeanConfig> createdBeansConfig, int deep)\n            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {\n        BeanConfig[] dependentBeansConfigs = dependencyManager.getBeanConfig(dep);\n        ArrayList<Object> dataToInject = new ArrayList<Object>();\n\n        for (BeanConfig b : dependentBeansConfigs) {\n            if (b == null) {\n                dataToInject.add(null);\n            } else {\n                if (!b.getKernel().beanInstances.containsKey(b)) {\n                    initBean(b, createdBeansConfig, deep + 1);\n                }\n                Object beanToInject = b.getKernel().getInstance(b);\n                // if (beanToInject != null)\n                dataToInject.add(beanToInject);\n            }\n        }\n        Object[] d;\n        if (dataToInject.isEmpty()) {\n            d = new Object[]{};\n        } else if (dep.getType() != null) {\n            Object[] z = (Object[]) Array.newInstance(dep.getType(), 1);\n            d = dataToInject.toArray(z);\n        } else {\n            d = dataToInject.toArray();\n        }\n        if (log.isLoggable(Level.FINER))\n            log.finer(\"[\" + getName() + \"] Injecting \" + Arrays.toString(d) + \" to \" + dep.getBeanConfig() + \"#\" + dep);\n\n        inject(d, dep, bean);\n\n    }\n\n    void injectIfRequired(final BeanConfig beanConfig) {\n        try {\n            Collection<Dependency> dps = dependencyManager.getDependenciesTo(beanConfig);\n            for (Dependency dep : dps) {\n                BeanConfig depbc = dep.getBeanConfig();\n\n                if (depbc.getState() == State.initialized) {\n                    if (beanConfig.getState() != State.initialized)\n                        initBean(beanConfig, new HashSet<BeanConfig>(), 0);\n                    Object bean = depbc.getKernel().getInstance(depbc);\n\n                    injectDependencies(bean, dep, new HashSet<BeanConfig>(), 0);\n                }\n\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n            throw new KernelException(\"Can't inject bean \" + beanConfig + \" to dependend beans.\", e);\n        }\n    }\n\n    public boolean isBeanClassRegistered(final String beanName) {\n        boolean x = dependencyManager.isBeanClassRegistered(beanName);\n        if (x == false && parent != null) {\n            x = parent.isBeanClassRegistered(beanName);\n        }\n        return x;\n    }\n\n    public void ln(String exportingBeanName, Kernel destinationKernel, String destinationName) {\n        final BeanConfig sbc = dependencyManager.getBeanConfig(exportingBeanName);\n        // Object bean = getInstance(sbc.getBeanName());\n\n        BeanConfig dbc = new DelegatedBeanConfig(destinationName, sbc);\n\n        destinationKernel.dependencyManager.register(dbc);\n    }\n\n    void putBeanInstance(BeanConfig beanConfig, Object beanInstance) {\n        this.beanInstances.put(beanConfig, beanInstance);\n        if (beanInstance instanceof Kernel && beanInstance != this) {\n            ((Kernel) beanInstance).setParent(this);\n        }\n        beanConfig.setState(State.initialized);\n    }\n\n    public BeanConfigBuilder registerBean(Class<?> beanClass) {\n        if (currentlyUsedConfigBuilder != null)\n            throw new KernelException(\"Registration of bean '\" + currentlyUsedConfigBuilder.getBeanName()\n                    + \"' is not finished yet!\");\n\n        Bean annotation = beanClass.getAnnotation(Bean.class);\n        if (annotation == null || annotation.name() == null || annotation.name().isEmpty())\n            throw new KernelException(\"Name of bean is not defined.\");\n\n        BeanConfigBuilder builder = new BeanConfigBuilder(this, dependencyManager, annotation.name());\n        this.currentlyUsedConfigBuilder = builder;\n        builder.asClass(beanClass);\n        return builder;\n    }\n\n    public BeanConfigBuilder registerBean(String beanName) {\n        if (currentlyUsedConfigBuilder != null)\n            throw new KernelException(\"Registration of bean '\" + currentlyUsedConfigBuilder.getBeanName()\n                    + \"' is not finished yet!\");\n        BeanConfigBuilder builder = new BeanConfigBuilder(this, dependencyManager, beanName);\n        this.currentlyUsedConfigBuilder = builder;\n        return builder;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    void setParent(Kernel parent) {\n        this.dependencyManager.setParent(parent.getDependencyManager());\n        this.parent = parent;\n    }\n\n    public void startSubKernels() {\n        for (BeanConfig bc : dependencyManager.getBeanConfigs(Registrar.class)) {\n            Registrar r = getInstance(bc.getBeanName());\n            Kernel k = getInstance(bc.getBeanName() + \"#KERNEL\");\n            r.start(k);\n            k.startSubKernels();\n        }\n\n    }\n\n    public void unregister(final String beanName) {\n        if (log.isLoggable(Level.FINER))\n            log.finer(\"[\" + getName() + \"] Unregistering bean \" + beanName);\n        BeanConfig unregisteredBeanConfig = dependencyManager.getBeanConfig(beanName);\n        if (unregisteredBeanConfig.getKernel() != this) {\n            unregisteredBeanConfig.getKernel().unregister(beanName);\n            return;\n        }\n\n        unregisterInt(beanName);\n        try {\n            for (BeanConfig bc : dependencyManager.getBeanConfigs()) {\n                if (bc.getState() != State.initialized)\n                    continue;\n                Object ob = bc.getKernel().getInstance(bc);\n                for (Dependency d : bc.getFieldDependencies().values()) {\n                    if (DependencyManager.match(d, unregisteredBeanConfig)) {\n                        BeanConfig[] cbcs = dependencyManager.getBeanConfig(d);\n                        if (cbcs.length == 1) {// Clearing single-instance\n                            // dependency. Like single field.\n                            // BeanConfig cbc = cbcs[0];\n                            // if (cbc != null && cbc.equals(removingBC)) {\n                            inject(null, d, ob);\n                            // }\n                        } else if (cbcs.length > 1) { // Clearing multi-instance\n                            // dependiency. Like\n                            // collections and arrays.\n\n                            injectDependencies(ob, d, new HashSet<BeanConfig>(), 0);\n                        }\n                    }\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n            throw new KernelException(\"Can't unregister bean\", e);\n        } finally {\n            dependencyManager.unregister(beanName);\n        }\n    }\n\n    void unregisterInt(String beanName) {\n        if (dependencyManager.isBeanClassRegistered(beanName)) {\n            // unregistering\n            if (log.isLoggable(Level.FINER))\n                log.finer(\"[\" + getName() + \"] Found registred bean \" + beanName + \". Unregistering...\");\n\n            BeanConfig oldBeanConfig = dependencyManager.unregister(beanName);\n            Object i = oldBeanConfig.getKernel().beanInstances.remove(oldBeanConfig);\n            if (i != null && i instanceof UnregisterAware) {\n                try {\n                    ((UnregisterAware) i).beforeUnregister();\n                } catch (Exception e) {\n                    e.printStackTrace();\n                    log.log(Level.WARNING, \"Problem during unregistering bean\", e);\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/kernel/core/RegistrarKernel.java",
    "content": "package tigase.kernel.core;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Set;\n\nimport tigase.kernel.Registrar;\n\npublic class RegistrarKernel extends Kernel {\n\n\tprivate Class<? extends Registrar> registrarClass;\n\n\t@Override\n\tprotected void initBean(BeanConfig beanConfig, Set<BeanConfig> createdBeansConfig, int deep) throws IllegalAccessException,\n\tIllegalArgumentException, InvocationTargetException, InstantiationException {\n\t\tsuper.initBean(beanConfig, createdBeansConfig, deep);\n\n\t}\n\n\tpublic void setRegistrar(Registrar registrar) {\n\t\tregistrar.register(this);\n\t\tregistrar.start(this);\n\n\t\tfor (BeanConfig rbc : getDependencyManager().getBeanConfigs(Registrar.class)) {\n\t\t\tRegistrar r = getInstance(rbc.getBeanName());\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/AdHocTask.java",
    "content": "package tigase.monitor;\n\nimport java.util.Collection;\n\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\npublic interface AdHocTask extends MonitorTask {\n\n\tCollection<Element> getAdHocCommands(JID toJID, JID senderJID);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/BeanConfigurator.java",
    "content": "package tigase.monitor;\n\nimport java.lang.reflect.Field;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.kernel.BeanUtils;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.core.DependencyManager;\nimport tigase.kernel.core.Kernel;\n\n@Bean(name = BeanConfigurator.NAME)\npublic class BeanConfigurator {\n\n\tpublic static final String NAME = \"bean-configurator\";\n\n\t@Inject\n\tprivate Kernel kernel;\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\tpublic void configureBeans(final Map<String, Object> props) {\n\t\tIterator<Entry<String, Object>> it = props.entrySet().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tEntry<String, Object> entry = it.next();\n\n\t\t\tif (!entry.getKey().contains(\"/\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tString[] tmp = entry.getKey().split(\"/\");\n\t\t\tif (!kernel.isBeanClassRegistered(tmp[0])) {\n\t\t\t\tlog.config(\"There is no bean '\" + tmp[0] + \"'.\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tfinal Object bean = kernel.getInstance(tmp[0]);\n\t\t\t\tBeanUtils.setValue(bean, tmp[1], entry.getValue());\n\t\t\t\tlog.config(\"Property has set: \" + tmp[0] + \".\" + tmp[1] + \"=\" + entry.getValue());\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.CONFIG, \"Cannot set property \" + tmp[1] + \" of bean \" + tmp[0], e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Field getField(String fieldName, Object bean) {\n\t\tField[] fields = DependencyManager.getAllFields(bean.getClass());\n\t\tfor (Field field : fields) {\n\t\t\tif (field.getName().equals(fieldName)) {\n\t\t\t\treturn field;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/ConfigurableTask.java",
    "content": "package tigase.monitor;\n\nimport tigase.form.Form;\n\npublic interface ConfigurableTask {\n\n\tForm getCurrentConfiguration();\n\n\tvoid setNewConfiguration(Form form);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/InfoTask.java",
    "content": "package tigase.monitor;\n\nimport tigase.form.Form;\n\npublic interface InfoTask {\n\n\tForm getTaskInfo();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/MonitorComponent.java",
    "content": "package tigase.monitor;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.logging.Level;\n\nimport javax.script.ScriptEngineManager;\n\nimport tigase.component.AbstractComponent;\nimport tigase.component.AbstractContext;\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.modules.Module;\nimport tigase.component.modules.impl.AdHocCommandModule;\nimport tigase.component.modules.impl.DiscoveryModule;\nimport tigase.component.modules.impl.JabberVersionModule;\nimport tigase.component.modules.impl.XmppPingModule;\nimport tigase.conf.ConfigurationException;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.core.Kernel;\nimport tigase.monitor.modules.AdHocCommandMonitorModule;\nimport tigase.monitor.modules.AddScriptTaskCommand;\nimport tigase.monitor.modules.AddTimerScriptTaskCommand;\nimport tigase.monitor.modules.DeleteScriptTaskCommand;\nimport tigase.monitor.modules.DiscoveryMonitorModule;\nimport tigase.server.monitor.MonitorRuntime;\nimport tigase.util.ClassUtil;\nimport tigase.util.TimerTask;\n\npublic class MonitorComponent extends AbstractComponent<MonitorContext> {\n\n\tprivate class MonitorContextImpl extends AbstractContext implements MonitorContext {\n\n\t\tpublic MonitorContextImpl(AbstractComponent<?> component) {\n\t\t\tsuper(component);\n\t\t}\n\n\t\t@Override\n\t\tpublic Kernel getKernel() {\n\t\t\treturn kernel;\n\t\t}\n\t}\n\n\tpublic static final String EVENTS_XMLNS = \"tigase:monitor:event\";\n\n\tprivate Kernel kernel = new Kernel();\n\n\tprivate final TimerTaskService timerTaskService = new TimerTaskService() {\n\n\t\t@Override\n\t\tpublic void addTimerTask(TimerTask task, long delay) {\n\t\t\tMonitorComponent.this.addTimerTask(task, delay);\n\t\t}\n\n\t\t@Override\n\t\tpublic void addTimerTask(TimerTask task, long initialDelay, long period) {\n\t\t\tMonitorComponent.this.addTimerTask(task, initialDelay, period);\n\t\t}\n\t};\n\n\t@Override\n\tprotected MonitorContext createContext() {\n\t\treturn new MonitorContextImpl(this);\n\t}\n\n\t@Override\n\tpublic String getComponentVersion() {\n\t\tString version = this.getClass().getPackage().getImplementationVersion();\n\t\treturn version == null ? \"0.0.0\" : version;\n\t}\n\n\t@Override\n\tprotected Map<String, Class<? extends Module>> getDefaultModulesList() {\n\t\tfinal Map<String, Class<? extends Module>> result = new HashMap<String, Class<? extends Module>>();\n\n\t\tresult.put(XmppPingModule.ID, XmppPingModule.class);\n\t\tresult.put(JabberVersionModule.ID, JabberVersionModule.class);\n\t\tresult.put(AdHocCommandModule.ID, AdHocCommandMonitorModule.class);\n\t\tresult.put(DiscoveryModule.ID, DiscoveryMonitorModule.class);\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategory() {\n\t\treturn \"component\";\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"monitor\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Monitor Component\";\n\t}\n\n\t@Override\n\tpublic boolean isDiscoNonAdmin() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.size() <= 1)\n\t\t\treturn;\n\t\tsuper.setProperties(props);\n\n\t\tkernel.registerBean(\"eventBus\").asInstance(context.getEventBus()).exec();\n\n\t\tkernel.registerBean(BeanConfigurator.class).exec();\n\n\t\tkernel.registerBean(TasksScriptRegistrar.ID).asClass(TasksScriptRegistrar.class).exec();\n\n\t\tScriptEngineManager scriptEngineManager = new ScriptEngineManager();\n\t\tkernel.registerBean(\"scriptEngineManager\").asInstance(scriptEngineManager).exec();\n\n\t\tkernel.registerBean(\"bindings\").asInstance(scriptEngineManager.getBindings()).exec();\n\t\tkernel.registerBean(\"context\").asInstance(getContext()).exec();\n\t\tkernel.registerBean(\"monitorComponent\").asInstance(this).exec();\n\t\tkernel.registerBean(\"timerTaskService\").asInstance(timerTaskService).exec();\n\t\tkernel.registerBean(\"runtime\").asInstance(MonitorRuntime.getMonitorRuntime()).exec();\n\t\tkernel.registerBean(\"kernel\").asInstance(kernel).exec();\n\n\t\tAdHocCommand ahc;\n\n\t\tString repoClass = TaskConfigItemJDBCRepository.class.getName();\n\n\t\ttry {\n\t\t\tComponentRepository<TaskConfigItem> repo_tmp = (ComponentRepository<TaskConfigItem>) Class.forName(repoClass).newInstance();\n\n\t\t\trepo_tmp.setProperties(props);\n\t\t\tlog.log(Level.WARNING, \"Monitoring Tasks: {0} with items: {1}\", new Object[] {repo_tmp, repo_tmp.toString()});\n\t\t\trepo_tmp.reload();\n\n\t\t\tkernel.registerBean(\"tasksRepo\").asInstance(repo_tmp).exec();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not create T repository instance for class: \" + repoClass, e);\n\t\t}\n\n\t\tahc = new AddScriptTaskCommand(context);\n\t\t((AdHocCommandMonitorModule) getModuleProvider().getModule(AdHocCommandModule.ID)).register(ahc);\n\t\tkernel.registerBean(ahc.getName()).asInstance(ahc).exec();\n\t\tahc = new AddTimerScriptTaskCommand(context);\n\t\t((AdHocCommandMonitorModule) getModuleProvider().getModule(AdHocCommandModule.ID)).register(ahc);\n\t\tkernel.registerBean(ahc.getName()).asInstance(ahc).exec();\n\t\tahc = new DeleteScriptTaskCommand(context);\n\t\t((AdHocCommandMonitorModule) getModuleProvider().getModule(AdHocCommandModule.ID)).register(ahc);\n\t\tkernel.registerBean(ahc.getName()).asInstance(ahc).exec();\n\n\t\ttry {\n\t\t\tSet<Class<MonitorTask>> classes = ClassUtil.getClassesImplementing(MonitorTask.class);\n\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\tlog.finer(\"Found monitor tasks classes: \" + classes.toString());\n\n\t\t\tfor (Class<MonitorTask> class1 : classes) {\n\t\t\t\tif (class1.getAnnotation(Bean.class) != null)\n\t\t\t\t\tkernel.registerBean(class1).exec();\n\t\t\t}\n\t\t} catch (ClassNotFoundException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\n\t\ttry {\n\t\t\tSet<Class<MonitorExtension>> classes = ClassUtil.getClassesImplementing(MonitorExtension.class);\n\t\t\tif (log.isLoggable(Level.FINER))\n\t\t\t\tlog.finer(\"Found monitor ext classes: \" + classes.toString());\n\n\t\t\tfor (Class<MonitorExtension> class1 : classes) {\n\t\t\t\tif (class1.getAnnotation(Bean.class) != null)\n\t\t\t\t\tkernel.registerBean(class1).exec();\n\t\t\t}\n\t\t} catch (ClassNotFoundException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\n\t\tif (kernel.isBeanClassRegistered(\"monitor-mailer\")) {\n\t\t\tObject mailerExt = kernel.getInstance(\"monitor-mailer\");\n\t\t\tif (mailerExt instanceof MonitorExtension) {\n\t\t\t\t((MonitorExtension) mailerExt).setProperties(props);\n\t\t\t}\n\t\t}\n\n\t\t// initialization\n\t\t((TasksScriptRegistrar) kernel.getInstance(TasksScriptRegistrar.ID)).load();\n\n\t\t((BeanConfigurator) kernel.getInstance(BeanConfigurator.NAME)).configureBeans(props);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/MonitorContext.java",
    "content": "package tigase.monitor;\n\nimport tigase.component.Context;\nimport tigase.kernel.core.Kernel;\n\npublic interface MonitorContext extends Context {\n\n\tKernel getKernel();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/MonitorExtension.java",
    "content": "package tigase.monitor;\n\nimport java.util.Map;\n\npublic interface MonitorExtension {\n\n\tvoid setProperties(Map<String, Object> props);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/MonitorTask.java",
    "content": "package tigase.monitor;\n\npublic interface MonitorTask {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/TaskConfigItem.java",
    "content": "package tigase.monitor;\n\nimport tigase.db.comp.RepositoryItemAbstract;\nimport tigase.form.Form;\nimport tigase.util.Base64;\nimport tigase.xml.Element;\n\npublic class TaskConfigItem extends RepositoryItemAbstract implements Comparable<TaskConfigItem> {\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"taskName=\" + taskName\n\t\t\t\t\t + \", taskClass=\" + taskClass\n\t\t\t\t\t + \", type=\" + type\n\t\t\t\t\t + \", configuration=\" + configuration;\n\t}\n\n\tpublic static enum Type {\n\t\tscriptTask,\n\t\tscriptTimerTask,\n\t\t/**\n\t\t * Default task, built with standard java class.\n\t\t */\n\t\ttask\n\t}\n\n\tpublic static final String CLASS_ELEM = \"class\";\n\n\tpublic static final String ELEM_NAME = \"monitor-task\";\n\n\tpublic static final String SCRIPT_ELEM = \"script\";\n\n\tpublic static final String SCRIPT_EXT_ATT = \"scriptExtension\";\n\n\tpublic static final String TASK_CLASS_ATT = \"taskClass\";\n\n\tprotected static final String[] TASK_CLASS_PATH = { ELEM_NAME, CLASS_ELEM };\n\n\tpublic static final String TASK_NAME_ATT = \"taskName\";\n\n\tprotected static final String[] TASK_SCRIPT_PATH = { ELEM_NAME, SCRIPT_ELEM };\n\n\tpublic static final String TASK_TYPE_ATT = \"type\";\n\n\tprivate Form configuration;\n\n\tprivate String scriptExtension;\n\n\tprivate Class<? extends MonitorTask> taskClass;\n\n\tprivate String taskName;\n\n\tprivate String taskScript;\n\n\tprivate Type type;\n\n\tpublic TaskConfigItem() {\n\t}\n\n\tpublic TaskConfigItem(String taskName, Class<? extends MonitorTask> taskClass) {\n\t\tthis.taskName = taskName;\n\t\tthis.taskClass = taskClass;\n\t\tthis.type = Type.task;\n\t}\n\n\t@Override\n\tpublic int compareTo(TaskConfigItem o) {\n\t\treturn taskName.compareTo(o.taskName);\n\t}\n\n\tpublic Form getConfiguration() {\n\t\treturn configuration;\n\t}\n\n\t@Override\n\tpublic String getElemName() {\n\t\treturn ELEM_NAME;\n\t}\n\n\t@Override\n\tpublic String getKey() {\n\t\treturn taskName;\n\t}\n\n\tpublic String getScriptExtension() {\n\t\treturn scriptExtension;\n\t}\n\n\tpublic Class<? extends MonitorTask> getTaskClass() {\n\t\treturn taskClass;\n\t}\n\n\tpublic String getTaskName() {\n\t\treturn taskName;\n\t}\n\n\tpublic String getTaskScript() {\n\t\treturn taskScript;\n\t}\n\n\tpublic Type getType() {\n\t\treturn type;\n\t}\n\n\t@Override\n\tpublic void initFromElement(Element elem) {\n\t\tif (elem.getName() != ELEM_NAME) {\n\t\t\tthrow new IllegalArgumentException(\"Incorrect element name, expected: \" + ELEM_NAME);\n\t\t}\n\t\tsuper.initFromElement(elem);\n\n\t\tthis.taskName = elem.getAttributeStaticStr(TASK_NAME_ATT);\n\t\ttry {\n\t\t\tthis.type = Type.valueOf(elem.getAttributeStaticStr(TASK_TYPE_ATT));\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tthis.scriptExtension = elem.getAttributeStaticStr(SCRIPT_EXT_ATT);\n\n\t\tsetTaskClass(elem.getAttributeStaticStr(TASK_CLASS_ATT));\n\t\tsetTaskScriptEncoded(elem.getCDataStaticStr(TASK_SCRIPT_PATH));\n\n\t\tElement form = elem.getChild(\"x\", \"jabber:x:data\");\n\t\tif (form != null) {\n\t\t\tthis.configuration = new Form(form);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initFromPropertyString(String propString) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\tpublic void setConfiguration(Form configuration) {\n\t\tthis.configuration = configuration;\n\t}\n\n\tpublic void setScriptExtension(String scriptExtension) {\n\t\tthis.scriptExtension = scriptExtension;\n\t}\n\n\tpublic void setTaskClass(Class<? extends MonitorTask> taskClass) {\n\t\tthis.taskClass = taskClass;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void setTaskClass(String tmp) {\n\t\tif (tmp == null)\n\t\t\treturn;\n\t\ttry {\n\t\t\tthis.taskClass = (Class<? extends MonitorTask>) Class.forName(tmp);\n\t\t} catch (ClassNotFoundException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic void setTaskName(String taskName) {\n\t\tthis.taskName = taskName;\n\t}\n\n\tpublic void setTaskScript(String taskScript) {\n\t\tthis.taskScript = taskScript;\n\t}\n\n\tprivate void setTaskScriptEncoded(String tmp) {\n\t\tif (tmp == null)\n\t\t\treturn;\n\t\tthis.taskScript = new String(Base64.decode(tmp));\n\t}\n\n\tpublic void setType(Type type) {\n\t\tthis.type = type;\n\t}\n\n\t@Override\n\tpublic Element toElement() {\n\t\tfinal Element elem = super.toElement();\n\n\t\telem.addAttribute(TASK_NAME_ATT, this.taskName);\n\t\telem.addAttribute(TASK_TYPE_ATT, this.type.name());\n\n\t\tif (this.scriptExtension != null)\n\t\t\telem.addAttribute(SCRIPT_EXT_ATT, this.scriptExtension);\n\n\t\tif (this.taskScript != null)\n\t\t\telem.addChild(new Element(SCRIPT_ELEM, Base64.encode(this.taskScript.getBytes())));\n\n\t\tif (this.taskClass != null)\n\t\t\telem.addChild(new Element(CLASS_ELEM, this.taskClass.getName()));\n\n\t\tif (this.configuration != null) {\n\t\t\telem.addChild(this.configuration.getElement());\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\t@Override\n\tpublic String toPropertyString() {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/TaskConfigItemJDBCRepository.java",
    "content": "package tigase.monitor;\n\nimport java.util.Map;\n\nimport tigase.db.DBInitException;\nimport tigase.db.comp.UserRepoRepository;\nimport tigase.xmpp.BareJID;\n\npublic class TaskConfigItemJDBCRepository extends UserRepoRepository<TaskConfigItem> {\n\n\tprivate final static String CONFIG_KEY = \"monitor-tasks\";\n\n\tprivate final static BareJID REPO_USER_JID = BareJID.bareJIDInstanceNS(\"tigase-monitor\");\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do\n\t}\n\n\t@Override\n\tpublic String getConfigKey() {\n\t\treturn CONFIG_KEY;\n\t}\n\n\t@Override\n\tpublic String[] getDefaultPropetyItems() {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic TaskConfigItem getItemInstance() {\n\t\treturn new TaskConfigItem();\n\t}\n\n\t@Override\n\tpublic String getPropertyKey() {\n\t\treturn \"--monitor-tasks\";\n\t}\n\n\t@Override\n\tpublic BareJID getRepoUser() {\n\t\treturn REPO_USER_JID;\n\t}\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/TasksScriptRegistrar.java",
    "content": "package tigase.monitor;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.ScriptException;\n\nimport tigase.db.TigaseDBException;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.db.comp.RepositoryChangeListenerIfc;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.core.Kernel;\nimport tigase.monitor.TaskConfigItem.Type;\nimport tigase.monitor.tasks.ScriptTask;\nimport tigase.monitor.tasks.ScriptTimerTask;\n\npublic class TasksScriptRegistrar {\n\n\tpublic static final String ID = \"TasksScriptRegistrar\";\n\n\t@Inject\n\tprivate Kernel kernel;\n\n\tprotected final Logger log = Logger.getLogger(this.getClass().getName());\n\n\t@Inject\n\tprivate ComponentRepository<TaskConfigItem> repo;\n\n\tpublic void delete(String taskName) {\n\t\ttry {\n\t\t\trepo.removeItem(taskName);\n\t\t} catch (TigaseDBException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic Kernel getKernel() {\n\t\treturn kernel;\n\t}\n\n\tpublic ComponentRepository<TaskConfigItem> getRepo() {\n\t\treturn repo;\n\t}\n\n\tprivate void initTaskFromTaskConfig(final TaskConfigItem item) throws ScriptException, TigaseDBException {\n\t\tType type;\n\t\ttry {\n\t\t\ttype = item.getType();\n\t\t\tif (type == null) {\n\t\t\t\trepo.removeItem(item.getKey());\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\trepo.removeItem(item.getKey());\n\t\t\treturn;\n\t\t}\n\t\tString taskName = item.getTaskName();\n\t\tString scriptExtension = item.getScriptExtension();\n\t\tString scriptContent = item.getTaskScript();\n\n\t\tswitch (type) {\n\t\tcase task:\n\t\t\tif (kernel.isBeanClassRegistered(item.getTaskName())) {\n\t\t\t\tMonitorTask task = kernel.getInstance(item.getTaskName());\n\t\t\t\tif (task instanceof ConfigurableTask) {\n\t\t\t\t\t((ConfigurableTask) task).setNewConfiguration(item.getConfiguration());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trepo.removeItem(item.getKey());\n\t\t\t}\n\t\t\tbreak;\n\t\tcase scriptTask:\n\t\t\trunScriptTask(taskName, scriptExtension, scriptContent, item.getConfiguration());\n\t\tcase scriptTimerTask:\n\t\t\trunScriptTimerTask(taskName, scriptExtension, scriptContent, item.getConfiguration());\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\tpublic void load() {\n\t\ttry {\n\t\t\tfor (TaskConfigItem item : repo.allItems()) {\n\t\t\t\tinitTaskFromTaskConfig(item);\n\t\t\t}\n\t\t} catch (TigaseDBException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (ScriptException e) {\n\t\t\te.printStackTrace();\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\n\t}\n\n\tpublic void registerScript(String scriptName, String scriptExtension, String scriptContent) throws ScriptException {\n\t\tScriptTask task = runScriptTask(scriptName, scriptExtension, scriptContent);\n\t\tsaveScript(Type.scriptTask, scriptName, scriptExtension, scriptContent, task.getCurrentConfiguration());\n\t}\n\n\tpublic void registerTimerScript(String scriptName, String scriptExtension, String scriptContent, Long delay)\n\t\t\tthrows ScriptException {\n\t\tScriptTimerTask task = runScriptTimerTask(scriptName, scriptExtension, scriptContent, delay);\n\t\tsaveScript(Type.scriptTimerTask, scriptName, scriptExtension, scriptContent, task.getCurrentConfiguration());\n\t}\n\n\tprivate ScriptTask runScriptTask(String scriptName, String scriptExtension, String scriptContent) throws ScriptException {\n\t\tkernel.registerBean(scriptName).asClass(ScriptTask.class).exec();\n\t\tScriptTask scriptTask = kernel.getInstance(scriptName);\n\t\tscriptTask.setScript(scriptContent, scriptExtension);\n\t\tscriptTask.setEnabled(true);\n\t\treturn scriptTask;\n\t}\n\n\tprivate ScriptTask runScriptTask(String scriptName, String scriptExtension, String scriptContent, Form config)\n\t\t\tthrows ScriptException {\n\t\tkernel.registerBean(scriptName).asClass(ScriptTask.class).exec();\n\t\tScriptTask scriptTask = kernel.getInstance(scriptName);\n\t\tscriptTask.setScript(scriptContent, scriptExtension);\n\t\tscriptTask.setNewConfiguration(config);\n\t\treturn scriptTask;\n\t}\n\n\tprivate ScriptTimerTask runScriptTimerTask(String scriptName, String scriptExtension, String scriptContent, Form config)\n\t\t\tthrows ScriptException {\n\t\tkernel.registerBean(scriptName).asClass(ScriptTimerTask.class).exec();\n\t\tScriptTimerTask scriptTask = kernel.getInstance(scriptName);\n\t\tscriptTask.setScript(scriptContent, scriptExtension);\n\t\tscriptTask.setNewConfiguration(config);\n\t\treturn scriptTask;\n\t}\n\n\tprivate ScriptTimerTask runScriptTimerTask(String scriptName, String scriptExtension, String scriptContent, Long delay)\n\t\t\tthrows ScriptException {\n\t\tkernel.registerBean(scriptName).asClass(ScriptTimerTask.class).exec();\n\t\tScriptTimerTask scriptTask = kernel.getInstance(scriptName);\n\t\tscriptTask.setScript(scriptContent, scriptExtension);\n\t\tscriptTask.setPeriod(delay);\n\t\tscriptTask.setEnabled(true);\n\t\treturn scriptTask;\n\t}\n\n\tprivate void saveScript(Type type, String scriptName, String scriptExtension, String scriptContent, Form configuration) {\n\t\tTaskConfigItem item = new TaskConfigItem();\n\t\titem.setTaskName(scriptName);\n\t\titem.setConfiguration(configuration);\n\t\titem.setScriptExtension(scriptExtension);\n\t\titem.setTaskScript(scriptContent);\n\t\titem.setType(type);\n\n\t\ttry {\n\t\t\trepo.addItem(item);\n\t\t} catch (TigaseDBException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\n\t}\n\n\tpublic void setKernel(Kernel kernel) {\n\t\tthis.kernel = kernel;\n\t}\n\n\tpublic void setRepo(ComponentRepository<TaskConfigItem> repo) {\n\t\tthis.repo = repo;\n\t\tthis.repo.addRepoChangeListener(new RepositoryChangeListenerIfc<TaskConfigItem>() {\n\n\t\t\t@Override\n\t\t\tpublic void itemAdded(TaskConfigItem item) {\n\t\t\t\tif (!kernel.isBeanClassRegistered(item.getTaskName())) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinitTaskFromTaskConfig(item);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem during initializing task\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void itemRemoved(TaskConfigItem item) {\n\t\t\t\ttry {\n\t\t\t\t\tkernel.unregister(item.getTaskName());\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Problem during unregistering task\", e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void itemUpdated(TaskConfigItem item) {\n\t\t\t\ttry {\n\t\t\t\t\tMonitorTask task = kernel.getInstance(item.getTaskName());\n\t\t\t\t\tif (task instanceof ConfigurableTask) {\n\t\t\t\t\t\t((ConfigurableTask) task).setNewConfiguration(item.getConfiguration());\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Problem during configuring task\", e);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void updateConfig(String taskName, Form form) {\n\t\tMonitorTask task = kernel.getInstance(taskName);\n\n\t\tTaskConfigItem item = repo.getItem(taskName);\n\t\tif (item == null) {\n\t\t\titem = new TaskConfigItem();\n\t\t\titem.setTaskName(taskName);\n\t\t\tif (task instanceof ScriptTimerTask) {\n\t\t\t\titem.setType(Type.scriptTimerTask);\n\t\t\t\titem.setScriptExtension(((ScriptTimerTask) task).getScriptExtension());\n\t\t\t\titem.setTaskScript(((ScriptTimerTask) task).getScript());\n\t\t\t} else if (task instanceof ScriptTask) {\n\t\t\t\titem.setType(Type.scriptTask);\n\t\t\t\titem.setScriptExtension(((ScriptTask) task).getScriptExtension());\n\t\t\t\titem.setTaskScript(((ScriptTask) task).getScript());\n\t\t\t} else {\n\t\t\t\titem.setType(Type.task);\n\t\t\t\titem.setTaskClass(task.getClass());\n\t\t\t}\n\t\t}\n\t\titem.setConfiguration(form);\n\n\t\ttry {\n\t\t\trepo.addItem(item);\n\t\t} catch (TigaseDBException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/TimerTaskService.java",
    "content": "package tigase.monitor;\n\npublic interface TimerTaskService {\n\n\tvoid addTimerTask(tigase.util.TimerTask task, long delay);\n\n\tvoid addTimerTask(tigase.util.TimerTask task, long initialDelay, long period);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/AdHocCommandMonitorModule.java",
    "content": "package tigase.monitor.modules;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocCommandManager;\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.modules.impl.AdHocCommandModule;\nimport tigase.monitor.MonitorContext;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class AdHocCommandMonitorModule extends AdHocCommandModule<MonitorContext> {\n\n\tprivate ConfigureTaskCommand configCommand;\n\n\tprivate final AdHocCommandManager customCommandsManager = new AdHocCommandManager();\n\n\tprivate InfoTaskCommand infoCommand;\n\n\tpublic AdHocCommandMonitorModule(ScriptCommandProcessor scriptProcessor) {\n\t\tsuper(scriptProcessor);\n\t}\n\n\t@Override\n\tpublic void afterRegistration() {\n\t\tsuper.afterRegistration();\n\t\tthis.infoCommand = new InfoTaskCommand(context);\n\t\tthis.configCommand = new ConfigureTaskCommand(context);\n\t}\n\n\tprivate AdHocCommand getCommand(final Object taskInstance, final String node) {\n\t\tif (node.equals(InfoTaskCommand.NODE)) {\n\t\t\treturn infoCommand;\n\t\t} else if (node.equals(ConfigureTaskCommand.NODE)) {\n\t\t\treturn configCommand;\n\t\t} else\n\t\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet) throws ComponentException {\n\t\tfinal JID jid = packet.getStanzaTo();\n\n\t\tfinal Object taskInstance = jid.getResource() != null ? context.getKernel().getInstance(jid.getResource()) : null;\n\n\t\tif (jid.getResource() != null && taskInstance != null) {\n\t\t\tprocessCommand(packet, taskInstance);\n\t\t} else if (jid.getResource() != null) {\n\t\t\tthrow new ComponentException(Authorization.ITEM_NOT_FOUND);\n\t\t} else if (jid.getResource() == null) {\n\t\t\tsuper.process(packet);\n\t\t} else {\n\t\t\tthrow new ComponentException(Authorization.NOT_ACCEPTABLE);\n\t\t}\n\t}\n\n\tprivate void processCommand(Packet packet, Object taskInstance) throws ComponentException {\n\t\tfinal Element element = packet.getElement();\n\t\tfinal JID senderJid = packet.getStanzaFrom();\n\t\tfinal Element command = element.getChild(Command.COMMAND_EL, Command.XMLNS);\n\t\tfinal String node = command.getAttributeStaticStr(\"node\");\n\t\tfinal String action = command.getAttributeStaticStr(\"action\");\n\t\tfinal String sessionId = command.getAttributeStaticStr(\"sessionid\");\n\n\t\tAdHocCommand adHocCommand = getCommand(taskInstance, node);\n\n\t\ttry {\n\t\t\twrite(customCommandsManager.process(packet, command, node, action, sessionId, adHocCommand));\n\t\t} catch (AdHocCommandException e) {\n\t\t\tthrow new ComponentException(e.getErrorCondition(), e.getMessage());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/AddScriptTaskCommand.java",
    "content": "package tigase.monitor.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.monitor.MonitorContext;\nimport tigase.monitor.TasksScriptRegistrar;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class AddScriptTaskCommand implements AdHocCommand {\n\n\tprivate MonitorContext monitorContext;\n\n\tpublic AddScriptTaskCommand(MonitorContext monitorContext) {\n\t\tthis.monitorContext = monitorContext;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tForm form = new Form(\"form\", \"Add monitor script\", null);\n\n\t\t\t\tList<ScriptEngineFactory> sef = monitorContext.getKernel().getInstance(\n\t\t\t\t\t\tScriptEngineManager.class).getEngineFactories();\n\t\t\t\tArrayList<String> labels = new ArrayList<String>();\n\t\t\t\tArrayList<String> values = new ArrayList<String>();\n\t\t\t\tfor (ScriptEngineFactory scriptEngineFactory : sef) {\n\t\t\t\t\tlabels.add(scriptEngineFactory.getLanguageName());\n\t\t\t\t\tvalues.add(scriptEngineFactory.getExtensions().get(0));\n\t\t\t\t}\n\n\t\t\t\tform.addField(Field.fieldTextSingle(\"scriptName\", \"\", \"Script name\"));\n\t\t\t\tform.addField(Field.fieldListSingle(\"scriptExtension\", \"\", \"Script engine\", labels.toArray(new String[] {}),\n\t\t\t\t\t\tvalues.toArray(new String[] {})));\n\t\t\t\tform.addField(Field.fieldTextMulti(\"scriptContent\", \"\", \"Script\"));\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tString scriptName = form.getAsString(\"scriptName\");\n\t\t\t\t\tString scriptExtension = form.getAsString(\"scriptExtension\");\n\t\t\t\t\tString scriptContent = form.getAsString(\"scriptContent\");\n\n\t\t\t\t\t((TasksScriptRegistrar) monitorContext.getKernel().getInstance(TasksScriptRegistrar.ID)).registerScript(\n\t\t\t\t\t\t\tscriptName, scriptExtension, scriptContent);\n\n\t\t\t\t}\n\t\t\t\tform = new Form(\"form\", \"Completed\", null);\n\t\t\t\tform.addField(Field.fieldFixed(\"Script added.\"));\n\t\t\t\tresponse.getElements().add(form.getElement());\n\n\t\t\t\tresponse.completeSession();\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Add monitor task\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn \"x-add-task\";\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/AddTimerScriptTaskCommand.java",
    "content": "package tigase.monitor.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.monitor.MonitorContext;\nimport tigase.monitor.TasksScriptRegistrar;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class AddTimerScriptTaskCommand implements AdHocCommand {\n\n\tprivate MonitorContext monitorContext;\n\n\tpublic AddTimerScriptTaskCommand(MonitorContext monitorContext) {\n\t\tthis.monitorContext = monitorContext;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tForm form = new Form(\"form\", \"Add monitor script\", null);\n\n\t\t\t\tList<ScriptEngineFactory> sef = monitorContext.getKernel().getInstance(\n\t\t\t\t\t\tScriptEngineManager.class).getEngineFactories();\n\t\t\t\tArrayList<String> labels = new ArrayList<String>();\n\t\t\t\tArrayList<String> values = new ArrayList<String>();\n\t\t\t\tfor (ScriptEngineFactory scriptEngineFactory : sef) {\n\t\t\t\t\tlabels.add(scriptEngineFactory.getLanguageName());\n\t\t\t\t\tvalues.add(scriptEngineFactory.getExtensions().get(0));\n\t\t\t\t}\n\n\t\t\t\tform.addField(Field.fieldTextSingle(\"scriptName\", \"\", \"Script name\"));\n\t\t\t\tform.addField(Field.fieldTextSingle(\"delay\", \"1000\", \"Delay\"));\n\t\t\t\tform.addField(Field.fieldListSingle(\"scriptExtension\", \"\", \"Script engine\", labels.toArray(new String[] {}),\n\t\t\t\t\t\tvalues.toArray(new String[] {})));\n\t\t\t\tform.addField(Field.fieldTextMulti(\"scriptContent\", \"\", \"Script\"));\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tString scriptName = form.getAsString(\"scriptName\");\n\t\t\t\t\tString scriptExtension = form.getAsString(\"scriptExtension\");\n\t\t\t\t\tString scriptContent = form.getAsString(\"scriptContent\");\n\t\t\t\t\tLong delay = form.getAsLong(\"delay\");\n\n\t\t\t\t\t((TasksScriptRegistrar) monitorContext.getKernel().getInstance(\n\t\t\t\t\t\t\tTasksScriptRegistrar.ID)).registerTimerScript(scriptName, scriptExtension, scriptContent, delay);\n\t\t\t\t}\n\n\t\t\t\tform = new Form(\"form\", \"Completed\", null);\n\t\t\t\tform.addField(Field.fieldFixed(\"Script added.\"));\n\t\t\t\tresponse.getElements().add(form.getElement());\n\n\t\t\t\tresponse.completeSession();\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Add monitor timer task\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn \"x-add-timer-task\";\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/ConfigureTaskCommand.java",
    "content": "package tigase.monitor.modules;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.monitor.ConfigurableTask;\nimport tigase.monitor.MonitorContext;\nimport tigase.monitor.TasksScriptRegistrar;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class ConfigureTaskCommand implements AdHocCommand {\n\n\tpublic static final String NODE = \"x-config\";\n\n\tprivate MonitorContext ctx;\n\n\tprivate TasksScriptRegistrar registrar;\n\n\tpublic ConfigureTaskCommand(MonitorContext ctx) {\n\t\tthis.ctx = ctx;\n\t\tthis.registrar = ctx.getKernel().getInstance(TasksScriptRegistrar.ID);\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tfinal ConfigurableTask taskInstance = ctx.getKernel().getInstance(request.getIq().getStanzaTo().getResource());\n\t\t\t\tForm form = taskInstance.getCurrentConfiguration();\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tfinal ConfigurableTask taskInstance = ctx.getKernel().getInstance(\n\t\t\t\t\t\t\trequest.getIq().getStanzaTo().getResource());\n\n\t\t\t\t\tregistrar.updateConfig(request.getIq().getStanzaTo().getResource(), form);\n\n\t\t\t\t\tform = new Form(\"form\", \"Completed\", null);\n\t\t\t\t\tform.addField(Field.fieldFixed(\"Script configured\"));\n\t\t\t\t\tresponse.getElements().add(form.getElement());\n\n\t\t\t\t\tresponse.completeSession();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Task config\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn NODE;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/DeleteScriptTaskCommand.java",
    "content": "package tigase.monitor.modules;\n\nimport java.util.Collection;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.monitor.MonitorContext;\nimport tigase.monitor.MonitorTask;\nimport tigase.monitor.TasksScriptRegistrar;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class DeleteScriptTaskCommand implements AdHocCommand {\n\n\tprivate MonitorContext monitorContext;\n\n\tpublic DeleteScriptTaskCommand(MonitorContext monitorContext) {\n\t\tthis.monitorContext = monitorContext;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tfinal Element data = request.getCommand().getChild(\"x\", \"jabber:x:data\");\n\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else if (data == null) {\n\t\t\t\tForm form = new Form(\"form\", \"Delete monitor task\", null);\n\n\t\t\t\tCollection<String> taskNames = monitorContext.getKernel().getNamesOf(MonitorTask.class);\n\n\t\t\t\tform.addField(Field.fieldListSingle(\"delete_task\", \"\", \"Task to delete\", taskNames.toArray(new String[] {}),\n\t\t\t\t\t\ttaskNames.toArray(new String[] {})));\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t\tresponse.startSession();\n\t\t\t} else {\n\t\t\t\tForm form = new Form(data);\n\n\t\t\t\tif (\"submit\".equals(form.getType())) {\n\t\t\t\t\tString taskName = form.getAsString(\"delete_task\");\n\n\t\t\t\t\tObject i = monitorContext.getKernel().getInstance(taskName);\n\t\t\t\t\tif (i instanceof MonitorTask) {\n\t\t\t\t\t\t((TasksScriptRegistrar) monitorContext.getKernel().getInstance(TasksScriptRegistrar.ID)).delete(\n\t\t\t\t\t\t\t\ttaskName);\n\t\t\t\t\t} else\n\t\t\t\t\t\tthrow new RuntimeException(\"Are you kidding me?\");\n\t\t\t\t}\n\n\t\t\t\tform = new Form(\"form\", \"Completed\", null);\n\t\t\t\tform.addField(Field.fieldFixed(\"Script removed\"));\n\t\t\t\tresponse.getElements().add(form.getElement());\n\n\t\t\t\tresponse.completeSession();\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Delete monitor task\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn \"x-delete-task\";\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/DiscoveryMonitorModule.java",
    "content": "package tigase.monitor.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport tigase.component.exceptions.ComponentException;\nimport tigase.component.exceptions.RepositoryException;\nimport tigase.component.modules.impl.DiscoveryModule;\nimport tigase.monitor.AdHocTask;\nimport tigase.monitor.ConfigurableTask;\nimport tigase.monitor.InfoTask;\nimport tigase.monitor.MonitorContext;\nimport tigase.monitor.MonitorTask;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class DiscoveryMonitorModule extends DiscoveryModule<MonitorContext> {\n\n\tprivate boolean isAdHocCompatible(Object taskInstance) {\n\t\treturn taskInstance != null\n\t\t\t\t&& (taskInstance instanceof AdHocTask || taskInstance instanceof InfoTask || taskInstance instanceof ConfigurableTask);\n\t}\n\n\t@Override\n\tprotected void processAdHocCommandItems(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tif (jid.getResource() != null && isAdHocCompatible(context.getKernel().getInstance(jid.getResource()))) {\n\t\t\tfinal Object taskInstance = context.getKernel().getInstance(jid.getResource());\n\n\t\t\tList<Element> items = new ArrayList<Element>();\n\t\t\tElement resultQuery = new Element(\"query\", new String[] { Packet.XMLNS_ATT }, new String[] { DISCO_ITEMS_XMLNS });\n\t\t\tPacket result = packet.okResult(resultQuery, 0);\n\n\t\t\tif (taskInstance instanceof InfoTask) {\n\t\t\t\titems.add(new Element(\"item\", new String[] { \"jid\", \"node\", \"name\" }, new String[] { jid.toString(),\n\t\t\t\t\t\tInfoTaskCommand.NODE, \"Task Info\" }));\n\t\t\t}\n\t\t\tif (taskInstance instanceof ConfigurableTask) {\n\t\t\t\titems.add(new Element(\"item\", new String[] { \"jid\", \"node\", \"name\" }, new String[] { jid.toString(),\n\t\t\t\t\t\tConfigureTaskCommand.NODE, \"Task config\" }));\n\t\t\t}\n\n\t\t\tif (taskInstance instanceof AdHocTask) {\n\t\t\t\titems.addAll(((AdHocTask) taskInstance).getAdHocCommands(jid, senderJID));\n\t\t\t}\n\n\t\t\tresultQuery.addChildren(items);\n\t\t\twrite(result);\n\n\t\t} else if (jid.getResource() != null) {\n\t\t\tthrow new ComponentException(Authorization.ITEM_NOT_FOUND);\n\t\t} else\n\t\t\tsuper.processAdHocCommandItems(packet, jid, node, senderJID);\n\t}\n\n\t@Override\n\tprotected void processDiscoInfo(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tif (jid.getResource() == null) {\n\t\t\tsuper.processDiscoInfo(packet, jid, node, senderJID);\n\t\t} else if (jid.getResource() != null && context.getKernel().getInstance(jid.getResource()) != null) {\n\t\t\tfinal Object taskInstance = context.getKernel().getInstance(jid.getResource());\n\n\t\t\tElement resultQuery = new Element(\"query\", new String[] { \"xmlns\" }, new String[] { DISCO_INFO_XMLNS });\n\t\t\tPacket resultIq = packet.okResult(resultQuery, 0);\n\n\t\t\tresultQuery.addChild(new Element(\"identity\", new String[] { \"category\", \"type\", \"name\" }, new String[] {\n\t\t\t\t\t\"automation\", \"task\", \"Task \" + jid.getResource() }));\n\n\t\t\tif (isAdHocCompatible(taskInstance)) {\n\t\t\t\tresultQuery.addChild(new Element(\"feature\", new String[] { \"var\" }, new String[] { Command.XMLNS }));\n\t\t\t}\n\n\t\t\twrite(resultIq);\n\t\t} else\n\t\t\tthrow new ComponentException(Authorization.ITEM_NOT_FOUND);\n\n\t}\n\n\t@Override\n\tprotected void processDiscoItems(Packet packet, JID jid, String node, JID senderJID) throws ComponentException,\n\t\t\tRepositoryException {\n\t\tif (node == null && jid.getResource() == null) {\n\t\t\tElement resultQuery = new Element(\"query\", new String[] { Packet.XMLNS_ATT }, new String[] { DISCO_ITEMS_XMLNS });\n\n\t\t\tCollection<String> taskNames = context.getKernel().getNamesOf(MonitorTask.class);\n\t\t\tfor (String taskName : taskNames) {\n\t\t\t\tresultQuery.addChild(new Element(\"item\", new String[] { \"jid\", \"name\" }, new String[] {\n\t\t\t\t\t\tjid.toString() + \"/\" + taskName, \"Task \" + taskName }));\n\t\t\t}\n\n\t\t\twrite(packet.okResult(resultQuery, 0));\n\t\t} else {\n\t\t\tElement resultQuery = new Element(\"query\", new String[] { Packet.XMLNS_ATT }, new String[] { DISCO_ITEMS_XMLNS });\n\t\t\twrite(packet.okResult(resultQuery, 0));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/modules/InfoTaskCommand.java",
    "content": "package tigase.monitor.modules;\n\nimport tigase.component.adhoc.AdHocCommand;\nimport tigase.component.adhoc.AdHocCommandException;\nimport tigase.component.adhoc.AdHocResponse;\nimport tigase.component.adhoc.AdhHocRequest;\nimport tigase.form.Form;\nimport tigase.monitor.InfoTask;\nimport tigase.monitor.MonitorContext;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\n\npublic class InfoTaskCommand implements AdHocCommand {\n\n\tpublic static final String NODE = \"x-info\";\n\n\tprivate MonitorContext ctx;\n\n\tpublic InfoTaskCommand(MonitorContext ctx) {\n\t\tthis.ctx = ctx;\n\t}\n\n\t@Override\n\tpublic void execute(AdhHocRequest request, AdHocResponse response) throws AdHocCommandException {\n\t\ttry {\n\t\t\tif (request.getAction() != null && \"cancel\".equals(request.getAction())) {\n\t\t\t\tresponse.cancelSession();\n\t\t\t} else {\n\t\t\t\tfinal InfoTask taskInstance = ctx.getKernel().getInstance(request.getIq().getStanzaTo().getResource());\n\n\t\t\t\tForm form = taskInstance.getTaskInfo();\n\n\t\t\t\tresponse.getElements().add(form.getElement());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tthrow new AdHocCommandException(Authorization.INTERNAL_SERVER_ERROR, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Task info\";\n\t}\n\n\t@Override\n\tpublic String getNode() {\n\t\treturn NODE;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(JID jid) {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/AbstractConfigurableTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.UnregisterAware;\nimport tigase.monitor.ConfigurableTask;\nimport tigase.monitor.MonitorTask;\n\npublic abstract class AbstractConfigurableTask implements MonitorTask, ConfigurableTask, UnregisterAware {\n\n\tprivate final static String ENABLED_VAR = \"x-task#enabled\";\n\n\tprivate boolean enabled = false;\n\n\t@Override\n\tpublic void beforeUnregister() {\n\t\tsetEnabled(false);\n\t}\n\n\tprotected void disable() {\n\t}\n\n\tprotected void enable() {\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm f = new Form(\"\", \"Task Configuration\", \"\");\n\n\t\tf.addField(Field.fieldBoolean(ENABLED_VAR, enabled, \"Enabled\"));\n\t\t// f.addField(Field.fieldTextSingle(\"period\", \"\" + period,\n\t\t// \"Period [ms]\"));\n\n\t\treturn f;\n\t}\n\n\tpublic boolean isEnabled() {\n\t\treturn enabled;\n\t}\n\n\tpublic void setEnabled(boolean value) {\n\t\tif (enabled && !value) {\n\t\t\t// turning off\n\t\t\tthis.enabled = value;\n\t\t\tdisable();\n\t\t} else if (!enabled && value) {\n\t\t\t// turning on\n\t\t\tthis.enabled = value;\n\t\t\tenable();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField f = form.get(ENABLED_VAR);\n\t\tif (f != null) {\n\t\t\tboolean value = Field.getAsBoolean(f);\n\t\t\tsetEnabled(value);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/AbstractConfigurableTimerTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.beans.UnregisterAware;\nimport tigase.monitor.TimerTaskService;\nimport tigase.util.TimerTask;\n\npublic abstract class AbstractConfigurableTimerTask extends AbstractConfigurableTask implements UnregisterAware {\n\n\tprivate final static String PERIOD_VAR = \"x-task#period\";\n\n\tprivate long period = 1000l;\n\n\t@Inject(bean = \"timerTaskService\")\n\tprivate TimerTaskService timerTaskService;\n\n\tprivate final TimerTask worker = new TimerTask() {\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tAbstractConfigurableTimerTask.this.run();\n\t\t}\n\t};\n\n\t@Override\n\tpublic void beforeUnregister() {\n\t\tsetEnabled(false);\n\t}\n\n\t@Override\n\tprotected void disable() {\n\t\tsuper.disable();\n\t\tworker.cancel();\n\t}\n\n\t@Override\n\tprotected void enable() {\n\t\tsuper.enable();\n\t\ttimerTaskService.addTimerTask(worker, 1000l, period);\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm f = super.getCurrentConfiguration();\n\n\t\tf.addField(Field.fieldTextSingle(PERIOD_VAR, \"\" + period, \"Period [ms]\"));\n\n\t\treturn f;\n\t}\n\n\tpublic long getPeriod() {\n\t\treturn period;\n\t}\n\n\tpublic TimerTaskService getTimerTaskService() {\n\t\treturn timerTaskService;\n\t}\n\n\tprotected abstract void run();\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField f = form.get(PERIOD_VAR);\n\t\tif (f != null) {\n\t\t\tlong value = Long.parseLong(f.getValue());\n\t\t\tsetPeriod(value);\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n\n\tpublic void setPeriod(long value) {\n\t\tif (this.period != value) {\n\t\t\tthis.period = value;\n\t\t\tif (isEnabled()) {\n\t\t\t\tworker.cancel();\n\t\t\t\ttimerTaskService.addTimerTask(worker, 1000l, period);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setPeriod(String value) {\n\t\tsetPeriod(Long.parseLong(value));\n\t}\n\n\tpublic void setTimerTaskService(TimerTaskService timerTaskService) {\n\t\tthis.timerTaskService = timerTaskService;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/ConnectionsTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.util.Date;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.conf.ConfiguratorAbstract;\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.kernel.beans.config.ConfigField;\nimport tigase.monitor.InfoTask;\nimport tigase.monitor.MonitorComponent;\nimport tigase.server.XMPPServer;\nimport tigase.server.xmppsession.SessionManager;\nimport tigase.util.DateTimeFormatter;\nimport tigase.xml.Element;\n\n@Bean(name = \"connections-task\")\npublic class ConnectionsTask extends AbstractConfigurableTimerTask implements InfoTask {\n\n\tprotected final static DateTimeFormatter dtf = new DateTimeFormatter();\n\tprotected static final Logger log = Logger.getLogger(ConnectionsTask.class.getName());\n\tprivate static final String USERS_DISCONNECTEED_EVENT_NAME = \"UsersDisconnected\";\n\t@Inject\n\tprotected MonitorComponent component;\n\t@Inject\n\tprotected EventBus eventBus;\n\tprivate int lastOnlineUsers;\n\t@ConfigField(desc = \"Minimal amount of disconnected users\")\n\tprivate int thresholdMinimal = 10;\n\t@ConfigField(desc = \"Percent of disconnected users\")\n\tprivate int threshold = 80;\n\n\t/**\n\t * Creates alarm event if required. Event will be created only if both\n\t * conditions will met.\n\t *\n\t * @param currentOnlineUsers\n\t *            current amount of online users.\n\t * @param lastOnlineUsers\n\t *            previous amount of online users.\n\t * @param thresholdMinimal\n\t *            minimal amount of disconnected users to create alarm event.\n\t * @param threshold\n\t *            percent of disconnected users to create alarm event.\n\t * @return event or <code>null</code>.\n\t */\n\tpublic static Element createAlarmEvent(int currentOnlineUsers, int lastOnlineUsers, int thresholdMinimal, int threshold) {\n\t\tfinal int delta = currentOnlineUsers - lastOnlineUsers;\n\t\tfinal float percent = (lastOnlineUsers == 0 ? 1 : ((float) delta) / (float) lastOnlineUsers) * 100;\n\n\t\tif (log.isLoggable(Level.FINE))\n\t\t\tlog.fine(\"Data: lastOnlineUsers=\" + lastOnlineUsers + \"; currentOnlineUsers=\" + currentOnlineUsers + \"; delta=\"\n\t\t\t\t\t+ delta + \"; percent=\" + percent + \"; thresholdMinimal=\" + thresholdMinimal + \"; threshold=\" + threshold);\n\n\t\tif (-1 * delta >= thresholdMinimal && -1 * percent >= threshold) {\n\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\tlog.fine(\"Creating event!\");\n\n\t\t\tElement event = new Element(USERS_DISCONNECTEED_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\tevent.addChild(new Element(\"disconnections\", \"\" + (-1 * delta)));\n\t\t\tevent.addChild(new Element(\"disconnectionsPercent\", \"\" + (-1 * percent)));\n\n\t\t\treturn event;\n\t\t} else\n\t\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm x = super.getCurrentConfiguration();\n\t\tx.addField(Field.fieldTextSingle(\"threshold\", \"\" + threshold, \"Percent of disconnected users\"));\n\t\tx.addField(Field.fieldTextSingle(\"thresholdMinimal\", \"\" + thresholdMinimal, \"Minimal amount of disconnected users\"));\n\t\treturn x;\n\t}\n\n\t@Override\n\tpublic Form getTaskInfo() {\n\t\tForm x = new Form(\"\", \"Task Info\", \"\");\n\t\tx.addField(Field.fieldTextSingle(\"lastUsersOnline\", \"\" + lastOnlineUsers, \"Last measured online users\"));\n\t\treturn x;\n\t}\n\n\tpublic int getThreshold() {\n\t\treturn threshold;\n\t}\n\n\tpublic void setThreshold(int threshold) {\n\t\tthis.threshold = threshold;\n\t}\n\n\tpublic int getThresholdMinimal() {\n\t\treturn thresholdMinimal;\n\t}\n\n\tpublic void setThresholdMinimal(int thresholdMinimal) {\n\t\tthis.thresholdMinimal = thresholdMinimal;\n\t}\n\n\t@Override\n\tprotected void run() {\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.finest(\"Running task...\");\n\n\t\tConfiguratorAbstract configurator = XMPPServer.getConfigurator();\n\t\tSessionManager sess = (SessionManager) configurator.getComponent(\"sess-man\");\n\n\t\tfinal int currentOnlineUsers = sess.getOpenUsersConnectionsAmount();\n\n\t\tElement event = createAlarmEvent(currentOnlineUsers, lastOnlineUsers, thresholdMinimal, threshold);\n\t\tif (event != null) {\n\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\teventBus.fire(event);\n\t\t}\n\n\t\tthis.lastOnlineUsers = currentOnlineUsers;\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField thresholdPercent = form.get(\"threshold\");\n\t\tif (thresholdPercent != null) {\n\t\t\tthis.threshold = Integer.parseInt(thresholdPercent.getValue());\n\t\t}\n\n\t\tField thresholdNetto = form.get(\"thresholdMinimal\");\n\t\tif (thresholdNetto != null) {\n\t\t\tthis.thresholdMinimal = Integer.parseInt(thresholdNetto.getValue());\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/CpuTempTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.MonitorComponent;\nimport tigase.util.DateTimeFormatter;\nimport tigase.xml.Element;\n\n@Bean(name = \"cpu-temp-task\")\npublic class CpuTempTask extends AbstractConfigurableTimerTask {\n\n\tpublic static final String CPU_TEMP_MONITOR_EVENT_NAME = \"CPUTempMonitorEvent\";\n\n\tprivate final static DateTimeFormatter dtf = new DateTimeFormatter();\n\n\tprivate static final File FREQ_FILE = new File(\"/proc/cpuinfo\");\n\n\tprivate static final Logger log = Logger.getLogger(CpuTempTask.class.getName());\n\n\tprivate static final File TEMP_FILE = new File(\"/proc/acpi/thermal_zone/TZ01/temperature\");\n\n\tprivate static final String THROTT_DIR = \"/proc/acpi/processor/CPU\";\n\n\tprivate static final String THROTT_FILE = \"/throttling\";\n\n\t@Inject\n\tprivate MonitorComponent component;\n\n\tprivate float[] cpu_freq = new float[Runtime.getRuntime().availableProcessors()];\n\n\tprivate int cpu_temp;\n\n\tprivate int[] cpu_thrott_pr = new int[Runtime.getRuntime().availableProcessors()];\n\n\tprivate int[] cpu_thrott_st = new int[Runtime.getRuntime().availableProcessors()];\n\n\tprivate int cpuTempThreshold = 90;\n\n\t@Inject\n\tprivate EventBus eventBus;\n\n\tprivate final HashSet<String> triggeredEvents = new HashSet<String>();\n\n\tpublic CpuTempTask() {\n\t\tsetPeriod(1000 * 10);\n\t}\n\n\tprivate void checkCPUFrequency() {\n\t\ttry {\n\t\t\tint cpu = 0;\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(FREQ_FILE));\n\t\t\tString line = null;\n\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\tif (line.startsWith(\"cpu MHz\")) {\n\t\t\t\t\tint idx = line.indexOf(':');\n\t\t\t\t\tcpu_freq[cpu++] = Float.parseFloat(line.substring(idx + 1).trim());\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuffr.close();\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Can't read file: \" + FREQ_FILE, ex);\n\t\t}\n\t}\n\n\tprivate void checkCPUTemperature() {\n\t\ttry {\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(TEMP_FILE));\n\t\t\tString line = buffr.readLine();\n\t\t\tif (line != null) {\n\t\t\t\tcpu_temp = Integer.parseInt(line.substring(\"temperature:\".length(), line.length() - 1).trim());\n\t\t\t} else {\n\t\t\t\tlog.warning(\"Empty file: \" + TEMP_FILE);\n\t\t\t}\n\t\t\tbuffr.close();\n\t\t} catch (FileNotFoundException ex) {\n\t\t\tlog.log(Level.WARNING, \"File contains temperature doesn't exists. Disabling task cpu-temp-task\");\n\t\t\tsetEnabled(false);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Can't read file: \" + TEMP_FILE, ex);\n\t\t}\n\t}\n\n\tprivate void checkCPUThrottling() {\n\t\tfor (int i = 0; i < cpu_thrott_st.length; i++) {\n\t\t\ttry {\n\t\t\t\tFile file = new File(THROTT_DIR + i + THROTT_FILE);\n\t\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(file));\n\t\t\t\tString line = null;\n\t\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\t\tString line_trimmed = line.trim();\n\t\t\t\t\tif (line_trimmed.startsWith(\"*\")) {\n\t\t\t\t\t\tint idx = line_trimmed.indexOf(':');\n\t\t\t\t\t\tcpu_thrott_st[i] = Integer.parseInt(line_trimmed.substring(2, idx));\n\t\t\t\t\t\tString line_pr = line_trimmed.substring(idx + 1, line_trimmed.length() - 1).trim();\n\t\t\t\t\t\tcpu_thrott_pr[i] = Integer.parseInt(line_pr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbuffr.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't read file: \" + THROTT_DIR + i + THROTT_FILE, ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int getCpuTempThreshold() {\n\t\treturn cpuTempThreshold;\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm x = super.getCurrentConfiguration();\n\t\tx.addField(Field.fieldTextSingle(\"cpuTempThreshold\", \"\" + cpuTempThreshold, \"CPU Temp threshold\"));\n\t\t// x.addField(Field.fieldTextSingle(\"N270#cpuTemp\", \"\" +\n\t\t// cpuTempThreshold, \"CPU Temp threshold\"));\n\t\treturn x;\n\t};\n\n\t@Override\n\tprotected void run() {\n\t\tcheckCPUTemperature();\n\t\t// checkCPUFrequency();\n\t\t// checkCPUThrottling();\n\n\t\tif (cpu_temp >= cpuTempThreshold) {\n\t\t\tElement event = new Element(CPU_TEMP_MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\tevent.addChild(new Element(\"cpuTemp\", \"\" + cpu_temp));\n\n\t\t\tif (!triggeredEvents.contains(event.getName())) {\n\t\t\t\teventBus.fire(event);\n\t\t\t\ttriggeredEvents.add(event.getName());\n\t\t\t}\n\n\t\t} else {\n\t\t\ttriggeredEvents.remove(CPU_TEMP_MONITOR_EVENT_NAME);\n\t\t}\n\t}\n\n\tpublic void setCpuTempThreshold(Integer cpuTempThreshold) {\n\t\tthis.cpuTempThreshold = cpuTempThreshold;\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField cpuTempField = form.get(\"cpuTempThreshold\");\n\t\tif (cpuTempField != null) {\n\t\t\tthis.cpuTempThreshold = Integer.parseInt(cpuTempField.getValue());\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/DiskTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileReader;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Initializable;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.MonitorComponent;\nimport tigase.util.DateTimeFormatter;\nimport tigase.util.OSUtils;\nimport tigase.xml.Element;\n\n@Bean(name = \"disk-task\")\npublic class DiskTask extends AbstractConfigurableTimerTask implements Initializable {\n\n\tpublic static final String DISK_USAGE_MONITOR_EVENT_NAME = \"DiskUsageMonitorEvent\";\n\n\tprotected final static DateTimeFormatter dtf = new DateTimeFormatter();\n\n\tprivate static final Logger log = Logger.getLogger(DiskTask.class.getName());\n\n\t@Inject\n\tprotected MonitorComponent component;\n\n\t@Inject\n\tprotected EventBus eventBus;\n\n\tprivate File[] roots;\n\n\tprotected float threshold = 0.8F;\n\n\tprotected final HashSet<String> triggeredEvents = new HashSet<String>();\n\n\tpublic DiskTask() {\n\t\tsetPeriod(1000 * 60);\n\t}\n\n\tprivate void findAllRoots() {\n\t\tswitch (OSUtils.getOSType()) {\n\t\tcase windows:\n\t\t\tFile[] winRoots = File.listRoots();\n\t\t\troots = winRoots;\n\t\t\tbreak;\n\t\tcase linux:\n\t\t\tFile[] linRoots = getLinuxRoots();\n\t\t\troots = linRoots;\n\t\t\tbreak;\n\t\tcase sunos:\n\t\tcase solaris:\n\t\t\tFile[] solRoots = getSolarisRoots();\n\t\t\troots = solRoots;\n\t\t\tbreak;\n\t\tcase mac:\n\t\t\tFile[] macRoots = getMacRoots();\n\t\t\troots = macRoots;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tFile[] otherRoots = File.listRoots();\n\t\t\tif (otherRoots.length == 1) {\n\t\t\t\tFile[] mtabRoots = getLinuxRoots();\n\t\t\t\tif (mtabRoots != null && mtabRoots.length > 1) {\n\t\t\t\t\totherRoots = mtabRoots;\n\t\t\t\t}\n\t\t\t\troots = otherRoots;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm x = super.getCurrentConfiguration();\n\t\tx.addField(Field.fieldTextSingle(\"threshold\", \"\" + threshold, \"Disk usage ratio threshold\"));\n\t\treturn x;\n\t}\n\n\tprivate File[] getLinuxRoots() {\n\t\ttry {\n\t\t\tString mtab = \"/etc/mtab\";\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Reading mtab: \" + mtab);\n\t\t\t}\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(mtab));\n\t\t\tString line = null;\n\t\t\tArrayList<File> results = new ArrayList<File>();\n\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Analyzing line: \" + line);\n\t\t\t\t}\n\t\t\t\tif (line.contains(\"proc\") || line.contains(\"devfs\") || line.contains(\"tmpfs\") || line.contains(\"sysfs\")\n\t\t\t\t\t\t|| line.contains(\"devpts\") || line.contains(\"securityfs\")) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Found virtual fs line, omitting...\");\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Splitting line...\");\n\t\t\t\t}\n\t\t\t\tString[] parts = line.split(\"\\\\s\");\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Found file system: \" + parts[1]);\n\t\t\t\t}\n\t\t\t\tresults.add(new File(parts[1]));\n\t\t\t}\n\t\t\treturn results.toArray(new File[results.size()]);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"Can not read filesystems from /etc/mtab file\" + e);\n\t\t\treturn File.listRoots();\n\t\t}\n\n\t}\n\n\tprivate File[] getMacRoots() {\n\t\tFile volumes = new File(\"/Volumes\");\n\t\treturn volumes.listFiles(new FileFilter() {\n\t\t\t@Override\n\t\t\tpublic boolean accept(File path) {\n\t\t\t\treturn path.isDirectory();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate File[] getSolarisRoots() {\n\t\treturn File.listRoots();\n\t}\n\n\t@Override\n\tpublic void initialize() {\n\t\tfindAllRoots();\n\t};\n\n\t@Override\n\tprotected void run() {\n\t\tfor (File file : roots) {\n\t\t\tif (file.getUsableSpace() < file.getTotalSpace() * (1 - threshold)) {\n\n\t\t\t\tElement event = new Element(DISK_USAGE_MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\t\tevent.addChild(new Element(\"root\", file.toString()));\n\t\t\t\tevent.addChild(new Element(\"usableSpace\", \"\" + file.getUsableSpace()));\n\t\t\t\tevent.addChild(new Element(\"totalSpace\", \"\" + file.getTotalSpace()));\n\n\t\t\t\tif (!triggeredEvents.contains(DISK_USAGE_MONITOR_EVENT_NAME + \":\" + file)) {\n\t\t\t\t\teventBus.fire(event);\n\t\t\t\t\ttriggeredEvents.add(DISK_USAGE_MONITOR_EVENT_NAME + \":\" + file);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\ttriggeredEvents.remove(DISK_USAGE_MONITOR_EVENT_NAME + \":\" + file);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField diskUsageField = form.get(\"threshold\");\n\t\tif (diskUsageField != null) {\n\t\t\tthis.threshold = Float.parseFloat(diskUsageField.getValue());\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n\n\tpublic void setThreshold(Float threshold) {\n\t\tthis.threshold = threshold;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/LoadCheckerTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.util.Date;\nimport java.util.HashSet;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.InfoTask;\nimport tigase.monitor.MonitorComponent;\nimport tigase.server.monitor.MonitorRuntime;\nimport tigase.util.DateTimeFormatter;\nimport tigase.xml.Element;\n\n@Bean(name = \"load-checker-task\")\npublic class LoadCheckerTask extends AbstractConfigurableTimerTask implements InfoTask {\n\n\tprivate final static DateTimeFormatter dtf = new DateTimeFormatter();\n\n\tpublic static final String MONITOR_EVENT_NAME = \"LoadAverageMonitorEvent\";\n\n\tprivate long averageLoadThreshold = 10;\n\n\t@Inject\n\tprivate MonitorComponent component;\n\n\t@Inject\n\tprivate EventBus eventBus;\n\n\t@Inject\n\tprivate MonitorRuntime runtime;\n\n\tprivate final HashSet<String> triggeredEvents = new HashSet<String>();\n\n\tpublic long getAverageLoadThreshold() {\n\t\treturn averageLoadThreshold;\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm form = super.getCurrentConfiguration();\n\n\t\tform.addField(Field.fieldTextSingle(\"averageLoadThreshold\", String.valueOf(averageLoadThreshold),\n\t\t\t\t\"Alarm when AverageLoad is bigger than\"));\n\n\t\treturn form;\n\t}\n\n\t@Override\n\tpublic Form getTaskInfo() {\n\t\tForm result = new Form(\"\", \"Load Information\", \"\");\n\t\tresult.addField(Field.fieldTextSingle(\"averageLoad\", Double.toString(runtime.getLoadAverage()), \"Load Average\"));\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tprotected void run() {\n\t\tdouble curAverageLoad = runtime.getLoadAverage();\n\t\tif (curAverageLoad >= averageLoadThreshold) {\n\t\t\tElement event = new Element(MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\tevent.addChild(new Element(\"averageLoad\", Double.toString(curAverageLoad)));\n\t\t\tevent.addChild(new Element(\"message\", \"Average Load is higher than \" + averageLoadThreshold + \" and it is equals \"\n\t\t\t\t\t+ Double.toString(curAverageLoad)));\n\n\t\t\tif (!triggeredEvents.contains(event.getName())) {\n\t\t\t\teventBus.fire(event);\n\t\t\t\ttriggeredEvents.add(event.getName());\n\t\t\t}\n\t\t} else {\n\t\t\ttriggeredEvents.remove(MONITOR_EVENT_NAME);\n\t\t}\n\t}\n\n\tpublic void setAverageLoadThreshold(Long averageLoadThreshold) {\n\t\tthis.averageLoadThreshold = averageLoadThreshold;\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField tmp = form.get(\"averageLoadThreshold\");\n\t\tif (tmp != null) {\n\t\t\tthis.averageLoadThreshold = Long.parseLong(tmp.getValue());\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/LoggerTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.logging.*;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.MonitorComponent;\nimport tigase.util.DateTimeFormatter;\nimport tigase.util.LogFormatter;\nimport tigase.xml.Element;\n\n@Bean(name = \"logger-task\")\npublic class LoggerTask extends AbstractConfigurableTask {\n\n\tprivate class MemoryHandlerFlush extends MemoryHandler {\n\n\t\tMonitorHandler monHandle = null;\n\n\t\tpublic MemoryHandlerFlush(MonitorHandler target, int size, Level pushLevel) {\n\t\t\tsuper(target, size, pushLevel);\n\t\t\tmonHandle = target;\n\t\t}\n\n\t\t@Override\n\t\tpublic void push() {\n\t\t\tsuper.push();\n\t\t\tflush();\n\t\t}\n\n\t\tpublic String pushToString() {\n\t\t\tsuper.push();\n\t\t\treturn monHandle.logsToString();\n\t\t}\n\t}\n\n\tprivate class MonitorHandler extends Handler {\n\n\t\tprivate LogFormatter formatter = new LogFormatter();\n\t\tprivate LinkedList<String> logs = new LinkedList<String>();\n\n\t\t@Override\n\t\tpublic void close() throws SecurityException {\n\t\t}\n\n\t\t@Override\n\t\tpublic synchronized void flush() {\n\t\t\t++logWarings;\n\t\t\tif (System.currentTimeMillis() - lastWarningSent > 5 * 60000) {\n\t\t\t\tString logBuff = logsToString();\n\t\t\t\t// We don't want to flood the system with this in case of\n\t\t\t\t// some frequent error....\n\t\t\t\tsendWarningOut(logBuff);\n\t\t\t\tlastWarningSent = System.currentTimeMillis();\n\t\t\t}\n\t\t}\n\n\t\tpublic synchronized String logsToString() {\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tString logEntry = null;\n\t\t\twhile (((logEntry = logs.pollLast()) != null) && (sb.length() < maxLogBuffer)) {\n\t\t\t\tsb.insert(0, logEntry);\n\t\t\t}\n\t\t\tlogs.clear();\n\t\t\tString result = sb.length() <= maxLogBuffer ? sb.toString() : sb.substring(sb.length() - maxLogBuffer);\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic synchronized void publish(LogRecord record) {\n\t\t\tString logEntry = formatter.format(record).replace('<', '[').replace('>', ']');\n\t\t\tlogs.add(logEntry);\n\t\t}\n\n\t}\n\n\tprotected final static DateTimeFormatter dtf = new DateTimeFormatter();\n\n\tprivate static final String LOGGER_MONITOR_EVENT_NAME = \"LoggerMonitorEvent\";\n\n\t@Inject\n\tprotected MonitorComponent component;\n\n\t@Inject\n\tprotected EventBus eventBus;\n\n\tprivate long lastWarningSent = 0;\n\n\tprivate Level levelTreshold = Level.WARNING;\n\n\tprivate int loggerSize = 50;\n\n\tprivate long logWarings = 0;\n\n\tprivate int maxLogBuffer = 1000 * 1000;\n\n\tprivate MemoryHandlerFlush memoryHandler = null;\n\n\tprivate MonitorHandler monitorHandler = null;\n\n\t@Override\n\tprotected void disable() {\n\t\tremoveHandler();\n\t\tsuper.disable();\n\t}\n\n\t@Override\n\tprotected void enable() {\n\t\tregisterHandler();\n\t\tsuper.enable();\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm f = super.getCurrentConfiguration();\n\n\t\tField x = Field.fieldListSingle(\"levelTreshold\", levelTreshold.getName(), \"Log level threshold\",\n\t\t\t\tnew String[] { Level.SEVERE.getName(), Level.WARNING.getName(), Level.INFO.getName(), Level.CONFIG.getName(),\n\t\t\t\t\t\tLevel.FINE.getName(), Level.FINER.getName(), Level.FINEST.getName(), Level.ALL.getName() },\n\t\t\t\tnew String[] { Level.SEVERE.getName(), Level.WARNING.getName(), Level.INFO.getName(), Level.CONFIG.getName(),\n\t\t\t\t\t\tLevel.FINE.getName(), Level.FINER.getName(), Level.FINEST.getName(), Level.ALL.getName() });\n\n\t\tf.addField(x);\n\n\t\treturn f;\n\t}\n\n\tpublic Level getLevelTreshold() {\n\t\treturn levelTreshold;\n\t}\n\n\tprivate void registerHandler() {\n\t\tremoveHandler();\n\t\tif (monitorHandler == null) {\n\t\t\tmonitorHandler = new MonitorHandler();\n\t\t\tmonitorHandler.setLevel(Level.ALL);\n\t\t}\n\t\tmemoryHandler = new MemoryHandlerFlush(monitorHandler, loggerSize, levelTreshold);\n\t\tmemoryHandler.setLevel(Level.ALL);\n\t\tLogger.getLogger(\"\").addHandler(memoryHandler);\n\t}\n\n\tprivate void removeHandler() {\n\t\tif (memoryHandler != null) {\n\t\t\tLogger.getLogger(\"\").removeHandler(memoryHandler);\n\t\t}\n\t}\n\n\tpublic void sendWarningOut(String logBuff) {\n\t\tElement event = new Element(LOGGER_MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\tevent.addChild(new Element(\"log\", logBuff));\n\n\t\teventBus.fire(event);\n\t}\n\n\tpublic void setLevelTreshold(String levelTreshold) {\n\t\tboolean reregister = false;\n\t\tif (levelTreshold != null) {\n\t\t\tLevel v = Level.parse(levelTreshold);\n\t\t\treregister |= !v.equals(this.levelTreshold);\n\t\t\tthis.levelTreshold = v;\n\t\t}\n\n\t\tif (reregister) {\n\t\t\tregisterHandler();\n\t\t}\n\n\t\tSystem.out.println(\"HAAAAA \" + this.levelTreshold);\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField f = form.get(\"levelTreshold\");\n\t\tif (f != null)\n\t\t\tsetLevelTreshold(f.getValue());\n\t\tsuper.setNewConfiguration(form);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/MemoryCheckerTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport tigase.server.monitor.MonitorRuntime;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.InfoTask;\nimport tigase.monitor.MonitorComponent;\nimport tigase.util.DateTimeFormatter;\nimport tigase.xml.Element;\n\nimport java.util.Date;\nimport java.util.HashSet;\n\n@Bean(name = \"memory-checker-task\")\npublic class MemoryCheckerTask extends AbstractConfigurableTimerTask implements InfoTask {\n\n\tprivate final static DateTimeFormatter dtf = new DateTimeFormatter();\n\n\tpublic final static String HEAP_MEMORY_MONITOR_EVENT_NAME = \"HeapMemoryMonitorEvent\";\n\n\tpublic final static String NONHEAP_MEMORY_MONITOR_EVENT_NAME = \"NonHeapMemoryMonitorEvent\";\n\n\t@Inject\n\tprivate MonitorComponent component;\n\n\t@Inject\n\tprivate EventBus eventBus;\n\n\t/**\n\t * Percent\n\t */\n\tprivate int maxHeapMemUsagePercentThreshold = 90;\n\n\t/**\n\t * Percent\n\t */\n\tprivate int maxNonHeapMemUsagePercentThreshold = 90;\n\n\t@Inject\n\tprivate MonitorRuntime runtime;\n\n\tprivate final HashSet<String> triggeredEvents = new HashSet<String>();\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm form = super.getCurrentConfiguration();\n\n\t\tform.addField(Field.fieldTextSingle(\"maxHeapMemUsagePercentThreshold\", String.valueOf(maxHeapMemUsagePercentThreshold),\n\t\t\t\t\"Alarm when heap mem usage is bigger than [%]\"));\n\n\t\tform.addField(Field.fieldTextSingle(\"maxNonHeapMemUsagePercentThreshold\",\n\t\t\t\tString.valueOf(maxNonHeapMemUsagePercentThreshold), \"Alarm when non-heap mem usage is bigger than [%]\"));\n\n\t\treturn form;\n\t}\n\n\tpublic int getMaxHeapMemUsagePercentThreshold() {\n\t\treturn maxHeapMemUsagePercentThreshold;\n\t}\n\n\tpublic int getMaxNonHeapMemUsagePercentThreshold() {\n\t\treturn maxNonHeapMemUsagePercentThreshold;\n\t}\n\n\t@Override\n\tpublic Form getTaskInfo() {\n\t\tForm result = new Form(\"\", \"Memory Information\", \"\");\n\t\tresult.addField(Field.fieldTextSingle(\"heapMemMax\", Long.toString(runtime.getHeapMemMax()), \"Heap Memory Max\"));\n\t\tresult.addField(Field.fieldTextSingle(\"heapMemUsed\", Long.toString(runtime.getHeapMemUsed()), \"Heap Memory Used\"));\n\t\tresult.addField(Field.fieldTextSingle(\"heapMemUsedPercentage\", Float.toString(runtime.getHeapMemUsage()),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Heap Memory Used [%]\"));\n\t\tresult.addField(Field.fieldTextSingle(\"nonHeapMemMax\", Long.toString(runtime.getNonHeapMemMax()), \"Non-Heap Memory Max\"));\n\t\tresult.addField(Field.fieldTextSingle(\"nonHeapMemUsed\", Long.toString(runtime.getNonHeapMemUsed()),\n\t\t\t\t\"Non-Heap Memory Used\"));\n\t\tresult.addField(Field.fieldTextSingle(\"nonHeapMemUsedPercentage\", Float.toString(runtime.getNonHeapMemUsage()),\n\t\t\t\t\"Non-Heap Memory Used [%]\"));\n\t\tresult.addField(Field.fieldTextSingle(\"directMemUsed\", Long.toString(runtime.getDirectMemUsed()), \"Direct Memory Used\"));\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tprotected void run() {\n\t\tfloat curHeapMemUsagePercent = runtime.getHeapMemUsage();\n\t\tif (curHeapMemUsagePercent >= maxHeapMemUsagePercentThreshold) {\n\t\t\tElement event = new Element(HEAP_MEMORY_MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\tevent.addChild(new Element(\"heapMemUsage\", Float.toString(curHeapMemUsagePercent)));\n\t\t\tevent.addChild(new Element(\"heapMemMax\", Long.toString(runtime.getHeapMemMax())));\n\t\t\tevent.addChild(new Element(\"heapMemUsed\", Long.toString(runtime.getHeapMemUsed())));\n\t\t\tevent.addChild(new Element(\"nonHeapMemMax\", Long.toString(runtime.getNonHeapMemMax())));\n\t\t\tevent.addChild(new Element(\"nonHeapMemUsed\", Long.toString(runtime.getNonHeapMemUsed())));\n\t\t\tevent.addChild(new Element(\"directMemUsed\", Long.toString(runtime.getDirectMemUsed())));\n\t\t\tevent.addChild(new Element(\"message\", \"Heap memory usage is higher than \" + maxHeapMemUsagePercentThreshold\n\t\t\t\t\t+ \" and it equals \" + curHeapMemUsagePercent));\n\n\t\t\tif (!triggeredEvents.contains(event.getName())) {\n\t\t\t\teventBus.fire(event);\n\t\t\t\ttriggeredEvents.add(event.getName());\n\t\t\t}\n\t\t} else {\n\t\t\ttriggeredEvents.remove(HEAP_MEMORY_MONITOR_EVENT_NAME);\n\t\t}\n\n\t\tfloat curNonHeapMemUsagePercent = runtime.getNonHeapMemUsage();\n\t\tif (curNonHeapMemUsagePercent >= maxNonHeapMemUsagePercentThreshold) {\n\t\t\tElement event = new Element(NONHEAP_MEMORY_MONITOR_EVENT_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\t\tevent.addChild(new Element(\"hostname\", component.getDefHostName().toString()));\n\t\t\tevent.addChild(new Element(\"timestamp\", \"\" + dtf.formatDateTime(new Date())));\n\t\t\tevent.addChild(new Element(\"nonHeapMemUsage\", Float.toString(curNonHeapMemUsagePercent)));\n\t\t\tevent.addChild(new Element(\"heapMemMax\", Long.toString(runtime.getHeapMemMax())));\n\t\t\tevent.addChild(new Element(\"heapMemUsed\", Long.toString(runtime.getHeapMemUsed())));\n\t\t\tevent.addChild(new Element(\"nonHeapMemMax\", Long.toString(runtime.getNonHeapMemMax())));\n\t\t\tevent.addChild(new Element(\"nonHeapMemUsed\", Long.toString(runtime.getNonHeapMemUsed())));\n\t\t\tevent.addChild(new Element(\"directMemUsed\", Long.toString(runtime.getDirectMemUsed())));\n\t\t\tevent.addChild(new Element(\"message\", \"Non-Heap memory usage is higher than \" + maxNonHeapMemUsagePercentThreshold\n\t\t\t\t\t+ \" and it equals \" + curHeapMemUsagePercent));\n\n\t\t\tif (!triggeredEvents.contains(event.getName())) {\n\t\t\t\teventBus.fire(event);\n\t\t\t\ttriggeredEvents.add(event.getName());\n\t\t\t}\n\t\t} else {\n\t\t\ttriggeredEvents.remove(NONHEAP_MEMORY_MONITOR_EVENT_NAME);\n\t\t}\n\t}\n\n\tpublic void setMaxHeapMemUsagePercentThreshold(Integer maxHeapMemUsagePercentThreshold) {\n\t\tthis.maxHeapMemUsagePercentThreshold = maxHeapMemUsagePercentThreshold;\n\t}\n\n\tpublic void setMaxNonHeapMemUsagePercentThreshold(Integer maxNonHeapMemUsagePercentThreshold) {\n\t\tthis.maxNonHeapMemUsagePercentThreshold = maxNonHeapMemUsagePercentThreshold;\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField heapMemUsage = form.get(\"maxHeapMemUsagePercentThreshold\");\n\t\tif (heapMemUsage != null) {\n\t\t\tthis.maxHeapMemUsagePercentThreshold = Integer.parseInt(heapMemUsage.getValue());\n\t\t}\n\t\tField nonHeapMemUsage = form.get(\"maxNonHeapMemUsagePercentThreshold\");\n\t\tif (nonHeapMemUsage != null) {\n\t\t\tthis.maxNonHeapMemUsagePercentThreshold = Integer.parseInt(nonHeapMemUsage.getValue());\n\t\t}\n\t\tsuper.setNewConfiguration(form);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/SampleTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport java.util.Date;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.MonitorComponent;\nimport tigase.xml.Element;\n\n@Bean(name = \"sample-task\")\npublic class SampleTask extends AbstractConfigurableTimerTask {\n\n\t@Inject\n\tprivate EventBus eventBus;\n\tprivate String message = \"<->\";\n\n\t@Override\n\tprotected void enable() {\n\t\tsuper.enable();\n\n\t\tElement event = new Element(\"SampleTaskEnabled\", new String[] { \"xmlns\" },\n\t\t\t\tnew String[] { MonitorComponent.EVENTS_XMLNS });\n\t\tevent.addChild(new Element(\"timestamp\", \"\" + (new Date())));\n\t\tevent.addChild(new Element(\"message\", this.message));\n\t\tthis.message = \"<->\";\n\t\teventBus.fire(event);\n\n\t\tsetEnabled(false);\n\t}\n\n\t@Override\n\tpublic Form getCurrentConfiguration() {\n\t\tForm x = super.getCurrentConfiguration();\n\t\tx.addField(Field.fieldTextSingle(\"message\", \"\", \"Event message\"));\n\t\treturn x;\n\t}\n\n\t@Override\n\tprotected void run() {\n\t}\n\n\t@Override\n\tpublic void setNewConfiguration(Form form) {\n\t\tField m = form.get(\"message\");\n\t\tif (m == null) {\n\t\t\tthis.message = \"<not found>\";\n\t\t} else {\n\t\t\tthis.message = m.getValue();\n\t\t}\n\n\t\tsuper.setNewConfiguration(form);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/ScriptTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\n\nimport tigase.kernel.beans.Initializable;\nimport tigase.kernel.beans.Inject;\n\npublic class ScriptTask extends AbstractConfigurableTask implements Initializable {\n\n\t@Inject\n\tprotected Bindings bindings;\n\n\tprivate ScriptEngine engine;\n\n\tprivate String script;\n\n\t@Inject\n\tprotected ScriptEngineManager scriptEngineManager;\n\n\tprivate String scriptExtension;\n\n\t@Override\n\tprotected void enable() {\n\t\tsuper.enable();\n\n\t\ttry {\n\t\t\tengine.eval(script, bindings);\n\t\t} catch (ScriptException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic Bindings getBindings() {\n\t\treturn bindings;\n\t}\n\n\tpublic String getScript() {\n\t\treturn script;\n\t}\n\n\tpublic ScriptEngineManager getScriptEngineManager() {\n\t\treturn scriptEngineManager;\n\t}\n\n\tpublic String getScriptExtension() {\n\t\treturn scriptExtension;\n\t}\n\n\t@Override\n\tpublic void initialize() {\n\t}\n\n\tpublic void setBindings(Bindings bindings) {\n\t\tthis.bindings = bindings;\n\t}\n\n\tpublic void setScript(String script, String scriptExtension) {\n\t\tthis.engine = scriptEngineManager.getEngineByExtension(scriptExtension);\n\t\tthis.script = script;\n\t\tthis.scriptExtension = scriptExtension;\n\t}\n\n\tpublic void setScriptEngineManager(ScriptEngineManager scriptEngineManager) {\n\t\tthis.scriptEngineManager = scriptEngineManager;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/monitor/tasks/ScriptTimerTask.java",
    "content": "package tigase.monitor.tasks;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\n\nimport tigase.kernel.beans.Inject;\nimport tigase.monitor.ConfigurableTask;\n\npublic class ScriptTimerTask extends AbstractConfigurableTimerTask implements ConfigurableTask {\n\n\t@Inject\n\tprotected Bindings bindings;\n\n\tprivate ScriptEngine engine;\n\n\tprivate String script;\n\n\t@Inject\n\tprotected ScriptEngineManager scriptEngineManager;\n\n\tprivate String scriptExtension;\n\n\tpublic Bindings getBindings() {\n\t\treturn bindings;\n\t}\n\n\tpublic String getScript() {\n\t\treturn script;\n\t}\n\n\tpublic ScriptEngineManager getScriptEngineManager() {\n\t\treturn scriptEngineManager;\n\t}\n\n\tpublic String getScriptExtension() {\n\t\treturn scriptExtension;\n\t}\n\n\t@Override\n\tprotected void run() {\n\t\ttry {\n\t\t\tengine.eval(script, bindings);\n\t\t} catch (ScriptException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic void setBindings(Bindings bindings) {\n\t\tthis.bindings = bindings;\n\t}\n\n\tpublic void setScript(String script, String scriptExtension) {\n\t\tthis.engine = scriptEngineManager.getEngineByExtension(scriptExtension);\n\t\tthis.script = script;\n\t\tthis.scriptExtension = scriptExtension;\n\t}\n\n\tpublic void setScriptEngineManager(ScriptEngineManager scriptEngineManager) {\n\t\tthis.scriptEngineManager = scriptEngineManager;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/Accept.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.net;\n\nimport java.io.IOException;\nimport java.nio.channels.SocketChannel;\n\n/**\n * Describe interface Accept here.\n *\n *\n * Created: Sat May 14 07:00:16 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface Accept {\n\n  void accept(final SocketChannel sc) throws IOException;\n\n} // Accept\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/ConnectionOpenListener.java",
    "content": "/*\n * ConnectionOpenListener.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.net;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.net.InetSocketAddress;\n\nimport java.nio.channels.SocketChannel;\n\n/**\n * Describe interface ConnectionOpenListener here.\n *\n *\n * Created: Thu Jan 26 00:00:39 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ConnectionOpenListener {\n\t/**\n\t * <code>RECEIVE_BUFFER_SIZE</code> defines a size for TCP/IP packets.\n\t * XMPP data packets are quite small usually, below 1kB so we don't need\n\t * big TCP/IP data buffers.\n\t */\n\tpublic static final int DEF_RECEIVE_BUFFER_SIZE = 2 * 1024;\n\n\t/** Field description */\n\tpublic static final int IPTOS_LOWCOST = 0x02;\n\n\t/** Field description */\n\tpublic static final int IPTOS_LOWDELAY = 0x10;\n\n\t/** Field description */\n\tpublic static final int IPTOS_RELIABILITY = 0x04;\n\n\t/** Field description */\n\tpublic static final int IPTOS_THROUGHPUT = 0x08;\n\n\t/** Field description */\n\tpublic static final int DEF_TRAFFIC_CLASS = IPTOS_LOWCOST;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sc\n\t */\n\tvoid accept(SocketChannel sc);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tint getPort();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tString[] getIfcs();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tString getSRVType();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tString getRemoteHostname();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tInetSocketAddress getRemoteAddress();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tConnectionType getConnectionType();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tSocketType getSocketType();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tint getReceiveBufferSize();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tint getTrafficClass();\n}    // ConnectionOpenListener\n\n\n//~ Formatted in Tigase Code Convention on 13/03/11\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/ConnectionOpenThread.java",
    "content": "/*\n * ConnectionOpenThread.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.net;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.net.*;\n\nimport java.nio.channels.SelectableChannel;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.Selector;\nimport java.nio.channels.ServerSocketChannel;\nimport java.nio.channels.SocketChannel;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.Iterator;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\n/**\n * Describe class ConnectionOpenThread here.\n *\n *\n * Created: Wed Jan 25 23:51:28 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ConnectionOpenThread\n\t\t\t\timplements Runnable {\n\t/**\n\t *\n\t */\n\tpublic static final long def_5222_throttling = 200;\n\n\t/** Field description */\n\tpublic static final long def_5223_throttling = 50;\n\n\t/** Field description */\n\tpublic static final long def_5269_throttling = 100;\n\n\t/** Field description */\n\tpublic static final long            def_5280_throttling = 1000;\n\tprivate static ConnectionOpenThread acceptThread        = null;\n\tprivate static final Logger         log = Logger.getLogger(ConnectionOpenThread.class\n\t\t\t.getName());\n\n\t/** Field description */\n\tpublic static Map<Integer, PortThrottlingData> throttling =\n\t\t\tnew ConcurrentHashMap<Integer, PortThrottlingData>(10);\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected long                                        accept_counter = 0;\n\tprivate Selector                                      selector       = null;\n\tprivate boolean                                       stopping       = false;\n\tprivate Timer                                         timer          = null;\n\tprivate ConcurrentLinkedQueue<ConnectionOpenListener> waiting =\n\t\t\tnew ConcurrentLinkedQueue<ConnectionOpenListener>();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>ConnectionOpenThread</code> instance.\n\t *\n\t */\n\tprivate ConnectionOpenThread() {\n\t\ttimer = new Timer(\"Connections open timer\", true);\n\t\ttimer.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tfor (PortThrottlingData portData : throttling.values()) {\n\t\t\t\t\tportData.lastSecondConnections = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}, 1000, 1000);\n\t\ttry {\n\t\t\tselector = Selector.open();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Server I/O error, can't continue my work.\", e);\n\t\t\tstopping = true;\n\t\t}    // end of try-catch\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param al\n\t */\n\tpublic void addConnectionOpenListener(ConnectionOpenListener al) {\n\t\twaiting.offer(al);\n\t\tselector.wakeup();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param al\n\t */\n\tpublic void removeConnectionOpenListener(ConnectionOpenListener al) {\n\t\tfor (SelectionKey key : selector.keys()) {\n\t\t\tif (al == key.attachment()) {\n\t\t\t\ttry {\n\t\t\t\t\tkey.cancel();\n\n\t\t\t\t\tSelectableChannel channel = key.channel();\n\n\t\t\t\t\tchannel.close();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Exception during removing connection listener.\", e);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\twhile (!stopping) {\n\t\t\ttry {\n\t\t\t\tint select = selector.select();\n\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Selected: \" + select + \" from selector: \" + selector );\n\t\t\t\t}\n\n\t\t\t\tfor (Iterator i = selector.selectedKeys().iterator(); i.hasNext(); ) {\n\t\t\t\t\tSelectionKey sk = (SelectionKey) i.next();\n\n\t\t\t\t\ti.remove();\n\n\t\t\t\t\tSocketChannel sc        = null;\n\t\t\t\t\tboolean       throttled = false;\n\t\t\t\t\tint           port_no   = 0;\n\n\t\t\t\t\tif ((sk.readyOps() & SelectionKey.OP_ACCEPT) != 0) {\n\t\t\t\t\t\tServerSocketChannel nextReady = (ServerSocketChannel) sk.channel();\n\n\t\t\t\t\t\tport_no = nextReady.socket().getLocalPort();\n\t\t\t\t\t\tsc      = nextReady.accept();\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"OP_ACCEPT\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tPortThrottlingData port_throttling = throttling.get(port_no);\n\n\t\t\t\t\t\tif (port_throttling != null) {\n\t\t\t\t\t\t\t++port_throttling.lastSecondConnections;\n\t\t\t\t\t\t\tif (port_throttling.lastSecondConnections > port_throttling.throttling) {\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\t\t\"New connections throttling level {0} exceeded, closing: {0}\", new Object[] {port_throttling.lastSecondConnections, sc});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tsc.close();\n\t\t\t\t\t\t\t\tsc        = null;\n\t\t\t\t\t\t\t\tthrottled = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Hm, this should not happen actually\n\t\t\t\t\t\t\tlog.log(Level.WARNING, \"Throttling not configured for port: {0}\", port_no);\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (sk.readyOps() & SelectionKey.OP_ACCEPT)\n\t\t\t\t\tif ((sk.readyOps() & SelectionKey.OP_CONNECT) != 0) {\n\t\t\t\t\t\tsk.cancel();\n\t\t\t\t\t\tsc = (SocketChannel) sk.channel();\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"OP_CONNECT\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (sk.readyOps() & SelectionKey.OP_ACCEPT)\n\t\t\t\t\tif (sc != null) {\n\n\t\t\t\t\t\t// We have to catch exception here as sometimes socket is closed\n\t\t\t\t\t\t// or connection is broken before we start configuring it here\n\t\t\t\t\t\t// then whatever we do on the socket it throws an exception\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsc.configureBlocking(false);\n\t\t\t\t\t\t\tsc.socket().setSoLinger(false, 0);\n\t\t\t\t\t\t\tsc.socket().setReuseAddress(true);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINER, \"Registered new client socket: {0}\", sc);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tConnectionOpenListener al = (ConnectionOpenListener) sk.attachment();\n\n\t\t\t\t\t\t\tsc.socket().setTrafficClass(al.getTrafficClass());\n\t\t\t\t\t\t\tsc.socket().setReceiveBufferSize(al.getReceiveBufferSize());\n\t\t\t\t\t\t\tal.accept(sc);\n\t\t\t\t\t\t} catch (java.net.SocketException e) {\n\t\t\t\t\t\t\tlog.log(Level.INFO, \"Socket closed instantly after it had been opened?\", e);\n\n\t\t\t\t\t\t\tConnectionOpenListener al = (ConnectionOpenListener) sk.attachment();\n\n\t\t\t\t\t\t\tal.accept(sc);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\"Can not obtain socket channel from selection key, throttling activated = {0}, for port: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { throttled, port_no });\n\t\t\t\t\t}    // end of if (sc != null) else\n\t\t\t\t\t++accept_counter;\n\t\t\t\t}\n\t\t\t\taddAllWaiting();\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Server I/O error.\", e);\n\n\t\t\t\t// stopping = true;\n\t\t\t}        // end of catch\n\t\t\t\t\tcatch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Other service exception.\", e);\n\n\t\t\t\t// stopping = true;\n\t\t\t}        // end of catch\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void start() {\n\t\tThread t = new Thread(this);\n\n\t\tt.setName(\"ConnectionOpenThread\");\n\t\tt.start();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void stop() {\n\t\tstopping = true;\n\t\tselector.wakeup();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic static ConnectionOpenThread getInstance() {\n\n\t\t// Long new_throttling = Long.getLong(\"new-connections-throttling\");\n//  if (new_throttling != null) {\n//    throttling = new_throttling;\n//    log.log(Level.WARNING, \"New connections throttling set to: {0}\", throttling);\n//  }\n\t\tif (acceptThread == null) {\n\t\t\tacceptThread = new ConnectionOpenThread();\n\n\t\t\tThread thrd = new Thread(acceptThread);\n\n\t\t\tthrd.setName(\"ConnectionOpenThread\");\n\t\t\tthrd.start();\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"ConnectionOpenThread started.\");\n\t\t\t}\n\t\t}    // end of if (acceptThread == null)\n\n\t\treturn acceptThread;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void addAllWaiting() throws IOException {\n\t\tConnectionOpenListener al = null;\n\n\t\twhile ((al = waiting.poll()) != null) {\n\t\t\ttry {\n\t\t\t\taddPort(al);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error: creating connection for: \" + al, e);\n\t\t\t\tal.accept(null);\n\t\t\t}    // end of try-catch\n\t\t}      // end of for ()\n\t}\n\n\tprivate void addISA(InetSocketAddress isa, ConnectionOpenListener al)\n\t\t\t\t\tthrows IOException {\n\t\tswitch (al.getConnectionType()) {\n\t\tcase accept :\n\t\t\tlong port_throttling = getThrottlingForPort(isa.getPort());\n\n\t\t\tthrottling.put(isa.getPort(), new PortThrottlingData(port_throttling));\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Setting up throttling for the port {0} to {1} connections per second. isa: {2}\",\n\t\t\t\t\t\tnew Object[] { isa.getPort(), port_throttling, isa });\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Setting up 'accept' channel...\");\n\t\t\t}\n\n\t\t\tServerSocketChannel ssc = ServerSocketChannel.open();\n\n\t\t\tssc.socket().setReceiveBufferSize(al.getReceiveBufferSize());\n\t\t\tssc.configureBlocking(false);\n\t\t\tssc.socket().bind(isa, (int) (port_throttling));\n\t\t\tssc.register(selector, SelectionKey.OP_ACCEPT, al);\n\n\t\t\tbreak;\n\n\t\tcase connect :\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Setting up ''connect'' channel for: {0}/{1}\",\n\t\t\t\t\t\tnew Object[] { isa.getAddress(),\n\t\t\t\t\t\tisa.getPort() });\n\t\t\t}\n\n\t\t\tSocketChannel sc = SocketChannel.open();\n\n\t\t\tsc.socket().setReceiveBufferSize(al.getReceiveBufferSize());\n\t\t\tsc.socket().setTrafficClass(al.getTrafficClass());\n\t\t\tsc.configureBlocking(false);\n\t\t\tsc.connect(isa);\n\t\t\tsc.register(selector, SelectionKey.OP_CONNECT, al);\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tlog.log(Level.WARNING, \"Unknown connection type: {0}\", al.getConnectionType());\n\n\t\t\tbreak;\n\t\t}    // end of switch (al.getConnectionType())\n\t}\n\n\tprivate void addPort(ConnectionOpenListener al) throws IOException {\n\t\tif ((al.getConnectionType() == ConnectionType.connect) && (al.getRemoteAddress() !=\n\t\t\t\tnull)) {\n\t\t\taddISA(al.getRemoteAddress(), al);\n\t\t} else if ((al.getIfcs() == null) || (al.getIfcs().length == 0) || al.getIfcs()[0]\n\t\t\t\t.equals(\"ifc\") || al.getIfcs()[0].equals(\"*\")) {\n\t\t\taddISA(new InetSocketAddress(al.getPort()), al);\n\t\t} else {\n\t\t\tfor (String ifc : al.getIfcs()) {\n\t\t\t\taddISA(new InetSocketAddress(ifc, al.getPort()), al);\n\t\t\t}    // end of for ()\n\t\t}      // end of if (ip == null || ip.equals(\"\")) else\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate long getThrottlingForPort(int port) {\n\t\tlong result = def_5222_throttling;\n\n\t\tswitch (port) {\n\t\tcase 5223 :\n\t\t\tresult = def_5223_throttling;\n\n\t\t\tbreak;\n\n\t\tcase 5269 :\n\t\t\tresult = def_5269_throttling;\n\n\t\t\tbreak;\n\n\t\tcase 5280 :\n\t\t\tresult = def_5280_throttling;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tString throttling_prop = System.getProperty(\"new-connections-throttling\");\n\n\t\tif (throttling_prop != null) {\n\t\t\tString[] all_ports_thr = throttling_prop.split(\",\");\n\n\t\t\tfor (String port_thr : all_ports_thr) {\n\t\t\t\tString[] port_thr_ar = port_thr.split(\":\");\n\n\t\t\t\tif (port_thr_ar.length == 2) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tint port_no = Integer.parseInt(port_thr_ar[0]);\n\n\t\t\t\t\t\tif (port_no == port) {\n\t\t\t\t\t\t\treturn Long.parseLong(port_thr_ar[1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\n\t\t\t\t\t\t// bad configuration\n\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Connections throttling configuration error, bad format, \" +\n\t\t\t\t\t\t\t\t\"check the documentation for a correct syntax, \" +\n\t\t\t\t\t\t\t\t\"port throttling config: {0}\", port_thr);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// bad configuration\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Connections throttling configuration error, bad format, \" +\n\t\t\t\t\t\t\t\"check the documentation for a correct syntax, \" +\n\t\t\t\t\t\t\t\"port throttling config: {0}\", port_thr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class PortThrottlingData {\n\t\t/** Field description */\n\t\tprotected long lastSecondConnections = 0;\n\n\t\t/** Field description */\n\t\tprotected long throttling;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param throttling_prop\n\t\t */\n\t\tprivate PortThrottlingData(long throttling_prop) {\n\t\t\tthrottling = throttling_prop;\n\t\t}\n\t}\n}    // ConnectionOpenThread\n\n\n//~ Formatted in Tigase Code Convention on 13/07/06\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/ConnectionType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.net;\n\n/**\n * Describe class ConnectionType here.\n *\n *\n * Created: Sun Feb  5 09:26:44 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum ConnectionType {\n\n\taccept, connect;\n\n} // ConnectionType\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/IOService.java",
    "content": "/*\n * IOService.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.net;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cert.CertCheckResult;\nimport tigase.cert.CertificateUtil;\nimport tigase.io.*;\nimport tigase.stats.StatisticsList;\nimport tigase.util.IOListener;\nimport tigase.xmpp.JID;\n\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLPeerUnverifiedException;\nimport javax.net.ssl.TrustManager;\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.net.Socket;\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.CharBuffer;\nimport java.nio.channels.SocketChannel;\nimport java.nio.charset.*;\nimport java.security.cert.Certificate;\nimport java.security.cert.X509Certificate;\nimport java.util.Map;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * <code>IOService</code> offers thread safe\n * <code>call()</code> method execution, however you must be prepared that other\n * methods can be called simultaneously like\n * <code>stop()</code>,\n * <code>getProtocol()</code> or\n * <code>isConnected()</code>. <br> It is recommended that developers extend\n * <code>AbsractServerService</code> rather then implement\n * <code>ServerService</code> interface directly. <p> If you directly implement\n * <code>ServerService</code> interface you must take care about\n * <code>SocketChannel</code> I/O, queuing tasks, processing results and thread\n * safe execution of\n * <code>call()</code> method. If you however extend\n * <code>IOService</code> class all this basic operation are implemented and you\n * have only to take care about parsing data received from network socket.\n * Parsing data is expected to be implemented in\n * <code>parseData(char[] data)</code> method. </p>\n *\n * <p> Created: Tue Sep 28 23:00:34 2004 </p>\n *\n * @param <RefObject> is a reference object stored by this service. This is e\n * reference to higher level data object keeping more information about the\n * connection.\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class IOService<RefObject>\n\t\t\t\timplements Callable<IOService<?>>, TLSEventHandler,\n\t\t\t\tIOListener {\n\t/**\n\t * Field description\n\t */\n\tpublic static final String CERT_CHECK_RESULT = \"cert-check-result\";\n\t\n\t/**\n\t * Field description\n\t */\n\tpublic static final String CERT_REQUIRED_DOMAIN = \"cert-required-domain\";\n\n\t/**\n\t * Field description\n\t */\n\tpublic static final String HOSTNAME_KEY = \"hostname-key\";\n\n\t/**\n\t * Field description\n\t */\n\tpublic static final String PORT_TYPE_PROP_KEY = \"type\";\n\n\t/**\n\t * This is key used to store session ID in temporary session data\n\t * storage. As it is used by many components it is required that all\n\t * components access session ID with this constant.\n\t */\n\tpublic static final String SESSION_ID_KEY = \"sessionID\";\n\n\t/** Field description */\n\tpublic static final String SSL_PROTOCOLS_KEY = \"ssl-protocols\";\n\n\t/**\n\t * Variable\n\t * <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(IOService.class.getName());\n\tprivate static final long   MAX_ALLOWED_EMPTY_CALLS = 1000;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * The saved partial bytes for multi-byte UTF-8 characters between reads\n\t */\n\tprotected byte[]       partialCharacterBytes = null;\n\tprivate JID            connectionId          = null;\n\tprivate ConnectionType connectionType        = null;\n\tprivate JID            dataReceiver          = null;\n\n\t/**\n\t * Field description\n\t */\n\tprivate long   empty_read_call_count = 0;\n\tprivate String id                    = null;\n\n\t/**\n\t * This variable keeps the time of last transfer in any direction it is\n\t * used to help detect dead connections.\n\t */\n\tprivate long                                    lastTransferTime = 0;\n\tprivate String                                  local_address    = null;\n\tprivate long[]                                  rdData           = new long[60];\n\tprivate RefObject                               refObject        = null;\n\tprivate String                                  remote_address   = null;\n\tprivate IOServiceListener<IOService<RefObject>> serviceListener  = null;\n\tprivate boolean socketServiceReady = false;\n\n\t/**\n\t * <code>socketInput</code> buffer keeps data read from socket.\n\t */\n\tprivate ByteBuffer                    socketInput     = null;\n\tprivate int                           socketInputSize = 2048;\n\tprivate IOInterface                   socketIO        = null;\n\tprivate boolean                       stopping        = false;\n\tprivate long[]                        wrData          = new long[60];\n\tprivate ConcurrentMap<String, Object> sessionData = new ConcurrentHashMap<String,\n\t\t\tObject>(4, 0.75f, 4);\n\n\t// properties from block below should not be used without proper knowledge\n\t// ----- BEGIN ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected CharsetEncoder encoder = Charset.forName(\"UTF-8\").newEncoder();\n\n\t/** Field description */\n\tprotected CharsetDecoder decoder = Charset.forName(\"UTF-8\").newDecoder();\n\n\t/** Field description */\n\tprotected CharBuffer        cb              = CharBuffer.allocate(2048);\n\tprivate final ReentrantLock writeInProgress = new ReentrantLock();\n\tprivate final ReentrantLock readInProgress  = new ReentrantLock();\n\tprivate TrustManager[]      x509TrustManagers;\n\tprivate int bufferLimit = 0;\n\n\tprivate Certificate peerCertificate;\n\n\n\tprivate byte[] tlsUniqueId;\n\tprivate Certificate localCertificate;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method\n\t * <code>accept</code> is used to perform\n\t *\n\t * @param socketChannel a\n\t * <code>SocketChannel</code> value\n\t *\n\t * @throws IOException\n\t */\n\tpublic void accept(final SocketChannel socketChannel) throws IOException {\n\t\ttry {\n\t\t\tif (socketChannel.isConnectionPending()) {\n\t\t\t\tsocketChannel.finishConnect();\n\t\t\t}    // end of if (socketChannel.isConnecyionPending())\n\t\t\tsocketIO = new SocketIO(socketChannel);\n\t\t} catch (IOException e) {\n\t\t\tString host = (String) sessionData.get(\"remote-hostname\");\n\n\t\t\tif (host == null) {\n\t\t\t\thost = (String) sessionData.get(\"remote-host\");\n\t\t\t}\n\n\t\t\tString sock_str = null;\n\n\t\t\ttry {\n\t\t\t\tsock_str = socketChannel.socket().toString();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tsock_str = ex.toString();\n\t\t\t}\n\t\t\tlog.log(Level.FINER,\n\t\t\t\t\t\"Problem connecting to remote host: {0}, address: {1}, socket: {2} - exception: {3}, session data: {4}\",\n\t\t\t\t\tnew Object[] { host,\n\t\t\t\t\tremote_address, sock_str, e, sessionData });\n\n\t\t\tthrow e;\n\t\t}\n\t\tsocketInputSize = socketIO.getSocketChannel().socket().getReceiveBufferSize();\n\t\tsocketInput     = ByteBuffer.allocate(socketInputSize);\n\t\tsocketInput.order(byteOrder());\n\n\t\tSocket sock = socketIO.getSocketChannel().socket();\n\n\t\tlocal_address  = sock.getLocalAddress().getHostAddress();\n\t\tremote_address = sock.getInetAddress().getHostAddress();\n\t\tid = local_address + \"_\" + sock.getLocalPort() + \"_\" + remote_address + \"_\" + sock\n\t\t\t\t.getPort();\n\t\tsetLastTransferTime();\n\t}\n\n\t@Override\n\tpublic IOService<?> call() throws IOException {\n\t\twriteData(null);\n\n\t\tboolean readLock = true;\n\n\t\tif (stopping) {\n\t\t\tstop();\n\t\t} else {\n\t\t\treadLock = readInProgress.tryLock();\n\t\t\tif (readLock) {\n\t\t\t\ttry {\n\t\t\t\t\tprocessSocketData();\n\t\t\t\t\tif ((receivedPackets() > 0) && (serviceListener != null)) {\n\t\t\t\t\t\tserviceListener.packetsReady(this);\n\t\t\t\t\t}    // end of if (receivedPackets.size() > 0)\n\t\t\t\t} finally {\n\t\t\t\t\treadInProgress.unlock();\n\t\t\t\t\tif (!isConnected()) {\n\t\t\t\t\t\t// added to sooner detect disconnection of peer - ie. client\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, stopping connection due to the fact that it was disconnected, forceStop()\", toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tforceStop();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn readLock && socketServiceReady\n\t\t\t\t? this\n\t\t\t\t: null;\n\t}\n\t\n\t@Override\n\tpublic boolean checkBufferLimit(int bufferSize) {\n\t\treturn (bufferLimit == 0 || bufferSize <= bufferLimit);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic ConnectionType connectionType() {\n\t\treturn this.connectionType;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void forceStop() {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Socket: {0}, Force stop called...\", socketIO);\n\t\t}\n\t\ttry {\n\t\t\tif ((socketIO != null) && socketIO.isConnected()) {\n\t\t\t\tsynchronized (socketIO) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Calling stop on: {0}\", socketIO);\n\t\t\t\t\t}\n\t\t\t\t\tsocketIO.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\n\t\t\t// Well, do nothing, we are closing the connection anyway....\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Socket: \" + socketIO +\n\t\t\t\t\t\t\", Exception while stopping service: \" + connectionId, e);\n\t\t\t}\n\t\t} finally {\n\t\t\tif (serviceListener != null) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Calling stop on the listener: {0}\", serviceListener);\n\t\t\t\t}\n\n\t\t\t\tIOServiceListener<IOService<RefObject>> tmp = serviceListener;\n\n\t\t\t\tserviceListener = null;\n\n\t\t\t\t// The temp can still be null if the forceStop is called concurrently\n\t\t\t\tif (tmp != null) {\n\t\t\t\t\ttmp.serviceStopped(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Service listener is null: {0}\", socketIO);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handshakeCompleted(TLSWrapper wrapper) {\n\t\tString reqCertDomain = (String) getSessionData().get(CERT_REQUIRED_DOMAIN);\n\t\tCertCheckResult certCheckResult = wrapper.getCertificateStatus(false);\n\t\tif (reqCertDomain != null) { \n\t\t\t// if reqCertDomain is set then verify if certificate got from server\n\t\t\t// is allowed for reqCertDomain\n\t\t\ttry {\n\t\t\t\tCertificate[] certs = wrapper.getTlsEngine().getSession()\n\t\t\t\t\t\t.getPeerCertificates();\n\t\t\t\tif (certs != null && certs.length > 0) {\n\t\t\t\t\tCertificate peerCert = certs[0];\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, TLS handshake veryfing if certificate from connection matches domain {1}\", \n\t\t\t\t\t\t\t\tnew Object[]{this, reqCertDomain});\n\t\t\t\t\t}\n\t\t\t\t\tif (!CertificateUtil.verifyCertificateForDomain((X509Certificate) peerCert, reqCertDomain)) {\n\t\t\t\t\t\tcertCheckResult = CertCheckResult.invalid;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tcertCheckResult = CertCheckResult.invalid;\n\t\t\t}\n\t\t}\n\t\tsessionData.put(CERT_CHECK_RESULT, certCheckResult);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, TLS handshake completed: {1}\", new Object[]{this,\n\t\t\t\t\tcertCheckResult});\n\t\t}\n\t\tif (!wrapper.getTlsEngine().getUseClientMode()) {\n\t\t\tthis.tlsUniqueId = wrapper.getSessionId();\n\t\t\ttry {\n\t\t\t\tCertificate[] certs = wrapper.getTlsEngine().getSession().getLocalCertificates();\n\t\t\t\tthis.localCertificate = certs == null || certs.length == 0 ? null : certs[certs.length - 1];\n\t\t\t} catch (Exception e) {\n\t\t\t\tthis.localCertificate = null;\n\t\t\t\tlog.log(Level.WARNING, \"Cannot get local certificate\", e);\n\t\t\t}\n\t\t}\n\t\tif (!wrapper.getTlsEngine().getUseClientMode() && (wrapper.getTlsEngine().getWantClientAuth() || wrapper.getTlsEngine().getNeedClientAuth())) {\n\t\t\ttry {\n\t\t\t\tCertificate[] certs = wrapper.getTlsEngine().getSession()\n\t\t\t\t\t\t.getPeerCertificates();\n\t\t\t\tthis.peerCertificate = certs[certs.length - 1];\n\n\t\t\t} catch (SSLPeerUnverifiedException e) {\n\t\t\t\tthis.peerCertificate = null;\n\t\t\t} catch (Exception e) {\n\t\t\t\tthis.peerCertificate = null;\n\t\t\t\tlog.log(Level.WARNING, \"Problem with extracting subjectAltName\", e);\n\t\t\t}\n\t\t}\n\t\tserviceListener.tlsHandshakeCompleted(this);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws IOException\n\t */\n\tpublic abstract void processWaitingPackets() throws IOException;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clientMode\n\t *\n\t * @throws IOException\n\t */\n\tpublic void startSSL(boolean clientMode, boolean wantClientAuth, boolean needClientAuth) throws IOException {\n\t\tif (socketIO instanceof TLSIO) {\n\t\t\tthrow new IllegalStateException(\"SSL mode is already activated.\");\n\t\t}\n\n\t\tString tls_hostname = null;\n\t\tint port = 0;\n\t\tif (clientMode) {\n\t\t\ttls_hostname = (String) this.getSessionData().get(\"remote-host\");\n\t\t\tif (tls_hostname == null) \n\t\t\t\ttls_hostname = (String) this.getSessionData().get(\"remote-hostname\");\n\t\t\tport = ((InetSocketAddress) socketIO.getSocketChannel().getRemoteAddress()).getPort();\n\t\t}\n\t\tSSLContext sslContext;\n\n\t\tif (x509TrustManagers != null) {\n\t\t\tsslContext = TLSUtil.getSSLContext(\"SSL\", tls_hostname, clientMode, x509TrustManagers);\n\t\t} else {\n\t\t\tsslContext = TLSUtil.getSSLContext(\"SSL\", tls_hostname, clientMode);\n\t\t}\n\n\t\tTLSWrapper wrapper = new TLSWrapper(sslContext, this, tls_hostname, port, clientMode, wantClientAuth, needClientAuth);\n\n\t\tsocketIO = new TLSIO(socketIO, wrapper, byteOrder());\n\t\tsetLastTransferTime();\n\t\tencoder.reset();\n\t\tdecoder.reset();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param clientMode\n\t *\n\t * @throws IOException\n\t */\n\tpublic void startTLS(boolean clientMode, boolean wantClientAuth, boolean needClientAuth) throws IOException {\n\t\tif (socketIO.checkCapabilities(TLSIO.TLS_CAPS)) {\n\t\t\tthrow new IllegalStateException(\"TLS mode is already activated \" + connectionId);\n\t\t}\n\n\t\t// This should not take more then 100ms\n\tint counter = 0;\n\n\t\twhile (isConnected() && waitingToSend() && (++counter < 10)) {\n\t\t\twriteData(null);\n\t\t\ttry {\n\t\t\t\tThread.sleep(10);\n\t\t\t} catch (InterruptedException ex) {}\n\t\t}\n\t\tif (counter >= 10) {\n\t\t\tstop();\n\t\t} else {\n\t\t\tString tls_hostname = (String) sessionData.get(HOSTNAME_KEY);\n\t\t\tint port = 0;\n\t\t\tif (clientMode) {\n\t\t\t\tport = ((InetSocketAddress) socketIO.getSocketChannel().getRemoteAddress()).getPort();\n\t\t\t\tif (tls_hostname == null) {\n\t\t\t\t\ttls_hostname = (String) this.getSessionData().get(\"remote-host\");\n\t\t\t\t\tif (tls_hostname == null) \n\t\t\t\t\t\ttls_hostname = (String) this.getSessionData().get(\"remote-hostname\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Starting TLS for domain: {1}\", new Object[] { this,\n\t\t\t\t\t\ttls_hostname });\n\t\t\t}\n\n\t\t\tSSLContext sslContext;\n\n\t\t\tif (x509TrustManagers != null) {\n\t\t\t\tsslContext = TLSUtil.getSSLContext(\"TLS\", tls_hostname, clientMode,\n\t\t\t\t\t\tx509TrustManagers);\n\t\t\t} else {\n\t\t\t\tsslContext = TLSUtil.getSSLContext(\"TLS\", tls_hostname, clientMode);\n\t\t\t}\n\n\t\t\tTLSWrapper wrapper = new TLSWrapper(sslContext, this, tls_hostname, port, clientMode, wantClientAuth, needClientAuth);\n\n\t\t\tsocketIO = new TLSIO(socketIO, wrapper, byteOrder());\n\t\t\tsetLastTransferTime();\n\t\t\tencoder.reset();\n\t\t\tdecoder.reset();\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param level\n\t */\n\tpublic void startZLib(int level) {\n\t\tif (socketIO.checkCapabilities(ZLibIO.ZLIB_CAPS)) {\n\t\t\tthrow new IllegalStateException(\"ZLIB mode is already activated.\");\n\t\t}\n\t\tsocketIO = new ZLibIO(socketIO, level);\n\t\t((ZLibIO) socketIO).setIOListener(this);\n\t}\n\n\t/**\n\t * Describe\n\t * <code>stop</code> method here.\n\t *\n\t */\n\tpublic void stop() {\n\t\tif ((socketIO != null) && socketIO.waitingToSend()) {\n\t\t\tstopping = true;\n\t\t} else {\n\t\t\tforceStop();\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getConnectionId() + \", type: \" + connectionType + \", Socket: \" + socketIO;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean waitingToRead() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean waitingToSend() {\n\t\treturn socketIO.waitingToSend();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int waitingToSendSize() {\n\t\treturn socketIO.waitingToSendSize();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t * \n\t */\n\tpublic long getBuffOverflow(boolean reset) {\n\t\treturn socketIO.getBuffOverflow(reset);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t * \n\t */\n\tpublic long getBytesReceived(boolean reset) {\n\t\treturn socketIO.getBytesReceived(reset);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t * \n\t */\n\tpublic long getBytesSent(boolean reset) {\n\t\treturn socketIO.getBytesSent(reset);\n\t}\n\n\t/**\n\t * @return the connectionId\n\t */\n\tpublic JID getConnectionId() {\n\t\treturn connectionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic JID getDataReceiver() {\n\t\treturn this.dataReceiver;\n\t}\n\n\t/**\n\t * This method returns the time of last transfer in any direction\n\t * through this service. It is used to help detect dead connections.\n\t *\n\t * \n\t */\n\tpublic long getLastTransferTime() {\n\t\treturn lastTransferTime;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getLocalAddress() {\n\t\treturn local_address;\n\t}\n\n\tpublic byte[] getTlsUniqueId() {\n\t\treturn tlsUniqueId;\n\t}\n\n\t/**\n\t * Method returns local port of opened socket\n\t * \n\t * @return \n\t */\n\tpublic int getLocalPort() {\n\t\tSocket sock = socketIO.getSocketChannel().socket();\n\t\treturn sock.getLocalPort();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long[] getReadCounters() {\n\t\treturn rdData;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic RefObject getRefObject() {\n\t\treturn refObject;\n\t}\n\n\t/**\n\t * Returns a remote IP address for the TCP/IP connection.\n\t *\n\t *\n\t * @return a remote IP address for the TCP/IP connection.\n\t */\n\tpublic String getRemoteAddress() {\n\t\treturn remote_address;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic ConcurrentMap<String, Object> getSessionData() {\n\t\treturn sessionData;\n\t}\n\n\t/**\n\t * Method\n\t * <code>getSocketChannel</code> is used to perform\n\t *\n\t * @return a\n\t * <code>SocketChannel</code> value\n\t */\n\tpublic SocketChannel getSocketChannel() {\n\t\treturn socketIO.getSocketChannel();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param list\n\t * @param reset\n\t */\n\tpublic void getStatistics(StatisticsList list, boolean reset) {\n\t\tif (socketIO != null) {\n\t\t\tsocketIO.getStatistics(list, reset);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getTotalBuffOverflow() {\n\t\treturn socketIO.getTotalBuffOverflow();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getTotalBytesReceived() {\n\t\treturn socketIO.getTotalBytesReceived();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getTotalBytesSent() {\n\t\treturn socketIO.getTotalBytesSent();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getUniqueId() {\n\t\treturn id;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long[] getWriteCounters() {\n\t\treturn wrData;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic TrustManager[] getX509TrustManagers() {\n\t\treturn x509TrustManagers;\n\t}\n\n\t/**\n\t * Describe\n\t * <code>isConnected</code> method here.\n\t *\n\t * @return a\n\t * <code>boolean</code> value\n\t */\n\tpublic boolean isConnected() {\n\t\tboolean result = (socketIO == null)\n\t\t\t\t? false\n\t\t\t\t: socketIO.isConnected();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\n\t\t\t// if (socketIO.getSocketChannel().socket().getLocalPort() == 5269) {\n\t\t\t// Throwable thr = new Throwable();\n\t\t\t//\n\t\t\t// thr.fillInStackTrace();\n\t\t\t// log.log(Level.FINEST, \"Socket: \" + socketIO + \", Connected: \" + result,\n\t\t\t// thr);\n\t\t\t// }\n\t\t\tlog.log(Level.FINEST, \"Socket: {0}, Connected: {1}, id: {2}\", new Object[] {\n\t\t\t\t\tsocketIO,\n\t\t\t\t\tresult, connectionId });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tpublic void setBufferLimit(int bufferLimit) {\n\t\tthis.bufferLimit = bufferLimit;\n\t}\n\t\n\t/**\n\t * @param connectionId the connectionId to set\n\t */\n\tpublic void setConnectionId(JID connectionId) {\n\t\tthis.connectionId = connectionId;\n\t\tsocketIO.setLogId(connectionId.toString());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param address\n\t */\n\tpublic void setDataReceiver(JID address) {\n\t\tthis.dataReceiver = address;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sl\n\t */\n\n\t// @SuppressWarnings(\"unchecked\")\n\tpublic void setIOServiceListener(IOServiceListener<IOService<RefObject>> sl) {\n\t\tthis.serviceListener = sl;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param refObject\n\t */\n\tpublic void setRefObject(RefObject refObject) {\n\t\tthis.refObject = refObject;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param props\n\t */\n\tpublic void setSessionData(Map<String, Object> props) {\n\n\t\t// Sometimes, some values are null which is allowed in the original Map\n\t\t// however, ConcurrentHashMap does not allow nulls as value so we have\n\t\t// to copy Maps carefully.\n\t\tsessionData = new ConcurrentHashMap<String, Object>(props.size());\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getValue() != null) {\n\t\t\t\tsessionData.put(entry.getKey(), entry.getValue());\n\t\t\t}\n\t\t}\n\t\tconnectionType = ConnectionType.valueOf(sessionData.get(PORT_TYPE_PROP_KEY)\n\t\t\t\t.toString());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param trustManager\n\t */\n\tpublic void setX509TrustManagers(TrustManager[] trustManager) {\n\t\tthis.x509TrustManagers = trustManager;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tprotected ByteOrder byteOrder() {\n\t\treturn ByteOrder.BIG_ENDIAN;\n\t}\n\n\t/**\n\t * Describe\n\t * <code>debug</code> method here.\n\t *\n\t * @param msg a\n\t * <code>char[]</code> value\n\t * @return a\n\t * <code>boolean</code> value\n\t */\n\tprotected boolean debug(final char[] msg) {\n\t\tif (msg != null) {\n\t\t\tSystem.out.print(new String(msg));\n\n\t\t\t// log.finest(\"\\n\" + new String(msg) + \"\\n\");\n\t\t}    // end of if (msg != null)\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Describe\n\t * <code>debug</code> method here.\n\t *\n\t * @param msg a\n\t * <code>String</code> value\n\t * @param prefix\n\t * @return a\n\t * <code>boolean</code> value\n\t */\n\tprotected boolean debug(final String msg, final String prefix) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tif ((msg != null) && (msg.trim().length() > 0)) {\n\t\t\t\tString log_msg = \"\\n\" + ((connectionType() != null)\n\t\t\t\t\t\t? connectionType().toString()\n\t\t\t\t\t\t: \"null-type\") + \" \" + prefix + \"\\n\" + msg + \"\\n\";\n\n\t\t\t\t// System.out.print(log_msg);\n\t\t\t\tlog.finest(log_msg);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws IOException\n\t */\n\tprotected abstract void processSocketData() throws IOException;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t *\n\t * @throws IOException\n\t */\n\tprotected ByteBuffer readBytes() throws IOException {\n\t\tsetLastTransferTime();\n\t\tif (log.isLoggable(Level.FINEST) && (empty_read_call_count > 10)) {\n\t\t\tThrowable thr = new Throwable();\n\n\t\t\tthr.fillInStackTrace();\n\t\t\tlog.log(Level.FINEST, \"Socket: \" + socketIO, thr);\n\t\t}\n\t\ttry {\n\t\t\tByteBuffer tmpBuffer = socketIO.read(socketInput);\n\n\t\t\tif (socketIO.bytesRead() > 0) {\n\t\t\t\tempty_read_call_count = 0;\n\n\t\t\t\treturn tmpBuffer;\n\t\t\t} else {\n\t\t\t\tif ((++empty_read_call_count) > MAX_ALLOWED_EMPTY_CALLS && (!writeInProgress\n\t\t\t\t\t\t.isLocked())) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Socket: {0}, Max allowed empty calls excceeded, closing connection.\",\n\t\t\t\t\t\t\tsocketIO);\n\t\t\t\t\tforceStop();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (BufferUnderflowException ex) {\n\t\t\tresizeInputBuffer();\n\n\t\t\treturn readBytes();\n\t\t} catch (Exception eof) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Socket: \" + socketIO + \", Exception reading data\", eof);\n\t\t\t}\n\n\t\t\t// eof.printStackTrace();\n\t\t\tforceStop();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tprotected void readCompleted() {\n\t\tdecoder.reset();\n\t}\n\n\t/**\n\t * Describe\n\t * <code>readData</code> method here.\n\t *\n\t * @return a\n\t * <code>char[]</code> value\n\t * @exception IOException if an error occurs\n\t */\n\tprotected char[] readData() throws IOException {\n\t\tsetLastTransferTime();\n\t\tif (log.isLoggable(Level.FINEST) && (empty_read_call_count > 10)) {\n\t\t\tThrowable thr = new Throwable();\n\n\t\t\tthr.fillInStackTrace();\n\t\t\tlog.log(Level.FINEST, \"Socket: \" + socketIO, thr);\n\t\t}\n\n\t\t// Generally it should not happen as it is called only in\n\t\t// call() which has concurrent call protection.\n\t\t// synchronized (socketIO) {\n\t\ttry {\n\n\t\t\t// resizeInputBuffer();\n\t\t\t// Maybe we can shrink the input buffer??\n\t\t\tif ((socketInput.capacity() > socketInputSize) && (socketInput.remaining() ==\n\t\t\t\t\tsocketInput.capacity())) {\n\n\t\t\t\t// Yes, looks like we can\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE, \"Socket: {0}, Resizing socketInput down to {1} bytes.\",\n\t\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\t\tsocketInputSize });\n\t\t\t\t}\n\t\t\t\tsocketInput = ByteBuffer.allocate(socketInputSize);\n\t\t\t\tsocketInput.order(byteOrder());\n\t\t\t\tcb = CharBuffer.allocate(socketInputSize * 4);\n\t\t\t}\n\n\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t// log.finer(\"Before read from socket.\");\n\t\t\t// log.finer(\"socketInput.capacity()=\" + socketInput.capacity());\n\t\t\t// log.finer(\"socketInput.remaining()=\" + socketInput.remaining());\n\t\t\t// log.finer(\"socketInput.limit()=\" + socketInput.limit());\n\t\t\t// log.finer(\"socketInput.position()=\" + socketInput.position());\n\t\t\t// }\n\t\t\tByteBuffer tmpBuffer = socketIO.read(socketInput);\n\n\t\t\tif (socketIO.bytesRead() > 0) {\n\t\t\t\tempty_read_call_count = 0;\n\n\t\t\t\tchar[] result = null;\n\n\t\t\t\t// There might be some characters read from the network\n\t\t\t\t// but the buffer may still be null or empty because there might\n\t\t\t\t// be not enough data to decode TLS or compressed buffer.\n\t\t\t\tif (tmpBuffer != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, Reading network binary data: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\t\t\tsocketIO.bytesRead() });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Restore the partial bytes for multibyte UTF8 characters\n\t\t\t\t\tif (partialCharacterBytes != null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Reloading partial bytes \" + partialCharacterBytes.length);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tByteBuffer oldTmpBuffer = tmpBuffer;\n\n\t\t\t\t\t\ttmpBuffer = ByteBuffer.allocate(partialCharacterBytes.length + oldTmpBuffer\n\t\t\t\t\t\t\t\t.remaining() + 2);\n\t\t\t\t\t\ttmpBuffer.order(byteOrder());\n\t\t\t\t\t\ttmpBuffer.put(partialCharacterBytes);\n\t\t\t\t\t\ttmpBuffer.put(oldTmpBuffer);\n\t\t\t\t\t\ttmpBuffer.flip();\n\t\t\t\t\t\toldTmpBuffer.clear();\n\t\t\t\t\t\tpartialCharacterBytes = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t// log.finer(\"Before decoding data\");\n\t\t\t\t\t// log.finer(\"socketInput.capacity()=\" + socketInput.capacity());\n\t\t\t\t\t// log.finer(\"socketInput.remaining()=\" + socketInput.remaining());\n\t\t\t\t\t// log.finer(\"socketInput.limit()=\" + socketInput.limit());\n\t\t\t\t\t// log.finer(\"socketInput.position()=\" + socketInput.position());\n\t\t\t\t\t// log.finer(\"tmpBuffer.capacity()=\" + tmpBuffer.capacity());\n\t\t\t\t\t// log.finer(\"tmpBuffer.remaining()=\" + tmpBuffer.remaining());\n\t\t\t\t\t// log.finer(\"tmpBuffer.limit()=\" + tmpBuffer.limit());\n\t\t\t\t\t// log.finer(\"tmpBuffer.position()=\" + tmpBuffer.position());\n\t\t\t\t\t// log.finer(\"cb.capacity()=\" + cb.capacity());\n\t\t\t\t\t// log.finer(\"cb.remaining()=\" + cb.remaining());\n\t\t\t\t\t// log.finer(\"cb.limit()=\" + cb.limit());\n\t\t\t\t\t// log.finer(\"cb.position()=\" + cb.position());\n\t\t\t\t\t// }\n\t\t\t\t\t// tmpBuffer.flip();\n\t\t\t\t\tif (cb.capacity() < tmpBuffer.remaining() * 4) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, resizing character buffer to: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\t\t\t\ttmpBuffer.remaining() });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcb = CharBuffer.allocate(tmpBuffer.remaining() * 4);\n\t\t\t\t\t}\n\n\t\t\t\t\tCoderResult cr = decoder.decode(tmpBuffer, cb, false);\n\n\t\t\t\t\tif (cr.isMalformed()) {\n\t\t\t\t\t\tthrow new MalformedInputException(tmpBuffer.remaining());\n\t\t\t\t\t}\n\t\t\t\t\tif (cb.remaining() > 0) {\n\t\t\t\t\t\tcb.flip();\n\t\t\t\t\t\tresult = new char[cb.remaining()];\n\t\t\t\t\t\tcb.get(result);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, Decoded character data: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\t\t\t\tnew String(result) });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t// log.finer(\"Just after decoding.\");\n\t\t\t\t\t\t// log.finer(\"tmpBuffer.capacity()=\" + tmpBuffer.capacity());\n\t\t\t\t\t\t// log.finer(\"tmpBuffer.remaining()=\" + tmpBuffer.remaining());\n\t\t\t\t\t\t// log.finer(\"tmpBuffer.limit()=\" + tmpBuffer.limit());\n\t\t\t\t\t\t// log.finer(\"tmpBuffer.position()=\" + tmpBuffer.position());\n\t\t\t\t\t\t// log.finer(\"cb.capacity()=\" + cb.capacity());\n\t\t\t\t\t\t// log.finer(\"cb.remaining()=\" + cb.remaining());\n\t\t\t\t\t\t// log.finer(\"cb.limit()=\" + cb.limit());\n\t\t\t\t\t\t// log.finer(\"cb.position()=\" + cb.position());\n\t\t\t\t\t\t// }\n\t\t\t\t\t}\n\t\t\t\t\tif (cr.isUnderflow() && (tmpBuffer.remaining() > 0)) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, UTF-8 decoder data underflow: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\t\t\t\ttmpBuffer.remaining() });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Save the partial bytes of a multibyte character such that they\n\t\t\t\t\t\t// can be restored on the next read.\n\t\t\t\t\t\tpartialCharacterBytes = new byte[tmpBuffer.remaining()];\n\t\t\t\t\t\ttmpBuffer.get(partialCharacterBytes);\n\t\t\t\t\t}\n\t\t\t\t\ttmpBuffer.clear();\n\t\t\t\t\tcb.clear();\n\n\t\t\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t// log.finer(\"Before return from method.\");\n\t\t\t\t\t// log.finer(\"tmpBuffer.capacity()=\" + tmpBuffer.capacity());\n\t\t\t\t\t// log.finer(\"tmpBuffer.remaining()=\" + tmpBuffer.remaining());\n\t\t\t\t\t// log.finer(\"tmpBuffer.limit()=\" + tmpBuffer.limit());\n\t\t\t\t\t// log.finer(\"tmpBuffer.position()=\" + tmpBuffer.position());\n\t\t\t\t\t// log.finer(\"cb.capacity()=\" + cb.capacity());\n\t\t\t\t\t// log.finer(\"cb.remaining()=\" + cb.remaining());\n\t\t\t\t\t// log.finer(\"cb.limit()=\" + cb.limit());\n\t\t\t\t\t// log.finer(\"cb.position()=\" + cb.position());\n\t\t\t\t\t// }\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Detecting infinite read 0 bytes\n\t\t\t\t// sometimes it happens that the connection has been lost\n\t\t\t\t// and the select thinks there are some bytes waiting for reading\n\t\t\t\t// and 0 bytes are read\n\t\t\t\tif ((++empty_read_call_count) > MAX_ALLOWED_EMPTY_CALLS && (!writeInProgress\n\t\t\t\t\t\t.isLocked())) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Socket: {0}, Max allowed empty calls excceeded, closing connection.\",\n\t\t\t\t\t\t\tsocketIO);\n\t\t\t\t\tforceStop();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (BufferUnderflowException ex) {\n\n\t\t\t// Obtain more inbound network data for src,\n\t\t\t// then retry the operation.\n\t\t\tresizeInputBuffer();\n\n\t\t\treturn null;\n\n\t\t\t// } catch (MalformedInputException ex) {\n\t\t\t//// This happens after TLS initialization sometimes, maybe reset helps\n\t\t\t// decoder.reset();\n\t\t} catch (Exception eof) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Socket: \" + socketIO + \", Exception reading data\", eof);\n\t\t\t}\n\n\t\t\t// eof.printStackTrace();\n\t\t\tforceStop();\n\t\t}    // end of try-catch\n\n\t\t// }\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tprotected abstract int receivedPackets();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t */\n\tprotected void writeBytes(ByteBuffer data) {\n\n\t\t// Try to lock the data writing method\n\t\tboolean locked = writeInProgress.tryLock();\n\n\t\t// If cannot lock and nothing to send, just leave\n\t\tif (!locked && (data == null)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise wait.....\n\t\tif (!locked) {\n\t\t\twriteInProgress.lock();\n\t\t}\n\n\t\t// Avoid concurrent calls here (one from call() and another from\n\t\t// application)\n\t\ttry {\n\t\t\tif ((data != null) && data.hasRemaining()) {\n\t\t\t\tint length = data.remaining();\n\n\t\t\t\tsocketIO.write(data);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, wrote: {1}\", new Object[] { socketIO,\n\t\t\t\t\t\t\tlength });\n\t\t\t\t}\n\n\t\t\t\t// idx_start = idx_offset;\n\t\t\t\t// idx_offset = Math.min(idx_start + out_buff_size, data.length());\n\t\t\t\t// }\n\t\t\t\tsetLastTransferTime();\n\n\t\t\t\t// addWritten(data.length());\n\t\t\t\tempty_read_call_count = 0;\n\t\t\t} else {\n\t\t\t\tif (socketIO.waitingToSend()) {\n\t\t\t\t\tsocketIO.write(null);\n\t\t\t\t\tsetLastTransferTime();\n\t\t\t\t\tempty_read_call_count = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Data writing exception \" + connectionId, e);\n\t\t\t}\n\t\t\tforceStop();\n\t\t} finally {\n\t\t\twriteInProgress.unlock();\n\t\t}\n\t}\n\n\t/**\n\t * Describe\n\t * <code>writeData</code> method here.\n\t *\n\t * @param data a\n\t * <code>String</code> value\n\t */\n\tprotected void writeData(final String data) {\n\n\t\t// Try to lock the data writing method\n\t\tboolean locked = writeInProgress.tryLock();\n\n\t\t// If cannot lock and nothing to send, just leave\n\t\tif (!locked && (data == null)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise wait.....\n\t\tif (!locked) {\n\t\t\twriteInProgress.lock();\n\t\t}\n\n\t\t// Avoid concurrent calls here (one from call() and another from\n\t\t// application)\n\t\ttry {\n\t\t\tif ((data != null) && (data.length() > 0)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tif (data.length() < 256) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, Writing data ({1}): {2}\", new Object[] {\n\t\t\t\t\t\t\t\tsocketIO,\n\t\t\t\t\t\t\t\tdata.length(), data });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, Writing data: {1}\", new Object[] {\n\t\t\t\t\t\t\t\tsocketIO,\n\t\t\t\t\t\t\t\tdata.length() });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tByteBuffer dataBuffer = null;\n\n\t\t\t\t// int out_buff_size = data.length();\n\t\t\t\t// int idx_start = 0;\n\t\t\t\t// int idx_offset = Math.min(idx_start + out_buff_size, data.length());\n\t\t\t\t//\n\t\t\t\t// while (idx_start < data.length()) {\n\t\t\t\t// String data_str = data.substring(idx_start, idx_offset);\n\t\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t\t// log.finest(\"Writing data_str (\" + data_str.length() + \"), idx_start=\"\n\t\t\t\t// + idx_start + \", idx_offset=\" + idx_offset + \": \" + data_str);\n\t\t\t\t// }\n\t\t\t\tencoder.reset();\n\n\t\t\t\t// dataBuffer = encoder.encode(CharBuffer.wrap(data, idx_start,\n\t\t\t\t// idx_offset));\n\t\t\t\tdataBuffer = encoder.encode(CharBuffer.wrap(data));\n\t\t\t\tencoder.flush(dataBuffer);\n\t\t\t\tsocketIO.write(dataBuffer);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, wrote: {1}\", new Object[] { socketIO,\n\t\t\t\t\t\t\tdata.length() });\n\t\t\t\t}\n\n\t\t\t\t// idx_start = idx_offset;\n\t\t\t\t// idx_offset = Math.min(idx_start + out_buff_size, data.length());\n\t\t\t\t// }\n\t\t\t\tsetLastTransferTime();\n\n\t\t\t\t// addWritten(data.length());\n\t\t\t\tempty_read_call_count = 0;\n\t\t\t} else {\n\t\t\t\tif (socketIO.waitingToSend()) {\n\t\t\t\t\tsocketIO.write(null);\n\t\t\t\t\tsetLastTransferTime();\n\t\t\t\t\tempty_read_call_count = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Data writing exception \" + connectionId, e);\n\t\t\t}\n\t\t\tforceStop();\n\t\t} finally {\n\t\t\twriteInProgress.unlock();\n\t\t}\n\t}\n\t\n\tprotected boolean isSocketServiceReady() {\n\t\treturn socketServiceReady;\n\t}\n\t\n\tprotected void setSocketServiceReady(boolean value) {\n\t\tthis.socketServiceReady = value;\n\t}\t\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t * \n\t */\n\tprotected boolean isInputBufferEmpty() {\n\t\treturn (socketInput != null) && (socketInput.remaining() == socketInput.capacity());\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void resizeInputBuffer() throws IOException {\n\t\tint netSize = socketIO.getInputPacketSize();\n\n\t\t// Resize buffer if needed.\n\t\t// if (netSize > socketInput.remaining()) {\n\t\tif (netSize > socketInput.capacity() - socketInput.remaining()) {\n\n\t\t\t// int newSize = netSize + socketInput.capacity();\n\t\t\tint newSize = socketInput.capacity() + socketInputSize;\n\t\t\tif (!checkBufferLimit(bufferLimit)) {\n\t\t\t\tthrow new IOException(\"Input buffer size limit exceeded\");\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Socket: {0}, Resizing socketInput to {1} bytes.\",\n\t\t\t\t\t\tnew Object[] { socketIO,\n\t\t\t\t\t\tnewSize });\n\t\t\t}\n\n\t\t\tByteBuffer b = ByteBuffer.allocate(newSize);\n\n\t\t\tb.order(byteOrder());\n\t\t\tb.put(socketInput);\n\t\t\tsocketInput = b;\n\t\t} else {\n\n\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t// log.finer(\"     Before flip()\");\n\t\t\t// log.finer(\"input.capacity()=\" + socketInput.capacity());\n\t\t\t// log.finer(\"input.remaining()=\" + socketInput.remaining());\n\t\t\t// log.finer(\"input.limit()=\" + socketInput.limit());\n\t\t\t// log.finer(\"input.position()=\" + socketInput.position());\n\t\t\t// }\n\t\t\t// socketInput.flip();\n\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t// log.finer(\"     Before compact()\");\n\t\t\t// log.finer(\"input.capacity()=\" + socketInput.capacity());\n\t\t\t// log.finer(\"input.remaining()=\" + socketInput.remaining());\n\t\t\t// log.finer(\"input.limit()=\" + socketInput.limit());\n\t\t\t// log.finer(\"input.position()=\" + socketInput.position());\n\t\t\t// }\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Socket: {0}, Compacting socketInput.\", socketIO);\n\t\t\t}\n\t\t\tsocketInput.compact();\n\n\t\t\t// if (log.isLoggable(Level.FINEST)) {\n\t\t\t// log.finer(\"     After compact()\");\n\t\t\t// log.finer(\"input.capacity()=\" + socketInput.capacity());\n\t\t\t// log.finer(\"input.remaining()=\" + socketInput.remaining());\n\t\t\t// log.finer(\"input.limit()=\" + socketInput.limit());\n\t\t\t// log.finer(\"input.position()=\" + socketInput.position());\n\t\t\t// }\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprivate void setLastTransferTime() {\n\t\tlastTransferTime = System.currentTimeMillis();\n\t}\n\n\tpublic Certificate getPeerCertificate() {\n\t\treturn peerCertificate;\n\t}\n\n\tpublic Certificate getLocalCertificate() {\n\t\treturn localCertificate;\n\t}\n\n\n\n}    // IOService\n\n\n//~ Formatted in Tigase Code Convention on 13/05/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/IOServiceListener.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.net;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface IOServiceListener here.\n *\n *\n * Created: Mon Jan 30 22:37:51 2006\n *\n * @param <IO>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface IOServiceListener<IO extends IOService<?>> {\n\tvoid packetsReady(IO service) throws IOException;\n\n\tboolean serviceStopped(IO service);\n\n\tvoid tlsHandshakeCompleted(IO service);\n}    // IOServiceListener\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/IOUtil.java",
    "content": "/*\n * IOUtil.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.net;\n\nimport java.net.Socket;\nimport java.net.SocketException;\nimport java.nio.ByteBuffer;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport sun.nio.ch.DirectBuffer;\n\n/**\n *\n * @author andrzej\n */\npublic class IOUtil {\n\n\tprivate static final Logger log = Logger.getLogger(IOUtil.class.getCanonicalName());\n\t\n\tprivate static final String DIRECT_BUFFER_DEFAULT_SIZE = \"direct-buffer-default-size\";\n\t\n\tprivate static final ThreadLocal<BufferCache> buffers = new ThreadLocal<BufferCache>();\n\t\n\tprivate static int bufferSize;\n\t\n\tstatic {\n\t\tInteger size = Integer.getInteger(DIRECT_BUFFER_DEFAULT_SIZE);\n\t\tif (size == null) {\n\t\t\tSocket socket = new Socket();\n\t\t\ttry {\n\t\t\t\t// using socket native buffer size for best performance\n\t\t\t\tbufferSize = java.lang.Math.max(socket.getReceiveBufferSize(), socket.getSendBufferSize());\n\t\t\t}\n\t\t\tcatch(SocketException ex) {\n\t\t\t\t// cloud not get default value from system - setting to 64k\n\t\t\t\tbufferSize = 64 * 1024;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbufferSize = size;\n\t\t}\n\t\t\n\t\tlog.log(Level.CONFIG, \"using direct byte buffers with size {0} per buffer\", bufferSize);\n\t}\n\t\n\tpublic static ByteBuffer getDirectBuffer(int size) {\n\t\tBufferCache cache = buffers.get();\n\t\tif (cache == null) {\n\t\t\tcache = new BufferCache(bufferSize);\n\t\t\tbuffers.set(cache);\n\t\t}\n\t\t\n\t\treturn cache.get(size);\t\t\n\t}\n\t\n\tpublic static void returnDirectBuffer(ByteBuffer buf) {\n\t\tBufferCache cache = buffers.get();\n\t\tif (cache != null) {\n\t\t\tcache.offer(buf);\n\t\t}\n\t\telse {\n\t\t\tlog.log(Level.SEVERE, \"returning direct buffer to cache, but no cache found\");\n\t\t}\n\t}\n\t\n\tprivate static class BufferCache {\n\t\n\t\tprivate int count = 1;\n\t\tprivate final ByteBuffer buffer;\n\t\t\n\t\tpublic BufferCache(int size) {\n\t\t\tbuffer = ByteBuffer.allocateDirect(size);\n\t\t}\t\t\n\t\t\n\t\tpublic ByteBuffer get(int size) {\n\t\t\tif (count == 1 && size <= buffer.capacity()) {\n\t\t\t\tcount = 0;\n\t\t\t\tbuffer.limit(size);\n\t\t\t\treturn buffer;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"allocating buffer with size = {0}\", size);\n\t\t\t\t}\n\t\t\t\treturn ByteBuffer.allocateDirect(size);\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void offer(ByteBuffer buffer) {\n\t\t\tif (this.buffer == buffer) {\n\t\t\t\tcount = 1;\n\t\t\t\tbuffer.rewind();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfreeBuffer(buffer);\n\t\t\t}\n\t\t}\n\t\t\t\t\n\t\tprivate void freeBuffer(ByteBuffer buf) {\n\t\t\t((DirectBuffer) buf).cleaner().clean();\n\t\t}\n\t\t\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/ServiceCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.net;\n\n/**\n * <code>ServiceCommand</code> is enumerated type defining all possible\n * commands related to <code>ServiceData</code> instances.\n * These commands are processed by <code>MessageDispatcher</code>\n * implementations. Some commands are related to data encapsulated in\n * <code>ServiceData</code> instance like <code>SEND_MESSAGE</code> or\n * <code>BROADCAST</code> others are related to <code>ServerService</code>\n * sending or receiving this message like:\n * <code>STOP</code>, <code>CONNECTED</code> and so on. Please refer to detailed\n * API documentation for more information.\n *\n * <p>\n * Created: Sun Oct 17 22:32:22 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum ServiceCommand {\n\n  STOP,\n  STOPPED,\n  CONNECT,\n  CONNECTED,\n  SEND_MESSAGE,\n  BROADCAST;\n\n} // ServiceCommand\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/SocketThread.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.net;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.annotations.TODO;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.nio.channels.CancelledKeyException;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.Selector;\nimport java.nio.channels.SocketChannel;\n\nimport java.util.Comparator;\nimport java.util.Set;\nimport java.util.concurrent.CompletionService;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorCompletionService;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class SocketThread here.\n *\n *\n * Created: Mon Jan 30 12:01:17 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SocketThread implements Runnable {\n\tprivate static final Logger log = Logger.getLogger(SocketThread.class.getName());\n\n\t/** Field description */\n\tpublic static final int DEF_MAX_THREADS_PER_CPU = 8;\n\tprivate static final int MAX_EMPTY_SELECTIONS = 10;\n\tprivate static SocketThread[] socketReadThread = null;\n\tprivate static SocketThread[] socketWriteThread = null;\n\tprivate static int cpus = Runtime.getRuntime().availableProcessors();\n\tprivate static ThreadPoolExecutor executor = null;\n\n\t/**\n\t * Variable <code>completionService</code> keeps reference to server thread pool.\n\t * There is only one thread pool used by all server modules. Each module requiring\n\t * separate threads for tasks processing must have access to server thread pool.\n\t */\n\tprivate static CompletionService<IOService<?>> completionService = null;\n\n\t//~--- static initializers --------------------------------------------------\n\n//private static int threadNo = 0;\n//private static final int READ_ONLY = SelectionKey.OP_READ;\n//private static final int READ_WRITE = SelectionKey.OP_READ | SelectionKey.OP_WRITE;\n\tstatic {\n\t\tif (socketReadThread == null) {\n\t\t\tint nThreads = (cpus * DEF_MAX_THREADS_PER_CPU) / 2 + 1;\n\n\t\t\texecutor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,\n\t\t\t\t\tnew LinkedBlockingQueue<Runnable>());\n\t\t\tcompletionService = new ExecutorCompletionService<IOService<?>>(executor);\n\t\t\tsocketReadThread = new SocketThread[nThreads];\n\t\t\tsocketWriteThread = new SocketThread[nThreads];\n\n\t\t\tfor (int i = 0; i < socketReadThread.length; i++) {\n\t\t\t\tsocketReadThread[i] = new SocketThread(\"socketReadThread-\" + i);\n\t\t\t\tsocketReadThread[i].reading = true;\n\n\t\t\t\tThread thrd = new Thread(socketReadThread[i]);\n\n\t\t\t\tthrd.setName(\"socketReadThread-\" + i);\n\t\t\t\tthrd.start();\n\t\t\t}\n\n\t\t\tlog.log(Level.WARNING, \"{0} socketReadThreads started.\", socketReadThread.length);\n\n\t\t\tfor (int i = 0; i < socketWriteThread.length; i++) {\n\t\t\t\tsocketWriteThread[i] = new SocketThread(\"socketWriteThread-\" + i);\n\t\t\t\tsocketWriteThread[i].writing = true;\n\n\t\t\t\tThread thrd = new Thread(socketWriteThread[i]);\n\n\t\t\t\tthrd.setName(\"socketWriteThread-\" + i);\n\t\t\t\tthrd.start();\n\t\t\t}\n\n\t\t\tlog.log(Level.WARNING, \"{0} socketWriteThreads started.\", socketWriteThread.length);\n\t\t}    // end of if (acceptThread == null)\n\t}\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Selector clientsSel = null;\n\n\t// private boolean selecting = false;\n\tprivate int empty_selections = 0;\n\tprivate boolean reading = false;\n\tprivate boolean writing = false;\n\tprivate ConcurrentSkipListSet<IOService<?>> waiting =\n\t\tnew ConcurrentSkipListSet<IOService<?>>(new IOServiceComparator());\n\tprivate boolean stopping = false;\n\n\t// IOServices must be added to thread pool after they are removed from\n\t// the selector and the selector and key is cleared, otherwise we have\n\t// dead-lock somewhere down in the:\n\t// java.nio.channels.spi.AbstractSelectableChannel.removeKey(AbstractSelectableChannel.java:111)\n\tprivate ConcurrentSkipListSet<IOService<?>> forCompletion =\n\t\tnew ConcurrentSkipListSet<IOService<?>>(new IOServiceComparator());\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>SocketThread</code> instance.\n\t *\n\t */\n\tprivate SocketThread(String name) {\n\t\ttry {\n\t\t\tclientsSel = Selector.open();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Server I/O error, can't continue my work.\", e);\n\t\t\tstopping = true;\n\t\t}    // end of try-catch\n\n\t\tnew ResultsListener(\"ResultsListener-\" + name).start();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n///**\n// * Method description\n// *\n// *\n// * \n// */\n//public static SocketThread getInstance() {\n//  return socketReadThread[0];\n//}\n//private static final Object threadNoSync = new Object();\n//private int incrementAndGet() {\n//int result = 0;\n//synchronized (threadNoSync) {\n//  threadNo = (threadNo + 1) % socketReadThread.length;\n//  result = threadNo;\n//}\n//return result;\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param s\n\t */\n\tpublic static void addSocketService(IOService<?> s) {\n\t\ts.setSocketServiceReady(true);\n\t\t// Due to a delayed SelectionKey cancelling deregistering\n\t\t// nature this distribution doesn't work well, it leads to\n\t\t// dead-lock. Let's make sure the service is always processed\n\t\t// by the same thread thus the same Selector.\n\t\t// socketReadThread[incrementAndGet()].addSocketServicePriv(s);\n\t\tif (s.waitingToRead()) {\n\t\t\tsocketReadThread[s.hashCode() % socketReadThread.length].addSocketServicePriv(s);\n\t\t}\n\n\t\tif (s.waitingToSend()) {\n\t\t\tsocketWriteThread[s.hashCode() % socketWriteThread.length].addSocketServicePriv(s);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param s\n\t */\n\tpublic static void removeSocketService(IOService<Object> s) {\n\t\ts.setSocketServiceReady(false);\n\t\tsocketReadThread[s.hashCode() % socketReadThread.length].removeSocketServicePriv(s);\n\t\tsocketWriteThread[s.hashCode() % socketWriteThread.length].removeSocketServicePriv(s);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param s\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void addSocketServicePriv(IOService<?> s) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Adding to waiting: {0}\", s);\n\t\t}\n\n\t\twaiting.add((IOService<Object>) s);\n\n\t\t// Calling lazy wakeup to avoid multiple wakeup calls\n\t\t// when lots of new services are added....\n\t\tclientsSel.wakeup();\n\n\t\t// wakeupHelper.wakeup();\n\t}\n\n\tpublic void removeSocketServicePriv(IOService<?> s) {\n\t\twaiting.remove(s);\n\t\t\n\t\tSelectionKey key = s.getSocketChannel().keyFor(clientsSel);\n\t\tif ((key != null) && (key.attachment() == s)) {\n\t\t\tkey.cancel();\n\t\t}\n\t}\n\t\n\t@SuppressWarnings({ \"unchecked\" })\n\t@Override\n\tpublic void run() {\n\t\twhile ( !stopping) {\n\t\t\ttry {\n\t\t\t\tclientsSel.select();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Selector AWAKE: {0}\", clientsSel);\n\t\t\t\t}\n\n\t\t\t\tSet<SelectionKey> selected = clientsSel.selectedKeys();\n\t\t\t\tint selectedKeys = selected.size();\n\n\t\t\t\tif ((selectedKeys == 0) && (waiting.size() == 0)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Selected keys = 0!!! a bug again?\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((++empty_selections) > MAX_EMPTY_SELECTIONS) {\n\t\t\t\t\t\trecreateSelector();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tempty_selections = 0;\n\n\t\t\t\t\tif (selectedKeys > 0) {\n\n\t\t\t\t\t\t// This is dirty but selectNow() causes concurrent modification exception\n\t\t\t\t\t\t// and the selectNow() is needed because of a bug in JVM mentioned below\n\t\t\t\t\t\tfor (SelectionKey sk : selected) {\n\n\t\t\t\t\t\t\t// According to most guides we should use below code\n\t\t\t\t\t\t\t// removing SelectionKey from iterator, however a little later\n\t\t\t\t\t\t\t// we do cancel() on this key so removing is somehow redundant\n\t\t\t\t\t\t\t// and causes concurrency exception if a few calls are performed\n\t\t\t\t\t\t\t// at the same time.\n\t\t\t\t\t\t\t// selected_keys.remove(sk);\n\t\t\t\t\t\t\tIOService s = (IOService) sk.attachment();\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tStringBuilder sb = new StringBuilder(\"AWAKEN: \" + s.getUniqueId());\n\n\t\t\t\t\t\t\t\t\tif (sk.isWritable()) {\n\t\t\t\t\t\t\t\t\t\tsb.append(\", ready for WRITING\");\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (sk.isReadable()) {\n\t\t\t\t\t\t\t\t\t\tsb.append(\", ready for READING\");\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tsb.append(\", readyOps() = \").append(sk.readyOps());\n\t\t\t\t\t\t\t\t\tlog.finest(sb.toString());\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Set<SelectionKey> selected_keys = clientsSel.selectedKeys();\n\t\t\t\t\t\t\t\t// for (SelectionKey sk : selected_keys) {\n\t\t\t\t\t\t\t\t// Handling a bug or not a bug described in the\n\t\t\t\t\t\t\t\t// last comment to this issue:\n\t\t\t\t\t\t\t\t// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4850373\n\t\t\t\t\t\t\t\t// and\n\t\t\t\t\t\t\t\t// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933\n\t\t\t\t\t\t\t\tsk.cancel();\n\t\t\t\t\t\t\t\tforCompletion.add(s);\n\n\t\t\t\t\t\t\t\t// IOServices must be added to thread pool after they are removed from\n\t\t\t\t\t\t\t\t// the selector and the selector and key is cleared, otherwise we have\n\t\t\t\t\t\t\t\t// dead-lock somewhere down in the:\n\t\t\t\t\t\t\t\t// java.nio.channels.spi.AbstractSelectableChannel.\n\t\t\t\t\t\t\t\t// removeKey(AbstractSelectableChannel.java:111)\n\t\t\t\t\t\t\t\t// completionService.submit(s);\n\t\t\t\t\t\t\t} catch (CancelledKeyException e) {\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"CancelledKeyException, stopping the connection: {0}\",\n\t\t\t\t\t\t\t\t\t\t\ts.getUniqueId());\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\ts.forceStop();\n\t\t\t\t\t\t\t\t} catch (Exception ex2) {\n\t\t\t\t\t\t\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\t\t\t\t\t\t\tlog.log(Level.WARNING, \"got exception during forceStop: {0}\", e);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Clean-up cancelled keys...\n\t\t\t\t\tclientsSel.selectNow();\n\t\t\t\t}\n\n\t\t\t\taddAllWaiting();\n\n\t\t\t\tIOService serv = null;\n\n\t\t\t\twhile ((serv = forCompletion.pollFirst()) != null) {\n\t\t\t\t\tcompletionService.submit(serv);\n\t\t\t\t}\n\n\t\t\t\t// clientsSel.selectNow();\n\t\t\t} catch (CancelledKeyException brokene) {\n\n\t\t\t\t// According to Java API that should not happen.\n\t\t\t\t// I think it happens only on the broken Java implementation\n\t\t\t\t// from Apple.\n\t\t\t\tlog.log(Level.WARNING, \"Ups, broken JDK, Apple? \", brokene);\n\n\t\t\t\ttry {\n\t\t\t\t\trecreateSelector();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Serious problem, can't recreate selector: \", e);\n\n\t\t\t\t\t// stopping = true;\n\t\t\t\t}\n\t\t\t} catch (IOException ioe) {\n\n\t\t\t\t// According to Java API that should not happen.\n\t\t\t\t// I think it happens only on the broken Java implementation from Apple\n\t\t\t\t// and due to a bug: http://bugs.sun.com/view_bug.do?bug_id=6693490\n\t\t\t\tlog.log(Level.WARNING, \"Problem with the network connection: \", ioe);\n\n\t\t\t\ttry {\n\t\t\t\t\trecreateSelector();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Serious problem, can't recreate selector: \", e);\n\n\t\t\t\t\t// stopping = true;\n\t\t\t\t}\n\t\t\t} catch (Exception exe) {\n\t\t\t\tlog.log(Level.SEVERE, \"Server I/O error: \", exe);\n\n\t\t\t\ttry {\n\t\t\t\t\trecreateSelector();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Serious problem, can't recreate selector: \", e);\n\n\t\t\t\t\t// stopping = true;\n\t\t\t\t}\n\n\t\t\t\t// stopping = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param threads\n\t */\n\tpublic void setMaxThread(int threads) {\n\t\texecutor.setCorePoolSize(threads);\n\t\texecutor.setMaximumPoolSize(threads);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param threads\n\t */\n\tpublic void setMaxThreadPerCPU(int threads) {\n\t\tsetMaxThread(threads * cpus);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void addAllWaiting() throws IOException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"waiting.size(): {0}\", waiting.size());\n\t\t}\n\n\t\tIOService s = null;\n\n\t\t// boolean added = false;\n\t\twhile ((s = waiting.pollFirst()) != null) {\n\t\t\tSocketChannel sc = s.getSocketChannel();\n\n\t\t\ttry {\n\t\t\t\tif (sc.isConnected()) {\n\t\t\t\t\tif (reading) {\n\t\t\t\t\t\tsc.register(clientsSel, SelectionKey.OP_READ, s);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"ADDED OP_READ: {0}\", s.getUniqueId());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (writing) {\n\t\t\t\t\t\tsc.register(clientsSel, SelectionKey.OP_WRITE, s);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"ADDED OP_WRITE: {0}\", s.getUniqueId());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// added = true;\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket not connected: {0}\", s.getUniqueId());\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\tlog.log(Level.FINER, \"Forcing stopping the service: {0}\", s.getUniqueId());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts.forceStop();\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Exception while stopping service: \" + s.getUniqueId(), e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Forcing stopping the service: \" + s.getUniqueId(), e);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\ts.forceStop();\n\t\t\t\t} catch (Exception ez) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Exception while stopping service: \" + s.getUniqueId(), ez);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of try-catch\n\t\t}      // end of for ()\n\n//  if (added) {\n//    clientsSel.wakeup();\n//  }\n\t}\n\n\t// Implementation of java.lang.Runnable\n\tprivate synchronized void recreateSelector() throws IOException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Recreating selector, opened channels: {0}\", clientsSel.keys().size());\n\t\t}\n\n\t\tempty_selections = 0;\n\n\t\t// Handling a bug or not a bug described in the\n\t\t// last comment to this issue:\n\t\t// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4850373\n\t\t// and\n\t\t// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933\n\t\t// Recreating the selector and registering all channles with\n\t\t// the new selector\n\t\t// Selector tempSel = clientsSel;\n\t\t// clientsSel = Selector.open();\n\t\tboolean cancelled = false;\n\n\t\t// Sometimes this is just a broken connection which causes\n\t\t// selector spin... this is the cheaper solution....\n\t\tfor (SelectionKey sk : clientsSel.keys()) {\n\t\t\tIOService<?> serv = (IOService<?>) sk.attachment();\n\t\t\tSocketChannel sc = serv.getSocketChannel();\n\n\t\t\tif ((sc == null) ||!sc.isConnected()) {\n\t\t\t\tcancelled = true;\n\t\t\t\tsk.cancel();\n\n\t\t\t\ttry {\n\t\t\t\t\tlog.log(Level.INFO, \"Forcing stopping the service: {0}\", serv.getUniqueId());\n\t\t\t\t\tserv.forceStop();\n\t\t\t\t} catch (Exception e) {}\n\t\t\t}\n\n\t\t\t// waiting.offer(serv);\n\t\t}\n\n\t\tif (cancelled) {\n\t\t\tclientsSel.selectNow();\n\t\t} else {\n\n\t\t\t// Unfortunately must be something wrong with the selector\n\t\t\t// itself, now more expensive calculations...\n\t\t\tSelector tempSel = clientsSel;\n\n\t\t\tclientsSel = Selector.open();\n\n\t\t\tfor (SelectionKey sk : tempSel.keys()) {\n\t\t\t\tIOService<?> serv = (IOService<?>) sk.attachment();\n\n\t\t\t\tsk.cancel();\n\t\t\t\twaiting.add(serv);\n\t\t\t}\n\n\t\t\ttempSel.close();\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class IOServiceComparator implements Comparator<IOService<?>> {\n\n\t\t@Override\n\t\tpublic int compare(IOService<?> o1, IOService<?> o2) {\n\t\t\treturn o1.getUniqueId().compareTo(o2.getUniqueId());\n\t\t}\n\t}\n\n\n\t@TODO(note = \"ExecutionException is poorly implemented.\")\n\tprotected class ResultsListener extends Thread {\n\n\t\t/**\n\t\t * Constructs ...\n\t\t *\n\t\t *\n\t\t * @param name\n\t\t */\n\t\tpublic ResultsListener(String name) {\n\t\t\tsuper();\n\t\t\tsetName(name);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tIOService<?> service = completionService.take().get();\n\n\t\t\t\t\tif (service != null) {\n\t\t\t\t\t\tif (service.isConnected()) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"COMPLETED: {0}\", service.getUniqueId());\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\taddSocketService(service);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"REMOVED: {0}\", service.getUniqueId());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}    // end of else\n\t\t\t\t\t}\n\t\t\t\t} catch (ExecutionException e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Protocol execution exception.\", e);\n\n\t\t\t\t\t// TODO: Do something with this\n\t\t\t\t}        // end of catch\n\t\t\t\t\t\tcatch (InterruptedException e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Protocol execution interrupted.\", e);\n\t\t\t\t}        // end of try-catch\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Protocol execution unknown exception.\", e);\n\t\t\t\t}        // end of catch\n\t\t\t}          // end of for ()\n\t\t}\n\t}\n}    // SocketThread\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/net/SocketType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.net;\n\n/**\n * Describe class SocketType here.\n *\n *\n * Created: Sun Feb  5 09:27:34 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum SocketType {\n\n\tplain, ssl, tls;\n\n} // SocketType\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/Activator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.osgi;\n\nimport java.lang.reflect.Modifier;\nimport java.util.ArrayList;\nimport java.util.Hashtable;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport org.osgi.framework.Bundle;\nimport org.osgi.framework.BundleActivator;\nimport org.osgi.framework.BundleContext;\nimport org.slf4j.bridge.SLF4JBridgeHandler;\nimport tigase.conf.ConfiguratorAbstract;\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\nimport tigase.osgi.ModulesManager;\nimport tigase.osgi.util.ClassUtil;\nimport tigase.server.XMPPServer;\nimport tigase.xmpp.XMPPImplIfc;\n\npublic class Activator implements BundleActivator {\n\n        private static final Logger log = Logger.getLogger(Activator.class.getCanonicalName());\n\n        private static Bundle bundle = null;\n        \n        @Override\n        public void start(BundleContext bc) throws Exception {\n                try {\n                        bundle = bc.getBundle();\n                        \n                        if (!SLF4JBridgeHandler.isInstalled()) {\n                                SLF4JBridgeHandler.install();\n                        }\n                        \n                        XMPPServer.setOSGi(true);\n                        \n                        try {\n                                Set<Class<XMPPImplIfc>> procs = ClassUtil.getClassesImplementing(XMPPImplIfc.class);\n                                ArrayList<String> elems = new ArrayList<String>(32);\n                                \n                                for (Class<XMPPImplIfc> cproc : procs) {\n                                        if (!Modifier.isPublic(cproc.getModifiers())) {\n                                                continue;\n                                        }\n\n                                        if (cproc != null) {\n                                                ModulesManagerImpl.getInstance().registerPluginClass(cproc);\n                                        }\n                                }\n                        }\n                        catch (Exception e) {\n                                log.log(Level.SEVERE, \"Plugin loading excepton\", e);\n                        }\n                        \n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tSet<Class<Repository>> repos = ClassUtil.getClassesImplementing(Repository.class);\n\t\t\t\t\t\t\t\tRepositoryFactory.initialize(repos);\n\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tlog.log(Level.SEVERE, \"Could not initialize properly ResourceFactory\", e);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// we need to export this before we start, so if start will fail due to missing\n\t\t\t\t\t\t// dependencies we would be able to add them later and recorver from this\n\t\t\t\t\t\tModulesManagerImpl.getInstance().setActive(true);\n                        bc.registerService(ModulesManager.class.getName(), ModulesManagerImpl.getInstance(), new Hashtable());\n\t\t\t\t\t\t\n                        XMPPServer.start(new String[]{\n                                ConfiguratorAbstract.PROPERTY_FILENAME_PROP_KEY, \"etc/init.properties\"\n                        });\n                        \n                        // if it is not too late\n                        SLF4JBridgeHandler.install();\n                }\n                catch (Exception ex) {\n                        log.log(Level.SEVERE, \"Error starting bundle: \", ex);\n                        throw ex;\n                }\n        }\n\n        @Override\n        public void stop(BundleContext bc) throws Exception {\n                try {\n                        ModulesManagerImpl.getInstance().setActive(false);\n                        XMPPServer.stop();\n                }\n                catch (Exception ex) {\n                        log.log(Level.SEVERE, \"Error stopping bundle: \", ex);\n                        throw ex;\n                }\n        }\n        \n        public static Bundle getBundle() {\n                return bundle;\n        }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/ModulesManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2012 \"Andrzej Wójcik\" <andrzej.wojcik@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * Last modified by $Author: andrzej $\n */\npackage tigase.osgi;\n\nimport tigase.conf.Configurable;\nimport tigase.xmpp.XMPPImplIfc;\n\n/**\n *\n * @author andrzej\n */\npublic interface ModulesManager {\n\n\t\tvoid registerClass(Class<?> cls);\n\t\t\n\t\tvoid unregisterClass(Class<?> cls);\n\t\t\n        void registerPluginClass(Class<? extends XMPPImplIfc> pluginCls);\n\n        void unregisterPluginClass(Class<? extends XMPPImplIfc> pluginCls);\n\n        void registerServerComponentClass(Class<? extends Configurable> compCls);\n\n        void unregisterServerComponentClass(Class<? extends Configurable> compCls);\n\n        void update();\n        \n\t\tClass<?> forName(String className) throws ClassNotFoundException;\n\t\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/ModulesManagerImpl.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2012 \"Andrzej Wójcik\" <andrzej.wojcik@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * Last modified by $Author: andrzej $\n */\npackage tigase.osgi;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.Configurable;\nimport tigase.conf.Configurator;\nimport tigase.server.ServerComponent;\nimport tigase.server.XMPPServer;\nimport tigase.util.ClassUtil;\nimport tigase.xmpp.XMPPImplIfc;\n\n/**\n *\n * @author andrzej\n */\npublic class ModulesManagerImpl implements ModulesManager {\n\n\t\tprivate static final Logger log = Logger.getLogger(ModulesManagerImpl.class.getCanonicalName());\n\t\n        private static ModulesManagerImpl instance = null;\n        private Map<String, XMPPImplIfc> plugins = null;\n        private Map<String, Class<? extends Configurable>> componentsClasses = null;\n\t\t\t\tprivate ConcurrentHashMap<String, Class<?>> classes = null;\n        private boolean active = false;\n\n        public static ModulesManagerImpl getInstance() {\n                if (instance == null) {\n                        instance = new ModulesManagerImpl();\n                }\n                return instance;\n        }\n\n        private ModulesManagerImpl() {\n                plugins = new ConcurrentHashMap<String, XMPPImplIfc>();\n                componentsClasses = new ConcurrentHashMap<String, Class<? extends Configurable>>();\n\t\t\t\tclasses = new ConcurrentHashMap<String, Class<?>>();\n        }\n\n        @Override\n        public void registerPluginClass(Class<? extends XMPPImplIfc> pluginCls) {\n                synchronized (this) {\n                        try {\n                                XMPPImplIfc plugin = pluginCls.newInstance();\n\n//                                // is it really needed?\n//                                XMPPImplIfc oldPlugin = pluginsClasses.get(plugin.id());\n//                                if (oldPlugin != null) {\n//                                        if (!oldPlugin.getClass().getCanonicalName().startsWith(\"tigase.xmpp.impl\")) {\n//                                                return;\n//                                        }\n//                                        if (plugin.getClass().getCanonicalName().startsWith(\"tigase.xmpp.impl\")) {\n//                                                return;\n//                                        }\n//                                }\n                                \n                                plugins.put(plugin.id(), plugin);\n                        } catch (InstantiationException ex) {\n                                Logger.getLogger(ModulesManagerImpl.class.getName()).log(Level.SEVERE, null, ex);\n                        } catch (IllegalAccessException ex) {\n                                Logger.getLogger(ModulesManagerImpl.class.getName()).log(Level.SEVERE, null, ex);\n                        }\n                }\n        }\n\n        @Override\n        public void unregisterPluginClass(Class<? extends XMPPImplIfc> pluginClass) {\n                synchronized (this) {\n                        String key = null;\n                        \n                        for (Iterator<Entry<String, XMPPImplIfc>> it = plugins.entrySet().iterator(); it.hasNext();) {\n                                Entry<String,XMPPImplIfc> entry = it.next();\n                                if(pluginClass.equals(entry.getValue())) {\n                                        key = entry.getKey();\n                                }\n                        }\n                        \n                        if (key != null) {\n                                plugins.remove(key);\n                        }\n                }\n        }\n\n//        public static Set<String> getActivePlugins() {\n//                HashSet<String> active = new HashSet<String>();\n//                for (Entry<String, XMPPImplIfc> entry : getInstance().pluginsClasses.entrySet()) {\n//                        if (entry.getValue().getClass().getCanonicalName().startsWith(\"tigase.xmpp.impl.\")) {\n//                                continue;\n//                        }\n//\n//                        active.add(entry.getKey());\n//                }\n//                return active;\n//        }\n//\n//        public static Set<String> getActiveComponentsNames() {\n//                return new HashSet<String>(getInstance().activeComponents.keySet());\n//        }\n//\n//        public static String getComponentClassNameByName(String name) {\n//                return getInstance().activeComponents.get(name);\n//        }\n//\n//        public static ServerComponent getComponentInstance(String cls_name) {\n//                return getInstance().componentsClasses.get(cls_name);\n//        }\n\n        @Override\n        public void registerServerComponentClass(Class<? extends Configurable> compCls) {\n                synchronized (this) {\n                        componentsClasses.put(compCls.getCanonicalName(), compCls);\n                }\n        }\n\n        @Override\n        public void unregisterServerComponentClass(Class<? extends Configurable> compCls) {\n                synchronized (this) {\n                        componentsClasses.remove(compCls.getCanonicalName());\n                }\n        }\n\t\t\n\t\t@Override\n\t\tpublic void registerClass(Class<?> cls) {\n\t\t\tsynchronized (this) {\n\t\t\t\tString clsName = cls.getCanonicalName();\n\t\t\t\tclasses.put(clsName, cls);\n\t\t\t\tif (XMPPImplIfc.class.isAssignableFrom(cls)) {\n\t\t\t\t\tregisterPluginClass((Class<? extends XMPPImplIfc>) cls);\n\t\t\t\t}\n\t\t\t\tif (Configurable.class.isAssignableFrom(cls)) {\n\t\t\t\t\tregisterServerComponentClass((Class<? extends Configurable>) cls);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void unregisterClass(Class<?> cls) {\n\t\t\tsynchronized (this) {\n\t\t\t\tString clsName = cls.getCanonicalName();\n\t\t\t\tclasses.remove(clsName, cls);\n\t\t\t\tif (XMPPImplIfc.class.isAssignableFrom(cls)) {\n\t\t\t\t\tunregisterPluginClass((Class<? extends XMPPImplIfc>) cls);\n\t\t\t\t}\n\t\t\t\tif (Configurable.class.isAssignableFrom(cls)) {\n\t\t\t\t\tunregisterServerComponentClass((Class<? extends Configurable>) cls);\n\t\t\t\t}\n\t\t\t}\t\t\t\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic Class<?> forName(String className) throws ClassNotFoundException {\n\t\t\tif (\"tigase.cluster.strategy.OnlineUsersCachingStrategy\".equals(className)) {\n\t\t\t\tlog.warning(\"You are using old name for SM clustering strategy in property \"\n\t\t\t\t\t\t+ \"--sm-cluster-strategy-class\\nYou are using name: \" + className + \"\\n\"\n\t\t\t\t\t\t+ \" while name: tigase.server.cluster.strategy.OnlineUsersCachingStrategy\"\n\t\t\t\t\t\t+ \" should be used.\");\n\t\t\t\tclassName = \"tigase.server.cluster.strategy.OnlineUsersCachingStrategy\";\n\t\t\t}\n\t\t\tClass<?> cls = classes.get(className);\n\t\t\tif (cls == null) {\n\t\t\t\tcls = this.getClass().getClassLoader().loadClass(className);\n\t\t\t}\n\t\t\treturn cls;\n\t\t}\n\t\t\n\t\tpublic <T extends Class> Set<T> getImplementations(T cls) {\n\t\t\treturn ClassUtil.getClassesImplementing(classes.values(), cls);\n\t\t}\n\t\t\n        @Override\n        public void update() {\n                //synchronized (this) {\n                if (active) {\n\t\t\t\t\tConfigurator configurator = ((Configurator) XMPPServer.getConfigurator());\n\t\t\t\t\tif (configurator != null)\n\t\t\t\t\t\tconfigurator.updateMessageRouter();\n                }\n                //}\n        }\n\n        public XMPPImplIfc getPlugin(String plug_id) throws InstantiationException, IllegalAccessException {\n                return plugins.get(plug_id);                \n        }\n        \n        public boolean hasPluginForId(String plug_id) {\n                return plugins.containsKey(plug_id);\n        }\n        \n        public Class<? extends ServerComponent> getServerComponentClass(String className) {\n                return componentsClasses.get(className);\n        }\n        \n        public ServerComponent getServerComponent(String className) throws InstantiationException, IllegalAccessException {\n                Class<? extends Configurable> compCls = componentsClasses.get(className);\n                \n                if (compCls == null) {\n                        return null;\n                }\n                \n                return compCls.newInstance();\n        }\n        \n        public boolean hasClassForServerComponent(String className) {\n                return componentsClasses.containsKey(className);\n        }\n        \n        public void setActive(boolean active) {\n                this.active = active;\n        }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/OSGiScriptEngine.java",
    "content": "/*\n *   Copyright 2005 The Apache Software Foundation\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n *\n */\npackage tigase.osgi;\n\nimport java.io.Reader;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptContext;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptException;\n\npublic class OSGiScriptEngine implements ScriptEngine{\n\tprivate ScriptEngine engine;\n\tprivate OSGiScriptEngineFactory factory;\n\tpublic OSGiScriptEngine(ScriptEngine engine, OSGiScriptEngineFactory factory){\n\t\tthis.engine=engine;\n\t\tthis.factory=factory;\n\t}\n\tpublic Bindings createBindings() {\n\t\treturn engine.createBindings();\n\t}\n\tpublic Object eval(Reader reader, Bindings n) throws ScriptException {\n\t\treturn engine.eval(reader, n);\n\t}\n\tpublic Object eval(Reader reader, ScriptContext context) throws ScriptException {\n\t\treturn engine.eval(reader, context);\n\t}\n\tpublic Object eval(Reader reader) throws ScriptException {\n\t\treturn engine.eval(reader);\n\t}\n\tpublic Object eval(String script, Bindings n) throws ScriptException {\n\t\treturn engine.eval(script, n);\n\t}\n\tpublic Object eval(String script, ScriptContext context) throws ScriptException {\n\t\treturn engine.eval(script, context);\n\t}\n\tpublic Object eval(String script) throws ScriptException {\n\t\treturn engine.eval(script);\n\t}\n\tpublic Object get(String key) {\n\t\treturn engine.get(key);\n\t}\n\tpublic Bindings getBindings(int scope) {\n\t\treturn engine.getBindings(scope);\n\t}\n\tpublic ScriptContext getContext() {\n\t\treturn engine.getContext();\n\t}\n\tpublic ScriptEngineFactory getFactory() {\n\t\treturn factory;\n\t}\n\tpublic void put(String key, Object value) {\n\t\tengine.put(key, value);\n\t}\n\tpublic void setBindings(Bindings bindings, int scope) {\n\t\tengine.setBindings(bindings, scope);\n\t}\n\tpublic void setContext(ScriptContext context) {\n\t\tengine.setContext(context);\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/OSGiScriptEngineFactory.java",
    "content": "/*\n *   Copyright 2005 The Apache Software Foundation\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n *\n */\npackage tigase.osgi;\n\nimport java.util.List;\n\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineFactory;\n\n/**\n * This is a wrapper class for the ScriptEngineFactory class that deals with context class loader issues\n * It is necessary because engines (at least ruby) use the context classloader to find their resources (i.e., their \"native\" classes)\n *\n */\npublic class OSGiScriptEngineFactory implements ScriptEngineFactory{\n\tprivate ScriptEngineFactory factory;\n\tprivate ClassLoader contextClassLoader;\n\tpublic OSGiScriptEngineFactory (ScriptEngineFactory factory, ClassLoader contextClassLoader){\n\t\tthis.factory=factory;\n\t\tthis.contextClassLoader=contextClassLoader;\n\t}\n\tpublic String getEngineName() {\n\t\treturn factory.getEngineName();\n\t}\n\tpublic String getEngineVersion() {\n\t\treturn factory.getEngineVersion();\n\t}\n\tpublic List<String> getExtensions() {\n\t\treturn factory.getExtensions();\n\t}\n\tpublic String getLanguageName() {\n\t\treturn factory.getLanguageName();\n\t}\n\tpublic String getLanguageVersion() {\n\t\treturn factory.getLanguageVersion();\n\t}\n\tpublic String getMethodCallSyntax(String obj, String m, String... args) {\n\t\treturn factory.getMethodCallSyntax(obj, m, args);\n\t}\n\tpublic List<String> getMimeTypes() {\n\t\treturn factory.getMimeTypes();\n\t}\n\tpublic List<String> getNames() {\n\t\treturn factory.getNames();\n\t}\n\tpublic String getOutputStatement(String toDisplay) {\n\t\treturn factory.getOutputStatement(toDisplay);\n\t}\n\tpublic Object getParameter(String key) {\n\t\treturn factory.getParameter(key);\n\t}\n\tpublic String getProgram(String... statements) {\n\t\treturn factory.getProgram(statements);\n\t}\n\tpublic ScriptEngine getScriptEngine() {\n\t\tScriptEngine engine=null;\n\t\tif(contextClassLoader!=null){\n\t\tClassLoader old=Thread.currentThread().getContextClassLoader();\n\t\tThread.currentThread().setContextClassLoader(contextClassLoader);\n\t\tengine=factory.getScriptEngine();\n\t\tThread.currentThread().setContextClassLoader(old);\n\t\t}\n\t\telse engine=factory.getScriptEngine();\n\t\treturn engine;\n\t}\n\t\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/OSGiScriptEngineManager.java",
    "content": "/*\n *   Copyright 2005 The Apache Software Foundation\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n *\n */\npackage tigase.osgi;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\nimport javax.script.SimpleBindings;\n\nimport org.osgi.framework.Bundle;\nimport org.osgi.framework.BundleContext;\n\n/**\n * This class acts as a delegate for all the available ScriptEngineManagers. Unluckily, the standard did not\n * define it as an interface, so we need to extend it to allow polymorphism. However, no calls to super are used.\n * It wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a merged ScriptEngineManager.\n * \n * Internally, what this class does is creating ScriptEngineManagers for each bundle \n * that contains a ScriptEngineFactory and includes a META-INF/services/javax.script.ScriptEngineFactory file. \n * It assumes that the file contains a list of @link ScriptEngineFactory classes. For each bundle, it creates a\n * ScriptEngineManager, then merges them. @link ScriptEngineFactory objects are wrapped\n * into @link OSGiScriptEngineFactory objects to deal with problems of context class loader:\n * Those scripting engines that rely on the ContextClassloader for finding resources need to use this wrapper\n * and the @link OSGiScriptFactory. Mainly, jruby does.\n * \n * Note that even if no context classloader issues arose, it would still be needed to search manually for the \n * factories and either use them directly (losing the mimeType/extension/shortName mechanisms for finding engines\n * or manually registering them) or still use this class, which would be smarter. In the latter case, \n * it would only be needed to remove the hack that temporarily sets the context classloader to the appropriate, \n * bundle-related, class loader.\n * \n * Caveats:\n * <ul><li>\n * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not wrapped,\n * calls like \n * <code>\n * ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);<br>\n * ScriptEngine engine=osgiManager.getEngineByName(\"ruby\");\n * ScriptEngineFactory factory=engine.getFactory() //this does not return the OSGiFactory wrapper\n * factory.getScriptEngine(); //this might fail, as it does not use OSGiScriptEngineFactory wrapper\n * </code>\n * might result in unexpected errors. Future versions may wrap the ScriptEngine with a OSGiScriptEngine to solve this\n * issue, but for the moment it is not needed.\n * </li>\n * </ul>\n * \n */\npublic class OSGiScriptEngineManager extends ScriptEngineManager{\n        \n        private static final Logger log = Logger.getLogger(OSGiScriptEngineManager.class.getCanonicalName());\n        \n\tprivate Bindings bindings;\n\tprivate Map <ScriptEngineManager, ClassLoader> classLoaders;\n\tprivate BundleContext context;\n\t\n        public OSGiScriptEngineManager() {\n                this(Activator.getBundle().getBundleContext());\n        }\n        \n\tpublic OSGiScriptEngineManager(BundleContext context){\n\t\tthis.context=context;\n\t\tbindings=new SimpleBindings();\n\t\tthis.classLoaders=findManagers(context);\n\t}\n\t/**\n\t * This method is the only one that is visible and not part of the ScriptEngineManager class.\n\t * Its purpose is to find new managers that weren't available before, but keeping the globalScope bindings\n\t * set.\n\t * If you want to clean the bindings you can either get a fresh instance of OSGiScriptManager or\n\t * setting up a new bindings object.\n\t * This can be done with:\n\t * <code>\n\t * ScriptEngineManager manager=new OSGiScriptEngineManager(context);\n\t * (...)//do stuff\n\t * osgiManager=(OSGiScriptEngineManager)manager;//cast to ease reading\n\t * osgiManager.reloadManagers();\n\t * \n\t * manager.setBindings(new OSGiBindings());//or you can use your own bindings implementation\n\t * \n\t * </code>   \n\t *\n\t */\n\tpublic void reloadManagers(){\n\t\tthis.classLoaders=findManagers(context);\n\t}\n\t\n\tpublic Object get(String key) {\n\t\treturn bindings.get(key);\n\t}\n\n\tpublic Bindings getBindings() {\n\t\treturn bindings;\n\t}\n\n\tpublic ScriptEngine getEngineByExtension(String extension) {\n\t\t//TODO this is a hack to deal with context class loader issues\n\t\tScriptEngine engine=null;\n\t\tfor(ScriptEngineManager manager: classLoaders.keySet()){\n\t\t\tClassLoader old=Thread.currentThread().getContextClassLoader();\n\t\t\tThread.currentThread().setContextClassLoader(classLoaders.get(manager));\n\t\t\tengine=manager.getEngineByExtension(extension);\n\t\t\tThread.currentThread().setContextClassLoader(old);\n\t\t\tif (engine!=null) break;\n\t\t}\n \t\treturn engine;\n\t}\n\n\tpublic ScriptEngine getEngineByMimeType(String mimeType) {\n\t\t//TODO this is a hack to deal with context class loader issues\n\t\tScriptEngine engine=null;\n\t\tfor(ScriptEngineManager manager: classLoaders.keySet()){\n\t\t\tClassLoader old=Thread.currentThread().getContextClassLoader();\n\t\t\tThread.currentThread().setContextClassLoader(classLoaders.get(manager));\n\t\t\tengine=manager.getEngineByMimeType(mimeType);\n\t\t\tThread.currentThread().setContextClassLoader(old);\n\t\t\tif (engine!=null) break;\n\t\t}\n \t\treturn engine;\n\t}\n\n\tpublic ScriptEngine getEngineByName(String shortName) {\n\t\t//TODO this is a hack to deal with context class loader issues\n\t\tfor(ScriptEngineManager manager: classLoaders.keySet()){\n\t\t\tClassLoader old=Thread.currentThread().getContextClassLoader();\n\t\t\tThread.currentThread().setContextClassLoader(classLoaders.get(manager));\n\t\t\tScriptEngine engine=manager.getEngineByName(shortName);\n\t\t\tThread.currentThread().setContextClassLoader(old);\n\t\t\tif (engine!=null){\n\t\t\t\treturn new OSGiScriptEngine(engine, new OSGiScriptEngineFactory(engine.getFactory(), classLoaders.get(manager)));\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\tpublic List<ScriptEngineFactory> getEngineFactories() {\n\t\tList<ScriptEngineFactory> osgiFactories=new ArrayList<ScriptEngineFactory>();\n\t\tfor(ScriptEngineManager engineManager: classLoaders.keySet()){\n\t\t\tfor (ScriptEngineFactory factory : engineManager.getEngineFactories()){\n\t\t\t\tosgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders.get(engineManager)));\n\t\t}\n\t\t}\n\t\treturn osgiFactories;\n\t}\n\n\tpublic void put(String key, Object value) {\n\t\tbindings.put(key, value);\n\t}\n\n\tpublic void registerEngineExtension(String extension, ScriptEngineFactory factory) {\n\t\tfor(ScriptEngineManager engineManager: classLoaders.keySet())\n\t\t\tengineManager.registerEngineExtension(extension, factory);\n\t}\n\n\tpublic void registerEngineMimeType(String type, ScriptEngineFactory factory) {\n\t\tfor(ScriptEngineManager engineManager: classLoaders.keySet())\n\t\tengineManager.registerEngineMimeType(type, factory);\n\t}\n\n\tpublic void registerEngineName(String name, ScriptEngineFactory factory) {\n\t\tfor(ScriptEngineManager engineManager: classLoaders.keySet())\n\t\t\tengineManager.registerEngineName(name, factory);\n\t}\n\t/**\n\t * Follows the same behavior of @link javax.script.ScriptEngineManager#setBindings(Bindings)\n\t * This means that the same bindings are applied to all the underlying managers.\n\t * @param bindings\n\t */\n\tpublic void setBindings(Bindings bindings) {\n\t\tthis.bindings=bindings;\n\t\tfor(ScriptEngineManager manager: classLoaders.keySet()){\n\t\t\tmanager.setBindings(bindings);\n\t\t}\n\n\t}\n\n\n\tprivate Map<ScriptEngineManager, ClassLoader> findManagers(BundleContext context) {\n\t\tMap<ScriptEngineManager, ClassLoader> managers=new HashMap<ScriptEngineManager, ClassLoader>();\n\t\ttry {\n\t\t\tfor(String factoryName: findFactoryCandidates(context)){\n\t\t\t\t//We do not really need the class, but we need the classloader \n\t\t\t\tClassLoader factoryLoader=Class.forName(factoryName).getClassLoader();\n                                factoryLoader = new CustomClassLoader(new ClassLoader[] {\n                                        factoryLoader,\n                                        this.getClass().getClassLoader()\n                                }, factoryLoader);\n\t\t\t\tScriptEngineManager manager=new ScriptEngineManager(factoryLoader);\n\t\t\t\tmanager.setBindings(bindings);\n\t\t\t\tmanagers.put(manager, factoryLoader);\n\t\t\t}\n\t\t\treturn managers;\n\t\t} catch (IOException ioe) {\n\t\t\tthrow new RuntimeException(ioe);\n\t\t} catch (ClassNotFoundException cnfe) {\n\t\t\tthrow new RuntimeException(cnfe);\n\t\t}\n\t}\n\t/**\n\t * Iterates through all bundles to get the available @link ScriptEngineFactory classes\n\t * @return the names of the available ScriptEngineFactory classes\n\t * @throws IOException\n\t */\n\tprivate List<String> findFactoryCandidates(BundleContext context) throws IOException{\n\t\tBundle[] bundles = context.getBundles();\n\t\tList<String> factoryCandidates = new ArrayList<String>();\n\t\tfor (Bundle bundle : bundles) {\n                        if (log.isLoggable(Level.FINEST)) {\n                                log.log(Level.FINEST, \"checking bundle for script engine manager - Id: {0} Bundle: {1}  Version: {2}\", \n                                        new Object[]{bundle.getBundleId(), bundle.getSymbolicName(), bundle.getVersion().toString()});\n                        }\n\t\t\tif(bundle.getSymbolicName() == null \n                                || bundle.getSymbolicName().equals(\"system.bundle\")) continue;\n\t\t\tEnumeration urls = bundle.findEntries(\"META-INF/services\",\n\t\t\t\t\t\"javax.script.ScriptEngineFactory\", false);\n\t\t\tif (urls == null)\n\t\t\t\tcontinue;\n\t\t\twhile (urls.hasMoreElements()) {\n\t\t\t\tURL u = (URL) urls.nextElement();\n\t\t\t\tBufferedReader reader = new BufferedReader(\n\t\t\t\t\t\tnew InputStreamReader(u.openStream()));\n\t\t\t\tString line;\n\t\t\t\twhile ((line = reader.readLine()) != null) {\n\t\t\t\t\tfactoryCandidates.add(line.trim());\n\t\t}\n\t\t\t}\n\t\t}\n\t\treturn factoryCandidates;\n\t}\n        \n        private class CustomClassLoader extends ClassLoader {\n\n                private final ClassLoader[] loaders;\n                \n                public CustomClassLoader(ClassLoader[] loaders, ClassLoader mainLoader) {\n                        super(mainLoader);\n                        this.loaders = loaders;\n                }\n\n                @Override\n                public Class<?> loadClass(String name) throws ClassNotFoundException {\n                        return findClass(name);\n                }\n                \n                @Override\n                public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {\n                        return findClass(name);\n                }\n\n                @Override\n                protected Class<?> findClass(String name) throws ClassNotFoundException {\n                        Class<?> cls = null;\n                        for (ClassLoader cl : loaders) {\n                                try {\n                                        cls = cl.loadClass(name);\n                                        if (cls != null)\n                                                return cls;\n                                }\n                                catch (Exception ex) {                \n                                }\n                        }\n                        \n                        if (cls == null) {\n                                return findSystemClass(name);\n                        }\n                        \n                        return cls;\n                }\n                \n        }\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/osgi/util/ClassUtil.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.osgi.util;\n\n//~--- JDK imports ------------------------------------------------------------\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Modifier;\nimport java.net.URL;\nimport java.util.Collection;\nimport java.util.Enumeration;\nimport java.util.Set;\nimport java.util.StringTokenizer;\nimport java.util.TreeSet;\nimport java.util.jar.JarEntry;\nimport java.util.jar.JarFile;\nimport java.util.logging.Logger;\nimport org.osgi.framework.Bundle;\nimport tigase.osgi.Activator;\nimport tigase.util.ClassComparator;\nimport tigase.util.ObjectComparator;\n\n//~--- classes ----------------------------------------------------------------\n/**\n * <code>ClassUtil</code> file contains code used for loading all\n * implementations of specified <em>interface</em> or <em>abstract class</em>\n * found in classpath. As a result of calling some functions you can have\n * <code>Set</code> containing all required classes.\n *\n * <p>\n * Created: Wed Oct  6 08:25:52 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev: 609 $\n */\npublic class ClassUtil {\n\n        private static final String[] SKIP_CONTAINS = {\n                \".ui.\", \".swing\", \".awt\", \".sql.\", \".xml.\", \".terracotta.\"\n        };\n        private static final String[] SKIP_STARTS = {\n                \"com.mysql\", \"tigase.pubsub.Utils\", \"org.apache.derby\", \"org.apache.xml\", \"org.postgresql\",\n                \"com.sun\", \"groovy\", \"org.codehaus.groovy\", \"org.netbeans\", \"org.python\", \"com.google.gwt\",\n                \"xtigase.http.client.BasePanel\", \"org.osgi\"\n        };\n\n        //~--- get methods ----------------------------------------------------------\n        /**\n         * Method description\n         *\n         *\n         * @param fileName\n         *\n         * \n         */\n        public static String getClassNameFromFileName(String fileName) {\n                String class_name = null;\n                if (fileName.endsWith(\".class\")) {\n//       class_name = fileName.substring(0,\n//         fileName.length()-6).replace(File.separatorChar, '.');\n                        // Above code does not works on MS Windows if we load\n                        // files from jar file. Jar manipulation code always returns\n                        // file names with unix style separators\n                        int off = fileName.charAt(0) == '/' ? 1 : 0;\n                        String tmp_class_name = fileName.substring(off,\n                                fileName.length() - 6).replace('\\\\', '.');\n                        class_name = tmp_class_name.replace('/', '.');\n                } // end of if (entry_name.endsWith(\".class\"))\n                return class_name;\n        }\n\n        public static void walkInDirForFiles(File base_dir,\n                String path, Set<String> set) {\n                File tmp_file = new File(base_dir, path);\n                if (tmp_file.isDirectory()) {\n                        String[] files = tmp_file.list();\n                        for (String file : files) {\n                                walkInDirForFiles(base_dir, new File(path, file).toString(), set);\n                        } // end of for ()\n                }\n                else {\n                        if (path.toString().contains(\"Plugin\")) {\n                                System.out.println(\"File: \" + path.toString());\n                        }\n                        set.add(path);\n                } // end of if (file.isDirectory()) else\n        }\n\n        public static Set<String> getFileListDeep(File path) {\n                Set<String> set = new TreeSet<String>();\n                if (path.isDirectory()) {\n                        String[] files = path.list();\n                        for (String file : files) {\n                                walkInDirForFiles(path, file, set);\n                        } // end of for ()\n                }\n                else {\n                        set.add(path.toString());\n                } // end of if (file.isDirectory()) else\n                return set;\n        }\n\n        public static Set<String> getClassNamesFromDir(File dir) {\n                Set<String> tmp_set = getFileListDeep(dir);\n                Set<String> result = new TreeSet<String>();\n                for (String elem : tmp_set) {\n                        String class_name = getClassNameFromFileName(elem);\n                        if (class_name != null) {\n                                result.add(class_name);\n                                if (class_name.contains(\"Plugin\")) {\n                                        System.out.println(\"class name: \" + class_name);\n                                }\n                        } // end of if (class_name != null)\n                } // end of for ()\n                return result;\n        }\n\n        public static Set<String> getClassNamesFromJar(File jarFile)\n                throws IOException {\n                Set<String> result = new TreeSet<String>();\n                JarFile jar = new JarFile(jarFile);\n                Enumeration<JarEntry> jar_entries = jar.entries();\n                while (jar_entries.hasMoreElements()) {\n                        JarEntry jar_entry = jar_entries.nextElement();\n                        String class_name = getClassNameFromFileName(jar_entry.getName());\n                        if (class_name != null) {\n                                result.add(class_name);\n                                //        System.out.println(\"class name: \"+class_name);\n                        } // end of if (entry_name.endsWith(\".class\"))\n                } // end of while (jar_entries.hasMoreElements())\n\n                return result;\n        }\n\n        public static Set<String> getClassNamesFromWar(File jarFile)\n                throws IOException {\n                Set<String> result = new TreeSet<String>();\n                JarFile jar = new JarFile(jarFile);\n                Enumeration<JarEntry> jar_entries = jar.entries();\n                while (jar_entries.hasMoreElements()) {\n                        JarEntry jar_entry = jar_entries.nextElement();\n                        String name = jar_entry.getName();\n                        if (!name.startsWith(\"WEB-INF/classes/\")) {\n                                continue;\n                        }\n                        name = name.substring(16);\n                        String class_name = getClassNameFromFileName(name);\n                        if (class_name != null) {\n                                result.add(class_name);\n                                //        System.out.println(\"class name: \"+class_name);\n                        } // end of if (entry_name.endsWith(\".class\"))\n                } // end of while (jar_entries.hasMoreElements())\n\n                return result;\n        }\n\n        public static Set<Class> getClassesFromNames(ClassLoader loader, Set<String> names)\n                throws ClassNotFoundException {\n                Set<Class> classes = new TreeSet<Class>(new ClassComparator());\n                for (String name : names) {\n                        try {\n                                boolean skip_class = false;\n                                for (String test_str : SKIP_CONTAINS) {\n                                        skip_class = name.contains(test_str);\n                                        if (skip_class) {\n                                                break;\n                                        }\n                                }\n                                if (!skip_class) {\n                                        for (String test_str : SKIP_STARTS) {\n                                                skip_class = name.startsWith(test_str);\n                                                if (skip_class) {\n                                                        break;\n                                                }\n                                        }\n                                }\n                                if (!skip_class) {\n                                        //Class cls = Class.forName(name);\n                                        Class cls = loader.loadClass(name);\n                                        classes.add(cls);\n                                }\n                        }\n                        catch (NoClassDefFoundError e) {\n                                System.out.println(\"Class not found name: \" + name);\n                        }\n                        catch (UnsatisfiedLinkError e) {\n                                System.out.println(\"Class unsatisfied name: \" + name);\n                        }\n                        catch (Throwable e) {\n                                Throwable cause = e.getCause();\n                                System.out.println(\"Class name: \" + name);\n                                e.printStackTrace();\n                                if (cause != null) {\n                                        cause.printStackTrace();\n                                }\n                        }\n                } // end of for ()\n                return classes;\n        }\n\n        public static Set<Class> getClassesFromClassPath()\n                throws IOException, ClassNotFoundException {\n\n                Set<Class> classes_set = new TreeSet<Class>(new ClassComparator());\n\n                String classpath = System.getProperty(\"java.class.path\");\n                System.out.println(\"classpath: \" + classpath);\n                ClassLoader loader = ClassUtil.class.getClassLoader();\n                StringTokenizer stok =\n                        new StringTokenizer(classpath, File.pathSeparator, false);\n                while (stok.hasMoreTokens()) {\n                        String path = stok.nextToken();\n                        File file = new File(path);\n                        if (file.exists()) {\n                                if (file.isDirectory()) {\n                                        System.out.println(\"directory: \" + path);\n                                        Set<String> class_names = getClassNamesFromDir(file);\n                                        classes_set.addAll(getClassesFromNames(loader, class_names));\n                                } // end of if (file.isDirectory())\n                                if (file.isFile()) {\n                                        //System.out.println(\"jar file: \"+path);\n                                        Set<String> class_names = getClassNamesFromJar(file);\n                                        classes_set.addAll(getClassesFromNames(loader, class_names));\n                                        //System.out.println(\"Loaded jar file: \"+path);\n                                } // end of if (file.isFile())\n                        } // end of if (file.exists())\n                } // end of while (stok.hasMoreTokens())\n\n                return classes_set;\n        }\n\n        @SuppressWarnings({\"unchecked\"})\n        public static <T extends Class> Set<T> getClassesImplementing(Collection<Class> classes, T cls) {\n\n                Set<T> classes_set = new TreeSet<T>(new ClassComparator());\n\n                for (Class c : classes) {\n                        if (c.getName().contains(\"Plugin\")) {\n                                System.out.println(c.getName() + \" \" + cls.isAssignableFrom(c));\n                        }\n                        if (cls.isAssignableFrom(c)) {\n                                int mod = c.getModifiers();\n                                if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) {\n                                        classes_set.add((T) c);\n                                } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod))\n                        } // end of if (cls.isAssignableFrom(c))\n                } // end of for ()\n\n                return classes_set;\n        }\n\n        public static <T extends Class> Set<T> getClassesImplementing(T cls)\n                throws IOException, ClassNotFoundException {\n                // @TODO: Temporary?? fix for xmpp processors loading\n                return getClassesImplementing(Activator.getBundle(), cls);\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        public static <T> Set<T> getImplementations(Class<T> obj)\n                throws IOException, ClassNotFoundException,\n                InstantiationException, IllegalAccessException {\n\n                Set<T> result = new TreeSet<T>(new ObjectComparator());\n\n                for (Class cls : getClassesImplementing(obj)) {\n                        result.add((T) cls.newInstance());\n                } // end of for ()\n                return result;\n        }\n\n        @SuppressWarnings({\"unchecked\"})\n        public static <T extends Class> Set<T> getClassesImplementing(ClassLoader loader, File f, T cls) throws IOException, ClassNotFoundException {\n\n                Set<String> class_names = (f.getName().endsWith(\".war\")) ? ClassUtil.getClassNamesFromWar(f) : ClassUtil.getClassNamesFromJar(f);\n                Set<Class> classes = ClassUtil.getClassesFromNames(loader, class_names);\n\n                return ClassUtil.getClassesImplementing(classes, cls);\n        }\n\n        /**\n         * Scans OSGI bundle for classes implementing class T\n         * \n         * @param <T>       return type param\n         * @param bundle    bundle to scan\n         * @param cls       base class\n         * @return          returns set of implementations\n         * @throws IOException\n         * @throws ClassNotFoundException \n         */\n        @SuppressWarnings({\"unchecked\"})\n        public static <T extends Class> Set<T> getClassesImplementing(Bundle bundle, T cls) throws IOException, ClassNotFoundException {\n\n                Set<T> classes_set = new TreeSet<T>(new ClassComparator());\n                Enumeration e = bundle.findEntries(\"/\", \"*.class\", true);\n                if (e != null) {\n                        while (e.hasMoreElements()) {\n                                URL clsUrl = (URL) e.nextElement();\n                                String clsName = getClassNameFromFileName(clsUrl.getPath());\n\n                                boolean skip_class = false;\n                                for (String prefix : SKIP_STARTS) {\n                                        if (clsName.startsWith(prefix)) {\n                                                skip_class = true;\n                                                break;\n                                        }\n                                }\n                                if (skip_class) {\n                                        continue;\n                                }\n\n                                for (String part : SKIP_CONTAINS) {\n                                        if (clsName.contains(part)) {\n                                                skip_class = true;\n                                                break;\n                                        }\n                                }\n                                if (skip_class) {\n                                        continue;\n                                }\n\n\n                                try {\n                                        Class c = bundle.loadClass(clsName);\n                                        if (cls.isAssignableFrom(c)) {\n                                                int mod = c.getModifiers();\n                                                if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) {\n                                                        classes_set.add((T) c);\n                                                } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod))\n                                        } // end of if (cls.isAssignableFrom(c))\n                                }\n                                catch (ClassNotFoundException ex) {\n                                        Logger.getLogger(ClassUtil.class.getCanonicalName()).warning(\"Could not find class = \" + clsName);\n                                }\n                        }\n                }\n                return classes_set;\n                //return ClassUtil.getClassesImplementing(classes, cls);\n        }\n\n        /**\n         * Scans file for classes annotated with annotation T\n         * \n         * @param <T>\n         * @param <S>\n         * @param loader    class loader used to load classes\n         * @param f         file to scan for classes\n         * @param cls       annotation class\n         * @return          set of annotated classes\n         * @throws IOException\n         * @throws ClassNotFoundException \n         */\n        @SuppressWarnings({\"unchecked\"})\n        public static <T extends Class, S extends Class> Set<S> getClassesAnnotated(ClassLoader loader, File f, T cls) throws IOException, ClassNotFoundException {\n\n                Set<String> class_names = (f.getName().endsWith(\".war\")) ? ClassUtil.getClassNamesFromWar(f) : ClassUtil.getClassNamesFromJar(f);\n                Set<Class> classes = ClassUtil.getClassesFromNames(loader, class_names);\n                Set<S> classes_set = new TreeSet<S>(new ClassComparator());\n\n                for (Class c : classes) {\n                        Annotation[] annots = c.getAnnotations();\n                        if (c.isAnnotationPresent(cls)) {\n                                int mod = c.getModifiers();\n                                if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) {\n                                        classes_set.add((S) c);\n                                } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod))\n                        } // end of if (cls.isAssignableFrom(c))\n                } // end of for ()\n\n                return classes_set;\n        }\n\n        /**\n         * Scans OSGI bundle for classes annotated with annotation T\n         * \n         * @param <T>\n         * @param <S>\n         * @param bundle    bundle to scan for annotated classes\n         * @param cls       annotation class\n         * @return          set of annotated classes\n         * @throws IOException\n         * @throws ClassNotFoundException \n         */\n        @SuppressWarnings({\"unchecked\"})\n        public static <T extends Class, S extends Class> Set<S> getClassesAnnotated(Bundle bundle, T cls) throws IOException, ClassNotFoundException {\n\n                Set<S> classes_set = new TreeSet<S>(new ClassComparator());\n                Enumeration e = bundle.findEntries(\"/\", \"*.class\", true);\n                if (e != null) {\n                        while (e.hasMoreElements()) {\n                                URL clsUrl = (URL) e.nextElement();\n                                String clsName = getClassNameFromFileName(clsUrl.getPath());\n\n                                boolean skip_class = false;\n                                for (String prefix : SKIP_STARTS) {\n                                        if (clsName.startsWith(prefix)) {\n                                                skip_class = true;\n                                                break;\n                                        }\n                                }\n                                if (skip_class) {\n                                        continue;\n                                }\n\n                                for (String part : SKIP_CONTAINS) {\n                                        if (clsName.contains(part)) {\n                                                skip_class = true;\n                                                break;\n                                        }\n                                }\n                                if (skip_class) {\n                                        continue;\n                                }\n\n\n                                try {\n                                        Class c = bundle.loadClass(clsName);\n                                        Annotation[] annots = c.getAnnotations();\n                                        if (c.isAnnotationPresent(cls)) {\n                                                int mod = c.getModifiers();\n                                                if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) {\n                                                        classes_set.add((S) c);\n                                                } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod))\n                                        } // end of if (cls.isAssignableFrom(c))\n                                }\n                                catch (ClassNotFoundException ex) {\n                                        Logger.getLogger(ClassUtil.class.getCanonicalName()).warning(\"Could not find class = \" + clsName);\n                                }\n                        }\n                }\n\n                return classes_set;\n        }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/receipt/BufferedMessageReceiptsStore.java",
    "content": "package tigase.receipt;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Delayed;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Logger;\n\nimport org.apache.commons.lang.StringUtils;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.util.ThreadPoolUtils;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\n\n\n\npublic class BufferedMessageReceiptsStore implements MessageReceiptsStore {\n\n    private static final Logger LOG = Logger.getLogger(BufferedMessageReceiptsStore.class.getName());\n\n    private Map<String, UserMessageCollection> messages = new ConcurrentHashMap<String, UserMessageCollection>();\n    private ScheduledThreadPoolExecutor executorService = ThreadPoolUtils.newScheduledPool(\"BufferedMessageStorePool\",\n            \"BufferedMessageStorePoolSize\");\n    \n    private static BufferedMessageReceiptsStore instance = null;\n    \n    private long holdTime = 2500L;\n    private Callback callback = null;\n\n    public BufferedMessageReceiptsStore(long holdTime) {\n        this.holdTime = holdTime;\n    }\n\n    @Override\n    public void setCallback(Callback callback) {\n        if (null == this.callback) {\n            this.callback = callback;\n        }\n    }\n    \n    public static BufferedMessageReceiptsStore getInstance() {\n    \tif (instance == null){\n    \t\tinstance = new BufferedMessageReceiptsStore(5000);\n    \t}\n\t\treturn instance;\n    }\n    \n\n    /*\n     * (non-Javadoc)\n     * @see com.suning.openfire.MessageReceiptsStore#append(org.xmpp.packet.Message)\n     */\n    @Override\n    public void append(Packet packet, XMPPResourceConnection session, NonAuthUserRepository userRepo) {\n        this.store(packet.getStanzaTo(), packet, session, userRepo);\n    }\n\n    /*\n     * (non-Javadoc)\n     * @see com.suning.openfire.MessageReceiptsStore#remove(org.xmpp.packet.JID, java.lang.String)\n     */\n    @Override\n    public void remove(JID jid, String messageId) {\n        this.drop(jid, messageId);\n    }\n\n    public Lock getLock(String barejid) {\n        UserMessageCollection collection = this.messages.get(barejid);\n        return null == collection ? null : collection.getLock();\n    }\n\n    /**\n     * 功能描述: <br>\n     * 〈功能详细描述〉\n     * \n     * @param collection\n     * @see [相关类/方法](可选)\n     * @since [产品/模块版本](可选)\n     */\n    private void removeIfEmpty(UserMessageCollection collection) {\n        if (collection.isEmpty()) {\n            synchronized (this.messages) {\n            \tthis.messages.remove(collection.getBareJid());\n            }\n        }\n    }\n\n    public void store(JID jid, Packet message, XMPPResourceConnection session, NonAuthUserRepository userRepo) {\n    \tfinal String id = message.getStanzaId();\n        if (StringUtils.isNotBlank(id)) {\n        \tif(message.getElement().getAttributeStaticStr(\"type\").equals(StanzaType.groupchat))\n        \t\treturn;\n        \t\n        \tif(message.getElement().getChild(\"body\") == null)\n    \t\t\treturn;\n\n        \t// add by cai \n\t\t\t// add stamp\n\t\t\tif(message.getElement().getChild(\"stamp\") == null)\n\t\t\t\tmessage.getElement().addChild(new Element(\"stamp\", System.currentTimeMillis() + \"\"));\n        \t\n        \tfinal String bareJid = jid.getBareJID().toString();\n        \t\n            UserMessageCollection collection = this.messages.get(bareJid);\n            if (null == collection) {\n                synchronized (this.messages) {\n                    if (null == collection) {\n                        collection = new UserMessageCollection(bareJid, session, userRepo);\n                        this.messages.put(bareJid, collection);\n                    }\n                }\n            }\n            \n            final BufferedMessage buffered = new BufferedMessage(message, this.holdTime, collection.getLock());\n            \n            BufferedMessage old = collection.remove(id);\n            if( old != null){\n            \told.drop();\n            }\n            collection.add(buffered);\n            \n            System.out.println(\"----------save---------\" + buffered.getMessageId());\n\n            this.executorService.schedule(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        buffered.getLock().lock();\n                        UserMessageCollection collection = messages.get(buffered.getTo().getBareJID().toString());\n                        if(collection != null){\n                        \tcollection.remove(buffered);\n                        \tremoveIfEmpty(collection);\n                        }\n                        if (buffered.isDroped()) {\n                        \tSystem.out.println(\"----------Droped---------\" + buffered.getMessageId());\n                        } else {\n                        \tcallback.messageExpired(buffered.message, buffered.arrivedTiem, collection.getSession(), collection.getUserRepo());\n                        }\n                        \n                    } catch (Exception ex) {\n                    \tex.printStackTrace();\n//                        LOG.warning(\"BufferedMessageReceiptsStore MessageID: \"\n//                                + buffered.message.getStanzaId()\n//                                + \" \" + ex.getMessage());\n                    } finally {\n                        buffered.getLock().unlock();\n                    }\n                }\n            }, this.holdTime, TimeUnit.MILLISECONDS);\n        }\n    }\n\n    public void drop(JID jid, String messageId) {\n        if (null != jid && StringUtils.isNotBlank(messageId)) {\n            UserMessageCollection collection = this.messages.get(jid.getBareJID().toString());\n            if (null != collection) {\n                try {\n                    collection.getLock().lock();\n                    BufferedMessage buffered = collection.remove(messageId);\n                    if (null != buffered) {\n                        //缓存队列中删除\n                        buffered.drop();\n                        System.out.println(\"----------droping--------\" + buffered.getMessageId());\n//                        this.callback.messageDropped(jid, messageId, true);\n                        return;\n                    }\n                } finally {\n                    collection.getLock().unlock();\n                }\n            }\n            \n            if(this.callback != null)\n            \tthis.callback.messageDropped(jid, messageId, false);\n        }\n    }\n\n//    private UserMessageCollection getUserMessageCollection(String bareJid) {\n//        UserMessageCollection collection = this.messages.get(bareJid);\n//        if (null == collection) {\n//            synchronized (this.messages) {\n//                if (null == collection) {\n//                    collection = new UserMessageCollection(bareJid, session);\n//                    this.messages.put(bareJid, collection);\n//                }\n//            }\n//        }\n//        return collection;\n//    }\n\n//    public Collection<OfflineMessage> getStoredMessages(JID jid) {\n//        List<OfflineMessage> messages = new ArrayList<OfflineMessage>();\n//        UserMessageCollection collection = this.messages.get(jid.toBareJID());\n//        if (null != collection) {\n//            for (BufferedMessage buffered : collection.getBufferedMessages()) {\n//                if (!buffered.isDroped()) {\n//                    messages.add(new OfflineMessage(new Date(buffered.arrivedTiem), buffered.message.getElement()\n//                            .createCopy()));\n//                }\n//            }\n//        }\n//        return messages;\n//    }\n\n    private class UserMessageCollection {\n    \t\n    \tprivate XMPPResourceConnection session;\n    \t\n    \tprivate NonAuthUserRepository userRepo;\n\n        private String bareJid = null;\n        private Lock lock = new ReentrantLock();\n        private Map<String, BufferedMessage> messages = new ConcurrentHashMap<String, BufferedMessage>();\n\n        /**\n         * @param bareJid\n         */\n        private UserMessageCollection(String bareJid, XMPPResourceConnection session, NonAuthUserRepository userRepo) {\n            this.session = session;\n            this.bareJid = bareJid;\n            this.userRepo = userRepo;\n        }\n\n        /**\n         * 功能描述: <br>\n         * 〈功能详细描述〉\n         * \n         * @return\n         * @see [相关类/方法](可选)\n         * @since [产品/模块版本](可选)\n         */\n        private Lock getLock() {\n            return lock;\n        }\n\n        /**\n         * @return the bareJid\n         */\n        private String getBareJid() {\n            return bareJid;\n        }\n\n\t\tprivate XMPPResourceConnection getSession() {\n        \treturn this.session;\n        }\n\t\t\n\t\tpublic NonAuthUserRepository getUserRepo() {\n\t\t\treturn userRepo;\n\t\t}\n\n        /**\n         * 功能描述: <br>\n         * 〈功能详细描述〉\n         * \n         * @param messageId\n         * @see [相关类/方法](可选)\n         * @since [产品/模块版本](可选)\n         */\n        public BufferedMessage remove(String messageId) {\n            return this.messages.remove(messageId);\n        }\n\n        private void add(BufferedMessage message) {\n            this.messages.put(message.getMessageId(), message);\n        }\n\n        private boolean isEmpty() {\n            return this.messages.isEmpty();\n        }\n\n        private boolean remove(BufferedMessage message) {\n            return null != this.messages.remove(message.getMessageId());\n        }\n\n        private Collection<BufferedMessage> getBufferedMessages() {\n            Collection<BufferedMessage> messages = this.messages.values();\n            List<BufferedMessage> list = new ArrayList<BufferedMessage>(messages);\n            Collections.sort(list);\n            return list;\n        }\n    }\n\n    private class BufferedMessage implements Delayed {\n        private long arrivedTiem = 0;\n        private Message message = null;\n        private long holdTime = 0;\n        private boolean droped = false;\n        private Lock lock = null;\n\n        private BufferedMessage(Packet packet, long holdTime, Lock lock) {\n            try {\n\t\t\t\tthis.message = new Message(packet.copyElementOnly().getElement());\n\t            this.arrivedTiem = System.currentTimeMillis();\n\t            this.holdTime = holdTime;\n\t            this.lock = lock;\n            } catch (TigaseStringprepException e) {\n            \te.printStackTrace();\n            }\n        }\n\n        private String getMessageId() {\n            return this.message.getStanzaId();\n        }\n\n        /**\n         * @return the lock\n         */\n        private Lock getLock() {\n            return lock;\n        }\n\n        /*\n         * (non-Javadoc)\n         * @see java.lang.Comparable#compareTo(java.lang.Object)\n         */\n        @Override\n        public int compareTo(Delayed o) {\n            return (int) (this.arrivedTiem - ((BufferedMessage) o).arrivedTiem);\n        }\n\n        /*\n         * (non-Javadoc)\n         * @see java.util.concurrent.Delayed#getDelay(java.util.concurrent.TimeUnit)\n         */\n        @Override\n        public long getDelay(TimeUnit unit) {\n            return (this.arrivedTiem + this.holdTime) - System.currentTimeMillis();\n        }\n\n        private void drop() {\n            this.droped = true;\n        }\n\n        private boolean isDroped() {\n            return this.droped;\n        }\n\n        private JID getTo() {\n            return this.message.getStanzaTo();\n        }\n    }\n\n    /**\n     * 〈一句话功能简述〉<br>\n     * 〈功能详细描述〉\n     * \n     * @author Administrator\n     * @see [相关类/方法]（可选）\n     * @since [产品/模块版本] （可选）\n     */\n    public interface Callback {\n\n        /**\n         * 功能描述: <br>\n         * 〈功能详细描述〉\n         * \n         * @param message\n         * @param arrivedTime\n         * @see [相关类/方法](可选)\n         * @since [产品/模块版本](可选)\n         */\n        void messageExpired(Packet message, long arrivedTime, XMPPResourceConnection session, NonAuthUserRepository userRepo);\n\n        /**\n         * 功能描述: <br>\n         * 〈功能详细描述〉\n         * \n         * @param jid\n         * @param messageId\n         * @see [相关类/方法](可选)\n         * @since [产品/模块版本](可选)\n         */\n        void messageDropped(JID jid, String messageId, boolean hasBuffered);\n\n    }\n    \n    public void stop(){\n//        for(UserMessageCollection collection :messages.values()){\n//            Collection<BufferedMessage>  bufferedMsgs=  collection.getBufferedMessages();\n//            for(BufferedMessage msg: bufferedMsgs){\n//                callback.messageExpired(msg.message, msg.arrivedTiem, null, null);\n//            }\n//        }\n    }\n    \n    public List<Message> getAllReceiptsBufferedMsgs(){\n        List<Message> list = new ArrayList<Message>();\n        for(UserMessageCollection collection :messages.values()){\n            Collection<BufferedMessage>  bufferedMsgs=  collection.getBufferedMessages();\n            for(BufferedMessage msg: bufferedMsgs){\n                list.add(msg.message);\n            }\n        }\n        return list;\n    }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/receipt/MessageReceiptsStore.java",
    "content": "package tigase.receipt;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.receipt.BufferedMessageReceiptsStore.Callback;\nimport tigase.server.Packet;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n\npublic interface MessageReceiptsStore {\n\t\n    void append(Packet message, XMPPResourceConnection session, NonAuthUserRepository userRepo);\n    \n    void remove(JID jid, String messageId);\n\n\tvoid setCallback(Callback callback);\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/receipt/MessageReceiptsStoreFactory.java",
    "content": "package tigase.receipt;\n\nimport java.util.logging.Logger;\n\nimport tigase.server.Packet;\n\npublic class MessageReceiptsStoreFactory {\n\tprivate static final Logger log    = Logger.getLogger(MessageReceiptsStoreFactory.class.getName());\n    private final static MessageReceiptsStoreFactory instance = new MessageReceiptsStoreFactory();\n\n    private FactoryStrategy proxy = null;\n\n    private MessageReceiptsStoreFactory() {\n\n    }\n\n    public MessageReceiptsStore create(Packet packet) {\n        if (null != this.proxy) {\n            return this.proxy.match(packet);\n        } else {\n        \tlog.warning(\"No set MessageReceiptsStoreFactory strategy\");\n        }\n        return null;\n    }\n\n    public static MessageReceiptsStoreFactory getInstance() {\n        return instance;\n    }\n\n    public void setFactoryStrategy(FactoryStrategy strategy) {\n        this.proxy = strategy;\n    }\n\n    public interface FactoryStrategy {\n        public MessageReceiptsStore match(Packet packet);\n    }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/AbstractComponentRegistrator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport tigase.conf.ConfigurationException;\n\n/**\n * This is an archetype of a special types of classes which collect some data\n * from Tigase components or provide these data to components. They normally\n * do not process normall packets and are usually accessed by admins via ad-hoc\n * commands. Good examples of such components are <code>StatisticsCollector</code>\n * or <code>Configurator</code>.<br>\n * Extensions of these class can process packets addresses to the component via\n * <code>processPacket(Packet packet, Queue&lt;Packet&gt; results)</code> method.\n * Alternatively scripting API can be used via ad-hoc commands.<br>\n * The class does not have any queues buffering packets or separate threads for\n * packets processing. All packets are processed from <code>MessageRouter</code>\n * threads via <code>processPacket(Packet packet, Queue&lt;Packet&gt; results)</code>\n * method. Hence this is important that processing implemented in extensions to the\n * class does not take long time. In particular no DB processing is expected.\n *\n *\n * Created: Tue Nov 22 22:57:44 2005\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class AbstractComponentRegistrator<E extends ServerComponent>\n\t\textends BasicComponent implements ComponentRegistrator {\n\tprivate long packetId = 0;\n\n\t/**\n\t * A collection of server components which implement special interface, related to the\n\t * functionality provided by extension of the class.\n\t */\n\tprotected Map<String, E> components = new LinkedHashMap<String, E>();\n\n\t/**\n\t * Creates a new <code>AbstractComponentRegistrator</code> instance.\n\t *\n\t */\n\tpublic AbstractComponentRegistrator() {}\n\n\t/**\n\t * Method provides a callback mechanism signaling that a new component implementing\n\t * special interface has been added to the internal <code>components</code> collection.\n\t *\n\t *\n\t * @param component is a reference to the component just added to the collection.\n\t */\n\tpublic abstract void componentAdded(E component) throws ConfigurationException;\n\n\t/**\n\t * Method provides a callback mechanism signaling that a component implementing\n\t * special interface has been removed from the internal <code>components</code>\n\t * collection.\n\t *\n\t *\n\t * @param component is a reference to the component removed from the collection.\n\t */\n\tpublic abstract void componentRemoved(E component);\n\n\t/**\n\t * Method checks whether the component provides as method parameter is correct type\n\t * that is implements special interface or extends special class. Result of the method\n\t * determines whether the component can be added to the internal <code>components</code>\n\t * collection.\n\t *\n\t *\n\t * @param component is a reference to the component being checked.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if the component is of a\n\t * correct type and <code>false</code> otherwise.\n\t */\n\tpublic abstract boolean isCorrectType(ServerComponent component);\n\n\t/**\n\t * Method checks whether the component is of a correct type, adds it to the internal\n\t * <code>components</code> collection and calls <code>componentAdded(...)</code> callback.\n\t *\n\t *\n\t * @param component a reference to the component which is being added to the intenal\n\t * collection.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if the component\n\t * has been added to the internal collection and <code>false</code> otherwise.\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\t@Override\n\tpublic boolean addComponent(ServerComponent component) throws ConfigurationException {\n\t\tif (isCorrectType(component)) {\n\t\t\tcomponents.put(component.getName(), (E) component);\n\t\t\tcomponentAdded((E) component);\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Method removes specified component from the internal <code>components</code>\n\t * collection and calls <code>componentRemoved(...)</code> callback method.\n\t *\n\t * @param component is a reference to the component being removed.\n\t * @return a <code>boolean</code> value of <code>true</code> if the component\n\t * has been removed from the internal collection and <code>false</code> otherwise.\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\t@Override\n\tpublic boolean deleteComponent(ServerComponent component) {\n\t\tif (isCorrectType(component)) {\n\t\t\tcomponents.remove(component.getName());\n\t\t\tcomponentRemoved((E) component);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method returns a component for a specified component name from internal\n\t * <code>components</code> collection or <code>null</code> of there is no such\n\t * component in the collection.\n\t *\n\t *\n\t * @param name is a <code>String</code> value of the component name.\n\t *\n\t * @return a reference to the component found in the internal collection or\n\t * <code>null</code> if no component has been found.\n\t */\n\tpublic E getComponent(String name) {\n\t\treturn components.get(name);\n\t}\n\n\t/**\n\t * Method generates and returns an unique packet ID. The ID is unique within running\n\t * Tigase instance. The method can be overwritten to change the generation of the\n\t * packet ID.\n\t *\n\t *\n\t * @param prefix is a <code>String</code> value of the ID profix or <code>null</code>\n\t * if no prefix is necessary.\n\t *\n\t * @return a <code>String</code> instance of a new packet ID.\n\t */\n\tpublic String newPacketId(String prefix) {\n\t\tStringBuilder sb = new StringBuilder(32);\n\n\t\tif (prefix != null) {\n\t\t\tsb.append(prefix).append(\"-\");\n\t\t}\n\n\t\tsb.append(getName()).append(++packetId);\n\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic void release() {}\n}    // AbstractComponentRegistrator\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/AbstractMessageReceiver.java",
    "content": "/*\n * AbstractMessageReceiver.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.regex.Pattern;\nimport tigase.annotations.TODO;\nimport tigase.conf.ConfigurationException;\nimport tigase.stats.StatisticType;\nimport tigase.stats.StatisticsContainer;\nimport tigase.stats.StatisticsList;\nimport tigase.util.PatternComparator;\nimport tigase.util.PriorityQueueAbstract;\n\n/**\n * This is an archetype for all classes processing user-level packets. The\n * implementation is designed for a heavy packets processing with internal\n * queues and number of separate threads depending on number of CPUs. Extensions\n * of the class can process normall user packets and administrator packets via\n * ad-hoc commands. Good examples of such components are <code>MUC</code>,\n * <code>PubSub</code>, <code>SessionManager</code>.\n * <br>\n * The class offers scripting API for administrator ad-hoc commands.\n * <br>\n * By default it internally uses priority queues which in some rare cases may\n * lead to packets reordering. When this happens and it is unacceptable for the\n * deployment non-priority queues can be used. The queues size is limited and\n * depends on the available memory size.\n * <br>\n * Packets are processed by <code>processPacket(Packet packet)</code> method\n * which is concurrently called from multiple threads.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class AbstractMessageReceiver\n\t\t\t\textends BasicComponent\n\t\t\t\timplements StatisticsContainer, MessageReceiver {\n\t/**\n\t * Configuration property key for setting incoming packets filters on the\n\t * component level.\n\t */\n\tpublic static final String INCOMING_FILTERS_PROP_KEY = \"incoming-filters\";\n\n\t/**\n\t * Configuration property default vakue with a default incoming packet filter\n\t * loaded by Tigase server.\n\t * <br>\n\t * This is a comma-separated list of classes which should be loaded as packet\n\t * filters. The classes must implement <code>PacketFilterIfc</code> interface.\n\t */\n\tpublic static final String INCOMING_FILTERS_PROP_VAL =\n\t\t\t\"tigase.server.filters.PacketCounter\";\n\n\t/**\n\t * Configuration property key allowing to overwrite a default (memory size\n\t * dependent) size for the component internal queues. By default the queue\n\t * size is adjusted to the available memory size to avoid out of memory\n\t * errors.\n\t */\n\tpublic static final String MAX_QUEUE_SIZE_PROP_KEY = \"max-queue-size\";\n\n\t/**\n\t * A default value for max queue size property. The value is calculated at the\n\t * server startup time using following formula: <br>\n\t * <code>Runtime.getRuntime().maxMemory() / 400000L</code> You can change the\n\t * default queue size by setting a different value for the\n\t * <code>MAX_QUEUE_SIZE_PROP_KEY</code> property in the server configuration.\n\t */\n\tpublic static final Integer MAX_QUEUE_SIZE_PROP_VAL = new Long(Runtime.getRuntime()\n\t\t\t.maxMemory() / 400000L).intValue();\n\n\t/**\n\t * Configuration property key for setting outgoing packets filters on the\n\t * component level. This is a comma-separated list of classes which should be\n\t * loaded as packet filters. The classes must implement\n\t * <code>PacketFilterIfc</code> interface.\n\t */\n\tpublic static final String OUTGOING_FILTERS_PROP_KEY = \"outgoing-filters\";\n\n\t/**\n\t * Configuration property default vakue with a default outgoing packet filter\n\t * loaded by Tigase server.\n\t * <br>\n\t * This is a comma-separated list of classes which should be loaded as packet\n\t * filters. The classes must implement <code>PacketFilterIfc</code> interface.\n\t */\n\tpublic static final String OUTGOING_FILTERS_PROP_VAL =\n\t\t\t\"tigase.server.filters.PacketCounter\";\n\n\t/**\n\t * Configuration property key for setting number of threads used by component\n\t * ScheduledExecutorService.\n\t */\n\tpublic static final String SCHEDULER_THREADS_PROP_KEY = \"scheduler-threads\";\n\n\t/**\n\t * Constant used in time calculation procedures. Indicates a second that is\n\t * 1000 milliseconds.\n\t */\n\tprotected static final long SECOND = 1000;\n\n\t/**\n\t * Constant used in time calculation procedures. Indicates a minute that is 60\n\t * <code>SECOND</code>s.\n\t */\n\tprotected static final long MINUTE = 60 * SECOND;\n\n\t/**\n\t * Constant used in time calculation procedures. Indicates a hour that is 60\n\t * <code>MINUTE</code>s.\n\t */\n\tprotected static final long HOUR = 60 * MINUTE;\n\n\t// String added intentionally!!\n\t// Don't change to AbstractMessageReceiver.class.getName()\n\n\tprivate static final Logger log = Logger.getLogger(\n\t\t\t\"tigase.debug.AbstractMessageReceiver\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\t// private static final TigaseTracer tracer =\n\t// TigaseTracer.getTracer(\"abstract\");\n\tprivate int  in_queues_size      = 1;\n\tprivate long last_hour_packets   = 0;\n\tprivate long last_minute_packets = 0;\n\tprivate long last_second_packets = 0;\n\tprivate int  out_queues_size     = 1;\n\n\tprotected int                    maxQueueSize          = MAX_QUEUE_SIZE_PROP_VAL;\n\tprotected int                    maxInQueueSize        = MAX_QUEUE_SIZE_PROP_VAL;\n\tprotected int                    maxOutQueueSize       = MAX_QUEUE_SIZE_PROP_VAL;\n\tprivate QueueListener            out_thread            = null;\n\tprivate long                     packetId              = 0;\n\tprivate long                     packets_per_hour      = 0;\n\tprivate long                     packets_per_minute    = 0;\n\tprivate long                     packets_per_second    = 0;\n\tprivate MessageReceiver          parent                = null;\n\tprivate int                      pptIdx                = 0;\n\tprivate final long[]             processPacketTimings  = new long[100];\n\tprivate ScheduledExecutorService receiverScheduler     = null;\n\tprivate Timer                    receiverTasks         = null;\n\tprivate int                      schedulerThreads_size = 1;\n\n\t// Array cache to speed processing up....\n\tprivate final Priority[]                            pr_cache = Priority.values();\n\tprivate final CopyOnWriteArrayList<PacketFilterIfc> outgoing_filters =\n\t\t\tnew CopyOnWriteArrayList<PacketFilterIfc>();\n\tprivate final List<PriorityQueueAbstract<Packet>> out_queues =\n\t\t\tnew ArrayList<PriorityQueueAbstract<Packet>>(pr_cache.length);\n\n\t// PriorityQueueAbstract.getPriorityQueue(pr_cache.length, maxQueueSize);\n\tprivate final CopyOnWriteArrayList<PacketFilterIfc> incoming_filters =\n\t\t\tnew CopyOnWriteArrayList<PacketFilterIfc>();\n\tprivate final List<PriorityQueueAbstract<Packet>> in_queues =\n\t\t\tnew ArrayList<PriorityQueueAbstract<Packet>>(pr_cache.length);\n\n\t/**\n\t * Variable <code>statAddedMessagesEr</code> keeps counter of unsuccessfuly\n\t * added messages due to queue overflow.\n\t */\n\tprivate long statReceivedPacketsEr = 0;\n\n\t/**\n\t * Variable <code>statAddedMessagesOk</code> keeps counter of successfuly\n\t * added messages to queue.\n\t */\n\tprivate long                                                statReceivedPacketsOk = 0;\n\tprivate long                                                statSentPacketsEr     = 0;\n\tprivate long                                                statSentPacketsOk     = 0;\n\tprivate ArrayDeque<QueueListener>                           threadsQueue          =\n\t\t\tnull;\n\tprivate final ThreadFactory\t\t\t\t\t\t\t\t\tthreadFactory\t\t  =\n\t\t\tnew ThreadFactory() {\n\n\t\t\t\t\tprivate final ThreadFactory internal = Executors.defaultThreadFactory();\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Thread newThread(Runnable r) {\n\t\t\t\t\t\tThread th = internal.newThread(r);\n\t\t\t\t\t\tth.setName(\"scheduler_\" + th.getName() + \"-\" + getName());\n\t\t\t\t\t\treturn th;\n\t\t\t\t\t}\n\n\t\t\t\t};\n\tprivate final ConcurrentHashMap<String, PacketReceiverTask> waitingTasks =\n\t\t\tnew ConcurrentHashMap<String, PacketReceiverTask>(16, 0.75f, 4);\n\tprivate final Set<Pattern> regexRoutings = new ConcurrentSkipListSet<Pattern>(\n\t\t\tnew PatternComparator());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method adds a <code>Packet</code> object to the internal input queue.\n\t * Packets from the input queue are later passed to the\n\t * <code>processPacket(Packet)</code> method. This is a blocking method\n\t * waiting if necessary for the room if the queue is full.\n\t * <br>\n\t * The method returns a <code>boolean</code> value of <code>true</code> if the\n\t * packet has been successfully added to the queue and <code>false</code>\n\t * otherwise.\n\t * <br>\n\t * There can be many queues and many threads processing packets for the\n\t * component, however the method makes the best effort to guarantee that\n\t * packets are later processed in the correct order. For example that packets\n\t * for a single user always end up in the same exact queue. You can tweak the\n\t * packets distribution among threads by overwriting\n\t * <code>hashCodeForPacket(Packet)</code> method.<br>\n\t * If there is <code>N</code> threads the packets are distributed among thread\n\t * using following logic:\n\t *\n\t * <pre>\n\t * int threadNo = Math.abs(hashCodeForPacket(packet) % N);\n\t * </pre>\n\t *\n\t * This is a preferred method to be used by most Tigase components. If the\n\t * queues are full the component should stop and wait for more room. The\n\t * blocking methods aim to prevent from the system overloading or wasting\n\t * resources for generating packets which can't be processed anyway.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance being put to the component\n\t *          internal input queue.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if the packet has\n\t *         been successfully added to the queue and <code>false</code>\n\t *         otherwise.\n\t */\n\t@Override\n\tpublic boolean addPacket(Packet packet) {\n\t\tint queueIdx = Math.abs(hashCodeForPacket(packet) % in_queues_size);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"[{0}] queueIdx={1}, {2}\", new Object[] { getName(), queueIdx,\n\t\t\t\t\tpacket.toStringSecure() });\n\t\t}\n\t\ttry {\n\t\t\tin_queues.get(queueIdx).put(packet, packet.getPriority().ordinal());\n\t\t\t++statReceivedPacketsOk;\n\t\t} catch (InterruptedException e) {\n\t\t\t++statReceivedPacketsEr;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet dropped for unknown reason: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}    // end of try-catch\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * This is a variant of <code>addPacket(Packet)</code> method which adds\n\t * <code>Packet</code> to in the internal input queue without blocking.\n\t * <br>\n\t * The method returns a <code>boolean</code> value of <code>true</code> if the\n\t * packet has been successful added to the queue and <code>false</code>\n\t * otherwise.\n\t * <br>\n\t * Use of the non-blocking methods is not recommended for most of the\n\t * components implementations. The only component which is allowed to use them\n\t * is the server <code>MessageRouter</code> implementation which can not hang\n\t * on any method. This would cause a dead-lock in the application. All other\n\t * components must use blocking methods and wait if the system is under so\n\t * high load that it's queues are full.\n\t * <br>\n\t * See <code>addPacket(Packet)</code> method's documentation for some more\n\t * details.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance being put to the component\n\t *          internal input queue.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if the packet has\n\t *         been successfully added to the queue and <code>false</code>\n\t *         otherwise.\n\t * @see AbstractMessageReceiver#addPacket(Packet packet)\n\t */\n\t@Override\n\tpublic boolean addPacketNB(Packet packet) {\n\t\tint queueIdx = Math.abs(hashCodeForPacket(packet) % in_queues_size);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"[{0}] queueIdx={1}, {2}\", new Object[] { getName(), queueIdx,\n\t\t\t\t\tpacket.toStringSecure() });\n\t\t}\n\n\t\tboolean result = in_queues.get(queueIdx).offer(packet, packet.getPriority()\n\t\t\t\t.ordinal());\n\n\t\tif (result) {\n\t\t\t++statReceivedPacketsOk;\n\t\t} else {\n\n\t\t\t// Queue overflow!\n\t\t\t++statReceivedPacketsEr;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet dropped due to queue overflow: {0}\", packet);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * This is a convenience method for adding all packets stored in given queue\n\t * to the component's internal input queue.<br>\n\t * The method calls <code>addPacket(Packet)</code> in a loop for each packet\n\t * in the queue. If the call returns <code>true</code> then the packet is\n\t * removed from the given queue, otherwise the methods ends the loop and\n\t * returns <code>false</code>.\n\t * <br>\n\t * Please note, if the method returns <code>true</code> it means that all the\n\t * packets from the queue passed as a parameter have been successfuly run\n\t * through the <code>addPacket(Packet)</code> method and the queue passed as a\n\t * parameter should be empty. If the method returns false then at least one\n\t * packet from the parameter queue wasn't successfully run through the\n\t * <code>addPacket(Packet)</code> method. If the method returns\n\t * <code>false</code> then the queue passed as a parameter is not empty and it\n\t * contains packet which was unseccessfully run through the\n\t * <code>addPacket(Packet)</code> method and all the packets which were not\n\t * run at all.\n\t *\n\t *\n\t * @param packets\n\t *          is a <code>Queue</code> of packets for adding to the component\n\t *          internal input queue. All the packets are later processed by\n\t *          <code>processPacket(Packet)</code> method in the same exact order\n\t *          if they are processed by the same thread. See documentation\n\t *          <code>hashCodeForPacket(Packet)</code> method how to control\n\t *          assiging packets to particular threads.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if all packets\n\t *         has been successfully added to the component's internal input queue\n\t *         and <code>false</code> otherwise.\n\t * @see AbstractMessageReceiver#hashCodeForPacket(Packet packet)\n\t */\n\t@Override\n\tpublic boolean addPackets(Queue<Packet> packets) {\n\t\tboolean result = true;\n\t\tPacket  p      = packets.peek();\n\n\t\twhile (p != null) {\n\t\t\tresult = addPacket(p);\n\t\t\tif (result) {\n\t\t\t\tpackets.poll();\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}    // end of if (result) else\n\t\t\tp = packets.peek();\n\t\t}      // end of while ()\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method adds a new routing address for the component. Routing addresses are\n\t * used by the <code>MessageRouter</code> to calculate packet's destination.\n\t * If the packet's destination address matches one of the component's routing\n\t * addresses the packet is added to the component's internal input queue.\n\t * <br>\n\t * By default all components accept packets addressed to the componentId and\n\t * to:\n\t *\n\t * <pre>\n\t * component.getName() + '@' + any virtual domain\n\t * </pre>\n\t *\n\t * TODO: The future implementation most likely accept packets addressed to:\n\t *\n\t *        <pre>\n\t * any virtual domain + '/' + component.getName()\n\t * </pre>\n\t *\n\t *        instead.\n\t *        <br>\n\t *        The routings are passed as Java regular expression strings are the\n\t *        extra addresses accepted by the component. In most cases this is\n\t *        used by the external component protocol implementations which can\n\t *        dynamically change accepted addresses depending on the connected\n\t *        external components.\n\t *\n\t * @param address\n\t *          is a Java regular expression string for the packet's destination\n\t *          address accepted by this component.\n\t */\n\tpublic void addRegexRouting(String address) {\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"{0} - attempt to add regex routing: {1}\", new Object[] {\n\t\t\t\t\tgetName(),\n\t\t\t\t\taddress });\n\t\t}\n\t\tregexRoutings.add(Pattern.compile(address, Pattern.CASE_INSENSITIVE));\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"{0} - success adding regex routing: {1}\", new Object[] {\n\t\t\t\t\tgetName(),\n\t\t\t\t\taddress });\n\t\t}\n\t}\n\n\t/**\n\t * Method queues and executes timer tasks using ScheduledExecutorService\n\t * which allows using more than one thread for executing tasks.\n\t *\n\t * @param task\n\t * @param delay\n\t */\n\tpublic void addTimerTask(tigase.util.TimerTask task, long delay) {\n\t\tScheduledFuture<?> future = receiverScheduler.schedule(task, delay, TimeUnit\n\t\t\t\t.MILLISECONDS);\n\n\t\ttask.setScheduledFuture(future);\n\t}\n\t\n\tpublic void addTimerTask(tigase.util.TimerTask task, long initialDelay, long period) {\n\t\tScheduledFuture<?> future = receiverScheduler.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.MILLISECONDS);\n\t\ttask.setScheduledFuture(future);\n\t}\n\n\t/**\n\t * Method queues and executes all timer tasks on Timer SINGLE thread.\n\t *\n\t * @param task\n\t * @param delay\n\t * @deprecated\n\t */\n\t@Deprecated\n\tpublic void addTimerTask(TimerTask task, long delay) {\n\t\treceiverTasks.schedule(task, delay);\n\t}\n\n\t/**\n\t * Method clears, removes all the component routing addresses. After this\n\t * method call the component accepts only packets addressed to default\n\t * routings that is component ID or the component name + '@' + virtual domains\n\t */\n\tpublic void clearRegexRoutings() {\n\t\tregexRoutings.clear();\n\t}\n\n\t/**\n\t * Utility method executed precisely every hour. A component can overwrite the\n\t * method to put own code to be executed at the regular intervals of time.\n\t * <br>\n\t * Note, no extensive calculations should happen in this method nor long\n\t * lasting operations. It is essential that the method processing does not\n\t * exceed 1 hour. The overriding method must call the the super method first\n\t * and only then run own code.\n\t */\n\t@Override\n\tpublic synchronized void everyHour() {\n\t\tpackets_per_hour  = statReceivedPacketsOk - last_hour_packets;\n\t\tlast_hour_packets = statReceivedPacketsOk;\n\t\tsuper.everyHour();\n\t}\n\n\t/**\n\t * Utility method executed precisely every minute. A component can overwrite\n\t * the method to put own code to be executed at the regular intervals of time.\n\t * <br>\n\t * Note, no extensive calculations should happen in this method nor long\n\t * lasting operations. It is essential that the method processing does not\n\t * exceed 1 minute. The overriding method must call the the super method first\n\t * and only then run own code.\n\t */\n\t@Override\n\tpublic synchronized void everyMinute() {\n\t\tpackets_per_minute  = statReceivedPacketsOk - last_minute_packets;\n\t\tlast_minute_packets = statReceivedPacketsOk;\n\t\treceiverTasks.purge();\n\t\tsuper.everyMinute();\n\t}\n\n\t/**\n\t * Utility method executed precisely every second. A component can overwrite\n\t * the method to put own code to be executed at the regular intervals of time.\n\t * <br>\n\t * Note, no extensive calculations should happen in this method nor long\n\t * lasting operations. It is essential that the method processing does not\n\t * exceed 1 second. The overriding method must call the the super method first\n\t * and only then run own code.\n\t */\n\t@Override\n\tpublic synchronized void everySecond() {\n\t\tpackets_per_second  = statReceivedPacketsOk - last_second_packets;\n\t\tlast_second_packets = statReceivedPacketsOk;\n\t\tsuper.everySecond();\n\t}\n\n\t/**\n\t * This method decides how incoming packets are distributed among processing\n\t * threads. Different components needs different distribution to efficient use\n\t * all threads and avoid packets re-ordering.\n\t * <br>\n\t * If there are N processing threads, packets are distributed among threads\n\t * using following code:\n\t *\n\t * <pre>\n\t * int threadNo = Math.abs(hashCodeForPacket(packet) % N);\n\t * </pre>\n\t *\n\t * For a PubSub component, for example, a better packets distribution would be\n\t * based on the PubSub channel name, for SM a better distribution is based on\n\t * the destination address, etc....\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> which needs to be processed by some\n\t *          thread.\n\t * @return a hash code generated for the input thread.\n\t */\n\tpublic int hashCodeForPacket(Packet packet) {\n\t\t// use of getPacketFrom was moved to SM as it worked OK only in use case of SM \n\t\t// where packet may came from connection manager\n\t\tif ((packet.getPacketTo() != null) &&!getComponentId().equals(packet.getPacketTo())) {\n\t\t\treturn packet.getPacketTo().hashCode();\n\t\t}\n\n\t\t// If not, then a better way is to get hashCode from the elemTo address\n\t\t// as this would be by the destination address user name:\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().getBareJID().hashCode();\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param prefix\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String newPacketId(String prefix) {\n\t\tStringBuilder sb = new StringBuilder(32);\n\n\t\tif (prefix != null) {\n\t\t\tsb.append(prefix).append(\"-\");\n\t\t}\n\t\tsb.append(getName()).append(++packetId);\n\n\t\treturn sb.toString();\n\t}\n\n\t/**\n\t * Concurrency control method. Returns preferable number of threads set for\n\t * this component.\n\t *\n\t *\n\t * @return preferable number of threads set for this component.\n\t */\n\tpublic int processingInThreads() {\n\t\treturn 1;\n\t}\n\n\t/**\n\t * Concurrency control method. Returns preferable number of threads set for\n\t * this component.\n\t *\n\t *\n\t * @return preferable number of threads set for this component.\n\t */\n\tpublic int processingOutThreads() {\n\t\treturn 1;\n\t}\n\n\t/**\n\t * There is now a separate setting for incoming packets and outgoing packets\n\t * processing. Some components are uni-directional, hence they don't even use\n\t * any threads in one direction. This way you can save resources by reducing\n\t * unneeded threads. Use <code>processingOutThreads()</code> and\n\t * <code>processingInThreads()</code> instead.\n\t *\n\t *\n\t *\n\t * @return a value of <code>int</code>\n\t */\n\t@Deprecated\n\tpublic int processingThreads() {\n\t\treturn 1;\n\t}\n\n\t/**\n\t * By default this method just copies the given packet between queue. This\n\t * method operates on packets which have been already processed somehow by the\n\t * component so usually the default action is the best one, however some\n\t * components in rare cases may choose to process packets differently. In most\n\t * cases this method should not be overridden.\n\t *\n\t * @param packet\n\t *          is an output packet which normally has to go to other component\n\t *          for further processing.\n\t */\n\tpublic void processOutPacket(Packet packet) {\n\t\tif (parent != null) {\n\t\t\tparent.addPacket(packet);\n\t\t} else {\n\n\t\t\t// It may happen for MessageRouter and this is intentional\n\t\t\taddPacketNB(packet);\n\n\t\t\t// log.warning(\"[\" + getName() + \"]  \" + \"No parent!\");\n\t\t}    // end of else\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * This is the main <code>Packet</code> processing method. It is called\n\t * concurrently from many threads so implementing it in thread save manner is\n\t * essential. The method is called for each packet addressed to the component.\n\t * <br>\n\t * Please note, the <code>Packet</code> instance may be processed by different\n\t * parts of the server, different components or plugins at the same time.\n\t * Therefore this is very important to tread the <code>Packet</code> instance\n\t * as unmodifiable object.\n\t * <br>\n\t * Processing in this method is asynchronous, therefore there is no result\n\t * value. If there are some 'result' packets generated during processing, they\n\t * should be passed back using <code>addOutPacket(Packet)</code> method.\n\t *\n\t *\n\t * @param packet\n\t *          is an instance of the <code>Packet</code> class passed for\n\t *          processing.\n\t */\n\tpublic abstract void processPacket(Packet packet);\n\n\t@Override\n\tpublic final void processPacket(final Packet packet, final Queue<Packet> results) {\n\t\taddPacketNB(packet);\n\t}\n\n\t@Override\n\tpublic void release() {\n\t\tstop();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param address\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean removeRegexRouting(String address) {\n\t\treturn regexRoutings.remove(Pattern.compile(address, Pattern.CASE_INSENSITIVE));\n\t}\n\n\t/**\n\t * Method returns default number of threads used by SchedulerExecutorService\n\t *\n\t *\n\t *\n\t * @return a value of <code>int</code>\n\t */\n\tpublic int schedulerThreads() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.INFO, \"{0}: starting queue management threads ...\", getName());\n\t\t}\n\t\tstartThreads();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void stop() {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.INFO, \"{0}: stopping queue management threads ...\", getName());\n\t\t}\n\t\tstopThreads();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns default configuration settings for the component as a\n\t * <code>Map</code> with keys as configuration property IDs and values as the\n\t * configuration property values. All the default parameters returned from\n\t * this method are later passed to the <code>setProperties(...)</code> method.\n\t * Some of them may have changed value if they have been overwritten in the\n\t * server configuration. The configuration property value can be of any of the\n\t * basic types: <code>int</code>, <code>long</code>, <code>boolean</code>,\n\t * <code>String</code>.\n\t *\n\t * @param params\n\t *          is a <code>Map</code> with some initial properties set for the\n\t *          starting up server. These parameters can be used as a hints to\n\t *          generate component's default configuration.\n\t *\n\t * @return a <code>Map</code> with the component default configuration.\n\t */\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs         = super.getDefaults(params);\n\t\tString              queueSize    = (String) params.get(GEN_MAX_QUEUE_SIZE);\n\t\tint                 queueSizeInt = MAX_QUEUE_SIZE_PROP_VAL;\n\n\t\tif (queueSize != null) {\n\t\t\ttry {\n\t\t\t\tqueueSizeInt = Integer.parseInt(queueSize);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\tqueueSizeInt = MAX_QUEUE_SIZE_PROP_VAL;\n\t\t\t}\n\t\t}\n\t\tdefs.put(MAX_QUEUE_SIZE_PROP_KEY, getMaxQueueSize(queueSizeInt));\n\t\tdefs.put(SCHEDULER_THREADS_PROP_KEY, schedulerThreads());\n\t\tdefs.put(INCOMING_FILTERS_PROP_KEY, INCOMING_FILTERS_PROP_VAL);\n\t\tdefs.put(OUTGOING_FILTERS_PROP_KEY, OUTGOING_FILTERS_PROP_VAL);\n\n\t\treturn defs;\n\t}\n\n\t/**\n\t * Method returns a <code>Set</code> with all component's routings as a\n\t * compiled regular expression patterns. The <code>Set</code> can be empty but\n\t * it can not be null.\n\t *\n\t * @return a <code>Set</code> with all component's routings as a compiled\n\t *         regular expression patterns.\n\t */\n\tpublic Set<Pattern> getRegexRoutings() {\n\t\treturn regexRoutings;\n\t}\n\n\t/**\n\t * Method returns component statistics. Please note, the method can be called\n\t * every second by the server monitoring system therefore no extensive or\n\t * lengthy calculations are allowed. If there are some statistics requiring\n\t * lengthy operations like database access they must have\n\t * <code>Level.FINEST</code> assigned and must be put inside the level guard\n\t * to prevent generating them by the system monitor. The system monitor does\n\t * not collect <code>FINEST</code> statistics.\n\t * <br>\n\t * Level guard code looks like the example below:\n\t *\n\t * <pre>\n\t * if (list.checkLevel(Level.FINEST)) {\n\t *   // Some CPU intensive calculations or lengthy operations\n\t *   list.add(getName(), \"Statistic description\", stat_value, Level.FINEST);\n\t * }\n\t *\n\t * </pre>\n\t * This way you make sure your extensive operation is not executed every second by the\n\t * monitoring system and does not affect the server performance.\n\t *\n\t * @param list is a <code>StatistcsList</code>\n\t * where all statistics are stored.\n\t */\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tlist.add(getName(), \"Last second packets\", packets_per_second, Level.FINE);\n\t\tlist.add(getName(), \"Last minute packets\", packets_per_minute, Level.FINE);\n\t\tlist.add(getName(), \"Last hour packets\", packets_per_hour, Level.FINE);\n\t\tlist.add(getName(), \"Processing threads\", processingInThreads(), Level.FINER);\n\t\tlist.add(getName(), StatisticType.MSG_RECEIVED_OK.getDescription(),\n\t\t\t\tstatReceivedPacketsOk, Level.FINE);\n\t\tlist.add(getName(), StatisticType.MSG_SENT_OK.getDescription(), statSentPacketsOk,\n\t\t\t\tLevel.FINE);\n\t\tif (list.checkLevel(Level.FINEST)) {\n\t\t\tint[] in_priority_sizes = in_queues.get(0).size();\n\n\t\t\tfor (int i = 1; i < in_queues.size(); i++) {\n\t\t\t\tint[] tmp_pr_sizes = in_queues.get(i).size();\n\n\t\t\t\tfor (int j = 0; j < tmp_pr_sizes.length; j++) {\n\t\t\t\t\tin_priority_sizes[j] += tmp_pr_sizes[j];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tint[] out_priority_sizes = out_queues.get(0).size();\n\n\t\t\tfor (int i = 1; i < out_queues.size(); i++) {\n\t\t\t\tint[] tmp_pr_sizes = out_queues.get(i).size();\n\n\t\t\t\tfor (int j = 0; j < tmp_pr_sizes.length; j++) {\n\t\t\t\t\tout_priority_sizes[j] += tmp_pr_sizes[j];\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int i = 0; i < in_priority_sizes.length; i++) {\n\t\t\t\tPriority queue = Priority.values()[i];\n\n\t\t\t\tlist.add(getName(), \"In queue wait: \" + queue.name(),\n\t\t\t\t\t\tin_priority_sizes[queue.ordinal()], Level.FINEST);\n\t\t\t}\n\t\t\tfor (int i = 0; i < out_priority_sizes.length; i++) {\n\t\t\t\tPriority queue = Priority.values()[i];\n\n\t\t\t\tlist.add(getName(), \"Out queue wait: \" + queue.name(),\n\t\t\t\t\t\tout_priority_sizes[queue.ordinal()], Level.FINEST);\n\t\t\t}\n\t\t}\n\n\t\tint in_queue_size = 0;\n\n\t\tfor (PriorityQueueAbstract<Packet> total_size : in_queues) {\n\t\t\tin_queue_size += total_size.totalSize();\n\t\t}\n\n\t\tint out_queue_size = 0;\n\n\t\tfor (PriorityQueueAbstract<Packet> total_size : out_queues) {\n\t\t\tout_queue_size += total_size.totalSize();\n\t\t}\n\t\tlist.add(getName(), \"Total In queues wait\", in_queue_size, Level.INFO);\n\t\tlist.add(getName(), \"Total Out queues wait\", out_queue_size, Level.INFO);\n\t\tlist.add(getName(), \"Total queues wait\", (in_queue_size + out_queue_size), Level\n\t\t\t\t.INFO);\n\t\tlist.add(getName(), StatisticType.MAX_QUEUE_SIZE.getDescription(), (maxInQueueSize *\n\t\t\t\tprocessingInThreads()), Level.FINEST);\n\t\tlist.add(getName(), StatisticType.IN_QUEUE_OVERFLOW.getDescription(),\n\t\t\t\tstatReceivedPacketsEr, Level.INFO);\n\t\tlist.add(getName(), StatisticType.OUT_QUEUE_OVERFLOW.getDescription(),\n\t\t\t\tstatSentPacketsEr, Level.INFO);\n\t\tlist.add(getName(), \"Total queues overflow\", (statReceivedPacketsEr +\n\t\t\t\tstatSentPacketsEr), Level.INFO);\n\n\t\tlong res = 0;\n\n\t\tfor (long ppt : processPacketTimings) {\n\t\t\tres += ppt;\n\t\t}\n\n\t\tlong prcessingTime = res / processPacketTimings.length;\n\n\t\tlist.add(getName(), \"Average processing time on last \" + processPacketTimings\n\t\t\t\t.length + \" runs [ms]\", prcessingTime, Level.FINE);\n\t\tfor (PacketFilterIfc packetFilter : incoming_filters) {\n\t\t\tpacketFilter.getStatistics(list);\n\t\t}\n\t\tfor (PacketFilterIfc packetFilter : outgoing_filters) {\n\t\t\tpacketFilter.getStatistics(list);\n\t\t}\n\t\tif (list.checkLevel(Level.FINEST)) {\n\t\t\tfor (QueueListener thread : threadsQueue) {\n\t\t\t\tlist.add(getName(), \"Processed packets thread: \" + thread.getName(), thread\n\t\t\t\t\t\t.packetCounter, Level.FINEST);\n\t\t\t}\n\t\t}\n\t\tsuper.getStatistics(list);\n\t}\n\n\t@Override\n\tpublic boolean isInRegexRoutings(String address) {\n\n\t\t// log.finest(getName() + \" looking for regex routings: \" + address);\n\t\tfor (Pattern pat : regexRoutings) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} matching: {1} against {2}\", new Object[] { getName(),\n\t\t\t\t\t\taddress, pat.toString() });\n\t\t\t}\n\t\t\tif (pat.matcher(address).matches()) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// log.finest(getName() + \" matching failed against pattern: \" +\n\t\t\t// pat.toString());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t// ~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param maxQueueSize\n\t *\n\t */\n\tpublic void setMaxQueueSize(int maxQueueSize) {\n\t\tif ((this.maxQueueSize != maxQueueSize) || (in_queues.size() == 0)) {\n\t\t\tthis.maxQueueSize = maxQueueSize;\n\t\t\t\n\t\t\t// out_queue = PriorityQueueAbstract.getPriorityQueue(pr_cache.length,\n\t\t\t// maxQueueSize);\n\t\t\t// Processing threads number is split to incoming and outgoing queues...\n\t\t\t// So real processing threads number of in_queues is processingThreads()/2\n\t\t\tthis.maxInQueueSize  = (maxQueueSize / processingInThreads()) * 2;\n\t\t\tthis.maxOutQueueSize = (maxQueueSize / processingOutThreads()) * 2;\n\t\t\tlog.log(Level.FINEST, \"{0} maxQueueSize: {1}, maxInQueueSize: {2}, maxOutQueueSize: {3}\", new Object[] {getName(), maxQueueSize, maxInQueueSize, maxOutQueueSize});\n\t\t\tif (in_queues.size() == 0) {\n\t\t\t\tfor (int i = 0; i < in_queues_size; i++) {\n\t\t\t\t\tPriorityQueueAbstract<Packet> queue = PriorityQueueAbstract.getPriorityQueue(\n\t\t\t\t\t\t\tpr_cache.length, maxInQueueSize);\n\n\t\t\t\t\tin_queues.add(queue);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (int i = 0; i < in_queues.size(); i++) {\n\t\t\t\t\tin_queues.get(i).setMaxSize(maxInQueueSize);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (out_queues.size() == 0) {\n\t\t\t\tfor (int i = 0; i < out_queues_size; i++) {\n\t\t\t\t\tPriorityQueueAbstract<Packet> queue = PriorityQueueAbstract.getPriorityQueue(\n\t\t\t\t\t\t\tpr_cache.length, maxOutQueueSize);\n\n\t\t\t\t\tout_queues.add(queue);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (int i = 0; i < out_queues.size(); i++) {\n\t\t\t\t\tout_queues.get(i).setMaxSize(maxOutQueueSize);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// out_queue.setMaxSize(maxQueueSize);\n\t\t}    // end of if (this.maxQueueSize != maxQueueSize)\n\t}\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t\tin_queues_size        = processingInThreads();\n\t\tout_queues_size       = processingOutThreads();\n\t\tschedulerThreads_size = schedulerThreads();\n\t\tsetMaxQueueSize(maxQueueSize);\n\t}\n\n\t@Override\n\tpublic void setParent(MessageReceiver parent) {\n\t\tthis.parent = parent;\n\t}\n\n\t@Override\n\t@TODO(note = \"Replace fixed filers loading with configurable options for that\")\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.get(MAX_QUEUE_SIZE_PROP_KEY) != null) {\n\t\t\tint queueSize = (Integer) props.get(MAX_QUEUE_SIZE_PROP_KEY);\n\n\t\t\tsetMaxQueueSize(queueSize);\n\t\t}\n\t\tif (props.get(SCHEDULER_THREADS_PROP_KEY) != null) {\n\t\t\tint threads = (Integer) props.get(SCHEDULER_THREADS_PROP_KEY);\n\n\t\t\tif (threads != schedulerThreads_size) {\n\t\t\t\tschedulerThreads_size = threads;\n\n\t\t\t\tScheduledExecutorService scheduler = receiverScheduler;\n\n\t\t\t\treceiverScheduler = Executors.newScheduledThreadPool(threads, threadFactory);\n\t\t\t\tscheduler.shutdown();\n\t\t\t}\n\t\t}\n\n\t\tString filters = (String) props.get(INCOMING_FILTERS_PROP_KEY);\n\n\t\tif ((filters != null) &&!filters.trim().isEmpty()) {\n\t\t\tincoming_filters.clear();\n\n\t\t\tString[] incoming = filters.trim().split(\",\");\n\n\t\t\tfor (String inc : incoming) {\n\t\t\t\ttry {\n\t\t\t\t\tPacketFilterIfc filter = (PacketFilterIfc) Class.forName(inc).newInstance();\n\n\t\t\t\t\tfilter.init(getName(), QueueType.IN_QUEUE);\n\t\t\t\t\tincoming_filters.add(filter);\n\t\t\t\t\tlog.log(Level.CONFIG, \"{0} loaded incoming filter: {1}\", new Object[] {\n\t\t\t\t\t\t\tgetName(),\n\t\t\t\t\t\t\tinc });\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Problem loading filter: \" + inc + \" in component: \" +\n\t\t\t\t\t\t\tgetName(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfilters = (String) props.get(OUTGOING_FILTERS_PROP_KEY);\n\t\tif ((filters != null) &&!filters.trim().isEmpty()) {\n\t\t\toutgoing_filters.clear();\n\n\t\t\tString[] outgoing = filters.trim().split(\",\");\n\n\t\t\tfor (String out : outgoing) {\n\t\t\t\ttry {\n\t\t\t\t\tPacketFilterIfc filter = (PacketFilterIfc) Class.forName(out).newInstance();\n\n\t\t\t\t\tfilter.init(getName(), QueueType.OUT_QUEUE);\n\t\t\t\t\toutgoing_filters.add(filter);\n\t\t\t\t\tlog.log(Level.CONFIG, \"{0} loaded outgoing filter: {1}\", new Object[] {\n\t\t\t\t\t\t\tgetName(),\n\t\t\t\t\t\t\tout });\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Problem loading filter: \" + out + \" in component: \" +\n\t\t\t\t\t\t\tgetName(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected boolean addOutPacket(Packet packet) {\n\t\tint queueIdx = Math.abs(hashCodeForPacket(packet) % out_queues_size);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"[{0}]  queueIdx={1}, {2}\", new Object[] { getName(),\n\t\t\t\t\tqueueIdx, packet.toStringSecure() });\n\t\t}\n\t\ttry {\n\t\t\tout_queues.get(queueIdx).put(packet, packet.getPriority().ordinal());\n\t\t\t++statSentPacketsOk;\n\t\t} catch (InterruptedException e) {\n\t\t\t++statSentPacketsEr;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet dropped for unknown reason: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}    // end of try-catch\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Non blocking version of <code>addOutPacket</code>.\n\t *\n\t * @param packet\n\t *          a <code>Packet</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\tprotected boolean addOutPacketNB(Packet packet) {\n\t\tint queueIdx = Math.abs(hashCodeForPacket(packet) % out_queues_size);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"[{0}]  queueIdx={1}, {2}\", new Object[] { getName(),\n\t\t\t\t\tqueueIdx, packet.toStringSecure() });\n\t\t}\n\n\t\tboolean result = false;\n\n\t\tresult = out_queues.get(queueIdx).offer(packet, packet.getPriority().ordinal());\n\t\tif (result) {\n\t\t\t++statSentPacketsOk;\n\t\t} else {\n\n\t\t\t// Queue overflow!\n\t\t\t++statSentPacketsEr;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet dropped due to queue overflow: {0}\", packet);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packets\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean addOutPackets(Queue<Packet> packets) {\n\t\tPacket  p      = null;\n\t\tboolean result = true;\n\n\t\twhile ((p = packets.peek()) != null) {\n\t\t\tresult = addOutPacket(p);\n\t\t\tif (result) {\n\t\t\t\tpackets.poll();\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}    // end of if (result) else\n\t\t}      // end of while ()\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param handler\n\t * @param delay\n\t * @param unit\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean addOutPacketWithTimeout(Packet packet,\n\t\t\tReceiverTimeoutHandler handler, long delay, TimeUnit unit) {\n\n\t\t// It is automatically added to collections and the Timer\n\t\tnew PacketReceiverTask(handler, delay, unit, packet);\n\n\t\treturn addOutPacket(packet);\n\t}\n\n\t/**\n\t * Method queues and executes timer tasks using ScheduledExecutorService\n\t * which allows using more than one thread for executing tasks.\n\t *\n\t * @param task\n\t * @param delay\n\t * @param unit\n\t */\n\tprotected void addTimerTask(tigase.util.TimerTask task, long delay, TimeUnit unit) {\n\t\tScheduledFuture<?> future = receiverScheduler.schedule(task, delay, unit);\n\n\t\ttask.setScheduledFuture(future);\n\t}\n\n\t/**\n\t * Method queues and executes all timer tasks on Timer SINGLE thread.\n\t *\n\t * @param task\n\t * @param delay\n\t * @param unit\n\t * @deprecated\n\t */\n\t@Deprecated\n\tprotected void addTimerTask(TimerTask task, long delay, TimeUnit unit) {\n\t\treceiverTasks.schedule(task, unit.toMillis(delay));\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param def\n\t *\n\t *\n\t *\n\t * @return a value of <code>Integer</code>\n\t */\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate Packet filterPacket(Packet packet,\n\t\t\tCopyOnWriteArrayList<PacketFilterIfc> filters) {\n\t\tPacket result = packet;\n\n\t\tfor (PacketFilterIfc packetFilterIfc : filters) {\n\t\t\tresult = packetFilterIfc.filter(result);\n\t\t\tif (result == null) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate void startThreads() {\n\t\tif (threadsQueue == null) {\n\t\t\tthreadsQueue = new ArrayDeque<QueueListener>(8);\n\t\t\tfor (int i = 0; i < in_queues_size; i++) {\n\t\t\t\tQueueListener in_thread = new QueueListener(in_queues.get(i), QueueType.IN_QUEUE);\n\n\t\t\t\tin_thread.setName(\"in_\" + i + \"-\" + getName());\n\t\t\t\tin_thread.start();\n\t\t\t\tthreadsQueue.add(in_thread);\n\t\t\t}\n\t\t\tfor (int i = 0; i < out_queues_size; i++) {\n\t\t\t\tQueueListener out_thread = new QueueListener(out_queues.get(i), QueueType\n\t\t\t\t\t\t.OUT_QUEUE);\n\n\t\t\t\tout_thread.setName(\"out_\" + i + \"-\" + getName());\n\t\t\t\tout_thread.start();\n\t\t\t\tthreadsQueue.add(out_thread);\n\t\t\t}\n\t\t}    // end of if (thread == null || ! thread.isAlive())\n\n\t\t// if ((out_thread == null) ||!out_thread.isAlive()) {\n\t\t// out_thread = new QueueListener(out_queue, QueueType.OUT_QUEUE);\n\t\t// out_thread.setName(\"out_\" + getName());\n\t\t// out_thread.start();\n\t\t// } // end of if (thread == null || ! thread.isAlive())\n\t\treceiverScheduler = Executors.newScheduledThreadPool(schedulerThreads_size, threadFactory);\n\t\treceiverTasks     = new Timer(getName() + \" tasks\", true);\n\t\treceiverTasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\teverySecond();\n\t\t\t}\n\t\t}, SECOND, SECOND);\n\t\treceiverTasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\teveryMinute();\n\t\t\t}\n\t\t}, MINUTE, MINUTE);\n\t\treceiverTasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\teveryHour();\n\t\t\t}\n\t\t}, HOUR, HOUR);\n\t}\n\n\tprivate void stopThreads() {\n\n\t\t// stopped = true;\n\t\ttry {\n\t\t\tif (threadsQueue != null) {\n\t\t\t\tfor (QueueListener in_thread : threadsQueue) {\n\t\t\t\t\tin_thread.threadStopped = true;\n\t\t\t\t\tin_thread.interrupt();\n\t\t\t\t\twhile (in_thread.isAlive()) {\n\t\t\t\t\t\tThread.sleep(100);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (out_thread != null) {\n\t\t\t\tout_thread.threadStopped = true;\n\t\t\t\tout_thread.interrupt();\n\t\t\t\twhile (out_thread.isAlive()) {\n\t\t\t\t\tThread.sleep(100);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (InterruptedException e) {}\n\t\tthreadsQueue = null;\n\t\tout_thread   = null;\n\t\tif (receiverTasks != null) {\n\t\t\treceiverTasks.cancel();\n\t\t\treceiverTasks = null;\n\t\t}\n\t\tif (receiverScheduler != null) {\n\t\t\treceiverScheduler.shutdownNow();\n\t\t\treceiverScheduler = null;\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class PacketReceiverTask\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\tprivate ReceiverTimeoutHandler handler = null;\n\t\tprivate String                 id      = null;\n\t\tprivate Packet                 packet  = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate PacketReceiverTask(ReceiverTimeoutHandler handler, long delay, TimeUnit unit,\n\t\t\t\tPacket packet) {\n\t\t\tsuper();\n\t\t\tthis.handler = handler;\n\t\t\tthis.packet  = packet;\n\t\t\tid           = packet.getFrom().toString() + packet.getStanzaId();\n\t\t\twaitingTasks.put(id, this);\n\t\t\taddTimerTask(this, delay, unit);\n\n\t\t\t// log.finest(\"[\" + getName() + \"]  \" + \"Added timeout task for: \" + id);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * @param response\n\t\t */\n\t\tpublic void handleResponse(Packet response) {\n\n\t\t\t// waitingTasks.remove(packet.getFrom() + packet.getId());\n\t\t\tthis.cancel();\n\n\t\t\t// log.finest(\"[\" + getName() + \"]  \" + \"Response received for id: \" +\n\t\t\t// id);\n\t\t\thandler.responseReceived(packet, response);\n\t\t}\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t */\n\t\tpublic void handleTimeout() {\n\n\t\t\t// log.finest(\"[\" + getName() + \"]  \" + \"Fired timeout for id: \" + id);\n\t\t\twaitingTasks.remove(id);\n\t\t\thandler.timeOutExpired(packet);\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\thandleTimeout();\n\t\t}\n\t}\n\n\n\tprivate class QueueListener\n\t\t\t\t\textends Thread {\n\t\tprivate String                        compName      = null;\n\t\tprivate long                          packetCounter = 0;\n\t\tprivate QueueType                     type          = null;\n\t\tprivate boolean                       threadStopped = false;\n\t\tprivate PriorityQueueAbstract<Packet> queue;\n\n\t\t//~--- constructors -------------------------------------------------------\n\t\tprivate QueueListener(PriorityQueueAbstract<Packet> q, QueueType type) {\n\t\t\tthis.queue = q;\n\t\t\tthis.type  = type;\n\t\t\tcompName   = AbstractMessageReceiver.this.getName();\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} starting queue processing.\", getName());\n\t\t\t}\n\n\t\t\tPacket        packet  = null;\n\t\t\tQueue<Packet> results = new ArrayDeque<Packet>(2);\n\n\t\t\twhile (!threadStopped) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Now process next waiting packet\n\t\t\t\t\t// log.finest(\"[\" + getName() + \"] before take... \" + type);\n\t\t\t\t\t// packet = queue.take(getName() + \":\" + type);\n\t\t\t\t\tpacket = queue.take();\n\t\t\t\t\t++packetCounter;\n\n\t\t\t\t\t// if (log.isLoggable(Level.INFO)) {\n\t\t\t\t\t// log.info(\"[\" + getName() + \"] packet from \" + type + \" queue: \" +\n\t\t\t\t\t// packet);\n\t\t\t\t\t// }\n\t\t\t\t\tswitch (type) {\n\t\t\t\t\tcase IN_QUEUE :\n\t\t\t\t\t\tlong startPPT = System.currentTimeMillis();\n\n\t\t\t\t\t\t// tracer.trace(null, packet.getElemTo(), packet.getElemFrom(),\n\t\t\t\t\t\t// packet.getFrom(), getName(), type.name(), null, packet);\n\t\t\t\t\t\tPacketReceiverTask task = null;\n\n\t\t\t\t\t\tif (packet.getTo() != null) {\n\t\t\t\t\t\t\tString id = packet.getTo().toString() + packet.getStanzaId();\n\n\t\t\t\t\t\t\ttask = waitingTasks.remove(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (task != null) {\n\t\t\t\t\t\t\ttask.handleResponse(packet);\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// log.finest(\"[\" + getName() + \"]  \" +\n\t\t\t\t\t\t\t// \"No task found for id: \" + id);\n\t\t\t\t\t\t\t// Maybe this is a command for local processing...\n\t\t\t\t\t\t\tboolean processed = false;\n\n\t\t\t\t\t\t\tif (packet.isCommand() && (packet.getStanzaTo() != null) && compName.equals(\n\t\t\t\t\t\t\t\t\tpacket.getStanzaTo().getLocalpart()) && isLocalDomain(packet\n\t\t\t\t\t\t\t\t\t.getStanzaTo().getDomain())) {\n\t\t\t\t\t\t\t\tprocessed = processScriptCommand(packet, results);\n\t\t\t\t\t\t\t\tif (processed) {\n\t\t\t\t\t\t\t\t\tPacket result = null;\n\n\t\t\t\t\t\t\t\t\twhile ((result = results.poll()) != null) {\n\t\t\t\t\t\t\t\t\t\taddOutPacket(result);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!processed && ((packet = filterPacket(packet, incoming_filters)) !=\n\t\t\t\t\t\t\t\t\tnull)) {\n\t\t\t\t\t\t\t\tprocessPacket(packet);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// It is all concurrent so we have to use a local index variable\n\t\t\t\t\t\t\tint idx = pptIdx;\n\n\t\t\t\t\t\t\tpptIdx = (pptIdx + 1) % processPacketTimings.length;\n\n\t\t\t\t\t\t\tlong timing = System.currentTimeMillis() - startPPT;\n\n\t\t\t\t\t\t\tprocessPacketTimings[idx] = timing;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OUT_QUEUE :\n\n\t\t\t\t\t\t// tracer.trace(null, packet.getElemTo(), packet.getElemFrom(),\n\t\t\t\t\t\t// packet.getTo(), getName(), type.name(), null, packet);\n\t\t\t\t\t\tif ((packet = filterPacket(packet, outgoing_filters)) != null) {\n\t\t\t\t\t\t\tprocessOutPacket(packet);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault :\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"Unknown queue element type: {0}\", type);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}    // end of switch (qel.type)\n\t\t\t\t} catch (InterruptedException e) {\n\n\t\t\t\t\t// log.log(Level.SEVERE, \"Exception during packet processing: \", e);\n\t\t\t\t\t// stopped = true;\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tif (!threadStopped)\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"[\" + getName() +\n\t\t\t\t\t\t\t\t\"] Exception during packet processing: \" + packet, e);\n\t\t\t\t\telse {\n\t\t\t\t\t\t//log.log(Level.FINEST, \"[\" + getName() + \"] Stopping processing thread\");\n\t\t\t\t\t}\n\t\t\t\t}    // end of try-catch\n\t\t\t}      // end of while (! threadStopped)\n\t\t}\n\t}\n}    // AbstractMessageReceiver\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/BasicComponent.java",
    "content": "/*\n * BasicComponent.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cluster.api.ClusterControllerIfc;\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.conf.Configurable;\nimport tigase.conf.ConfigurationException;\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\nimport tigase.disco.XMPPService;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.osgi.OSGiScriptEngineManager;\nimport tigase.server.script.AddScriptCommand;\nimport tigase.server.script.CommandIfc;\nimport tigase.server.script.RemoveScriptCommand;\nimport tigase.stats.StatisticsList;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.vhosts.VHostListener;\nimport tigase.vhosts.VHostManagerIfc;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\nimport java.io.*;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Oct 17, 2009 7:49:05 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BasicComponent\n\t\t\t\timplements Configurable, XMPPService, VHostListener, ClusteredComponentIfc {\n\t/** Field description */\n\tpublic static final String ALL_PROP_KEY = \"ALL\";\n\n\t/** Field description */\n\tpublic static final String COMMAND_PROP_NODE = \"command\";\n\n\t/** Field description */\n\tpublic static final String SCRIPTS_DIR_PROP_DEF = \"scripts/admin\";\n\n\t/** Field description */\n\tpublic static final String SCRIPTS_DIR_PROP_KEY = \"scripts-dir\";\n\n\tprivate static final Logger log = Logger.getLogger(BasicComponent.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected VHostManagerIfc vHostManager          = null;\n\tprivate ComponentInfo     cmpInfo               = null;\n\tprivate JID               compId                = null;\n\tprivate String            DEF_HOSTNAME_PROP_VAL = null;\n\tprivate String            name                  = null;\n\tprivate BareJID           defHostname = null;\n\n\t/** Field description */\n\tprotected Map<String, CommandIfc> scriptCommands = new ConcurrentHashMap<String,\n\t\t\tCommandIfc>(20);\n\tprivate boolean                      nonAdminCommands = false;\n\tprivate Map<String, EnumSet<CmdAcl>> commandsACL = new ConcurrentHashMap<String,\n\t\t\tEnumSet<CmdAcl>>(20);\n\n\tprotected Set<BareJID>      admins = new ConcurrentSkipListSet<BareJID>();\n\tprotected Set<String>       trusted = new ConcurrentSkipListSet<String>();\n\tprivate ScriptEngineManager scriptEngineManager     = null;\n\tprivate String              scriptsBaseDir          = null;\n\tprivate String              scriptsCompDir          = null;\n\tprivate ServiceEntity       serviceEntity           = null;\n\tprivate boolean             initializationCompleted = false;\n\tprivate String[]\t\t    trustedProp = null;\n\t\n\tprivate final CopyOnWriteArrayList<JID> connectedNodes = new CopyOnWriteArrayList<JID>();\n\tprivate final List<JID> connectedNodes_ro = Collections.unmodifiableList(connectedNodes);\n\tprivate final CopyOnWriteArrayList<JID> connectedNodesWithLocal = new CopyOnWriteArrayList<JID>();\n\tprivate final List<JID> connectedNodesWithLocal_ro = Collections.unmodifiableList(connectedNodesWithLocal);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t */\n\tpublic void addComponentDomain(String domain) {\n\t\tvHostManager.addComponentDomain(domain);\n\t}\n\n\t/**\n\t *\n\t * @param jid\n\t * @param commandId\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean canCallCommand(JID jid, String commandId) {\n\t\tboolean result = isAdmin(jid) || isTrusted(jid);\n\n\t\tif (result) {\n\t\t\treturn true;\n\t\t}\n\n\t\tEnumSet<CmdAcl> acl = commandsACL.get(ALL_PROP_KEY);\n\n\t\tif (acl != null) {\n\t\t\tresult = checkCommandAcl(jid, acl);\n\t\t}\n\t\tif (!result) {\n\t\t\tacl = commandsACL.get(commandId);\n\t\t\tif (acl != null) {\n\t\t\t\tresult = checkCommandAcl(jid, acl);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param acl\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean checkCommandAcl(JID jid, EnumSet<CmdAcl> acl) {\n\t\tfor (CmdAcl cmdAcl : acl) {\n\t\t\tswitch (cmdAcl) {\n\t\t\tcase ALL :\n\t\t\t\treturn true;\n\n\t\t\tcase ADMIN :\n\t\t\t\tif (isAdmin(jid)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase LOCAL :\n\t\t\t\tif (isLocalDomain(jid.getDomain())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase DOMAIN :\n\t\t\t\tif (jid.getDomain().equals(cmdAcl.getAclVal())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase JID :\n\t\t\tcase OTHER :\n\t\t\tdefault :\n\t\t\t\tif (jid.getBareJID().toString().equals(cmdAcl.getAclVal())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic void everyHour() {\n\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\tcomm.everyHour();\n\t\t}\t\t\n\t}\n\t\n\tpublic void everyMinute() {\n\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\tcomm.everyMinute();\n\t\t}\t\t\n\t}\n\t\n\tpublic void everySecond() {\n\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\tcomm.everySecond();\n\t\t}\t\t\n\t}\t\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\t@Override\n\tpublic boolean handlesLocalDomains() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean handlesNameSubdomains() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean handlesNonLocalDomains() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Initialize a mapping of key/value pairs which can be used in scripts\n\t * loaded by the server\n\t *\n\t * @param binds A mapping of key/value pairs, all of whose keys are Strings.\n\t */\n\tpublic void initBindings(Bindings binds) {\n\t\tbinds.put(CommandIfc.VHOST_MANAGER, vHostManager);\n\t\tbinds.put(CommandIfc.ADMINS_SET, admins);\n\t\tbinds.put(CommandIfc.COMMANDS_ACL, commandsACL);\n\t\tbinds.put(CommandIfc.SCRI_MANA, scriptEngineManager);\n\t\tbinds.put(CommandIfc.ADMN_CMDS, scriptCommands);\n\t\tbinds.put(CommandIfc.ADMN_DISC, serviceEntity);\n\t\tbinds.put(CommandIfc.SCRIPT_BASE_DIR, scriptsBaseDir);\n\t\tbinds.put(CommandIfc.SCRIPT_COMP_DIR, scriptsCompDir);\n\t\tbinds.put(CommandIfc.CONNECTED_NODES, connectedNodes);\n\t\tbinds.put(CommandIfc.CONNECTED_NODES_WITH_LOCAL, connectedNodesWithLocal);\n\t\tbinds.put(CommandIfc.COMPONENT_NAME, getName());\n\t\tbinds.put(CommandIfc.COMPONENT, this);\n\t}\n\n\t@Override\n\tpublic void initializationCompleted() {\n\t\tinitializationCompleted = true;\n\n//  log.log(Level.WARNING,\n//      \"initializationCompleted for component name: {0}, full JID: {1}\", new Object[] {\n//      getName(),\n//      getComponentId() });\n//  Thread.dumpStack();\n\t}\n\t\n\t@Override\n\tpublic void nodeConnected(String node) {\n\t\tJID jid = JID.jidInstanceNS(getName(), node, null);\n\t\tboolean added = false;\n\t\t\n\t\tsynchronized (connectedNodesWithLocal) {\n\t\t\tif (!connectedNodesWithLocal.contains(jid)) {\n\t\t\t\tJID[] tmp = connectedNodesWithLocal.toArray(new JID[connectedNodesWithLocal.size() + 1]);\n\t\t\t\ttmp[tmp.length-1] = jid;\n\t\t\t\tArrays.sort(tmp);\n\t\t\t\tint pos = Arrays.binarySearch(tmp, jid);\n\t\t\t\tconnectedNodesWithLocal.add(pos, jid);\n\t\t\t\tadded = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tsynchronized (connectedNodes) {\n\t\t\tif (!connectedNodes.contains(jid) && !getComponentId().equals(jid)) {\n\t\t\t\tJID[] tmp = connectedNodes.toArray(new JID[connectedNodes.size() + 1]);\n\t\t\t\ttmp[tmp.length-1] = jid;\n\t\t\t\tArrays.sort(tmp);\n\t\t\t\tint pos = Arrays.binarySearch(tmp, jid);\n\t\t\t\tconnectedNodes.add(pos, jid);\n\t\t\t\tadded = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (added) {\n\t\t\tlog.log(Level.FINE, \"Node connected: {0}\", node);\n\t\t\tonNodeConnected(jid);\n\t\t\trefreshTrustedJids();\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void nodeDisconnected(String node) {\n\t\tJID jid = JID.jidInstanceNS(getName(), node, null);\n\t\tboolean removed = false;\n\t\t\n\t\tsynchronized (connectedNodesWithLocal) {\n\t\t\tremoved |= connectedNodesWithLocal.remove(jid);\n\t\t}\n\t\t\n\t\tsynchronized (connectedNodes) {\n\t\t\tremoved |= connectedNodes.remove(jid);\n\t\t}\n\t\t\n\t\tif (removed) {\n\t\t\tlog.log(Level.FINE, \"Node disonnected: {0}\", node);\n\t\t\tonNodeDisconnected(jid);\n\t\t\trefreshTrustedJids();\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void processPacket(Packet packet, Queue<Packet> results) {\n\t\tif (packet.isCommand() && getName().equals(packet.getStanzaTo().getLocalpart()) &&\n\t\t\t\tisLocalDomain(packet.getStanzaTo().getDomain())) {\n\t\t\tprocessScriptCommand(packet, results);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void release() {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t */\n\tpublic void removeComponentDomain(String domain) {\n\t\tvHostManager.removeComponentDomain(domain);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param description\n\t */\n\tpublic void removeServiceDiscoveryItem(String jid, String node, String description) {\n\t\tServiceEntity item = new ServiceEntity(jid, node, description);\n\n\t\t// item.addIdentities(new ServiceIdentity(\"component\", identity_type,\n\t\t// name));\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Modifying service-discovery info, removing: {0}\", item);\n\t\t}\n\t\tserviceEntity.removeItems(item);\n\t}\n\t\n\t@Override\n\tpublic void setClusterController(ClusterControllerIfc cl_controller) {\n\t\t\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param description\n\t * @param admin\n\t */\n\tpublic void updateServiceDiscoveryItem(String jid, String node, String description,\n\t\t\tboolean admin) {\n\t\tupdateServiceDiscoveryItem(jid, node, description, admin, (String[]) null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param description\n\t * @param admin\n\t * @param features\n\t */\n\tpublic void updateServiceDiscoveryItem(String jid, String node, String description,\n\t\t\tboolean admin, String... features) {\n\t\tupdateServiceDiscoveryItem(jid, node, description, null, null, admin, features);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param node\n\t * @param description\n\t * @param category\n\t * @param type\n\t * @param admin\n\t * @param features\n\t */\n\tpublic void updateServiceDiscoveryItem(String jid, String node, String description,\n\t\t\tString category, String type, boolean admin, String... features) {\n\t\tif (serviceEntity.getJID().equals(jid) && (serviceEntity.getNode() == node)) {\n\t\t\tserviceEntity.setAdminOnly(admin);\n\t\t\tserviceEntity.setDescription(description);\n\t\t\tif ((category != null) || (type != null)) {\n\t\t\t\tserviceEntity.addIdentities(new ServiceIdentity(category, type, description));\n\t\t\t}\n\t\t\tif (features != null) {\n\t\t\t\tserviceEntity.setFeatures(\"http://jabber.org/protocol/commands\");\n\t\t\t\tserviceEntity.addFeatures(features);\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Modifying service-discovery info: {0}\", serviceEntity);\n\t\t\t}\n\t\t} else {\n\t\t\tServiceEntity item = new ServiceEntity(jid, node, description, admin);\n\n\t\t\tif ((category != null) || (type != null)) {\n\t\t\t\titem.addIdentities(new ServiceIdentity(category, type, description));\n\t\t\t}\n\t\t\tif (features != null) {\n\t\t\t\titem.addFeatures(features);\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Adding new item: {0}\", item);\n\t\t\t}\n\t\t\tserviceEntity.addItems(item);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void updateServiceEntity() {\n\t\tserviceEntity = new ServiceEntity(name, null, getDiscoDescription(), true);\n\t\tserviceEntity.addIdentities(new ServiceIdentity(getDiscoCategory(),\n\t\t\t\tgetDiscoCategoryType(), getDiscoDescription()));\n\t\tserviceEntity.addFeatures(\"http://jabber.org/protocol/commands\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic JID getComponentId() {\n\t\treturn compId;\n\t}\n\n\t@Override\n\tpublic ComponentInfo getComponentInfo() {\n\t\tif (cmpInfo == null) {\n\t\t\tcmpInfo = new ComponentInfo(getName(), this.getClass());\n\t\t}\n\n\t\treturn cmpInfo;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = new LinkedHashMap<String, Object>(50);\n\n\t\tdefs.put(COMPONENT_ID_PROP_KEY, compId.toString());\n\t\tDEF_HOSTNAME_PROP_VAL = DNSResolverFactory.getInstance().getDefaultHost();\n\t\tdefs.put(DEF_HOSTNAME_PROP_KEY, DEF_HOSTNAME_PROP_VAL);\n\n\t\tString[] adm = null;\n\n\t\tif (params.get(GEN_ADMINS) != null) {\n\t\t\tadm = ((String) params.get(GEN_ADMINS)).split(\",\");\n\t\t} else {\n\t\t\tadm = new String[] { \"admin@localhost\" };\n\t\t}\n\t\tdefs.put(ADMINS_PROP_KEY, adm);\n\n\t\tString scripts_dir = (String) params.get(GEN_SCRIPT_DIR);\n\n\t\tif (scripts_dir == null) {\n\t\t\tscripts_dir = SCRIPTS_DIR_PROP_DEF;\n\t\t}\n\t\tdefs.put(SCRIPTS_DIR_PROP_KEY, scripts_dir);\n\t\tdefs.put(COMMAND_PROP_NODE + \"/\" + ALL_PROP_KEY, CmdAcl.ADMIN.name());\n\n\t\tString trusted_def = System.getProperty(TRUSTED_PROP_KEY);\n\t\tif (trusted_def != null) {\n\t\t\tdefs.put(TRUSTED_PROP_KEY, trusted_def.split(\",\"));\n\t\t}\n\t\t\n\t\treturn defs;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>BareJID</code>\n\t */\n\tpublic BareJID getDefHostName() {\n\t\treturn defHostname;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>BareJID</code>\n\t */\n\tpublic BareJID getDefVHostItem() {\n\t\treturn (vHostManager != null)\n\t\t\t\t? vHostManager.getDefVHostItem()\n\t\t\t\t: getDefHostName();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getDiscoCategory() {\n\t\treturn \"component\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"generic\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getDiscoDescription() {\n\t\treturn \"Undefined description\";\n\t}\n\n\t/**\n\t * Exists for backward compatibility with the old API.\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\t@Deprecated\n\tpublic List<Element> getDiscoFeatures() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn getDiscoFeatures();\n\t}\n\n\t/**\n\t * Exists for backward compatibility with the old API.\n\t *\n\t * @param node\n\t * @param jid\n\t *\n\t *\n\t *\n\t * @return a value of <code>Element</code>\n\t */\n\t@Deprecated\n\tpublic Element getDiscoInfo(String node, JID jid) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\n\t\t// This is only to support the old depreciated API.\n\t\tElement result = getDiscoInfo(node, jid);\n\n\t\tif (result != null) {\n\t\t\treturn result;\n\t\t}\n\n\t\t// OLD API support end\n\t\tif (getName().equals(jid.getLocalpart()) || jid.toString().startsWith(getName() +\n\t\t\t\t\".\")) {\n\t\t\treturn serviceEntity.getDiscoInfo(node, isAdmin(from) || nonAdminCommands);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Exists for backward compatibility with the old API.\n\t *\n\t * @deprecated\n\t *\n\t * @param node\n\t * @param jid\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\t@Deprecated\n\tpublic List<Element> getDiscoItems(String node, JID jid) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\n\t\t// This is only to support the old depreciated API.\n\t\tList<Element> result = getDiscoItems(node, jid);\n\n\t\tif (result != null) {\n\t\t\treturn result;\n\t\t}\n\n\t\t// OLD API support end\n\t\tboolean isAdminFrom = isAdmin(from);\n\n\t\tif (getName().equals(jid.getLocalpart()) || jid.toString().startsWith(getName() +\n\t\t\t\t\".\")) {\n\t\t\tif (node != null) {\n\t\t\t\tif (node.equals(\"http://jabber.org/protocol/commands\") && (isAdminFrom ||\n\t\t\t\t\t\tnonAdminCommands)) {\n\t\t\t\t\tresult = new LinkedList<Element>();\n\t\t\t\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\t\t\t\tif (!comm.isAdminOnly() || isAdminFrom) {\n\t\t\t\t\t\t\tElement item = new Element(\"item\", new String[] { \"node\", \"name\", \"jid\" },\n\t\t\t\t\t\t\t\t\tnew String[] { comm.getCommandId(),\n\t\t\t\t\t\t\t\t\tcomm.getDescription(), jid.toString() });\n\t\t\t\t\t\t\tif (comm.getGroup() != null) {\n\t\t\t\t\t\t\t\titem.setAttribute(\"group\", comm.getGroup());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult.add(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = serviceEntity.getDiscoItems(node, jid.toString(), (isAdminFrom ||\n\t\t\t\t\t\t\tnonAdminCommands));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult = serviceEntity.getDiscoItems(null, jid.toString(), (isAdminFrom ||\n\t\t\t\t\t\tnonAdminCommands));\n\t\t\t\tif (result != null) {\n\t\t\t\t\tfor (Iterator<Element> it = result.iterator(); it.hasNext(); ) {\n\t\t\t\t\t\tElement element = it.next();\n\n\t\t\t\t\t\tif (element.getAttributeStaticStr(\"node\") == null) {\n\t\t\t\t\t\t\tit.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Element result = serviceEntity.getDiscoItem(null, getName() + \".\" + jid);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Found disco items: {0}\", ((result != null)\n\t\t\t\t\t\t? result.toString()\n\t\t\t\t\t\t: null));\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} General disco items request, node: {1}\",\n\t\t\t\t\t\tnew Object[] { getName(),\n\t\t\t\t\t\tnode });\n\t\t\t}\n\t\t\tif (node == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0} Disco items request for null node\", new Object[] {\n\t\t\t\t\t\t\tgetName() });\n\t\t\t\t}\n\n\t\t\t\tElement res = null;\n\n\t\t\t\tif (!serviceEntity.isAdminOnly() || isAdmin(from) || nonAdminCommands) {\n\t\t\t\t\tres = serviceEntity.getDiscoItem(null, isSubdomain()\n\t\t\t\t\t\t\t? (getName() + \".\" + jid)\n\t\t\t\t\t\t\t: getName() + \"@\" + jid.toString());\n\t\t\t\t}\n\t\t\t\tresult = serviceEntity.getDiscoItems(null, null, (isAdminFrom ||\n\t\t\t\t\t\tnonAdminCommands));\n\t\t\t\tif (res != null) {\n\t\t\t\t\tif (result != null) {\n\t\t\t\t\t\tfor (Iterator<Element> it = result.iterator(); it.hasNext(); ) {\n\t\t\t\t\t\t\tElement element = it.next();\n\n\t\t\t\t\t\t\tif (element.getAttributeStaticStr(\"node\") != null) {\n\t\t\t\t\t\t\t\tit.remove();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult.add(0, res);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = Arrays.asList(res);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic void getStatistics(StatisticsList list) {\n\t\tString compName = getName();\n\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\tcomm.getStatistics(compName, list);\n\t\t}\n\t\tif (connectedNodes.size() > 0) {\n\t\t\tlist.add(getName(), \"Known cluster nodes\", connectedNodes.size(), Level.FINEST);\n\t\t}\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param node\n\t * @param jid\n\t * @param from\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<Element>}\n\t */\n\tpublic List<Element> getScriptItems(String node, JID jid, JID from) {\n\t\tLinkedList<Element> result      = null;\n\t\tboolean             isAdminFrom = isAdmin(from);\n\n\t\tif (node.equals(\"http://jabber.org/protocol/commands\") && (isAdminFrom ||\n\t\t\t\tnonAdminCommands)) {\n\t\t\tresult = new LinkedList<Element>();\n\t\t\tfor (CommandIfc comm : scriptCommands.values()) {\n\t\t\t\tif (!comm.isAdminOnly() || isAdminFrom) {\n\t\t\t\t\tresult.add(new Element(\"item\", new String[] { \"node\", \"name\", \"jid\" },\n\t\t\t\t\t\t\tnew String[] { comm.getCommandId(),\n\t\t\t\t\t\t\tcomm.getDescription(), jid.toString() }));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t *\n\t *\n\t * @return a value of <code>VHostItem</code>\n\t */\n\tpublic VHostItem getVHostItem(String domain) {\n\t\treturn (vHostManager != null)\n\t\t\t\t? vHostManager.getVHostItem(domain)\n\t\t\t\t: null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isAdmin(JID jid) {\n\t\treturn admins.contains(jid.getBareJID());\n\t}\n\n\t@Override\n\tpublic boolean isInitializationComplete() {\n\t\treturn initializationCompleted;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isLocalDomain(String domain) {\n\t\treturn (vHostManager != null)\n\t\t\t\t? vHostManager.isLocalDomain(domain)\n\t\t\t\t: false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isLocalDomainOrComponent(String domain) {\n\t\treturn (vHostManager != null)\n\t\t\t\t? vHostManager.isLocalDomainOrComponent(domain)\n\t\t\t\t: false;\n\t}\n\n\t/**\n\t * Method returns true is component should be represented as subdomain\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isSubdomain() {\n\t\treturn false;\n\t}\n\n\tpublic boolean isTrusted(JID jid) {\n\t\tif (trusted.contains(jid.getBareJID().toString()))\n\t\t\treturn true;\n\t\t\t\t\n\t\treturn isAdmin(jid);\n\t}\n\t\n\tpublic boolean isTrusted(String jid) {\n\t\treturn trusted.contains(jid);\n\t}\n\t\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\n\t\tDEF_HOSTNAME_PROP_VAL = DNSResolverFactory.getInstance().getDefaultHost();\n\t\tdefHostname = BareJID.bareJIDInstanceNS( DEF_HOSTNAME_PROP_VAL );\n\n\t\ttry {\n\t\t\tcompId = JID.jidInstance(name, defHostname.getDomain(), null);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem setting component ID: \", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.size() > 1) {\n\t\t\tif (props.get(TRUSTED_PROP_KEY) != null) {\n\t\t\t\ttrustedProp = (String[]) props.get(TRUSTED_PROP_KEY);\t\t\t\t\n\t\t\t}\n\t\t}\n\t\tnodeConnected(defHostname.getDomain());\n\t\trefreshTrustedJids();\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\treturn;\n\t\t}\n\t\tif (scriptEngineManager == null) {\n\t\t\tif (XMPPServer.isOSGi()) {\n\t\t\t\tscriptEngineManager = new OSGiScriptEngineManager();\n\t\t\t} else {\n\t\t\t\tscriptEngineManager = new ScriptEngineManager();\n\t\t\t}\n\t\t}\n\t\tif (props.get(COMPONENT_ID_PROP_KEY) != null) {\n\t\t\ttry {\n\t\t\t\tcompId = JID.jidInstance((String) props.get(COMPONENT_ID_PROP_KEY));\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem setting component ID: \", ex);\n\t\t\t}\n\t\t}\n\t\tif (props.get(DEF_HOSTNAME_PROP_KEY) != null) {\n\t\t\tdefHostname = BareJID.bareJIDInstanceNS((String) props.get(DEF_HOSTNAME_PROP_KEY));\n\t\t\t}\n\n\t\tString[] admins_tmp = (String[]) props.get(ADMINS_PROP_KEY);\n\n\t\tif (admins_tmp != null) {\n\t\t\tfor (String admin : admins_tmp) {\n\t\t\t\ttry {\n\t\t\t\t\tadmins.add(BareJID.bareJIDInstance(admin));\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.CONFIG, \"Incorrect admin JID: \", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(COMMAND_PROP_NODE)) {\n\t\t\t\tString          cmdId  = entry.getKey().substring(COMMAND_PROP_NODE.length() + 1);\n\t\t\t\tString[]        cmdAcl = entry.getValue().toString().split(\",\");\n\t\t\t\tEnumSet<CmdAcl> acl    = EnumSet.noneOf(CmdAcl.class);\n\n\t\t\t\tfor (String cmda : cmdAcl) {\n\t\t\t\t\tCmdAcl acl_tmp = CmdAcl.valueof(cmda);\n\n\t\t\t\t\tacl.add(acl_tmp);\n\t\t\t\t\tif (acl_tmp != CmdAcl.ADMIN) {\n\t\t\t\t\t\tnonAdminCommands = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcommandsACL.put(cmdId, acl);\n\t\t\t}\n\t\t}\n\t\tupdateServiceEntity();\n\n\t\tCommandIfc command = new AddScriptCommand();\n\n\t\tcommand.init(CommandIfc.ADD_SCRIPT_CMD, \"New command script\", \"Scripts\");\n\t\tscriptCommands.put(command.getCommandId(), command);\n\t\tcommand = new RemoveScriptCommand();\n\t\tcommand.init(CommandIfc.DEL_SCRIPT_CMD, \"Remove command script\", \"Scripts\");\n\t\tscriptCommands.put(command.getCommandId(), command);\n\t\tif (props.get(SCRIPTS_DIR_PROP_KEY) != null) {\n\t\t\tscriptsBaseDir = (String) props.get(SCRIPTS_DIR_PROP_KEY);\n\t\t\tscriptsCompDir = scriptsBaseDir + \"/\" + getName();\n\t\t\tloadScripts();\n\t\t}\n\t\tcmpInfo = new ComponentInfo(getName(), this.getClass());\n\t}\n\n\t@Override\n\tpublic void setVHostManager(VHostManagerIfc manager) {\n\t\tthis.vHostManager = manager;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic List<JID> getNodesConnected() {\n\t\treturn connectedNodes_ro;\n\t}\n\t\n\tpublic List<JID> getNodesConnectedWithLocal() {\n\t\treturn connectedNodesWithLocal_ro;\n\t}\n\t\n\tprotected void onNodeConnected(JID jid) {\n\t\t\n\t}\n\t\n\tprotected void onNodeDisconnected(JID jid) {\n\t\t\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param pc\n\t * @param results\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean processScriptCommand(Packet pc, Queue<Packet> results) {\n\n\t\t// TODO: test if this is right\n\t\t// It is not, the packet should actually have packetFrom set at all times\n\t\t// to ensure the error can be sent back to the original sender.\n\t\t// if ((pc.getStanzaFrom() == null) || (pc.getPacketFrom() != null)) {\n\t\t//\n\t\t//// The packet has not gone through session manager yet\n\t\t// return false;\n\t\t// }\n\t\t// This test is more correct as it says whether the packet went through\n\t\t// session manager checking.\n\t\t// TODO: test if commands still work for users from different XMPP servers\n\t\t// with the right permission set.\n\t\tif (pc.getPermissions() == Permissions.NONE) {\n\t\t\treturn false;\n\t\t}\n\n\t\tIq             iqc    = (Iq) pc;\n\t\tCommand.Action action = Command.getAction(iqc);\n\n\t\tif (action == Command.Action.cancel) {\n\t\t\tPacket result = iqc.commandResult(Command.DataType.result);\n\n\t\t\tCommand.addTextField(result, \"Note\", \"Command canceled.\");\n\t\t\tresults.offer(result);\n\n\t\t\treturn true;\n\t\t}\n\n\t\tString     strCommand = iqc.getStrCommand();\n\t\tCommandIfc com        = scriptCommands.get(strCommand);\n\n\t\tif ((strCommand != null) && (com != null)) {\n\t\t\tboolean admin = false;\n\n\t\t\ttry {\n\t\t\t\tadmin = canCallCommand(iqc.getStanzaFrom(), strCommand);\n\t\t\t\tif (admin) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Processing admin command: {0}\", pc);\n\t\t\t\t\t}\n\n\t\t\t\t\tBindings binds = com.getBindings();\n\n\t\t\t\t\tif (binds == null) {\n\t\t\t\t\t\tbinds = scriptEngineManager.getBindings();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Bindings binds = scriptEngineManager.getBindings();\n\t\t\t\t\tinitBindings(binds);\n\t\t\t\t\tcom.runCommand(iqc, binds, results);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Command rejected non-admin detected: {0}\", pc\n\t\t\t\t\t\t\t\t.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t\tresults.offer(Authorization.FORBIDDEN.getResponseMessage(pc,\n\t\t\t\t\t\t\t\"Only Administrator can call the command.\", true));\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Unknown admin command processing exception: \" + pc, e);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code Map<String,CommandIfc>}\n\t */\n\tprotected Map<String, CommandIfc> getScriptCommands() {\n\t\treturn scriptCommands;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>ServiceEntity</code>\n\t */\n\tprotected ServiceEntity getServiceEntity() {\n\t\treturn serviceEntity;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean isNonAdminCommands() {\n\t\treturn nonAdminCommands;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void loadScripts() {\n\t\tlog.log(Level.CONFIG, \"Loading admin scripts for component: {0}.\", new Object[] {\n\t\t\t\tgetName() });\n\n\t\tFile             file       = null;\n\t\tAddScriptCommand addCommand = new AddScriptCommand();\n\t\tBindings         binds      = scriptEngineManager.getBindings();\n\t\tList<String>     extensions = new ArrayList<>();\n\t\tfor ( ScriptEngineFactory engineFactory :  scriptEngineManager.getEngineFactories()) {\n\t\t\textensions.addAll( engineFactory.getExtensions());\n\t\t}\n\n\t\tinitBindings(binds);\n\n\t\tString[] dirs = new String[] { scriptsBaseDir, scriptsCompDir };\n\n\t\t// check class only from main directory\n\n\n\t\tfor (String scriptsPath : dirs) {\n\t\t\tlog.log(Level.CONFIG, \"{0}: Loading scripts from directory: {1}\", new Object[] {\n\t\t\t\t\tgetName(),\n\t\t\t\t\tscriptsPath });\n\t\t\ttry {\n\t\t\t\tFile adminDir = new File(scriptsPath);\n\n\t\t\t\tif ((adminDir != null) && adminDir.exists()) {\n\t\t\t\t\tfor ( File f : adminDir.listFiles( new ExtFilter( extensions ) ) ) {\n\n\t\t\t\t\t\t// Just regular files here....\n\t\t\t\t\t\tif (f.isFile() &&!f.toString().endsWith(\"~\") &&!f.isHidden())  {\n\t\t\t\t\t\t\tString cmdId    = null;\n\t\t\t\t\t\t\tString cmdDescr = null;\n\t\t\t\t\t\t\tString cmdGroup = null;\n\t\t\t\t\t\t\tString comp     = null;\n\t\t\t\t\t\t\tString compClass = null;\n\n\t\t\t\t\t\t\tfile = f;\n\n\t\t\t\t\t\t\tStringBuilder  sb    = new StringBuilder();\n\t\t\t\t\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(file));\n\t\t\t\t\t\t\tString         line  = null;\n\n\t\t\t\t\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\t\t\t\t\tsb.append(line).append(\"\\n\");\n\n\t\t\t\t\t\t\t\tint idx = line.indexOf(CommandIfc.SCRIPT_DESCRIPTION);\n\n\t\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\t\tcmdDescr = line.substring(idx + CommandIfc.SCRIPT_DESCRIPTION.length())\n\t\t\t\t\t\t\t\t\t\t\t.trim();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tidx = line.indexOf(CommandIfc.SCRIPT_ID);\n\t\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\t\tcmdId = line.substring(idx + CommandIfc.SCRIPT_ID.length()).trim();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tidx = line.indexOf(CommandIfc.SCRIPT_COMPONENT);\n\t\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\t\tcomp = line.substring(idx + CommandIfc.SCRIPT_COMPONENT.length())\n\t\t\t\t\t\t\t\t\t\t\t.trim();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tidx = line.indexOf(CommandIfc.SCRIPT_CLASS);\n\t\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\t\tcompClass = line.substring(idx + CommandIfc.SCRIPT_CLASS.length())\n\t\t\t\t\t\t\t\t\t\t\t.trim();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tidx = line.indexOf(CommandIfc.SCRIPT_GROUP);\n\t\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\t\tcmdGroup = line.substring(idx + CommandIfc.SCRIPT_GROUP.length())\n\t\t\t\t\t\t\t\t\t\t\t.trim();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbuffr.close();\n\t\t\t\t\t\t\tif ((cmdId == null) || (cmdDescr == null)) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t\"Admin script found but it has no command ID or command\" +\n\t\t\t\t\t\t\t\t\t\t\"description: \" + \"{0}\", file);\n\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tboolean  found      = false;\n\n\t\t\t\t\t\t\tif (comp != null) {\n\t\t\t\t\t\t\t\t// Which components should load the script\n\t\t\t\t\t\t\t\tString[] comp_names = comp.split(\",\");\n\n\t\t\t\t\t\t\t\t// check component names\n\t\t\t\t\t\t\t\tfor (String cmp : comp_names) {\n\t\t\t\t\t\t\t\t\tcmp = cmp.trim();\n\t\t\t\t\t\t\t\t\tfound |= getName().equals(cmp);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// check component classes\n\t\t\t\t\t\t\tif ( null != compClass ){\n\t\t\t\t\t\t\t\t// do we need this check? it blocks us from loading adhoc\n\t\t\t\t\t\t\t\t// commands from component named directory if it is marked\n\t\t\t\t\t\t\t\t// as for a specific component class - this should be allowed\n//\t\t\t\t\t\t\t\tif ( scriptsPath.endsWith( getName() ) ){\n//\t\t\t\t\t\t\t\t\t// ok, this is script for component of particular name, skip\n//\t\t\t\t\t\t\t\t\t// loading based on class\n//\t\t\t\t\t\t\t\t\tcontinue;\n//\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tString[] comp_classes = compClass.split( \",\" );\n\t\t\t\t\t\t\t\tfor ( String cmp : comp_classes ) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t// we also check whether script is loaded for particular class or it's subclasses\n\t\t\t\t\t\t\t\t\t\tClass<?> loadClass = ModulesManagerImpl.getInstance().forName(cmp);\n\t\t\t\t\t\t\t\t\t\tfound |= loadClass.isAssignableFrom( this.getClass());\n\n\t\t\t\t\t\t\t\t\t} catch ( NoClassDefFoundError ex ) {\n\t\t\t\t\t\t\t\t\t\tlog.log( Level.WARNING, \"Tried loading script with class defined as: {0} for class: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { cmp, this.getClass().getCanonicalName() } );\n\t\t\t\t\t\t\t\t\t} catch ( ClassNotFoundException ex ) {\n\t\t\t\t\t\t\t\t\t\t// just ignore\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t\t \"{0}: skipping admin script {1}, id: {2}, descr: {3}, group: {4} for component: {5} or class: {6}\",\n\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { getName(), file, cmdId, cmdDescr, cmdGroup, comp, compClass } );\n\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tint    idx = file.toString().lastIndexOf('.');\n\t\t\t\t\t\t\tString ext = file.toString().substring(idx + 1);\n\n\t\t\t\t\t\t\tif (cmdGroup != null && cmdGroup.contains(\"${componentName}\")) {\n\t\t\t\t\t\t\t\tcmdGroup = cmdGroup.replace(\"${componentName}\", this.getDiscoDescription());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\taddCommand.addAdminScript(cmdId, cmdDescr, cmdGroup, sb.toString(), null, ext, binds);\n\t\t\t\t\t\t\tlog.log(Level.CONFIG,\n\t\t\t\t\t\t\t\t\t\"{0}: Loaded admin command from file: {1}, id: {2}, ext: {3}, descr: {4}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { getName(), file, cmdId, ext, cmdDescr });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} catch (IOException | ScriptException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't load the admin script file: \" + file, e);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tprivate void refreshTrustedJids() {\n\t\tsynchronized (connectedNodesWithLocal) {\n\t\t\ttrusted.clear();\n\t\t\tif (trustedProp != null) {\n\t\t\t\tfor (String trustedStr : trustedProp) {\n\t\t\t\t\tif (trustedStr.contains(\"{clusterNode}\")) {\n\t\t\t\t\t\tfor (JID nodeJid : connectedNodesWithLocal) {\n\t\t\t\t\t\t\tString node = nodeJid.getDomain();\n\t\t\t\t\t\t\tString jid = trustedStr.replace(\"{clusterNode}\", node);\n\t\t\t\t\t\t\ttrusted.add(jid);\t\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttrusted.add(trustedStr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"component {0} got trusted jids set as {1}\", new Object[] { getName(), trusted });\n\t\t}\n\t}\n\n\tprivate class ExtFilter\n\t\t\t\t\timplements FileFilter {\n\n\t\tList<String> extensions;\n\n\t\tpublic ExtFilter( List<String> extensions ) {\n\t\t\tthis.extensions = extensions;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean accept( File file ) {\n\n\t\t\tboolean matched = false;\n\t\t\tfor ( String extension : extensions ) {\n\t\t\t\tmatched |= file.isFile() && file.getName().toLowerCase().endsWith( extension );\n\t\t\t}\n\t\t\treturn matched;\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/12/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/CmdAcl.java",
    "content": "package tigase.server;\n\n//~--- enums ------------------------------------------------------------------\n\n/**\n *\n */\npublic enum CmdAcl {\n\t\n\t/**\n\t * Everybody can execute the command, even users from a different servers.\n\t */\n\tALL,\n\t/**\n\t * Only local server administrators can execute command.\n\t */\n\tADMIN,\n\t/**\n\t * Only users who have accounts on this local server can execute the command. \n\t */\n\tLOCAL,\n\t/**\n\t * Only users who have an account within the given domain can execute the command.\n\t */\n\tDOMAIN,\n\t/**\n\t * Comma separated list of JIDs of users who can execute the command. \n\t */\n\tJID,\n\t/**\n\t * This is the default. If no access control is provided than by default a list\n\t * of JIDs is assumed.\n\t */\n\tOTHER;\n\n\tprivate String aclVal = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param acl\n\t *\n\t * \n\t */\n\tpublic static CmdAcl valueof(String acl) {\n\t\tCmdAcl result = null;\n\t\tString[] aclArr = acl.split(\":\");\n\n\t\ttry {\n\t\t\tresult = valueOf(aclArr[0]);\n\n\t\t\tif (aclArr.length > 1) {\n\t\t\t\tresult.setAclVal(aclArr[1]);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tresult = OTHER;\n\t\t\tresult.setAclVal(acl);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected String getAclVal() {\n\t\treturn aclVal;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprotected void setAclVal(String aclVal) {\n\t\tthis.aclVal = aclVal;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Command.java",
    "content": "/*\n * Command.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Logger;\n\n/**\n * Helper enum to make it easier to operate on packets with ad-hoc commands. It\n * allows to create a packet with command, add and retrieve command data field\n * values, set actions and so on.\n *\n * It contains predefined set of commands used internally by the Tigase server\n * and also 'OTHER' command which refers all other not predefined commands.\n *\n * Most of the implementation details, constants and parameters is based on the\n * <a href=\"http://xmpp.org/extensions/xep-0050.html\">XEP-0050</a> for ad-hoc\n * commands protocol. Please refer to the XEP for more details.\n *\n * Created: Thu Feb 9 20:52:02 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum Command {\n\n\t/**\n\t * Command sent from a connection manager to the session manager when a new\n\t * stream from the client has been opened.\n\t */\n\tSTREAM_OPENED(Priority.SYSTEM),\n\n\t/**\n\t * Command sent from connection manager to the session manager after TLS handshake if\n\t * client sent certificate.\n\t */\n\tTLS_HANDSHAKE_COMPLETE(Priority.SYSTEM),\n\n\t/**\n\t * Command sent from session manager to the connection manager after successful\n\t * user login.\n\t */\n\tUSER_LOGIN(Priority.SYSTEM),\n\n\t/**\n\t * Command sent from a connection manager to the session manager when a\n\t * connection or stream has been closed.\n\t */\n\tSTREAM_CLOSED(Priority.SYSTEM), STREAM_CLOSED_UPDATE(Priority.SYSTEM),\n\t\n\t/**\n\t * Command sent from a connection manager to the session manager after\n\t * last packet from closed connection stream has been sent.\n\t */\n\tSTREAM_FINISHED(Priority.NORMAL),\n\n\t/**\n\t * Sends a command from SM to the connection holder to confirm whether the\n\t * connection is still active. Expects result for ok, error or timeout if the\n\t * connection is no longer active.\n\t */\n\tCHECK_USER_CONNECTION(Priority.SYSTEM),\n\n\t/**\n\t * Command sent from the session manager to a connection manager to start TLS\n\t * handshaking over the client connection.\n\t */\n\tSTARTTLS(Priority.NORMAL),\n\n\t/**\n\t * Command sent from the session manager to a connection manager to start zlib\n\t * compression on the connection stream.\n\t */\n\tSTARTZLIB(Priority.NORMAL),\n\n\t/**\n\t * Command sent between a connection manager and the session manager to\n\t * retrieve stream features.\n\t */\n\tGETFEATURES(Priority.HIGH),\n\n\t/**\n\t * This is depreciated command sent between components in the Tigase server\n\t * for service discovery handling.\n\t */\n\tGETDISCO(Priority.HIGH),\n\n\t/**\n\t * Command sent from the session manager to a client manager to close the\n\t * client connection.\n\t */\n\tCLOSE(Priority.SYSTEM),\n\n\t/**\n\t * Command used by the StatisticsCollector to provide server statistics\n\t * through ad-hoc command.\n\t */\n\tGETSTATS(Priority.HIGH),\n\n\t/**\n\t * Command sent to the session manager from an external entity to activate a\n\t * user session with the connection end-point at the given address.\n\t */\n\tUSER_STATUS(Priority.NORMAL),\n\n\t/**\n\t * Command used to set a broadcast message to all online users.\n\t */\n\tBROADCAST_TO_ONLINE(Priority.NORMAL),\n\n\t/**\n\t * Command used to set a broadcast message to all registered local users.\n\t */\n\tBROADCAST_TO_ALL(Priority.NORMAL),\n\n\t/**\n\t * Command used to redirect packets from a connection manager to other than\n\t * default session manager. (Mostly used in the clustering.)\n\t */\n\tREDIRECT(Priority.SYSTEM),\n\n\t/**\n\t * Command sent to the VHostManager to reload virtual hosts from the database.\n\t */\n\tVHOSTS_RELOAD(Priority.NORMAL),\n\n\t/**\n\t * Command sent to the VHostManager to add or update existing virtual host.\n\t */\n\tVHOSTS_UPDATE(Priority.NORMAL),\n\n\t/**\n\t * Command sent to the VHostManager to remove existing virtual host.\n\t */\n\tVHOSTS_REMOVE(Priority.NORMAL),\n\n\t/**\n\t * Command sent to SessionManager to change connectionId of existing session.\n\t */\n\tSTREAM_MOVED(Priority.NORMAL),\n\t\n\t/**\n\t * Identifies all other, not predefined commands.\n\t */\n\tOTHER(Priority.NORMAL);\n\n\t/** Field description */\n\tpublic static final String COMMAND_EL = \"command\";\n\n\t/** Field description */\n\t@Deprecated\n\tpublic static final String FIELD_EL = DataForm.FIELD_EL;\n\n\t/** Field description */\n\t@Deprecated\n\tpublic static final String VALUE_EL = DataForm.VALUE_EL;\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"http://jabber.org/protocol/commands\";\n\n\t/** Field description */\n\t@Deprecated\n\tprotected static final String[] FIELD_VALUE_PATH = DataForm.FIELD_VALUE_PATH;\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.server.Command\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Priority priority = Priority.NORMAL;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Ad-hoc command actions ad defined in the XEP-0050.\n\t */\n\tpublic enum Action {\n\n\t\t/**\n\t\t * The command should be executed or continue to be executed. This is the\n\t\t * default value.\n\t\t */\n\t\texecute,\n\n\t\t/**\n\t\t * The command should be canceled.\n\t\t */\n\t\tcancel,\n\n\t\t/**\n\t\t * The command should be digress to the previous stage of execution.\n\t\t */\n\t\tprev,\n\n\t\t/**\n\t\t * The command should progress to the next stage of execution.\n\t\t */\n\t\tnext,\n\n\t\t/**\n\t\t * The command should be completed (if possible).\n\t\t */\n\t\tcomplete,\n\n\t\t/**\n\t\t * Other, not recognized command action.\n\t\t */\n\t\tother;\n\t}\n\n\t/**\n\t * Data form-types as defined in the XEP-0050.\n\t */\n\tpublic enum DataType {\n\n\t\t/**\n\t\t * This is a form with ad-hoc command result data.\n\t\t */\n\t\tresult,\n\n\t\t/**\n\t\t * This is a form querying for more data from the user.\n\t\t */\n\t\tform,\n\n\t\t/**\n\t\t * Form filled with data sent as a response to 'form' request.\n\t\t */\n\t\tsubmit;\n\t}\n\n\t/**\n\t * Ad-hoc command statuses as defined in the XEP-0050.\n\t */\n\tpublic enum Status {\n\n\t\t/**\n\t\t * The command is being executed.\n\t\t */\n\t\texecuting,\n\n\t\t/**\n\t\t * The command has completed. The command session has ended.\n\t\t */\n\t\tcompleted,\n\n\t\t/**\n\t\t * The command has been canceled. The command session has ended.\n\t\t */\n\t\tcanceled,\n\n\t\t/**\n\t\t * Other, not recognized command status.\n\t\t */\n\t\tother;\n\t}\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tprivate Command(Priority priority) {\n\t\tthis.priority = priority;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param action\n\t */\n\tpublic static void addAction(final Packet packet, final Action action) {\n\t\taddActionEl(packet.getElement(), action);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param f_name\n\t * @param f_value\n\t */\n\tpublic static void addCheckBoxField(Packet packet, String f_name, boolean f_value) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\t\n\t\tDataForm.addCheckBoxField( command, f_name, f_value);\n\t}\n\n\t/**\n\t * A simple method for adding a multi-line (text-multi) data field to the\n\t * command data form. Only field name (variable name) and field default value\n\t * can be set.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance of the ad-hoc command request to\n\t *          be modified.\n\t * @param f_name\n\t *          is a <code>String</code> instance with the field name. In ad-hoc\n\t *          command terms this is a variable name. This field name (variable\n\t *          name) will be also displayed as the field label.\n\t * @param f_value\n\t *          is a list with lines of text to be displayed as a multi-line field\n\t *          content.\n\t */\n\tpublic static void addFieldMultiValue(final Packet packet, final String f_name,\n\t\t\t\t\tfinal List<String> f_value) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldMultiValue( command, f_name, f_value);\n\n\t}\n\n\tpublic static void addFieldMultiValue(final Packet packet, final String f_name,\n\t\t\t\t\tfinal Throwable ex) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldMultiValue( command, f_name, ex);\n\n\t}\n\n\t/**\n\t * Simple method for adding a new field to the command data form. Only field\n\t * name (variable name) and field default value can be set.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance of the ad-hoc command request to\n\t *          be modified.\n\t * @param f_name\n\t *          is a <code>String</code> instance with the field name. In ad-hoc\n\t *          command terms this is a variable name. This field name (variable\n\t *          name) will be also displayed as the field label.\n\t * @param f_value\n\t *          is a <code>String</code> instance with the field default value.\n\t */\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String f_value) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_value);\n\t}\n\n\t/**\n\t * This method allows to add a new multi-option-select-one data field to the\n\t * command data form. This is much more complex implementation allowing to set\n\t * a field label and labels for all provided field options. It allows the\n\t * end-user to select a single option from a given list.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance of the ad-hoc command request to\n\t *          be modified.\n\t * @param f_name\n\t *          is a <code>String</code> instance with the field name. In ad-hoc\n\t *          command terms this is a variable name.\n\t * @param f_value\n\t *          is a <code>String</code> instance with the field default value. It\n\t *          must match one of the options vaulues provided as a list in\n\t *          'options' parameter.\n\t * @param label\n\t *          is a <code>String</code> instance with the field label. This time\n\t *          a label set here is displayed to the user instead of the field\n\t *          name (variable name). This is useful if the variable name is not\n\t *          suitable or clear enough to the end-user.\n\t * @param labels\n\t *          is an array with options labels which are displayed to the\n\t *          end-user upon presenting the selection options.\n\t * @param options\n\t *          is an array with options values to be selected by the end-user.\n\t *          Normally these values are not displayed to the end-user. Only\n\t *          options labels are.\n\t */\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String f_value, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String[] labels, final String[] options) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_value, label, labels, options);\n\t}\n\n\t/**\n\t * This method allows to add a new multi-option-select-many data field to the\n\t * command data form. This is much more complex implementation allowing to set\n\t * a field label and labels for all provided field options. It allows the\n\t * end-user to select many options from the given list.\n\t *\n\t * @param packet\n\t *          is a <code>Packet</code> instance of the ad-hoc command request to\n\t *          be modified.\n\t * @param f_name\n\t *          is a <code>String</code> instance with the field name. In ad-hoc\n\t *          command terms this is a variable name.\n\t * @param f_values\n\t *          is an array of default values which are presented to the end user\n\t *          as preselected options. They must match options vaulues provided\n\t *          as a list in 'options' parameter.\n\t * @param label\n\t *          is a <code>String</code> instance with the field label. This time\n\t *          a label set here is displayed to the user instead of the field\n\t *          name (variable name). This is useful if the variable name is not\n\t *          suitable or clear enough to the end-user.\n\t * @param labels\n\t *          is an array with options labels which are displayed to the\n\t *          end-user upon presenting the selection options.\n\t * @param options\n\t *          is an array with options values to be selected by the end-user.\n\t *          Normally these values are not displayed to the end-user. Only\n\t *          options labels are.\n\t */\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String[] f_values, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String[] labels, final String[] options) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_values, label, labels, options);\n\t}\n\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String f_value, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String[] labels, final String[] options,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String type) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_value, label, labels, options, type);\n\t}\n\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String f_value, final String type) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_value, type );\n\t}\n\n\tpublic static void addFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String f_value, final String type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final String label) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue( command, f_name, f_value, type, label);\n\t}\n\n\tpublic static void addHiddenField(Packet packet, String f_name, String f_value) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue(command, f_name, f_value, \"hidden\");\n\t}\n\n\tpublic static void addInstructions(final Packet packet, final String instructions) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addInstructions( command, instructions);\n\t}\n\n\tpublic static void addNote(final Packet packet, final String note) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tElement notes   = command.getChild(\"note\");\n\n\t\tif (notes == null) {\n\t\t\tnotes = new Element(\"note\", new String[] { \"type\" }, new String[] { \"info\" });\n\t\t\tcommand.addChild(notes);\n\t\t}\n\t\tnotes.setCData(XMLUtils.escape(note));\n\t}\n\n\tpublic static void addTextField(Packet packet, String f_name, String f_value) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addFieldValue(command, f_name, f_value, \"fixed\");\n\t}\n\n\tpublic static void addTitle(final Packet packet, final String title) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tDataForm.addTitle( command, title);\n\t}\n\n\tpublic static Element createIqCommand(JID from, JID to, final StanzaType type,\n\t\t\t\t\tfinal String id, final String node, final DataType data_type) {\n\t\tElement iq = createCommandEl(from, to, type, id, node, data_type);\n\n\t\treturn iq;\n\t}\n\n\tpublic static Action getAction(final Packet packet) {\n\t\tString action = packet.getAttributeStaticStr(Iq.IQ_COMMAND_PATH, \"action\");\n\n\t\ttry {\n\t\t\treturn Action.valueOf(action);\n\t\t} catch (Exception e) {\n\t\t\treturn Action.other;\n\t\t}\n\t}\n\n\tpublic static boolean getCheckBoxFieldValue(Packet packet, String f_name) {\n\t\tString result = getFieldValue(packet, f_name);\n\n\t\tif (result == null) {\n\t\t\treturn false;\n\t\t}\n\t\tresult = result.trim();\n\n\t\treturn result.equalsIgnoreCase(\"true\") || result.equals(\"1\");\n\t}\n\n\tpublic static List<Element> getData(final Packet packet) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\treturn command.getChildren();\n\t}\n\n\tpublic static Element getData(final Packet packet, final String el_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String xmlns) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\treturn command.getChild(el_name, xmlns);\n\t}\n\n\tpublic static String getFieldValue(Packet packet, String f_name) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL, XMLNS);\n\t\tElement x       = command.getChild(\"x\", \"jabber:x:data\");\n\n\t\tif (x != null) {\n\t\t\tList<Element> children = x.getChildren();\n\n\t\t\tif (children != null) {\n\t\t\t\tfor (Element child : children) {\n\t\t\t\t\tif (child.getName().equals(FIELD_EL) &&\n\t\t\t\t\t\t\tchild.getAttributeStaticStr(\"var\").equals(f_name)) {\n\t\t\t\t\t\tString value = child.getChildCDataStaticStr(FIELD_VALUE_PATH);\n\n\t\t\t\t\t\tif (value != null) {\n\t\t\t\t\t\t\treturn XMLUtils.unescape(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static String getFieldValue(final Packet packet, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t boolean debug) {\n\t\tElement iq = packet.getElement();\n\n\t\tlog.info(\"Command iq: \" + iq.toString());\n\n\t\tElement command = iq.getChild(COMMAND_EL, XMLNS);\n\n\t\tlog.info(\"Command command: \" + command.toString());\n\n\t\tElement x = command.getChild(\"x\", \"jabber:x:data\");\n\n\t\tif (x == null) {\n\t\t\tlog.info(\"Command x: NULL\");\n\n\t\t\treturn null;\n\t\t}\n\t\tlog.info(\"Command x: \" + x.toString());\n\n\t\tList<Element> children = x.getChildren();\n\n\t\tfor (Element child : children) {\n\t\t\tlog.info(\"Command form child: \" + child.toString());\n\t\t\tif (child.getName().equals(FIELD_EL) &&\n\t\t\t\t\tchild.getAttributeStaticStr(\"var\").equals(f_name)) {\n\t\t\t\tString value = child.getChildCDataStaticStr(FIELD_VALUE_PATH);\n\n\t\t\t\tlog.info(\"Command found: field=\" + f_name + \", value=\" + value);\n\t\t\t\tif (value != null) {\n\t\t\t\t\treturn XMLUtils.unescape(value);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.info(\"Command not found: field=\" + f_name + \", value=\" +\n\t\t\t\t\t\t\t\t child.getChildCDataStaticStr(FIELD_VALUE_PATH));\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static String[] getFieldValues(final Packet packet, final String f_name) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL, XMLNS);\n\n\t\treturn DataForm.getFieldValues( command, f_name);\n\t}\n\n\tpublic static boolean removeFieldValue(final Packet packet, final String f_name) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL, XMLNS);\n\n\t\treturn DataForm.removeFieldValue( command, f_name);\n\t}\n\n\tpublic static String getFieldKeyStartingWith(Packet packet, String f_name) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL, XMLNS);\n\n\t\treturn DataForm.getFieldKeyStartingWith( command, f_name);\n\t}\n\n\tpublic static void setData(final Packet packet, final Element data) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\tcommand.addChild(data);\n\t}\n\n\tpublic static void setData(final Packet packet, final List<Element> data) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\tcommand.addChildren(data);\n\t}\n\n\tpublic static void setStatus(final Packet packet, final Status status) {\n\t\tElement iq      = packet.getElement();\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\tcommand.setAttribute(\"status\", status.toString());\n\t}\n\n\tpublic static Command valueof(String cmd) {\n\t\ttry {\n\t\t\treturn Command.valueOf(cmd);\n\t\t} catch (Exception e) {\n\t\t\treturn OTHER;\n\t\t}    // end of try-catch\n\t}\n\n\tprivate static void addActionEl(Element iq, Action action) {\n\t\tElement command = iq.getChild(COMMAND_EL);\n\t\tElement actions = command.getChild(\"actions\");\n\n\t\tif (actions == null) {\n\t\t\tactions = new Element(\"actions\", new String[] { Action.execute.toString() },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { action.toString() });\n\t\t\tcommand.addChild(actions);\n\t\t}\n\t\tactions.addChild(new Element(action.toString()));\n\t}\n\n\tprivate static Element addDataForm(Element command, DataType data_type) {\n\t\tElement x = new Element(\"x\", new String[] { \"xmlns\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"jabber:x:data\",\n\t\t\t\t\t\tdata_type.name() });\n\n\t\tcommand.addChild(x);\n\n\t\treturn x;\n\t}\n\n\tprivate static Element createCommandEl(JID from, JID to, StanzaType type, String id,\n\t\t\t\t\tString node, DataType data_type) {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { type.toString() });\n\n\t\tif (from != null) {\n\t\t\tiq.setAttribute(\"from\", from.toString());\n\t\t}\n\n\t\t// The IQ packet (and command for that matter) should have the id attribute\n\t\t// therefore if it is not set then NPE should be thrown.\n\t\t// if (id != null) {\n\t\tiq.setAttribute(\"id\", id);\n\n\t\t// }\n\t\tif (to != null) {\n\t\t\tiq.setAttribute(\"to\", to.toString());\n\t\t}\n\n\t\tElement command = new Element(COMMAND_EL, new String[] { \"xmlns\", \"node\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { XMLNS,\n\t\t\t\t\t\tnode });\n\n\t\tiq.addChild(command);\n\t\tif (data_type != null) {\n\t\t\taddDataForm(command, data_type);\n\t\t\tif (data_type == DataType.result) {\n\t\t\t\tsetStatusEl(iq, Status.completed);\n\t\t\t}\n\t\t\tif (data_type == DataType.form) {\n\t\t\t\tsetStatusEl(iq, Status.executing);\n\t\t\t\taddActionEl(iq, Action.complete);\n\t\t\t}\n\t\t}\n\n\t\treturn iq;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprivate static void setStatusEl(Element iq, Status status) {\n\t\tElement command = iq.getChild(COMMAND_EL);\n\n\t\tcommand.setAttribute(\"status\", status.name());\n\t}\n\n\tpublic Packet getPacket(JID from, JID to, final StanzaType type, final String id) {\n\t\tElement elem  = createIqCommand(from, to, type, id, this.toString(), null);\n\t\tPacket result = Packet.packetInstance(elem, from, to);\n\n\t\t// Added to ensure that command will be executed in proper thread\n\t\t// and to ensure that multiple threads will be used for processing\n\t\t// command packets\n\t\tresult.setPacketFrom(from);\n\t\tresult.setPacketTo(to);\n\t\t\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n\n\tpublic Packet getPacket(JID from, JID to, StanzaType type, String id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tDataType data_type) {\n\t\tElement elem  = createIqCommand(from, to, type, id, this.toString(), data_type);\n\t\tPacket result = Packet.packetInstance(elem, from, to);\n\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n}    // Command\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ComponentInfo.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.server;\n\nimport java.util.HashMap;\nimport tigase.cluster.api.ClusteredComponentIfc;\nimport tigase.xml.Element;\n\n/**\n * Helper class for storing and handling additional informations about components\n *\n * @author Wojciech Kapcia\n */\npublic class ComponentInfo {\n\tprivate String name = null;\n\tprivate String title;\n\tprivate String version;\n\tprivate String cls;\n\tprivate HashMap<String, Object> cmpData;\n\n\t/**\n\t * Creates ComponentInfo object with initial data\n\t *\n\t * @param cmpTitle title of the component\n\t * @param cmpVersion version of the component\n\t * @param cmpCls class of the component\n\t */\n\tpublic ComponentInfo( String cmpTitle, String cmpVersion, String cmpCls ) {\n\t\tthis( null, cmpTitle, cmpVersion, cmpCls);\n\t}\n\n\t/**\n\t * Creates ComponentInfo object with initial data\n\t *\n\t * @param cmpName name of the component\n\t * @param cmpTitle title of the component\n\t * @param cmpVersion version of the component\n\t * @param cmpCls class of the component\n\t */\n\tpublic ComponentInfo( String cmpName, String cmpTitle, String cmpVersion, String cmpCls ) {\n\t\tthis(null, cmpTitle, cmpVersion, cmpCls, new HashMap<String, Object>() );\n\t}\n\n\t/**\n\t * Creates ComponentInfo object with initial data\n\t *\n\t * @param cmpName name of the component\n\t * @param cmpTitle title of the component\n\t * @param cmpVersion version of the component\n\t * @param cmpCls class of the component\n\t * @param cmpData additional information about component\n\t */\n\tpublic ComponentInfo( String cmpName, String cmpTitle, String cmpVersion, String cmpCls, HashMap<String, Object> cmpData ) {\n\t\tthis.name = cmpName;\n\t\tthis.title = cmpTitle;\n\t\tthis.version = cmpVersion;\n\t\tthis.cls = cmpCls;\n\t\tthis.cmpData = cmpData;\n\t}\n\n\t/**\n\t * Creates ComponentInfo object with initial data\n\t *\n\t * @param c class of the component\n\t */\n\tpublic ComponentInfo( Class<?> c ) {\n\t\tthis( null, c);\n\t}\n\n\t/**\n\t * Creates ComponentInfo object with initial data\n\t *\n\t * @param cmpName name of the component\n\t * @param c class of the component\n\t */\n\tpublic ComponentInfo(String cmpName, Class<?> c ) {\n\t\tthis.name = cmpName;\n\t\tthis.title = getImplementationTitle( c );\n\t\tthis.version = getImplementationVersion( c );\n\t\tthis.cls = c.getName();\n\t\tthis.cmpData = new HashMap<>();\n\t}\n\n\t/**\n\t * Allows retrieving of component's name\n\t *\n\t * @return component name\n\t */\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * Allows retrieving of component's title\n\t *\n\t * @return component title\n\t */\n\tpublic String getComponentTitle() {\n\t\treturn title;\n\t}\n\n\t/**\n\t * Allows retrieving of component's version\n\t *\n\t * @return component version\n\t */\n\tpublic String getComponentVersion() {\n\t\treturn version;\n\t}\n\n\t/**\n\t * Allows retrieving of component's class\n\t *\n\t * @return component class\n\t */\n\tpublic String getComponentClass() {\n\t\treturn cls;\n\t}\n\n\t/**\n\t * Allows retrieving of component's additional data\n\t *\n\t * @return  component additional data\n\t */\n\tpublic HashMap<String, Object> getComponentData() {\n\t\treturn cmpData;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn (name == null ? \"\" : name + \" :: \") + \"componentInfo{\"\n\t\t\t\t\t + (title.isEmpty() ? \"\" : \"Title=\" + title + \", \")\n\t\t\t\t\t + (version.isEmpty() ? \"\" : \"Version=\" + version + \", \")\n\t\t\t\t\t + \"Class=\" + cls\n\t\t\t\t\t +  ( cmpData.isEmpty() ? \"\" : \", componentData=\" + cmpData) + '}';\n\t}\n\n\t/**\n\t * Allows retrieving of component's information as Element\n\t *\n\t * @return component information as Element\n\t */\n\tpublic Element toElement() {\n\t\tElement cmpInfo = new Element( \"cmpInfo\" );\n\t\tif ( name != null ){\n\t\t\tcmpInfo.addChild(new Element( \"name\", name ) );\n\t\t}\n\t\tif ( !title.isEmpty() ){\n\t\t\tcmpInfo.addChild( new Element( \"title\", title ) );\n\t\t}\n\t\tif ( !version.isEmpty() ){\n\t\t\tcmpInfo.addChild( new Element( \"version\", version ) );\n\t\t}\n\t\tif ( !cls.isEmpty() ){\n\t\t\tcmpInfo.addChild( new Element( \"class\", cls ) );\n\t\t}\n\t\tif ( !cmpData.isEmpty() ){\n\t\t\tElement data = new Element( \"cmpData\" );\n\t\t\tfor ( String key : cmpData.keySet() ) {\n\t\t\t\tdata.addChild( new Element( key, cmpData.get( key ).toString() ) );\n\t\t\t}\n\t\t\tcmpInfo.addChild( data );\n\t\t}\n\t\treturn cmpInfo;\n\t}\n\n\t/**\n\t * Allows retrieving implementation package (obtained from jar package)\n\t * for a given class\n\t *\n\t * @param c class for which package is to be retrieved\n\t * @return package containing given class\n\t */\n\tpublic static Package getImplementation( Class<?> c ) {\n\t\treturn c.getPackage() == null ? XMPPServer.class.getPackage() : c.getPackage();\n\t}\n\n\t/**\n\t * Allows retrieving implementation version (obtained from jar package)\n\t * for a given class\n\t *\n\t * @param c class for which Package version is to be retrieved\n\t * @return Package version of the given class\n\t */\n\tpublic static String getImplementationVersion( Class<?> c ) {\n\t\tPackage p = getImplementation( c );\n\n\t\tString version = p == null ? null : p.getImplementationVersion();\n\n\t\tif (ClusteredComponentIfc.class.isAssignableFrom(c)) {\n\t\t\tClass<?> superClass = c.getSuperclass();\n\t\t\tPackage superPackage = getImplementation( superClass );\n\t\t\tif (p != superPackage && superPackage != null && !p.equals(superPackage)) {\n\t\t\t\tString superVersion  = superPackage.getImplementationVersion();\n\t\t\t\tif (superVersion != null && version != null && !version.equals(superVersion)) {\n\t\t\t\t\tversion += \"-\" + superVersion;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn ( version == null ) ? \"\" : version;\n\t}\n\n\t/**\n\t * Allows retrieving implementation title (obtained from jar package)\n\t * for a given class\n\t *\n\t * @param c class for which Package title is to be retrieved\n\t * @return Package title of the given class\n\t */\n\tpublic static String getImplementationTitle( Class<?> c ) {\n\t\tPackage p = getImplementation( c );\n\n\t\tString title = p == null ? null : p.getImplementationTitle();\n\n\t\treturn title == null ? \"\" : title;\n\t}\n\n\t/**\n\t * Allows retrieving implementation information (obtained from jar package)\n\t * for a given class\n\t *\n\t * @param c class for which Package information is to be retrieved\n\t * @return title and version of the Package holding class\n\t */\n\tpublic static String getImplementationInfo( Class<?> c ) {\n\t\treturn getImplementationTitle( c ) + \", version: \" + getImplementationVersion( c );\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ComponentRegistrator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\nimport tigase.conf.ConfigurationException;\n\n/**\n * Interface ComponentRegistrator\n *\n * Collects information about all ServerComponents connected to MessageRouter\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ComponentRegistrator extends ServerComponent {\n\n  /**\n   *\n   * @param component\n   * @return a <code>boolean</code> value indicating whehether component has\n   * been successfuly added or not.\n   */\n\tboolean addComponent(ServerComponent component) throws ConfigurationException;\n\n  /**\n   *\n\t * @param component \n\t * @return a <code>boolean</code> value indicating whehether component has\n   * been successfuly removed or not.\n   */\n\tboolean deleteComponent(ServerComponent component);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ConnectionManager.java",
    "content": "/*\n * ConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\n\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.nio.channels.SocketChannel;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.net.ssl.TrustManager;\nimport javax.script.Bindings;\n\nimport tigase.annotations.TODO;\nimport tigase.conf.ConfigurationException;\nimport tigase.net.*;\n\nimport tigase.server.script.CommandIfc;\nimport tigase.server.xmppclient.ClientConnectionManager;\nimport tigase.server.xmppclient.ClientTrustManagerFactory;\nimport tigase.server.xmppclient.XMPPIOProcessor;\nimport tigase.stats.StatisticsList;\nimport tigase.util.DataTypes;\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.XMPPDomBuilderHandler;\nimport tigase.xmpp.XMPPIOService;\n\nimport static tigase.xmpp.XMPPIOService.DOM_HANDLER;\n\nimport tigase.xmpp.XMPPIOServiceListener;\n\n\n/**\n * Describe class ConnectionManager here.\n *\n *\n * Created: Sun Jan 22 22:52:58 2006\n *\n * @param <IO>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class ConnectionManager<IO extends XMPPIOService<?>>\n\t\t\t\textends AbstractMessageReceiver\n\t\t\t\timplements XMPPIOServiceListener<IO> {\n\t/** Field description */\n\tpublic static final String HT_TRAFFIC_THROTTLING_PROP_KEY =\n\t\t\t\"--cm-ht-traffic-throttling\";\n\n\t/** Field description */\n\tpublic static final String HT_TRAFFIC_THROTTLING_PROP_VAL =\n\t\t\t\"xmpp:50k:0:disc,bin:400m:0:disc\";\n\n\t/** Field description. */\n\tpublic static final String NET_BUFFER_HT_PROP_KEY = \"--net-buff-high-throughput\";\n\n\t/** Field description. */\n\tpublic static final String NET_BUFFER_ST_PROP_KEY = \"--net-buff-standard\";\n\n\t/** Field description. */\n\tpublic static final String PORT_LOCAL_HOST_PROP_KEY = \"local-host\";\n\n\t/** Field description */\n\tpublic static final String ST_TRAFFIC_THROTTLING_PROP_KEY = \"--cm-traffic-throttling\";\n\n\t/** Field description */\n\tpublic static final String ST_TRAFFIC_THROTTLING_PROP_VAL =\n\t\t\t\"xmpp:2500:0:disc,bin:20m:0:disc\";\n\n\t/** Field description */\n\tpublic static final String TRAFFIC_THROTTLING_PROP_KEY = \"traffic-throttling\";\n\n\t/** Field description */\n\tprotected static final long LAST_MINUTE_BIN_LIMIT_PROP_VAL = 20000000L;\n\n\t/** Field description */\n\tprotected static final long LAST_MINUTE_PACKETS_LIMIT_PROP_VAL = 2500L;\n\n\t/** Field description */\n\tprotected static final String MAX_INACTIVITY_TIME = \"max-inactivity-time\";\n\n\t/** Field description */\n\tprotected static final String MAX_RECONNECTS_PROP_KEY = \"max-reconnects\";\n\n\t/** Field description */\n\tprotected static final int NET_BUFFER_HT_PROP_VAL = 64 * 1024;\n\n\t/** Field description */\n\tprotected static final String NET_BUFFER_PROP_KEY = \"net-buffer\";\n\n\t/** Field description */\n\tprotected static final int NET_BUFFER_ST_PROP_VAL = 2 * 1024;\n\n\t/** Field description */\n\tprotected static final int NET_BUFFER_LIMIT_HT_PROP_VAL = 20*1024*1024;\n\n\t/** Field description */\n\tprotected static final String NET_BUFFER_LIMIT_PROP_KEY= \"net-buffer-limit\";\n\n\t/** Field description */\n\tprotected static final int NET_BUFFER_LIMIT_ST_PROP_VAL = 2*1024*1024;\n\t/**\n\t * Key name of the system property for configuration protection\n\t * from system overload and DOS attack.\n\t */\n\tpublic static final String ELEMENTS_NUMBER_LIMIT_PROP_KEY = \"elements-number-limit\";\n\n\t/**\n\t * Default value for the system property for configuration protection\n\t * from system overload and DOS attack.\n\t */\n\tpublic static int ELEMENTS_NUMBER_LIMIT_PROP_VAL = 1000;\n\n\t/** Field description */\n\tprotected static final String PORT_CLASS_PROP_KEY = \"class\";\n\n\t/** Field description */\n\tprotected static final String PORT_IFC_PROP_KEY = \"ifc\";\n\n\t/** Field description */\n\tprotected static final String PORT_KEY = \"port-no\";\n\n\t/** Field description */\n\tprotected static final String PORT_REMOTE_HOST_PROP_KEY = \"remote-host\";\n\n\t/** Field description */\n\tprotected static final String PORT_REMOTE_HOST_PROP_VAL = \"localhost\";\n\n\t/** Field description */\n\tprotected static final String PORT_SOCKET_PROP_KEY = \"socket\";\n\n\t/** Field description */\n\tprotected static final String PORT_TYPE_PROP_KEY = \"type\";\n\n\t/** Field description */\n\tprotected static final String PROP_KEY = \"connections/\";\n\n\t/** Field description */\n\tprotected static final long TOTAL_BIN_LIMIT_PROP_VAL = 0L;\n\n\t/** Field description */\n\tprotected static final long TOTAL_PACKETS_LIMIT_PROP_VAL = 0L;\n\n\t/** Field description */\n\tprotected static final String WHITE_CHAR_ACK_PROP_KEY = \"white-char-ack\";\n\n\t/** Field description */\n\tprotected static final String       XMPP_ACK_PROP_KEY = \"xmpp-ack\";\n\tprivate static final Logger         log = Logger.getLogger(ConnectionManager.class\n\t\t\t.getName());\n\tprivate static ConnectionOpenThread connectThread = ConnectionOpenThread.getInstance();\n\n\t/** Field description */\n\tprotected static final boolean XMPP_ACK_PROP_VAL = false;\n\n\t/** Field description */\n\tprotected static final boolean WHITE_CHAR_ACK_PROP_VAL = false;\n\n\t/** Field description */\n\tprotected static final String PORTS_PROP_KEY = PROP_KEY + \"ports\";\n\n\t/** Field description */\n\tprotected static final boolean TLS_USE_PROP_VAL = true;\n\t//J-\n\t/** Field description */\n\tprotected static final String TLS_PROP_KEY = PROP_KEY + \"tls/\";\n\n\t/** Field description */\n\tprotected static final String TLS_USE_PROP_KEY = TLS_PROP_KEY + \"use\";\n\n\t/** Field description */\n\tprotected static final boolean TLS_REQUIRED_PROP_VAL = false;\n\n\t/** Field description */\n\tprotected static final String TLS_REQUIRED_PROP_KEY = TLS_PROP_KEY + \"required\";\n\n\tprotected static final String WATCHDOG_DELAY = \"watchdog_delay\";\n\tprotected static final String WATCHDOG_TIMEOUT = \"watchdog_timeout\";\n\tprotected static final String WATCHDOG_PING_TYPE_KEY = \"watchdog_ping_type\";\n\n\tprotected static final Element pingElement = new Element( \"iq\",\n\t\t\t\t\t\t\t\tnew Element[] { new Element( \"ping\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:ping\" } ) },\n\t\t\t\t\t\t\t\tnew String[] { \"type\", \"id\" },\n\t\t\t\t\t\t\t\tnew String[] { \"get\", \"tigase-ping\" } );\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description. */\n\tpublic String[]                         PORT_IFC_PROP_VAL = { \"*\" };\n\tprivate long                            bytesReceived     = 0;\n\tprivate long                            bytesSent         = 0;\n\tprivate int                             services_size     = 0;\n\tprivate long                            socketOverflow    = 0;\n\tprivate Thread                          watchdog          = null;\n\tprivate long                            watchdogRuns      = 0;\n\tprivate long                            watchdogStopped   = 0;\n\tprivate long                            watchdogTests     = 0;\n\tprotected long                          watchdogDelay     = 10 * MINUTE; // 600 000\n\tprotected long                          watchdogTimeout   = 29 * MINUTE; // 1 740 000\n\tprivate boolean                         white_char_ack    = WHITE_CHAR_ACK_PROP_VAL;\n\tprivate boolean                         xmpp_ack          = XMPP_ACK_PROP_VAL;\n\tprivate LinkedList<Map<String, Object>> waitingTasks = new LinkedList<Map<String,\n\t\t\tObject>>();\n\tprivate long                          total_packets_limit =\n\t\t\tTOTAL_PACKETS_LIMIT_PROP_VAL;\n\tprivate long                          total_bin_limit     = TOTAL_BIN_LIMIT_PROP_VAL;\n\t/**\n\t * Protection from the system overload and DOS attack. We want to limit number\n\t * of elements created within a single XMPP stanza.\n\t *\n\t */\n\tprotected int elements_number_limit = 0;\n\tprivate ConcurrentHashMap<String, IO> services = new ConcurrentHashMap<String, IO>();\n\tprivate Set<ConnectionListenerImpl>   pending_open = Collections.synchronizedSet(\n\t\t\tnew HashSet<ConnectionListenerImpl>());;\n\tprivate long                      maxInactivityTime       = getMaxInactiveTime();\n\tprivate long                      last_minute_packets_limit =\n\t\t\tLAST_MINUTE_PACKETS_LIMIT_PROP_VAL;\n\tprivate long                      last_minute_bin_limit =\n\t\t\tLAST_MINUTE_BIN_LIMIT_PROP_VAL;\n\tprivate int net_buffer_limit = 0;\n\tprivate IOServiceStatisticsGetter ioStatsGetter = new IOServiceStatisticsGetter();\n\tprivate boolean                   initializationCompleted = false;\n\tprotected XMPPIOProcessor[]       processors              = new XMPPIOProcessor[0];\n\n\t/** Field description */\n\tprotected int net_buffer = NET_BUFFER_ST_PROP_VAL;\n\n\t/** Field description */\n\tprotected long       connectionDelay = 2 * SECOND;\n\tprivate LIMIT_ACTION xmppLimitAction = LIMIT_ACTION.DISCONNECT;\n\tprotected WATCHDOG_PING_TYPE watchdogPingType = WATCHDOG_PING_TYPE.WHITESPACE;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Describe class <code>LIMIT_ACTION</code> here.\n\t *\n\t */\n\tpublic static enum LIMIT_ACTION { DISCONNECT, DROP_PACKETS; }\n\t/** Holds possible types of ping to be used in watchdog service for detection\n\t * of broken connections */\n\tpublic static enum WATCHDOG_PING_TYPE { WHITESPACE, XMPP; }\n\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean checkTrafficLimits(IO serv) {\n\t\tboolean xmppLimitHit = false;\n\n\t\tif (last_minute_packets_limit > 0) {\n\t\t\txmppLimitHit = (serv.getPacketsReceived(false) >= last_minute_packets_limit)\n//\t\t\t\t\t\t\t|| (serv.getPacketsSent(false) >= last_minute_packets_limit)\n\t\t\t\t\t\t\t;\n\t\t}\n\t\tif (!xmppLimitHit && (total_packets_limit > 0)) {\n\t\t\txmppLimitHit = (serv.getTotalPacketsReceived() >= total_packets_limit)\n//\t\t\t\t\t\t\t|| (serv.getTotalPacketsSent() >= total_packets_limit)\n\t\t\t\t\t\t\t;\n\t\t}\n\t\tif (xmppLimitHit) {\n\t\t\tLevel level = Level.FINER;\n\n\t\t\tif (isHighThroughput()) {\n\t\t\t\tlevel = Level.WARNING;\n\t\t\t}\n\t\t\tswitch (xmppLimitAction) {\n\t\t\tcase DROP_PACKETS :\n\t\t\t\tif (log.isLoggable(level)) {\n\t\t\t\t\tlog.log(level, \"[[{0}]] XMPP Limits exceeded on connection {1}\" +\n\t\t\t\t\t\t\t\" dropping pakcets: {2}\", new Object[] { getName(),\n\t\t\t\t\t\t\tserv, serv.getReceivedPackets() });\n\t\t\t\t}\n\t\t\t\twhile (serv.getReceivedPackets().poll() != null);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tif (log.isLoggable(level)) {\n\t\t\t\t\tlog.log(level, \"[[{0}]] XMPP Limits exceeded on connection {1}\" +\n\t\t\t\t\t\t\t\" stopping, packets dropped: {2}\", new Object[] { getName(),\n\t\t\t\t\t\t\tserv, serv.getReceivedPackets() });\n\t\t\t\t}\n\t\t\t\tserv.forceStop();\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tboolean binLimitHit   = false;\n\t\tlong    bytesSent     = serv.getBytesSent(false);\n\t\tlong    bytesReceived = serv.getBytesReceived(false);\n\n\t\tif (last_minute_bin_limit > 0) {\n\t\t\tbinLimitHit = (bytesSent >= last_minute_bin_limit) || (bytesReceived >=\n\t\t\t\t\tlast_minute_bin_limit);\n\t\t}\n\n\t\tlong totalSent     = serv.getTotalBytesSent();\n\t\tlong totalReceived = serv.getTotalBytesReceived();\n\n\t\tif (!binLimitHit && (total_bin_limit > 0)) {\n\t\t\tbinLimitHit = (totalReceived >= total_bin_limit) || (totalSent >= total_bin_limit);\n\t\t}\n\t\tif (binLimitHit) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"[[{0}]] Binary Limits exceeded ({1}:{2}:{3}:{4}) on\" +\n\t\t\t\t\t\t\" connection {5} stopping, packets dropped: {6}\", new Object[] {\n\t\t\t\t\tgetName(), bytesSent, bytesReceived, totalSent, totalReceived, serv,\n\t\t\t\t\tserv.getReceivedPackets()\n\t\t\t\t});\n\t\t\t}\n\t\t\tserv.forceStop();\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic synchronized void everyMinute() {\n\t\tsuper.everyMinute();\n\n\t\t// This variable used to provide statistics gets off on a busy\n\t\t// services as it is handled in methods called concurrently by\n\t\t// many threads. While accuracy of this variable is not critical\n\t\t// for the server functions, statistics should be as accurate as\n\t\t// possible to provide valuable metrics data.\n\t\t// So in the watchdog thread we re-synchronize this number\n\t\tint tmp = services.size();\n\n\t\tservices_size = tmp;\n\t\tdoForAllServices(ioStatsGetter);\n\t}\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().hashCode();\n\t\t}\n\t\tif (packet.getTo() != null) {\n\t\t\treturn packet.getTo().hashCode();\n\t\t}\n\n\t\treturn super.hashCodeForPacket(packet);\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(CommandIfc.SERVICES_MAP, services);\n\t}\n\n\t@Override\n\tpublic void initializationCompleted() {\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\treturn;\n\t\t}\n\t\tsuper.initializationCompleted();\n\t\tinitializationCompleted = true;\n\t\tfor (Map<String, Object> params : waitingTasks) {\n\t\t\treconnectService(params, connectionDelay);\n\t\t}\n\t\twaitingTasks.clear();\n\t\tif ( null != watchdog ){\n\t\t\twatchdog.start();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void packetsReady(IO serv) throws IOException {\n\n\t\t// Under a high load data, especially lots of packets on a single\n\t\t// connection it may happen that one threads started processing\n\t\t// socketData and then another thread reads more packets which\n\t\t// may take over earlier data depending on a thread scheduler used.\n\t\t// synchronized (serv) {\n\t\tif (checkTrafficLimits(serv)) {\n\t\t\twritePacketsToSocket(serv, processSocketData(serv));\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors() * 4;\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors() * 4;\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\twritePacketToSocket(packet);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t *\n\t *\n\t *\n\t * @return a value of {@code Queue<Packet>}\n\t */\n\tpublic abstract Queue<Packet> processSocketData(IO serv);\n\n\t/**\n\t * Processes undelivered packets\n\t * @param packet\n\t * @param stamp - timestamp when packet was received to be written to XMPPIOService\n\t * @param errorMessage\n\t */\n\tpublic abstract boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param port_props\n\t */\n\tpublic abstract void reconnectionFailed(Map<String, Object> port_props);\n\n\t@Override\n\tpublic void release() {\n\n\t\t// delayedTasks.cancel();\n\t\treleaseListeners();\n\t\tsuper.release();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param service\n\t */\n\t@TODO(note = \"Do something if service with the same unique ID is already started, \" +\n\t\t\t\"possibly kill the old one...\")\n\tpublic void serviceStarted(final IO service) {\n\n\t\t// synchronized(services) {\n\t\tString id = getUniqueId(service);\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"[[{0}]] Connection started: {1}\", new Object[] { getName(),\n\t\t\t\t\tservice });\n\t\t}\n\n\t\tIO serv = services.get(id);\n\n\t\tif (serv != null) {\n\t\t\tif (serv == service) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"{0}: That would explain a lot, adding the same service twice, ID: {1}\",\n\t\t\t\t\t\tnew Object[] { getName(),\n\t\t\t\t\t\tserv });\n\t\t\t} else {\n\n\t\t\t\t// Is it at all possible to happen???\n\t\t\t\t// let's log it for now....\n\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\"{0}: Attempt to add different service with the same ID: {1}; old: {2} (stopped)\", new Object[] {\n\t\t\t\t\t\tgetName(), service, serv });\n\t\t\t\t// And stop the old service....\n\t\t\t\tserv.stop();\n\t\t\t}\n\t\t}\n\t\tservices.put(id, service);\n\t\t++services_size;\n\n\t\t// }\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(IO service) {\n\n\t\t// Hopefuly there is no exception at this point, but just in case...\n\t\t// This is a very fresh code after all\n\t\ttry {\n\t\t\tioStatsGetter.check(service);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\"Nothing serious to worry about but please notify the developer.\", e);\n\t\t}\n\n\t\t// synchronized(service) {\n\t\tString id = getUniqueId(service);\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"[[{0}]] Connection stopped: {1}\", new Object[] { getName(),\n\t\t\t\t\tservice });\n\t\t}\n\n\t\t// id might be null if service is stopped in accept method due to\n\t\t// an exception during establishing TCP/IP connection\n\t\t// IO serv = (id != null ? services.get(id) : null);\n\t\tif (id != null) {\n\t\t\tboolean result = services.remove(id, service);\n\n\t\t\tif (result) {\n\t\t\t\t--services_size;\n\t\t\t\t\n\t\t\t\tQueue<Packet> undeliveredPackets = service.getWaitingPackets();\n\t\t\t\tPacket p = null;\n\t\t\t\twhile ((p = undeliveredPackets.poll()) != null) {\n\t\t\t\t\tprocessUndeliveredPacket(p, null, null);\n\t\t\t\t}\n\t\t\t} else if (log.isLoggable(Level.FINER)) {\n\n\t\t\t\t// Is it at all possible to happen???\n\t\t\t\t// let's log it for now....\n\t\t\t\tlog.log(Level.FINER, \"[[{0}]] Attempt to stop incorrect service: {1}\",\n\t\t\t\t\t\tnew Object[] { getName(),\n\t\t\t\t\t\tservice });\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tthis.releaseListeners();\n\n\t\t// when stopping connection manager we need to stop all active connections as well\n\t\tfor (IO service : services.values()) {\n\t\t\tservice.forceStop();\n\t\t}\n\t\tsuper.stop();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param port_props\n\t */\n\tpublic void updateConnectionDetails(Map<String, Object> port_props) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t * @param packets\n\t */\n\tpublic void writePacketsToSocket(IO serv, Queue<Packet> packets) {\n\t\tif (serv != null) {\n\n\t\t\t// synchronized (serv) {\n\t\t\tif ((packets != null) && (packets.size() > 0)) {\n\t\t\t\tPacket p = null;\n\n\t\t\t\twhile ((p = packets.poll()) != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER) &&!log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"{0}, Processing packet: {1}, type: {2}\", new Object[] {\n\t\t\t\t\t\t\t\tserv,\n\t\t\t\t\t\t\t\tp.getElemName(), p.getType() });\n\t\t\t\t\t}\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Writing packet: {1}\", new Object[] { serv, p });\n\t\t\t\t\t}\n\t\t\t\t\tserv.addPacketToSend(p);\n\t\t\t\t}      // end of for ()\n\t\t\t\ttry {\n\t\t\t\t\tserv.processWaitingPackets();\n\t\t\t\t\tSocketThread.addSocketService(serv);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, serv + \"Exception during writing packets: \", e);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t} catch (Exception e1) {\n\t\t\t\t\t\tlog.log(Level.WARNING, serv + \"Exception stopping XMPPIOService: \", e1);\n\t\t\t\t\t}    // end of try-catch\n\t\t\t\t}      // end of try-catch\n\t\t\t}\n\n\t\t\t// }\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Can't find service for packets: [{0}] \", packets);\n\t\t\t}\n\t\t}          // end of if (ios != null) else\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ios\n\t * @param p\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean writePacketToSocket(IO ios, Packet p) {\n\t\tif (ios != null) {\n\t\t\tif (log.isLoggable(Level.FINER) &&!log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINER, \"{0}, Processing packet: {1}, type: {2}\", new Object[] { ios,\n\t\t\t\t\t\tp.getElemName(), p.getType() });\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Writing packet: {1}\", new Object[] { ios, p });\n\t\t\t}\n\n\t\t\t// if packet is added to waiting packets queue then we can assume it is sent\n\t\t\t// as if it will fail it will be returned as error by serviceStopped method\n\t\t\tios.addPacketToSend(p);\n\t\t\tif (ios.writeInProgress.tryLock()) {\n\t\t\t\ttry {\n\t\t\t\t\tios.processWaitingPackets();\n\t\t\t\t\tSocketThread.addSocketService(ios);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, ios + \"Exception during writing packets: \", e);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tios.stop();\n\t\t\t\t\t} catch (Exception e1) {\n\t\t\t\t\t\tlog.log(Level.WARNING, ios + \"Exception stopping XMPPIOService: \", e1);\n\t\t\t\t\t}    // end of try-catch\n\t\t\t\t} finally {\n\t\t\t\t\tios.writeInProgress.unlock();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Can''t find service for packet: <{0}> {1}, service id: {2}\",\n\t\t\t\t\t\tnew Object[] { p.getElemName(),\n\t\t\t\t\t\tp.getTo(), getServiceId(p) });\n\t\t\t}\n\t\t}    // end of if (ios != null) else\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String xmppStreamError(IO serv, List<Element> err_el) {\n\t\tStreamError streamError\t= StreamError.getByCondition(err_el.get(0).getName());\t\n\t\t\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, streamError);\n\t\t}\t\t\n\t\treturn \"<stream:error>\" + err_el.get(0).toString() + \"</stream:error>\";\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tlog.log(Level.CONFIG, \"{0} defaults: {1}\", new Object[] { getName(),\n\t\t\t\tparams.toString() });\n\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tprops.put(TLS_USE_PROP_KEY, TLS_USE_PROP_VAL);\n\t\tcheckHighThroughputProperty(NET_BUFFER_HT_PROP_KEY, NET_BUFFER_HT_PROP_VAL,\n\t\t\t\tNET_BUFFER_ST_PROP_KEY, NET_BUFFER_ST_PROP_VAL, NET_BUFFER_PROP_KEY,\n\t\t\t\tInteger.class, params, props);\n\t\tcheckHighThroughputProperty(HT_TRAFFIC_THROTTLING_PROP_KEY,\n\t\t\t\tgetDefTrafficThrottling(), ST_TRAFFIC_THROTTLING_PROP_KEY,\n\t\t\t\tgetDefTrafficThrottling(), TRAFFIC_THROTTLING_PROP_KEY, String.class, params,\n\t\t\t\tprops);\n\n\t\tprops.put(NET_BUFFER_LIMIT_PROP_KEY, isHighThroughput()\n\t\t\t\t? NET_BUFFER_LIMIT_HT_PROP_VAL : NET_BUFFER_LIMIT_ST_PROP_VAL);\n\n\t\tif ( params.get( \"--\" + ELEMENTS_NUMBER_LIMIT_PROP_KEY ) != null ){\n\t\t\telements_number_limit = Integer.valueOf( (String)params.get( \"--\" + ELEMENTS_NUMBER_LIMIT_PROP_KEY ) );\n\t\t} else {\n\t\t\telements_number_limit = ELEMENTS_NUMBER_LIMIT_PROP_VAL;\n\t\t}\n\t\tprops.put( ELEMENTS_NUMBER_LIMIT_PROP_KEY, elements_number_limit );\n\n\t\tif ( params.get( \"--\" + WATCHDOG_DELAY ) != null ){\n\t\t\twatchdogDelay = Integer.valueOf( (String)params.get( \"--\" + WATCHDOG_DELAY ) );\n\t\t}\n\t\tprops.put( WATCHDOG_DELAY, watchdogDelay);\n\n\t\tif ( params.get( \"--\" + WATCHDOG_TIMEOUT ) != null ){\n\t\t\twatchdogTimeout =  Integer.valueOf( (String)params.get( \"--\" + WATCHDOG_TIMEOUT ) );\n\t\t}\n\t\tprops.put( WATCHDOG_TIMEOUT, watchdogTimeout);\n\n\t\tWATCHDOG_PING_TYPE pingtype = WATCHDOG_PING_TYPE.WHITESPACE;\n\t\tif ( params.get( \"--\" + WATCHDOG_PING_TYPE_KEY ) != null ){\n\t\t\tString type = (String)params.get( \"--\" + WATCHDOG_PING_TYPE_KEY );\n\t\t\tpingtype = WATCHDOG_PING_TYPE.valueOf( type.toUpperCase() );\n\t\t}\n\t\tprops.put( WATCHDOG_PING_TYPE_KEY, pingtype);\n\n\t\tint[]  ports     = null;\n\t\tString ports_str = (String) params.get(\"--\" + getName() + \"-ports\");\n\n\t\tif (ports_str != null) {\n\t\t\tString[] ports_stra = ports_str.split(\",\");\n\n\t\t\tports = new int[ports_stra.length];\n\n\t\t\tint k = 0;\n\n\t\t\tfor (String p : ports_stra) {\n\t\t\t\ttry {\n\t\t\t\t\tports[k++] = Integer.parseInt(p);\n\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\tlog.warning(\"Incorrect ports default settings: \" + p);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint ports_size = 0;\n\n\t\tif (ports != null) {\n\t\t\tlog.config(\"Port settings preset: \" + Arrays.toString(ports));\n\t\t\tfor (int port : ports) {\n\t\t\t\tputDefPortParams(props, port, SocketType.plain);\n\t\t\t}        // end of for (int i = 0; i < idx; i++)\n\t\t\tprops.put(PORTS_PROP_KEY, ports);\n\t\t} else {\n\t\t\tint[] plains = getDefPlainPorts();\n\n\t\t\tif (plains != null) {\n\t\t\t\tports_size += plains.length;\n\t\t\t}        // end of if (plains != null)\n\n\t\t\tint[] ssls = getDefSSLPorts();\n\n\t\t\tif (ssls != null) {\n\t\t\t\tports_size += ssls.length;\n\t\t\t}        // end of if (ssls != null)\n\t\t\tif (ports_size > 0) {\n\t\t\t\tports = new int[ports_size];\n\t\t\t}        // end of if (ports_size > 0)\n\t\t\tif (ports != null) {\n\t\t\t\tint idx = 0;\n\n\t\t\t\tif (plains != null) {\n\t\t\t\t\tidx = plains.length;\n\t\t\t\t\tfor (int i = 0; i < idx; i++) {\n\t\t\t\t\t\tports[i] = plains[i];\n\t\t\t\t\t\tputDefPortParams(props, ports[i], SocketType.plain);\n\t\t\t\t\t}    // end of for (int i = 0; i < idx; i++)\n\t\t\t\t}      // end of if (plains != null)\n\t\t\t\tif (ssls != null) {\n\t\t\t\t\tfor (int i = idx; i < idx + ssls.length; i++) {\n\t\t\t\t\t\tports[i] = ssls[i - idx];\n\t\t\t\t\t\tputDefPortParams(props, ports[i], SocketType.ssl);\n\t\t\t\t\t}    // end of for (int i = 0; i < idx + ssls.length; i++)\n\t\t\t\t}      // end of if (ssls != null)\n\t\t\t\tprops.put(PORTS_PROP_KEY, ports);\n\t\t\t}        // end of if (ports != null)\n\t\t}\n\n\t\tString acks = (String) params.get(XMPP_STANZA_ACK);\n\n\t\tif (acks != null) {\n\t\t\tString[] acks_arr = acks.split(\",\");\n\n\t\t\tfor (String ack_type : acks_arr) {\n\t\t\t\tif (STANZA_WHITE_CHAR_ACK.equals(ack_type)) {\n\t\t\t\t\twhite_char_ack = true;\n\t\t\t\t}\n\t\t\t\tif (STANZA_XMPP_ACK.equals(ack_type)) {\n\t\t\t\t\txmpp_ack = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprops.put(WHITE_CHAR_ACK_PROP_KEY, white_char_ack);\n\t\tprops.put(XMPP_ACK_PROP_KEY, xmpp_ack);\n\t\tprops.put(MAX_INACTIVITY_TIME, getMaxInactiveTime() / SECOND);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getName(), \"Open connections\", services_size, Level.INFO);\n\t\tif (list.checkLevel(Level.FINEST) || (services.size() < 1000)) {\n\t\t\tint waitingToSendSize = 0;\n\n\t\t\tfor (IO serv : services.values()) {\n\t\t\t\twaitingToSendSize += serv.waitingToSendSize();\n\t\t\t}\n\t\t\tlist.add(getName(), \"Waiting to send\", waitingToSendSize, Level.FINE);\n\t\t}\n\t\tlist.add(getName(), \"Bytes sent\", bytesSent, Level.FINE);\n\t\tlist.add(getName(), \"Bytes received\", bytesReceived, Level.FINE);\n\t\tlist.add(getName(), \"Socket overflow\", socketOverflow, Level.FINE);\n\t\tlist.add(getName(), \"Watchdog runs\", watchdogRuns, Level.FINER);\n\t\tlist.add(getName(), \"Watchdog tests\", watchdogTests, Level.FINE);\n\t\tlist.add(getName(), \"Watchdog stopped\", watchdogStopped, Level.FINE);\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.getStatistics(list);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serviceId\n\t *\n\t *\n\t *\n\t * @return a value of <code>IO</code>\n\t */\n\tpublic IO getXMPPIOService(String serviceId) {\n\t\treturn services.get(serviceId);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t\tsetupWatchdogThread();\n\t}\n\n\tprotected void setupWatchdogThread() {\n\t\twatchdog = new Thread( newWatchdog(), \"Watchdog - \" + getName());\n\t\twatchdog.setDaemon(true);\n\t}\n\n\tprotected Watchdog newWatchdog() {\n\t\treturn new Watchdog();\n\t}\n\t\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.get(MAX_INACTIVITY_TIME) != null) {\n\t\t\tmaxInactivityTime = (Long) props.get(MAX_INACTIVITY_TIME) * SECOND;\n\t\t}\n\t\tif (props.get(WHITE_CHAR_ACK_PROP_KEY) != null) {\n\t\t\twhite_char_ack = (Boolean) props.get(WHITE_CHAR_ACK_PROP_KEY);\n\t\t}\n\t\tif (props.get(XMPP_ACK_PROP_KEY) != null) {\n\t\t\txmpp_ack = (Boolean) props.get(XMPP_ACK_PROP_KEY);\n\t\t}\n\t\tif (props.get(NET_BUFFER_PROP_KEY) != null) {\n\t\t\tnet_buffer = (Integer) props.get(NET_BUFFER_PROP_KEY);\n\t\t}\n\t\tif (props.get(NET_BUFFER_LIMIT_PROP_KEY) != null) {\n\t\t\tnet_buffer_limit = (Integer) props.get(NET_BUFFER_LIMIT_PROP_KEY);\n\t\t}\n\t\tif (props.get(TRAFFIC_THROTTLING_PROP_KEY) != null) {\n\t\t\tString[] tmp = ((String) props.get(TRAFFIC_THROTTLING_PROP_KEY)).split(\",\");\n\n\t\t\tfor (String tmp_s : tmp) {\n\t\t\t\tString[] tmp_thr = tmp_s.split(\":\");\n\n\t\t\t\tif (tmp_thr[0].equalsIgnoreCase(\"xmpp\")) {\n\t\t\t\t\tlast_minute_packets_limit = DataTypes.parseNum(tmp_thr[1], Long.class,\n\t\t\t\t\t\t\tLAST_MINUTE_PACKETS_LIMIT_PROP_VAL);\n\t\t\t\t\tlog.warning(getName() + \" last_minute_packets_limit = \" +\n\t\t\t\t\t\t\tlast_minute_packets_limit);\n\t\t\t\t\ttotal_packets_limit = DataTypes.parseNum(tmp_thr[2], Long.class,\n\t\t\t\t\t\t\tTOTAL_PACKETS_LIMIT_PROP_VAL);\n\t\t\t\t\tlog.warning(getName() + \" total_packets_limit = \" + total_packets_limit);\n\t\t\t\t\tif (tmp_thr[3].equalsIgnoreCase(\"disc\")) {\n\t\t\t\t\t\txmppLimitAction = LIMIT_ACTION.DISCONNECT;\n\t\t\t\t\t}\n\t\t\t\t\tif (tmp_thr[3].equalsIgnoreCase(\"drop\")) {\n\t\t\t\t\t\txmppLimitAction = LIMIT_ACTION.DROP_PACKETS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tmp_thr[0].equalsIgnoreCase(\"bin\")) {\n\t\t\t\t\tlast_minute_bin_limit = DataTypes.parseNum(tmp_thr[1], Long.class,\n\t\t\t\t\t\t\tLAST_MINUTE_BIN_LIMIT_PROP_VAL);\n\t\t\t\t\tlog.warning(getName() + \" last_minute_bin_limit = \" + last_minute_bin_limit);\n\t\t\t\t\ttotal_bin_limit = DataTypes.parseNum(tmp_thr[2], Long.class,\n\t\t\t\t\t\t\tTOTAL_BIN_LIMIT_PROP_VAL);\n\t\t\t\t\tlog.warning(getName() + \" total_bin_limit = \" + total_bin_limit);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( props.get (ELEMENTS_NUMBER_LIMIT_PROP_KEY ) != null ){\n\t\t\telements_number_limit = (int) props.get (ELEMENTS_NUMBER_LIMIT_PROP_KEY );\n\t\t}\n\n\t\tif ( props.get( WATCHDOG_DELAY ) != null ){\n\t\t\twatchdogDelay =  (long) props.get( WATCHDOG_DELAY );\n\t\t}\n\t\tif ( props.get( WATCHDOG_TIMEOUT ) != null ){\n\t\t\twatchdogTimeout =  (long) props.get( WATCHDOG_TIMEOUT );\n\t\t}\n\t\tif ( props.get( WATCHDOG_PING_TYPE_KEY ) != null ){\n\t\t\tString value = String.valueOf( props.get( WATCHDOG_PING_TYPE_KEY ) );\n\t\t\twatchdogPingType = WATCHDOG_PING_TYPE.valueOf( value.toUpperCase() );\n\t\t}\n\n\t\tif (props.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update and\n\t\t\t// ConnectionManager does not support it yet.\n\t\t\treturn;\n\t\t}\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\t// Looks like reconfiguration for the port is not working correctly anyway\n\t\t\t// so for now we do not want to do it.\n\t\t\treturn;\n\t\t}\n\t\treleaseListeners();\n\n\t\tint[] ports = (int[]) props.get(PORTS_PROP_KEY);\n\n\t\tif (ports != null) {\n\t\t\tfor (int i = 0; i < ports.length; i++) {\n\t\t\t\tMap<String, Object> port_props = new LinkedHashMap<String, Object>(20);\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\t\tif (entry.getKey().startsWith(PROP_KEY + ports[i])) {\n\t\t\t\t\t\tint    idx = entry.getKey().lastIndexOf('/');\n\t\t\t\t\t\tString key = entry.getKey().substring(idx + 1);\n\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Adding port property key: {0}={1}\", new Object[] { key,\n\t\t\t\t\t\t\t\tentry.getValue() });\n\t\t\t\t\t\tport_props.put(key, entry.getValue());\n\t\t\t\t\t}    // end of if (entry.getKey().startsWith())\n\t\t\t\t}      // end of for ()\n\t\t\t\tport_props.put(PORT_KEY, ports[i]);\n\t\t\t\tif (port_props.containsKey(PORT_TYPE_PROP_KEY) \n\t\t\t\t\t\t&& !(port_props.get(PORT_TYPE_PROP_KEY) instanceof ConnectionType)) {\n\t\t\t\t\tObject val = port_props.get(PORT_TYPE_PROP_KEY);\n\t\t\t\t\tport_props.put(PORT_TYPE_PROP_KEY, ConnectionType.valueOf(val.toString()));\n\t\t\t\t}\n\t\t\t\tif (port_props.containsKey(PORT_SOCKET_PROP_KEY) \n\t\t\t\t\t\t&& !(port_props.get(PORT_SOCKET_PROP_KEY) instanceof SocketType)) {\n\t\t\t\t\tObject val = port_props.get(PORT_SOCKET_PROP_KEY);\n\t\t\t\t\tport_props.put(PORT_SOCKET_PROP_KEY, SocketType.valueOf(val.toString()));\n\t\t\t\t}\t\t\t\t\n\t\t\t\taddWaitingTask(port_props);\n\t\t\t\t// reconnectService(port_props, startDelay);\n\t\t\t}        // end of for (int i = 0; i < ports.length; i++)\n\t\t}          // end of if (ports != null)\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param conn\n\t */\n\tprotected void addWaitingTask(Map<String, Object> conn) {\n\t\tif (initializationCompleted) {\n\t\t\treconnectService(conn, connectionDelay);\n\t\t} else {\n\t\t\twaitingTasks.add(conn);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ht_def_key\n\t * @param ht_dev_val\n\t * @param st_def_key\n\t * @param st_def_val\n\t * @param prop_key\n\t * @param prop_val_class\n\t * @param params\n\t * @param props\n\t * @param <T>\n\t */\n\tprotected <T> void checkHighThroughputProperty(String ht_def_key, T ht_dev_val,\n\t\t\tString st_def_key, T st_def_val, String prop_key, Class<T> prop_val_class,\n\t\t\tMap<String, Object> params, Map<String, Object> props) {\n\t\tT tmp = st_def_val;\n\t\tString str_tmp = null;\n\n\t\tif (isHighThroughput()) {\n\t\t\ttmp = ht_dev_val;\n\t\t\tstr_tmp = (String) params.get(ht_def_key);\n\t\t} else {\n\t\t\ttmp = st_def_val;\n\t\t\tstr_tmp = (String) params.get(st_def_key);\n\t\t}\n\t\tif (tmp == null)\n\t\t\ttmp = st_def_val;\n\n\t\tif (str_tmp != null) {\n\t\t\tif (prop_val_class.isAssignableFrom(Integer.class)) {\n\t\t\t\ttmp = prop_val_class.cast(DataTypes.parseNum(str_tmp, Integer.class,\n\t\t\t\t\t\t(Integer) tmp));\n\t\t\t}\n\t\t\tif (prop_val_class.isAssignableFrom(Long.class)) {\n\t\t\t\ttmp = prop_val_class.cast(DataTypes.parseNum(str_tmp, Long.class, (Long) tmp));\n\t\t\t}\n\t\t\tif (prop_val_class.isAssignableFrom(String.class)) {\n\t\t\t\ttmp = prop_val_class.cast(str_tmp);\n\t\t\t}\n\t\t}\n\t\tprops.put(prop_key, tmp);\n\n\t}\n\n\t/**\n\t * Returns number of active network connections (IOServices).\n\t *\n\t * @return number of active network connections (IOServices).\n\t */\n\tprotected int countIOServices() {\n\t\treturn services.size();\n\t}\n\n\t/**\n\t * Perform a given action defined by ServiceChecker for all active IOService\n\t * objects (active network connections).\n\t *\n\t * @param checker\n\t *          is a <code>ServiceChecker</code> instance defining an action to\n\t *          perform for all IOService objects.\n\t */\n\tprotected void doForAllServices(ServiceChecker<IO> checker) {\n\t\tfor (IO service : services.values()) {\n\t\t\tchecker.check(service);\n\t\t}\n\t}\n\n\t/**\n\t *\n\t * @param p\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean writePacketToSocket(Packet p) {\n\t\tIO ios = getXMPPIOService(p);\n\n\t\tif (ios != null) {\n\t\t\treturn writePacketToSocket(ios, p);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param p\n\t * @param serviceId\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean writePacketToSocket(Packet p, String serviceId) {\n\t\tIO ios = getXMPPIOService(serviceId);\n\n\t\tif (ios != null) {\n\t\t\treturn writePacketToSocket(ios, p);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ios\n\t * @param data\n\t */\n\tprotected void writeRawData(IO ios, String data) {\n\t\ttry {\n\t\t\tios.writeRawData(data);\n\t\t\tSocketThread.addSocketService(ios);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, ios + \"Exception during writing data: \" + data, e);\n\t\t\ttry {\n\t\t\t\tios.stop();\n\t\t\t} catch (Exception e1) {\n\t\t\t\tlog.log(Level.WARNING, ios + \"Exception stopping XMPPIOService: \", e1);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>int[]</code>\n\t */\n\tprotected int[] getDefPlainPorts() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>int[]</code>\n\t */\n\tprotected int[] getDefSSLPorts() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tprotected String getDefTrafficThrottling() {\n\t\tString result = ST_TRAFFIC_THROTTLING_PROP_VAL;\n\n\t\tif (isHighThroughput()) {\n\t\t\tresult = HT_TRAFFIC_THROTTLING_PROP_VAL;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tprotected abstract long getMaxInactiveTime();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param port\n\t *\n\t *\n\t *\n\t * @return a value of {@code Map<String,Object>}\n\t */\n\tprotected Map<String, Object> getParamsForPort(int port) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tprotected String getServiceId(Packet packet) {\n\t\treturn getServiceId(packet.getTo());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tprotected String getServiceId(JID jid) {\n\t\treturn jid.getResource();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tprotected String getUniqueId(IO serv) {\n\t\treturn serv.getUniqueId();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param p\n\t *\n\t *\n\t *\n\t * @return a value of <code>IO</code>\n\t */\n\tprotected IO getXMPPIOService(Packet p) {\n\t\tString id = getServiceId(p);\n\n\t\tif (id != null) {\n\t\t\treturn services.get(id);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>IO</code>\n\t */\n\tprotected abstract IO getXMPPIOServiceInstance();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tprotected boolean isHighThroughput() {\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected void socketAccepted(IO serv, SocketType type) {\n\t}\n\t\n\tprivate void putDefPortParams(Map<String, Object> props, int port, SocketType sock) {\n\t\tlog.log(Level.CONFIG, \"Generating defaults for port: {0,number,#}\", port);\n\t\tprops.put(PROP_KEY + port + \"/\" + PORT_TYPE_PROP_KEY, ConnectionType.accept);\n\t\tprops.put(PROP_KEY + port + \"/\" + PORT_SOCKET_PROP_KEY, sock);\n\t\tprops.put(PROP_KEY + port + \"/\" + PORT_IFC_PROP_KEY, PORT_IFC_PROP_VAL);\n\t\tprops.put(PROP_KEY + port + \"/\" + PORT_REMOTE_HOST_PROP_KEY,\n\t\t\t\tPORT_REMOTE_HOST_PROP_VAL);\n\t\tprops.put(PROP_KEY + port + \"/\" + TLS_REQUIRED_PROP_KEY, TLS_REQUIRED_PROP_VAL);\n\n\t\tMap<String, Object> extra = getParamsForPort(port);\n\n\t\tif (extra != null) {\n\t\t\tfor (Map.Entry<String, Object> entry : extra.entrySet()) {\n\t\t\t\tprops.put(PROP_KEY + port + \"/\" + entry.getKey(), entry.getValue());\n\t\t\t}    // end of for ()\n\t\t}      // end of if (extra != null)\n\t}\n\n\tprivate void reconnectService(final Map<String, Object> port_props, long delay) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tString cid = \"\" + port_props.get(\"local-hostname\") + \"@\" + port_props.get(\n\t\t\t\t\t\"remote-hostname\");\n\n\t\t\tlog.log(Level.FINER,\n\t\t\t\t\t\"Reconnecting service for: {0}, scheduling next try in {1}secs, cid: {2}, props: {3}\",\n\t\t\t\t\tnew Object[] { getName(), delay / 1000, cid, port_props });\n\t\t}\n\t\taddTimerTask(new tigase.util.TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tString host = (String) port_props.get(PORT_REMOTE_HOST_PROP_KEY);\n\n\t\t\t\tif (host == null) {\n\t\t\t\t\thost = (String) port_props.get(\"remote-hostname\");\n\t\t\t\t}\n\n\t\t\t\tint port = (Integer) port_props.get(PORT_KEY);\n\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\"Reconnecting service for component: {0}, to remote host: {1} on port: {2,number,#}\",\n\t\t\t\t\t\t\tnew Object[] { getName(),\n\t\t\t\t\t\t\thost, port });\n\t\t\t\t}\n\t\t\t\tstartService(port_props);\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\tprivate void releaseListeners() {\n\t\tfor (ConnectionListenerImpl cli : pending_open) {\n\t\t\tconnectThread.removeConnectionOpenListener(cli);\n\t\t}\n\t\tpending_open.clear();\n\t}\n\n\tprivate void startService(Map<String, Object> port_props) {\n\t\tif (port_props == null) {\n\t\t\tthrow new NullPointerException(\"port_props cannot be null.\");\n\t\t}\n\n\t\tConnectionListenerImpl cli = new ConnectionListenerImpl(port_props);\n\n\t\tif (cli.getConnectionType() == ConnectionType.accept) {\n\t\t\tpending_open.add(cli);\n\t\t}\n\t\tconnectThread.addConnectionOpenListener(cli);\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class ConnectionListenerImpl\n\t\t\t\t\timplements ConnectionOpenListener {\n\t\tprivate Map<String, Object> port_props = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate ConnectionListenerImpl(Map<String, Object> port_props) {\n\t\t\tthis.port_props = port_props;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void accept(SocketChannel sc) {\n\t\t\tString cid = \"\" + port_props.get(\"local-hostname\") + \"@\" + port_props.get(\n\t\t\t\t\t\"remote-hostname\");\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Accept called for service: {0}, port_props: {1}\", new Object[] {cid, port_props} );\n\t\t\t}\n\n\t\t\tIO serv = getXMPPIOServiceInstance();\n\t\t\tserv.setBufferLimit( net_buffer_limit );\n\n\t\t\t( (XMPPDomBuilderHandler) serv.getSessionData().get( DOM_HANDLER ) ).setElementsLimit( elements_number_limit );\n\n\t\t\tserv.setIOServiceListener(ConnectionManager.this);\n\t\t\tserv.setSessionData(port_props);\n\t\t\ttry {\n\t\t\t\tserv.accept(sc);\n\t\t\t\tsocketAccepted(serv, getSocketType());\n\t\t\t\tif (getSocketType() == SocketType.ssl) {\n\t\t\t\t\tserv.startSSL(false, false, false);\n\t\t\t\t}    // end of if (socket == SocketType.ssl)\n\t\t\t\tserviceStarted(serv);\n\t\t\t\tSocketThread.addSocketService(serv);\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (getConnectionType() == ConnectionType.connect) {\n\n\t\t\t\t\t// Accept side for component service is not ready yet?\n\t\t\t\t\t// Let's wait for a few secs and try again.\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Problem reconnecting the service: {0}, port_props: {1}, exception: {2}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv, port_props, e });\n\t\t\t\t\t}\n\t\t\t\t\tupdateConnectionDetails(port_props);\n\n\t\t\t\t\tboolean reconnect  = false;\n\t\t\t\t\tInteger reconnects = (Integer) port_props.get(MAX_RECONNECTS_PROP_KEY);\n\n\t\t\t\t\tif (reconnects != null) {\n\t\t\t\t\t\tint recon = reconnects.intValue();\n\n\t\t\t\t\t\tif (recon != 0) {\n\t\t\t\t\t\t\tport_props.put(MAX_RECONNECTS_PROP_KEY, (--recon));\n\t\t\t\t\t\t\treconnect = true;\n\t\t\t\t\t\t}    // end of if (recon != 0)\n\t\t\t\t\t}\n\t\t\t\t\tif (reconnect) {\n\t\t\t\t\t\treconnectService(port_props, connectionDelay);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treconnectionFailed(port_props);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\n//      } catch (Exception e) {\n//        if (log.isLoggable(Level.FINEST)) {\n//          log.log(Level.FINEST, \"Can not accept connection cid: \" + cid, e);\n//        }\n//        log.log(Level.WARNING, \"Can not accept connection.\", e);\n//        serv.stop();\n\t\t\t}          // end of try-catch\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn port_props.toString();\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic ConnectionType getConnectionType() {\n\t\t\tString type = null;\n\n\t\t\tif (port_props.get(PORT_TYPE_PROP_KEY) == null) {\n\t\t\t\tlog.warning(getName() + \": connection type is null: \" + port_props.get(PORT_KEY)\n\t\t\t\t\t\t.toString());\n\t\t\t} else {\n\t\t\t\ttype = port_props.get(PORT_TYPE_PROP_KEY).toString();\n\t\t\t}\n\n\t\t\treturn ConnectionType.valueOf(type);\n\t\t}\n\n\t\t@Override\n\t\tpublic String[] getIfcs() {\n\t\t\treturn (String[]) port_props.get(PORT_IFC_PROP_KEY);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getPort() {\n\t\t\treturn (Integer) port_props.get(PORT_KEY);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getReceiveBufferSize() {\n\t\t\treturn net_buffer;\n\t\t}\n\n\t\t@Override\n\t\tpublic InetSocketAddress getRemoteAddress() {\n\t\t\treturn (InetSocketAddress) port_props.get(\"remote-address\");\n\t\t}\n\n\t\t@Override\n\t\tpublic String getRemoteHostname() {\n\t\t\tif (port_props.containsKey(PORT_REMOTE_HOST_PROP_KEY)) {\n\t\t\t\treturn (String) port_props.get(PORT_REMOTE_HOST_PROP_KEY);\n\t\t\t}\n\n\t\t\treturn (String) port_props.get(\"remote-hostname\");\n\t\t}\n\n\t\t@Override\n\t\tpublic SocketType getSocketType() {\n\t\t\treturn SocketType.valueOf(port_props.get(PORT_SOCKET_PROP_KEY).toString());\n\t\t}\n\n\t\t@Override\n\t\tpublic String getSRVType() {\n\t\t\tString type = (String) this.port_props.get(\"srv-type\");\n\n\t\t\tif ((type == null) || type.isEmpty()) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn type;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getTrafficClass() {\n\t\t\tif (isHighThroughput()) {\n\t\t\t\treturn IPTOS_THROUGHPUT;\n\t\t\t} else {\n\t\t\t\treturn DEF_TRAFFIC_CLASS;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tprivate class IOServiceStatisticsGetter\n\t\t\t\t\timplements ServiceChecker<IO> {\n\t\tprivate StatisticsList list = new StatisticsList(Level.ALL);\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic synchronized void check(IO service) {\n\t\t\tbytesReceived  += service.getBytesReceived(true);\n\t\t\tbytesSent      += service.getBytesSent(true);\n\t\t\tsocketOverflow += service.getBuffOverflow(true);\n\t\t\tservice.getPacketsReceived(true);\n\t\t\tservice.getPacketsSent(true);\n\n\t\t\t// service.getStatistics(list, true);\n\t\t\t// bytesReceived += list.getValue(\"socketio\", \"Bytes received\", -1l);\n\t\t\t// bytesSent += list.getValue(\"socketio\", \"Bytes sent\", -1l);\n\t\t\t// socketOverflow += list.getValue(\"socketio\", \"Buffers overflow\", -1l);\n\t\t}\n\t}\n\n\t/**\n\t * Class looks in all established connections and checks whether any of them\n\t * is dead by performing either whitspace or XMPP ping. If client fails to\n\t * respond within defined time then the service is stopped.\n\t *\n\t */\n\tprotected class Watchdog\n\t\t\t\t\timplements Runnable {\n\n\t\tPacket pingPacket;\n\t\t\n\t\tprotected long getDurationSinceLastTransfer(final XMPPIOService service) {\n\t\t\tlong curr_time = System.currentTimeMillis();\n\t\t\tlong lastTransfer;\n\t\t\tswitch (watchdogPingType) {\n\t\t\t\tcase XMPP:\n\t\t\t\t\tlastTransfer = service.getLastXmppPacketReceiveTime();\n\t\t\t\t\tbreak;\n\t\t\t\tcase WHITESPACE:\n\t\t\t\tdefault:\n\t\t\t\t\tlastTransfer = service.getLastTransferTime();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn curr_time - lastTransfer;\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Sleep...\n\t\t\t\t\tThread.sleep(watchdogDelay);\n\t\t\t\t\t++watchdogRuns;\n\n\t\t\t\t\t/** Walk through all connections and check whether they are really\n\t\t\t\t\t * alive. Depending on the configuration send either whitespace or\n\t\t\t\t\t * XMPP ping if the service is inactive for the configured period of\n\t\t\t\t\t * time\n\t\t\t\t\t */\n\t\t\t\t\tdoForAllServices(new ServiceChecker<IO>() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void check(final XMPPIOService service) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif ( null != service ){\n\t\t\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Testing service: {0}, sinceLastTransfer: {1}, maxInactivityTime: {2}, watchdogTimeout: {3}, watchdogDelay: {4}, watchdogPingType: {5} \",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { service, getDurationSinceLastTransfer( service ), maxInactivityTime, watchdogTimeout, watchdogDelay, watchdogPingType } );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlong sinceLastTransfer = getDurationSinceLastTransfer(service);\n\t\t\t\t\t\t\t\t\tif ( sinceLastTransfer >= maxInactivityTime ){\n\n\t\t\t\t\t\t\t\t\t\t// Stop the service if max keep-alive time is exceeded\n\t\t\t\t\t\t\t\t\t\t// for non-active connections.\n\t\t\t\t\t\t\t\t\t\tif ( log.isLoggable( Level.INFO ) ){\n\t\t\t\t\t\t\t\t\t\t\tlog.log( Level.INFO,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"{0}: Max inactive time exceeded, stopping: {1} ( sinceLastTransfer: {2}, maxInactivityTime: {3}, watchdogTimeout: {4}, watchdogDelay: {5}, watchdogPingType: {6} )\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { getName(), service, getDurationSinceLastTransfer( service ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmaxInactivityTime, watchdogTimeout, watchdogDelay, watchdogPingType } );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t++watchdogStopped;\n\t\t\t\t\t\t\t\t\t\tservice.stop();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif ( sinceLastTransfer >= ( watchdogTimeout ) ){\n\n\t\t\t\t\t\t\t\t\t\t\t/** At least once every configured timings check if the\n\t\t\t\t\t\t\t\t\t\t\t * connection is still alive with the use of configured\n\t\t\t\t\t\t\t\t\t\t\t * ping type. */\n\t\t\t\t\t\t\t\t\t\t\tswitch ( watchdogPingType ) {\n\t\t\t\t\t\t\t\t\t\t\t\tcase XMPP:\n\t\t\t\t\t\t\t\t\t\t\t\t\tpingPacket = Iq.packetInstance( pingElement.clone(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tJID.jidInstanceNS( (String) service.getSessionData().get( XMPPIOService.HOSTNAME_KEY ) ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tJID.jidInstanceNS( service.getUserJid() ) );\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, sending XMPP ping {1}\", new Object[] { service, pingPacket });\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( !writePacketToSocket( (IO) service, pingPacket ) ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// writing failed, stopp service\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t++watchdogStopped;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tservice.stop();\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\t\t\tcase WHITESPACE:\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Sending whitespace ping for service {0}\", new Object[] { service });\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tservice.writeRawData( \" \" );\n\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t++watchdogTests;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch ( IOException e ) {\n\n\t\t\t\t\t\t\t\t// Close the service\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif ( service != null ){\n\t\t\t\t\t\t\t\t\t\tlog.info( getName() + \"Found dead connection, stopping: \" + service );\n\t\t\t\t\t\t\t\t\t\t++watchdogStopped;\n\t\t\t\t\t\t\t\t\t\tservice.forceStop();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch ( Exception ignore ) {\n\t\t\t\t\t\t\t\t\t// Do nothing here as we expect Exception to be thrown here...\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t} catch ( InterruptedException e ) {    /* Do nothing here */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n}    // ConnectionManager\n\n\n//~ Formatted in Tigase Code Convention on 13/10/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/DataForm.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.server;\n\nimport tigase.server.Command.DataType;\n\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Logger;\n\n/**\n *\n * @author Wojciech Kapcia\n */\npublic class DataForm {\n\n\tpublic static final String FIELD_EL = \"field\";\n\tpublic static final String VALUE_EL = \"value\";\n\tprotected static final String[] FIELD_VALUE_PATH = { FIELD_EL, VALUE_EL };\n\n\tprivate static final Logger log = Logger.getLogger( DataForm.class.getName() );\n\n\t/**\n\t * Data form-types as defined in the XEP-0050.\n\t */\n\n\tpublic static void addCheckBoxField(final Element el, String f_name, boolean f_value) {\n\t\tDataForm.addFieldValue(el, f_name, Boolean.toString(f_value), \"boolean\");\n\t}\n\n\tpublic static Element addDataForm( Element el, DataType data_type ) {\n\t\tElement x = new Element( \"x\", new String[] { \"xmlns\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"jabber:x:data\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata_type.name() } );\n\n\t\tel.addChild( x );\n\n\t\treturn x;\n\t}\n\n\tpublic static void addFieldMultiValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final List<String> f_value ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.result );\n\t\t}\n\t\tif ( f_value != null ){\n\t\t\tElement field = new Element( FIELD_EL, new String[] { \"var\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"text-multi\" } );\n\n\t\t\tfor ( String val : f_value ) {\n\t\t\t\tif ( val != null ){\n\t\t\t\t\tElement value = new Element( VALUE_EL, XMLUtils.escape( val ) );\n\n\t\t\t\t\tfield.addChild( value );\n\t\t\t\t}\n\t\t\t}\n\t\t\tx.addChild( field );\n\t\t}\n\t}\n\n\tpublic static void addFieldMultiValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final Throwable ex ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tList<String> f_value = null;\n\n\t\tif ( ex != null ){\n\t\t\tf_value = new ArrayList<String>( 100 );\n\t\t\tf_value.add( ex.getLocalizedMessage() );\n\t\t\tfor ( StackTraceElement ste : ex.getStackTrace() ) {\n\t\t\t\tf_value.add( \"  \" + ste.toString() );\n\t\t\t}\n\t\t}\n\t\tif ( f_value != null ){\n\t\t\tElement field = new Element( FIELD_EL, new String[] { \"var\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"text-multi\" } );\n\n\t\t\tfor ( String val : f_value ) {\n\t\t\t\tif ( val != null ){\n\t\t\t\t\tElement value = new Element( VALUE_EL, XMLUtils.escape( val ) );\n\n\t\t\t\t\tfield.addChild( value );\n\t\t\t\t}\n\t\t\t}\n\t\t\tx.addChild( field );\n\t\t}\n\t}\n\n\tpublic static void addField( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_label, final String type ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\", \"type\", \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ), type, f_label } );\n\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_value ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( f_value ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ) } );\n\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_value, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] labels, final String[] options ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( f_value ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\", \"type\", \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ), \"list-single\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXMLUtils.escape( label ) } );\n\n\t\tfor ( int i = 0 ; i < labels.length ; i++ ) {\n\t\t\tfield.addChild( new Element( \"option\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( options[i] ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( labels[i] ) } ) );\n\t\t}\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] f_values, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] labels, final String[] options ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL, new String[] { \"var\", \"type\", \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"list-multi\", XMLUtils.escape( label ) } );\n\n\t\tfor ( int i = 0 ; i < labels.length ; i++ ) {\n\t\t\tfield.addChild( new Element( \"option\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( options[i] ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( labels[i] ) } ) );\n\t\t}\n\t\tfor ( int i = 0 ; i < f_values.length ; i++ ) {\n\t\t\tfield.addChild( new Element( VALUE_EL, XMLUtils.escape( f_values[i] ) ) );\n\t\t}\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_value, final String label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String[] labels, final String[] options,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String type ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( f_value ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\", \"type\", \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ), type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXMLUtils.escape( label ) } );\n\n\t\tfor ( int i = 0 ; i < labels.length ; i++ ) {\n\t\t\tfield.addChild( new Element( \"option\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( options[i] ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( labels[i] ) } ) );\n\t\t}\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_value, final String type ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( f_value ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ), type } );\n\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addFieldValue( final Element el, final String f_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String f_value, final String type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String label ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\n\t\tElement field = new Element( FIELD_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element( VALUE_EL, XMLUtils.escape( f_value ) ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\", \"type\", \"label\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLUtils.escape( f_name ), type, XMLUtils.escape( label ) } );\n\n\t\tx.addChild( field );\n\t}\n\n\tpublic static void addHiddenField( final Element el, String f_name, String f_value ) {\n\t\taddFieldValue( el, f_name, f_value, \"hidden\" );\n\t}\n\n\tpublic static void addInstructions( final Element el, final String instructions ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\t\tx.addChild( new Element( \"instructions\", instructions ) );\n\t}\n\n\n\tpublic static void addTextField( final Element el, String f_name, String f_value ) {\n\t\taddFieldValue( el, f_name, f_value, \"fixed\" );\n\t}\n\n\tpublic static void addTitle( final Element el, final String title ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x == null ){\n\t\t\tx = addDataForm( el, DataType.submit );\n\t\t}\n\t\tx.addChild( new Element( \"title\", title ) );\n\t}\n\n\tpublic static String getFieldValue( final Element el, String f_name ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x != null ){\n\t\t\tList<Element> children = x.getChildren();\n\n\t\t\tif ( children != null ){\n\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\tif ( child.getName().equals( FIELD_EL )\n\t\t\t\t\t\t\t && child.getAttributeStaticStr( \"var\" ).equals( f_name ) ){\n\t\t\t\t\t\tString value = child.getChildCDataStaticStr( FIELD_VALUE_PATH );\n\n\t\t\t\t\t\tif ( value != null ){\n\t\t\t\t\t\t\treturn XMLUtils.unescape( value );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static String[] getFieldValues( final Element el, final String f_name ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x != null ){\n\t\t\tList<Element> children = x.getChildren();\n\n\t\t\tif ( children != null ){\n\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\tif ( child.getName().equals( FIELD_EL )\n\t\t\t\t\t\t\t && child.getAttributeStaticStr( \"var\" ).equals( f_name ) ){\n\t\t\t\t\t\tList<String> values = new LinkedList<String>();\n\t\t\t\t\t\tList<Element> val_children = child.getChildren();\n\n\t\t\t\t\t\tif ( val_children != null ){\n\t\t\t\t\t\t\tfor ( Element val_child : val_children ) {\n\t\t\t\t\t\t\t\tif ( val_child.getName().equals( VALUE_EL ) ){\n\t\t\t\t\t\t\t\t\tString value = val_child.getCData();\n\n\t\t\t\t\t\t\t\t\tif ( value != null ){\n\t\t\t\t\t\t\t\t\t\tvalues.add( XMLUtils.unescape( value ) );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn values.toArray( new String[ 0 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static boolean removeFieldValue( final Element el, final String f_name ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x != null ){\n\t\t\tList<Element> children = x.getChildren();\n\n\t\t\tif ( children != null ){\n\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\tif ( child.getName().equals( FIELD_EL )\n\t\t\t\t\t\t\t && child.getAttributeStaticStr( \"var\" ).equals( f_name ) ){\n\t\t\t\t\t\treturn x.removeChild( child );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic static String getFieldKeyStartingWith( final Element el, String f_name ) {\n\t\tElement x = el.getChild( \"x\", \"jabber:x:data\" );\n\n\t\tif ( x != null ){\n\t\t\tList<Element> children = x.getChildren();\n\n\t\t\tif ( children != null ){\n\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\tif ( child.getName().equals( FIELD_EL )\n\t\t\t\t\t\t\t && child.getAttributeStaticStr( \"var\" ).startsWith( f_name ) ){\n\t\t\t\t\t\treturn child.getAttributeStaticStr( \"var\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/DisableDisco.java",
    "content": "/*\n * DisableDisco.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n/**\n * Disables service discovery processing for a component implementing this interface.\n *\n *\n * @version  13/03/04\n * @author   <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface DisableDisco {}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/04\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Iq.java",
    "content": "/*\n * Iq.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.disco.XMPPService;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\n\n/**\n * Created: Dec 31, 2009 8:43:21 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Iq\n\t\t\t\textends Packet {\n\t/** Field description */\n\tpublic static final String ELEM_NAME = \"iq\";\n\n\t/** Field description */\n\tpublic static final String QUERY_NAME = \"query\";\n\n\t/** Field description */\n\tpublic static final String[] IQ_QUERY_PATH = { ELEM_NAME, QUERY_NAME };\n\n\t/** Field description */\n\tpublic static final String[] IQ_PUBSUB_PATH = { ELEM_NAME, \"pubsub\" };\n\n\t/** Field description */\n\tpublic static final String[] IQ_ERROR_PATH = { ELEM_NAME, \"error\" };\n\n\t/** Field description */\n\tpublic static final String[] IQ_COMMAND_PATH = { ELEM_NAME, \"command\" };\n\n\t/** Field description */\n\tpublic static final String[] IQ_CHAT_PATH = { ELEM_NAME, \"chat\" };\n\n\t/** Field description */\n\tpublic static final String[] IQ_BIND_RESOURCE_PATH = { ELEM_NAME, \"bind\", \"resource\" };\n\n\t/** Field description */\n\tpublic static final String[] IQ_BIND_PATH = { ELEM_NAME, \"bind\" };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Command command      = null;\n\tprivate String iqQueryXMLNS  = null;\n\tprivate String strCommand    = null;\n\tprivate boolean serviceDisco = false;\n\tprivate boolean cmd          = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic Iq(Element elem) throws TigaseStringprepException {\n\t\tsuper(elem);\n\t\tinit();\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t * @param stanzaFrom\n\t * @param stanzaTo\n\t */\n\tpublic Iq(Element elem, JID stanzaFrom, JID stanzaTo) {\n\t\tsuper(elem, stanzaFrom, stanzaTo);\n\t\tinit();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic static Packet commandResultForm(Iq packet) throws TigaseStringprepException {\n\t\tPacket result = packet.commandResult(Command.DataType.form);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic static Packet commandResultResult(Iq packet) throws TigaseStringprepException {\n\t\tPacket result = packet.commandResult(Command.DataType.result);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description creates a new <code>Packet</code> instance or <code>Iq</code>\n\t * instance more specificly with a roster entry content.\n\t * TODO: Remove dependency on RosterAbstract class, possibly move the method again\n\t * to more proper location but it needs to be accessible from all parts of the application.\n\t *\n\t * @param iq_type is a <code>String</code> value with the stanza type: 'set', 'get',\n\t * 'result'.\n\t * @param iq_id is a <code>String</code> value with the stanza unique id.\n\t * @param from is a <code>JID</code> instance with the packet source address.\n\t * @param to is a <code>JID</code> instance with the packet destination address.\n\t * @param item_jid is a <code>JID</code> instance with the roster item JID, note in most\n\t * cases the jid should not have a resource part, but this method does not cut it off. This\n\t * is because there are cases when we want to have a resource part in the roster item.\n\t * @param item_name is a <code>String</code> vakue with the roster item name.\n\t * @param item_groups is a <code>String[]</code> array with all groups the item belongs\n\t * to.\n\t * @param subscription is a <code>String</code> instance with the item subscription state.\n\t * @param item_type is a <code>String</code> of the user item type. This is\n\t * <code>null</code> in most cases as this is not part of the XMPP RFC. Some deployments\n\t * needs some extra information about the roster item type though.\n\t *\n\t * @return a new <code>Packet</code> instance or <code>Iq</code> instance more\n\t * specificly with a roster entry content.\n\t */\n\tpublic static Iq createRosterPacket(String iq_type, String iq_id, JID from, JID to,\n\t\t\t\t\tJID item_jid, String item_name, String[] item_groups, String subscription,\n\t\t\t\t\tString item_type) {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\", \"id\" }, new String[] { iq_type,\n\t\t\t\t\t\tiq_id });\n\n\t\tiq.setXMLNS(CLIENT_XMLNS);\n\t\tif (from != null) {\n\t\t\tiq.addAttribute(\"from\", from.toString());\n\t\t}\n\t\tif (to != null) {\n\t\t\tiq.addAttribute(\"to\", to.toString());\n\t\t}\n\n\t\tElement query = new Element(\"query\");\n\n\t\tquery.setXMLNS(RosterAbstract.XMLNS);\n\t\tiq.addChild(query);\n\n\t\tElement item = new Element(\"item\", new String[] { \"jid\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { item_jid.toString() });\n\n\t\tif (item_type != null) {\n\t\t\titem.addAttribute(\"type\", item_type);\n\t\t}\n\t\tif (item_name != null) {\n\t\t\titem.addAttribute(RosterAbstract.NAME, item_name);\n\t\t}\n\t\tif (subscription != null) {\n\t\t\titem.addAttribute(RosterAbstract.SUBSCRIPTION, subscription);\n\t\t}\n\t\tif (item_groups != null) {\n\t\t\tfor (String gr : item_groups) {\n\t\t\t\tElement group = new Element(RosterAbstract.GROUP, gr);\n\n\t\t\t\titem.addChild(group);\n\t\t\t}\n\t\t}\n\t\tquery.addChild(item);\n\n\t\treturn new Iq(iq, from, to);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cmd_type\n\t *\n\t * \n\t */\n\tpublic Packet commandResult(Command.DataType cmd_type) {\n\t\tPacket result = packetInstance(command.createIqCommand(getStanzaTo(),\n\t\t\t\t\t\t\t\t\t\t\tgetStanzaFrom(), StanzaType.result, getStanzaId(), strCommand,\n\t\t\t\t\t\t\t\t\t\t\tcmd_type), getStanzaTo(), getStanzaFrom());\n\n\t\tresult.setPacketFrom(getTo());\n\t\tresult.setPacketTo(getFrom());\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Command getCommand() {\n\t\treturn command;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getIQChildName() {\n\t\tList<Element> children = elem.getChildren();\n\n\t\tif ((children != null) && (children.size() > 0)) {\n\t\t\treturn children.get(0).getName();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getIQXMLNS() {\n\t\tif (iqQueryXMLNS == null) {\n\t\t\tiqQueryXMLNS = elem.getXMLNSStaticStr(IQ_QUERY_PATH);\n\t\t}\n\n\t\treturn iqQueryXMLNS;\n\t}\n\n\t@Override\n\tprotected String[] getElNameErrorPath() {\n\t\treturn IQ_ERROR_PATH;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getStrCommand() {\n\t\treturn strCommand;\n\t}\n\n\t@Override\n\tpublic boolean isCommand() {\n\t\treturn cmd;\n\t}\n\n\t@Override\n\tpublic boolean isServiceDisco() {\n\t\treturn serviceDisco;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void init() {\n\t\tElement child = elem.getChild(\"command\", Command.XMLNS);\n\n\t\tif (child != null) {\n\t\t\tcmd        = true;\n\t\t\tstrCommand = child.getAttributeStaticStr(\"node\");\n\t\t\tcommand    = Command.valueof(strCommand);\n\t\t}\n\t\tserviceDisco = (isXMLNSStaticStr(IQ_QUERY_PATH, XMPPService.INFO_XMLNS) ||\n\t\t\t\t\t\t\t\t\t\tisXMLNSStaticStr(IQ_QUERY_PATH, XMPPService.ITEMS_XMLNS));\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Message.java",
    "content": "/*\n * Message.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Created: Dec 31, 2009 8:38:38 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Message\n\t\t\t\textends Packet {\n\t/** Field description */\n\tpublic static final String ELEM_NAME = \"message\";\n\n\t/** Field description */\n\tpublic static final String[] MESSAGE_BODY_PATH = { ELEM_NAME, \"body\" };\n\n\t/** Field description */\n\tpublic static final String[] MESSAGE_SUBJECT_PATH = { ELEM_NAME, \"subject\" };\n\n\t/** Field description */\n\tpublic static final String[] MESSAGE_ERROR_PATH = { ELEM_NAME, \"error\" };\n\n\t/** Field description */\n\tpublic static final String[] MESSAGE_DELAY_PATH = { ELEM_NAME, \"delay\" };\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic Message(Element elem) throws TigaseStringprepException {\n\t\tsuper(elem);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t * @param stanzaFrom\n\t * @param stanzaTo\n\t */\n\tpublic Message(Element elem, JID stanzaFrom, JID stanzaTo) {\n\t\tsuper(elem, stanzaFrom, stanzaTo);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Creates a packet with message stanza.\n\t *\n\t *\n\t * @param from\n\t *          is a <code>JID</code> instance with message source address.\n\t * @param to\n\t *          is a <code>JID</code> instance with message destination address.\n\t * @param type\n\t *          is a <code>StanzaType</code> object with the message type.\n\t * @param body\n\t *          is a <code>String</code> object with message body content.\n\t * @param subject\n\t *          is a <code>String</code> object with message subject.\n\t * @param thread\n\t *          is a <code>String</code> object with message thread.\n\t * @param id\n\t *          is a <code>String</code> object with packet id value. Normally we\n\t *          do not set packet IDs for messages but in some cases this might be\n\t *          useful.\n\t *\n\t * @return a new <code>Packet</code> instance (more specifically\n\t *         <code>Message</code> instance) with the message stanza.\n\t */\n\tpublic static Packet getMessage(JID from, JID to, StanzaType type, String body,\n\t\t\tString subject, String thread, String id) {\n\t\tElement message = new Element(\"message\", null, null);\n\n\t\tmessage.setXMLNS(CLIENT_XMLNS);\n\t\tif (body != null) {\n\t\t\tmessage.addChild(new Element(\"body\", body));\n\t\t}\n\t\tif (from != null) {\n\t\t\tmessage.addAttribute(\"from\", from.toString());\n\t\t}\n\t\tif (to != null) {\n\t\t\tmessage.addAttribute(\"to\", to.toString());\n\t\t}\n\t\tif (type != null) {\n\t\t\tmessage.addAttribute(\"type\", type.name());\n\t\t}\n\t\tif (id != null) {\n\t\t\tmessage.addAttribute(\"id\", id);\n\t\t}\n\t\tif (subject != null) {\n\t\t\tmessage.addChild(new Element(\"subject\", subject));\n\t\t}\n\t\tif (thread != null) {\n\t\t\tmessage.addChild(new Element(\"thread\", thread));\n\t\t}\n\n\t\treturn packetInstance(message, from, to);\n\t}\n\n\t@Override\n\tprotected String[] getElNameErrorPath() {\n\t\treturn MESSAGE_ERROR_PATH;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/MessageReceiver.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Interface MessageReceiver\n *\n * Objects of this type can receive messages. They can be in fact routing\n * destination depending on target address. Message are routed to proper\n * destination in MessageRouter class.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface MessageReceiver extends ServerComponent {\n\n\t/**\n\t * Describe <code>addPacket</code> method here.\n\t *\n\t * @param packet a <code>Packet</code> value\n\t * @return a <code>boolean</code> value <code>true</code> if packet has been\n\t * successfully added, <code>false</code> otherwise.\n\t */\n\tboolean addPacket(Packet packet);\n\n\tboolean addPacketNB(Packet packet);\n\n\t/**\n\t * Describe <code>addPackets</code> method here.\n\t *\n\t * @param packets\n\t * @return a <code>boolean</code> value\n\t */\n\tboolean addPackets(Queue<Packet> packets);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tBareJID getDefHostName();\n\n///**\n// * Returns array of Strings. Each String should be a regular expression\n// * defining destination addresses for which this receiver can process\n// * messages. There can be more than one message receiver for each messages.\n// *\n// * @return a <code>String[]</code> value\n// */\n//String[] getLocalAddresses();\n\t// Set<String> getRoutings();\n\tboolean isInRegexRoutings(String address);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Describe <code>setParent</code> method here.\n\t *\n\t * @param msg_rec a <code>MessageReceiver</code> value\n\t */\n\tvoid setParent(MessageReceiver msg_rec);\n\n\t//~--- methods --------------------------------------------------------------\n\n\tvoid start();\n\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/MessageRouter.java",
    "content": "/*\n * MessageRouter.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.MemoryUsage;\nimport java.text.DecimalFormat;\nimport java.text.NumberFormat;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.ConfigurationException;\nimport tigase.conf.ConfiguratorAbstract;\nimport tigase.disco.XMPPService;\nimport static tigase.server.MessageRouterConfig.*;\nimport tigase.stats.StatisticsList;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.TigaseStringprepException;\nimport tigase.util.UpdatesChecker;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Class MessageRouter\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MessageRouter\n\t\t\t\textends AbstractMessageReceiver\n\t\t\t\timplements MessageRouterIfc {\n\t// implements XMPPService {\n\t// public static final String INFO_XMLNS =\n\t// \"http://jabber.org/protocol/disco#info\";\n\t// public static final String ITEMS_XMLNS =\n\t// \"http://jabber.org/protocol/disco#items\";\n\tprivate static final Logger log = Logger.getLogger(MessageRouter.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate ConfiguratorAbstract config = null;\n\n\t// private static final long startupTime = System.currentTimeMillis();\n\t// private Set<String> localAddresses = new CopyOnWriteArraySet<String>();\n\tprivate String                            disco_name      = DISCO_NAME_PROP_VAL;\n\tprivate boolean                           disco_show_version =\n\t\t\tDISCO_SHOW_VERSION_PROP_VAL;\n\tprivate UpdatesChecker                    updates_checker = null;\n\tprivate Map<String, XMPPService>          xmppServices = new ConcurrentHashMap<>();\n\tprivate ConcurrentHashMap<String, ComponentRegistrator> registrators = new ConcurrentHashMap<>();\n\tprivate Map<String, MessageReceiver>      receivers = new ConcurrentHashMap<>();\n\tprivate boolean                           inProperties    = false;\n\tprivate Set<String>                       connectionManagerNames =\n\t\t\tnew ConcurrentSkipListSet<>();\n\tprivate Map<JID, ServerComponent>         components_byId = new ConcurrentHashMap<>();\n\tprivate Map<String, ServerComponent>      components      = new ConcurrentHashMap<>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param component\n\t */\n\tpublic void addComponent(ServerComponent component) throws ConfigurationException {\n\t\tlog.log(Level.INFO, \"Adding component: \", component.getClass().getSimpleName());\n\t\tfor (ComponentRegistrator registr : registrators.values()) {\n\t\t\tif (registr != component) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Adding: {0} component to {1} registrator.\",\n\t\t\t\t\t\t\tnew Object[] { component.getName(),\n\t\t\t\t\t\t\tregistr.getName() });\n\t\t\t\t}\n\t\t\t\tregistr.addComponent(component);\n\t\t\t}    // end of if (reg != component)\n\t\t}      // end of for ()\n\t\tcomponents.put(component.getName(), component);\n\t\tcomponents_byId.put(component.getComponentId(), component);\n\t\tif (component instanceof XMPPService) {\n\t\t\txmppServices.put(component.getName(), (XMPPService) component);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param registr\n\t */\n\tpublic void addRegistrator(ComponentRegistrator registr) throws ConfigurationException {\n\t\tlog.log(Level.INFO, \"Adding registrator: {0}\", registr.getClass().getSimpleName());\n\t\tregistrators.put(registr.getName(), registr);\n\t\taddComponent(registr);\n\t\tfor (ServerComponent comp : components.values()) {\n\n\t\t\t// if (comp != registr) {\n\t\t\tregistr.addComponent(comp);\n\n\t\t\t// } // end of if (comp != registr)\n\t\t}    // end of for (ServerComponent comp : components)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param receiver\n\t */\n\tpublic void addRouter(MessageReceiver receiver) throws ConfigurationException {\n\t\tlog.info(\"Adding receiver: \" + receiver.getClass().getSimpleName());\n\t\taddComponent(receiver);\n\t\treceivers.put(receiver.getName(), receiver);\n\t}\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\n\t\t// This is actually quite tricky part. We want to both avoid\n\t\t// packet reordering and also even packets distribution among\n\t\t// different threads.\n\t\t// If packet comes from a connection manager we must use packetFrom\n\t\t// address. However if the packet comes from SM, PubSub or other similar\n\t\t// component all packets would end-up in the same queue.\n\t\t// So, kind of a workaround here....\n\t\t// TODO: develop a proper solution discovering which components are\n\t\t// connection managers and use their names here instead of static names.\n\t\tif ((packet.getPacketFrom() != null) && (packet.getPacketFrom().getLocalpart() !=\n\t\t\t\tnull)) {\n\t\t\tif (connectionManagerNames.contains(packet.getPacketFrom().getLocalpart())) {\n\t\t\t\treturn packet.getPacketFrom().hashCode();\n\t\t\t}\n\t\t}\n\t\tif ((packet.getPacketTo() != null) && (packet.getPacketTo().getLocalpart() != null)) {\n\t\t\tif (connectionManagerNames.contains(packet.getPacketTo().getLocalpart())) {\n\t\t\t\treturn packet.getPacketTo().hashCode();\n\t\t\t}\n\t\t}\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().getBareJID().hashCode();\n\t\t}\n\t\tif ((packet.getPacketFrom() != null) &&!getComponentId().equals(packet\n\t\t\t\t.getPacketFrom())) {\n\n\t\t\t// This comes from connection manager so the best way is to get hashcode\n\t\t\t// by the connectionId, which is in the getFrom()\n\t\t\treturn packet.getPacketFrom().hashCode();\n\t\t}\n\t\tif ((packet.getPacketTo() != null) &&!getComponentId().equals(packet.getPacketTo())) {\n\t\t\treturn packet.getPacketTo().hashCode();\n\t\t}\n\n\t\t// If not, then a better way is to get hashCode from the elemTo address\n\t\t// as this would be by the destination address user name:\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors() * 4;\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn 1;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\n\t\t// We do not process packets with not destination address\n\t\t// Just dropping them and writing a log message\n\t\tif (packet.getTo() == null) {\n\t\t\tlog.log(Level.WARNING, \"Packet with TO attribute set to NULL: {0}\", packet);\n\n\t\t\treturn;\n\t\t}    // end of if (packet.getTo() == null)\n\n\t\t// Intentionally comparing to static, final String\n\t\t// This is kind of a hack to handle packets addressed specifically for the\n\t\t// SessionManager\n\t\t// TODO: Replace the hack with a proper solution\n\t\t// if (packet.getTo() == NULL_ROUTING) {\n\t\t// log.info(\"NULL routing, it is normal if server doesn't know how to\"\n\t\t// + \" process packet: \" + packet.toStringSecure());\n\t\t//\n\t\t// try {\n\t\t// Packet error =\n\t\t// Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t// \"Feature not supported yet.\", true);\n\t\t//\n\t\t// addOutPacketNB(error);\n\t\t// } catch (PacketErrorTypeException e) {\n\t\t// log.warning(\"Packet processing exception: \" + e);\n\t\t// }\n\t\t//\n\t\t// return;\n\t\t// }\n\t\t// if (log.isLoggable(Level.FINER)) {\n\t\t// log.finer(\"Processing packet: \" + packet.getElemName()\n\t\t// + \", type: \" + packet.getType());\n\t\t// }\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\t\t}\n\n\t\t// Detect inifinite loop if from == to\n\t\t// Maybe it is not needed anymore...\n\t\t// There is a need to process packets with the same from and to address\n\t\t// let't try to relax restriction and block all packets with error type\n\t\t// 2008-06-16\n\t\tif (((packet.getType() == StanzaType.error) && (packet.getFrom() != null) && packet\n\t\t\t\t.getFrom().equals(packet.getTo()) \n\t\t\t\t&& (packet.getStanzaFrom() == null || packet.getStanzaFrom().equals(packet.getStanzaTo())))) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Possible infinite loop, dropping packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (isLocalDiscoRequest(packet)) {\n\t\t\tQueue<Packet> results = new ArrayDeque<>();\n\n\t\t\tprocessDiscoQuery(packet, results);\n\t\t\tif (results.size() > 0) {\n\t\t\t\tfor (Packet res : results) {\n\n\t\t\t\t\t// No more recurrential calls!!\n\t\t\t\t\taddOutPacketNB(res);\n\t\t\t\t}    // end of for ()\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// It is not a service discovery packet, we have to find a component to\n\t\t// process\n\t\t// the packet. The below block of code is to \"quickly\" find a component if\n\t\t// the\n\t\t// the packet is addressed to the component ID where the component ID is\n\t\t// either\n\t\t// of one below:\n\t\t// 1. component name + \"@\" + default domain name\n\t\t// 2. component name + \"@\" + any virtual host name\n\t\t// 3. component name + \".\" + default domain name\n\t\t// 4. component name + \".\" + any virtual host name\n\t\t// TODO: check the efficiency for packets addressed to c2s component\n\t\tServerComponent comp = getLocalComponent(packet.getTo());\n\n\t\tif (comp != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"1. Packet will be processed by: {0}, {1}\", new Object[] {\n\t\t\t\t\t\tcomp.getComponentId(),\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\n\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\t\tif (comp == this) {\n\n\t\t\t\t// This is addressed to the MessageRouter itself. Has to be processed\n\t\t\t\t// separately to avoid recurential calls by the packet processing\n\t\t\t\t// method.\n\t\t\t\tprocessPacketMR(packet, results);\n\t\t\t} else {\n\n\t\t\t\t// All other components process the packet the same way.\n\t\t\t\tcomp.processPacket(packet, results);\n\t\t\t}\n\t\t\tif (results.size() > 0) {\n\t\t\t\tfor (Packet res : results) {\n\n\t\t\t\t\t// No more recurrential calls!!\n\t\t\t\t\taddOutPacketNB(res);\n\n\t\t\t\t\t// processPacket(res);\n\t\t\t\t}    // end of for ()\n\t\t\t}\n\n\t\t\t// If the component is found the processing ends here as there can be\n\t\t\t// only one component with specific ID.\n\t\t\treturn;\n\t\t}\n\n\t\t// This packet is not processed yet\n\t\t// The packet can be addressed to just a domain, one of the virtual hosts\n\t\t// The code below finds all components which handle packets addressed\n\t\t// to a virtual domains (implement VHostListener and return 'true' from\n\t\t// handlesLocalDomains() method call)\n\t\tString            host  = packet.getTo().getDomain();\n\t\tServerComponent[] comps = getComponentsForLocalDomain(host);\n\n\t\tif (comps == null) {\n\n\t\t\t// Still no component found, now the most expensive lookup.\n\t\t\t// Checking regex routings provided by the component.\n\t\t\tcomps = getServerComponentsForRegex(packet.getTo().getBareJID().toString());\n\t\t}\n\t\tif ((comps == null) &&!isLocalDomain(host)) {\n\n\t\t\t// None of the component want to process the packet.\n\t\t\t// If the packet is addressed to non-local domain then it is processed by\n\t\t\t// all components dealing with external world, like s2s\n\t\t\tcomps = getComponentsForNonLocalDomain(host);\n\t\t}\n\n\t\t// Ok, if any component has been found then process the packet in a standard\n\t\t// way\n\t\tif (comps != null) {\n\n\t\t\t// Processing packet and handling results out\n\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\t\tfor (ServerComponent serverComponent : comps) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"2. Packet will be processed by: {0}, {1}\",\n\t\t\t\t\t\t\tnew Object[] { serverComponent.getComponentId(),\n\t\t\t\t\t\t\tpacket });\n\t\t\t\t}\n\t\t\t\tserverComponent.processPacket(packet, results);\n\t\t\t\tif (results.size() > 0) {\n\t\t\t\t\tfor (Packet res : results) {\n\n\t\t\t\t\t\t// No more recurrential calls!!\n\t\t\t\t\t\taddOutPacketNB(res);\n\n\t\t\t\t\t\t// processPacket(res);\n\t\t\t\t\t}    // end of for ()\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t// No components for the packet, sending an error back\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"There is no component for the packet, sending it back\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\taddOutPacketNB(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\"There is no service found to process your request.\", true));\n\t\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t\t// This packet is to local domain, we don't want to send it out\n\t\t\t\t// drop packet :-(\n\t\t\t\tlog.warning(\"Can't process packet to local domain, dropping...\" + packet\n\t\t\t\t\t\t.toStringSecure());\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param results\n\t */\n\tpublic void processPacketMR(Packet packet, Queue<Packet> results) {\n\t\tIq iq = null;\n\n\t\tif (packet instanceof Iq) {\n\t\t\tiq = (Iq) packet;\n\t\t} else {\n\n\t\t\t// Not a command for sure...\n\t\t\tlog.warning(\"I expect command (Iq) packet here, instead I got: \" + packet\n\t\t\t\t\t.toString());\n\n\t\t\treturn;\n\t\t}\n\t\tif (packet.getPermissions() != Permissions.ADMIN) {\n\t\t\ttry {\n\t\t\t\tPacket res = Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"You are not authorized for this action.\", true);\n\n\t\t\t\tresults.offer(res);\n\n\t\t\t\t// processPacket(res);\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.warning(\"Packet processing exception: \" + e);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Command received: \" + iq.toString());\n\t\t}\n\t\tswitch (iq.getCommand()) {\n\t\tcase OTHER :\n\t\t\tif (iq.getStrCommand() != null) {\n\t\t\t\tif (iq.getStrCommand().startsWith(\"controll/\")) {\n\t\t\t\t\tString[] spl = iq.getStrCommand().split(\"/\");\n\t\t\t\t\tString   cmd = spl[1];\n\n\t\t\t\t\tif (cmd.equals(\"stop\")) {\n\t\t\t\t\t\tPacket result = iq.commandResult(Command.DataType.result);\n\n\t\t\t\t\t\tresults.offer(result);\n\n\t\t\t\t\t\t// processPacket(result);\n\t\t\t\t\t\tnew Timer(\"Stopping...\", true).schedule(new TimerTask() {\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\t\tSystem.exit(0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param component\n\t */\n\tpublic void removeComponent(ServerComponent component) {\n\t\tfor (ComponentRegistrator registr : registrators.values()) {\n\t\t\tif (registr != component) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Removing: {0} component from {1} registrator.\",\n\t\t\t\t\t\t\tnew Object[] { component.getName(),\n\t\t\t\t\t\t\tregistr.getName() });\n\t\t\t\t}\n\t\t\t\tregistr.deleteComponent(component);\n\t\t\t}    // end of if (reg != component)\n\t\t}      // end of for ()\n\t\tcomponents.remove(component.getName());\n\t\tcomponents_byId.remove(component.getComponentId());\n\t\tif (component instanceof XMPPService) {\n\t\t\txmppServices.remove(component.getName());\n\t\t}\n\t}\n\n\tpublic void removeRegistrator(ComponentRegistrator registr) {\n\t\tlog.log(Level.INFO, \"Removing registrator: {0}\", registr.getClass().getSimpleName());\n\t\tregistrators.remove(registr.getName(), registr);\n\t\tremoveComponent(registr);\n\t\tfor (ServerComponent comp : components.values()) {\n\n\t\t\t// if (comp != registr) {\n\t\t\tregistr.deleteComponent(comp);\n\n\t\t\t// } // end of if (comp != registr)\n\t\t}    // end of for (ServerComponent comp : components)\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param receiver\n\t */\n\tpublic void removeRouter(MessageReceiver receiver) {\n\t\tlog.info(\"Removing receiver: \" + receiver.getClass().getSimpleName());\n\t\treceivers.remove(receiver.getName());\n\t\tremoveComponent(receiver);\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tsuper.start();\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tSet<String> comp_names = new TreeSet<String>();\n\n\t\tcomp_names.addAll(components.keySet());\n\t\tfor (String name : comp_names) {\n\t\t\tServerComponent comp = components.remove(name);\n\n\t\t\tif ((comp != this) && (comp != null)) {\n\t\t\t\tcomp.release();\n\t\t\t}\n\t\t}\n\t\tsuper.stop();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\n\t\tMessageRouterConfig.getDefaults(defs, params, getName());\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"im\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn disco_name + (disco_show_version\n\t\t\t\t? (\" ver. \" + XMPPServer.getImplementationVersion())\n\t\t\t\t: \"\");\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getName(), \"Local hostname\", getDefHostName().getDomain(), Level.INFO);\n\n\t\tTigaseRuntime runtime = TigaseRuntime.getTigaseRuntime();\n\n\t\tlist.add(getName(), \"Uptime\", runtime.getUptimeString(), Level.INFO);\n\n\t\tNumberFormat format = NumberFormat.getNumberInstance();\n\n\t\tformat.setMaximumFractionDigits(4);\n\t\tlist.add(getName(), \"Load average\", format.format(runtime.getLoadAverage()), Level\n\t\t\t\t.FINE);\n\t\tlist.add(getName(), \"CPUs no\", runtime.getCPUsNumber(), Level.FINEST);\n\t\tlist.add(getName(), \"Threads count\", runtime.getThreadsNumber(), Level.FINEST);\n\n\t\tfloat cpuUsage     = runtime.getCPUUsage();\n\t\tfloat heapUsage    = runtime.getHeapMemUsage();\n\t\tfloat nonHeapUsage = runtime.getNonHeapMemUsage();\n\n\t\tlist.add(getName(), \"CPU usage [%]\", cpuUsage, Level.FINE);\n\t\tlist.add(getName(), \"HEAP usage [%]\", heapUsage, Level.FINE);\n\t\tlist.add(getName(), \"NONHEAP usage [%]\", nonHeapUsage, Level.FINE);\n\t\tformat = NumberFormat.getNumberInstance();\n\t\tformat.setMaximumFractionDigits(1);\n\n\t\tlist.add(getName(), \"CPU usage\", format.format(cpuUsage) + \"%\", Level.INFO);\n\n\t\tformat = NumberFormat.getIntegerInstance();\n\t\tif (format instanceof DecimalFormat) {\n\t\t\tDecimalFormat decf = (DecimalFormat) format;\n\n\t\t\tdecf.applyPattern(decf.toPattern() + \" KB\");\n\t\t}\n\t\tlist.add(getName(), \"Max Heap mem\", format.format(runtime.getHeapMemMax() / 1024), Level.INFO);\n\t\tlist.add(getName(), \"Used Heap\", format.format(runtime.getHeapMemUsed() / 1024), Level.INFO);\n\t\tlist.add(getName(), \"Free Heap\", format.format( runtime.getHeapMemMax() == -1 ? -1.0 :\n\t\t\t\t(runtime.getHeapMemMax() - runtime.getHeapMemUsed()) / 1024), Level.FINE);\n\t\tlist.add(getName(), \"Max NonHeap mem\", format.format(runtime.getNonHeapMemMax() / 1024), Level\n\t\t\t\t.FINE);\n\t\tlist.add(getName(), \"Used NonHeap\", format.format(runtime.getNonHeapMemUsed() / 1024), Level\n\t\t\t\t.FINE);\n\t\tlist.add(getName(), \"Free NonHeap\", format.format( runtime.getNonHeapMemMax() == -1 ? -1.0 :\n\t\t\t\t(runtime.getNonHeapMemMax() - runtime.getNonHeapMemUsed()) / 1024), Level.FINE);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setConfig(ConfiguratorAbstract config) throws ConfigurationException {\n\t\tcomponents.put(getName(), this);\n\t\tthis.config = config;\n\t\taddRegistrator(config);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (inProperties) {\n\t\t\treturn;\n\t\t} else {\n\t\t\tinProperties = true;\n\t\t}    // end of if (inProperties) else\n\t\tconnectionManagerNames.add(\"c2s\");\n\t\tconnectionManagerNames.add(\"bosh\");\n\t\tconnectionManagerNames.add(\"s2s\");\n\t\tif (props.get(DISCO_SHOW_VERSION_PROP_KEY) != null) {\n\t\t\tdisco_show_version = (Boolean) props.get(DISCO_SHOW_VERSION_PROP_KEY);\n\t\t}\n\t\tif (props.get(DISCO_NAME_PROP_KEY) != null) {\n\t\t\tdisco_name = (String) props.get(DISCO_NAME_PROP_KEY);\n\t\t}\n\t\ttry {\n\t\t\tsuper.setProperties(props);\n\t\t\tupdateServiceDiscoveryItem(getName(), null, getDiscoDescription(), \"server\", \"im\",\n\t\t\t\t\tfalse);\n\t\t\tif (props.size() == 1) {\n\n\t\t\t\t// If props.size() == 1, it means this is a single property update and\n\t\t\t\t// MR does\n\t\t\t\t// not support it yet.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tHashSet<String>     inactive_msgrec = new HashSet<String>(receivers.keySet());\n\t\t\tMessageRouterConfig conf            = new MessageRouterConfig(props);\n\t\t\tString[]            reg_names       = conf.getRegistrNames();\n\n\t\t\tfor (String name : reg_names) {\n\t\t\t\tinactive_msgrec.remove(name);\n\n\t\t\t\t// First remove it and later, add it again if still active\n\t\t\t\tComponentRegistrator cr = registrators.remove(name);\n\t\t\t\tString               cls_name = (String) props.get(REGISTRATOR_PROP_KEY + name +\n\t\t\t\t\t\t\".class\");\n\n\t\t\t\ttry {\n\t\t\t\t\tif ((cr == null) ||!cr.getClass().getName().equals(cls_name)) {\n\t\t\t\t\t\tif (cr != null) {\n\t\t\t\t\t\t\tcr.release();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcr = conf.getRegistrInstance(name);\n\t\t\t\t\t\tcr.setName(name);\n\t\t\t\t\t}    // end of if (cr == null)\n\t\t\t\t\taddRegistrator(cr);\n\t\t\t\t} catch (ConfigurationException ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"configuration of component \" + name + \" failed - disabling component, error: \" + ex.getMessage());\n\t\t\t\t\tif (cr != null) {\n\t\t\t\t\t\tremoveRegistrator(cr);\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}      // end of try-catch\n\t\t\t}        // end of for (String name: reg_names)\n\n\t\t\tString[] msgrcv_names = conf.getMsgRcvActiveNames();\n\n\t\t\tfor (String name : msgrcv_names) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Loading and registering message receiver: {0}\", name);\n\t\t\t\t}\n\t\t\t\tinactive_msgrec.remove(name);\n\n\t\t\t\t// First remove it and later, add it again if still active\n\t\t\t\tServerComponent mr = receivers.remove(name);\n\n\t\t\t\txmppServices.remove(name);\n\n\t\t\t\tString cls_name = (String) props.get(MSG_RECEIVERS_PROP_KEY + name + \".class\");\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// boolean start = false;\n\t\t\t\t\tif ((mr == null) || ((mr != null) &&!conf.componentClassEquals(cls_name, mr\n\t\t\t\t\t\t\t.getClass()))) {\n\t\t\t\t\t\tif (mr != null) {\n\t\t\t\t\t\t\tif (mr instanceof MessageReceiver) {\n\t\t\t\t\t\t\t\tremoveRouter((MessageReceiver) mr);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tremoveComponent(mr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmr.release();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmr = conf.getMsgRcvInstance(name);\n\t\t\t\t\t\tmr.setName(name);\n\t\t\t\t\t\tif (mr instanceof MessageReceiver) {\n\t\t\t\t\t\t\t((MessageReceiver) mr).setParent(this);\n\t\t\t\t\t\t\t((MessageReceiver) mr).start();\n\n//            start = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (cr == null)\n\t\t\t\t\t\n\t\t\t\t\tif (mr instanceof MessageReceiver) {\n\t\t\t\t\t\taddRouter((MessageReceiver) mr);\n\t\t\t\t\t} else {\n\t\t\t\t\t\taddComponent(mr);\n\t\t\t\t\t}\n\t\t\t\t\tSystem.out.println(\"Loading component: \" + mr.getComponentInfo());\n\n//        if (start) {\n//                ((MessageReceiver) mr).start();\n//        }\n\t\t\t\t}      // end of try\n\t\t\t\tcatch (ClassNotFoundException e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"class for component = {0} could not be found \" +\n\t\t\t\t\t\t\t\"- disabling component\", name);\t\t\t\t\t\n//        conf.setComponentActive(name, false);\n\t\t\t\t}    // end of try\n\t\t\t\tcatch (ConfigurationException ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"configuration of component \" + name + \" failed - disabling component, error: \" + ex.getMessage());\n\t\t\t\t\tif (mr != null) {\n\t\t\t\t\t\tif (mr instanceof MessageReceiver) {\n\t\t\t\t\t\t\tremoveRouter((MessageReceiver) mr);\n\t\t\t\t\t\t\t((MessageReceiver) mr).release();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tremoveComponent(mr);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (Exception e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}    // end of try-catch\n\t\t\t}      // end of for (String name: reg_names)\n\n//    String[] inactive_msgrec = conf.getMsgRcvInactiveNames();\n\t\t\tfor (String name : inactive_msgrec) {\n\t\t\t\tServerComponent mr = receivers.remove(name);\n\n\t\t\t\txmppServices.remove(name);\n\t\t\t\tif (mr != null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (mr instanceof MessageReceiver) {\n\t\t\t\t\t\t\tremoveRouter((MessageReceiver) mr);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tremoveComponent(mr);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmr.release();\n\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"exception releasing component:\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// for (MessageReceiver mr : tmp_rec.values()) {\n\t\t\t// mr.release();\n\t\t\t// } // end of for ()\n\t\t\t//\n\t\t\t// tmp_rec.clear();\n\t\t\tif ((Boolean) props.get(UPDATES_CHECKING_PROP_KEY)) {\n\t\t\t\tinstallUpdatesChecker((Long) props.get(UPDATES_CHECKING_INTERVAL_PROP_KEY));\n\t\t\t} else {\n\t\t\t\tlog.log(Level.INFO, \"Disabling updates checker.\");\n\t\t\t\tstopUpdatesChecker();\n\t\t\t}\n\t\t} finally {\n\t\t\tinProperties = false;\n\t\t}        // end of try-finally\n\t\tfor (ServerComponent comp : components.values()) {\n\t\t\tlog.log(Level.INFO, \"Initialization completed notification to: {0}\", comp\n\t\t\t\t\t.getName());\n\t\t\tcomp.initializationCompleted();\n\t\t}\n\n\t\t// log.info(\"Initialization completed notification to: \" +\n\t\t// config.getName());\n\t\t// config.initializationCompleted();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def * 10;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void installUpdatesChecker(long interval) {\n\t\tstopUpdatesChecker();\n\t\tupdates_checker = new UpdatesChecker(interval, this,\n\t\t\t\t\"This is automated message generated by updates checking module.\\n\" +\n\t\t\t\t\" You can disable this function changing configuration option: \" + \"'/\" +\n\t\t\t\tgetName() + \"/\" + UPDATES_CHECKING_PROP_KEY + \"' or adjust\" +\n\t\t\t\t\" updates checking interval time changing option: \" + \"'/\" + getName() + \"/\" +\n\t\t\t\tUPDATES_CHECKING_INTERVAL_PROP_KEY + \"' which\" + \" now set to \" + interval +\n\t\t\t\t\" days.\");\n\t\tupdates_checker.start();\n\t}\n\n\tprivate void processDiscoQuery(final Packet packet, final Queue<Packet> results) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing disco query by: {0}\", packet.toStringSecure());\n\t\t}\n\n\t\tJID     toJid   = packet.getStanzaTo();\n\t\tJID     fromJid = packet.getStanzaFrom();\n\t\tString  node    = packet.getAttributeStaticStr(Iq.IQ_QUERY_PATH, \"node\");\n\t\tElement query   = packet.getElement().getChild(\"query\").clone();\n\n\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, INFO_XMLNS)) {\n\t\t\tif (isLocalDomain(toJid.toString()) && (node == null)) {\n\t\t\t\ttry {\n\t\t\t\t\tquery = getDiscoInfo(node, (toJid.getLocalpart() == null)\n\t\t\t\t\t\t\t? JID.jidInstance(getName(), toJid.toString(), null)\n\t\t\t\t\t\t\t: toJid, fromJid);\n\t\t\t\t} catch (TigaseStringprepException e) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"processing by stringprep throw exception for = {0}@{1}\", new Object[] {\n\t\t\t\t\t\t\tgetName(),\n\t\t\t\t\t\t\ttoJid.toString() });\n\t\t\t\t}\n\t\t\t\tfor (XMPPService comp : xmppServices.values()) {\n\n\t\t\t\t\t// Buggy custom component may throw exceptions here (NPE most likely)\n\t\t\t\t\t// which may cause service disco problems for well-behaving components\n\t\t\t\t\t// too\n\t\t\t\t\t// So this is kind of a protection\n\t\t\t\t\ttry {\n\t\t\t\t\t\tList<Element> features = comp.getDiscoFeatures(fromJid);\n\n\t\t\t\t\t\tif (features != null) {\n\t\t\t\t\t\t\tquery.addChildren(features);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Component service disco problem: \" + comp.getName(),\n\t\t\t\t\t\t\t\te);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (XMPPService comp : xmppServices.values()) {\n\n\t\t\t\t\t// Buggy custom component may throw exceptions here (NPE most likely)\n\t\t\t\t\t// which may cause service disco problems for well-behaving components\n\t\t\t\t\t// too\n\t\t\t\t\t// So this is kind of a protection\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// if (jid.startsWith(comp.getName() + \".\")) {\n\t\t\t\t\t\tElement resp = comp.getDiscoInfo(node, toJid, fromJid);\n\n\t\t\t\t\t\tif (resp != null) {\n\t\t\t\t\t\t\tquery.addChildren(resp.getChildren());\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Component service disco problem: \" + comp.getName(),\n\t\t\t\t\t\t\t\te);\n\t\t\t\t\t}\n\n\t\t\t\t\t// }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, ITEMS_XMLNS)) {\n\t\t\tboolean localDomain = isLocalDomain(toJid.toString());\n\n\t\t\tif (localDomain) {\n\t\t\t\tfor (XMPPService comp : xmppServices.values()) {\n\n\t\t\t\t\t// Buggy custom component may throw exceptions here (NPE most likely)\n\t\t\t\t\t// which may cause service disco problems for well-behaving components\n\t\t\t\t\t// too\n\t\t\t\t\t// So this is kind of a protection\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// if (localDomain || (nick != null && comp.getName().equals(nick)))\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tList<Element> items = comp.getDiscoItems(node, toJid, fromJid);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"Localdomain: {0}, DiscoItems processed by: {1}, items: {2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { toJid,\n\t\t\t\t\t\t\t\t\tcomp.getComponentId(),\n\t\t\t\t\t\t\t\t\t(items == null)\n\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t: items.toString() });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((items != null) && (items.size() > 0)) {\n\t\t\t\t\t\t\tquery.addChildren(items);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Component service disco problem: \" + comp.getName(),\n\t\t\t\t\t\t\t\te);\n\t\t\t\t\t}\n\t\t\t\t}    // end of for ()\n\t\t\t} else {\n\t\t\t\tServerComponent comp = getLocalComponent(toJid);\n\n\t\t\t\tif ((comp != null) && (comp instanceof XMPPService)) {\n\t\t\t\t\tList<Element> items = ((XMPPService) comp).getDiscoItems(node, toJid, fromJid);\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"DiscoItems processed by: {0}, items: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { comp.getComponentId(), (items == null)\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: items.toString() });\n\t\t\t\t\t}\n\t\t\t\t\tif ((items != null) && (items.size() > 0)) {\n\t\t\t\t\t\tquery.addChildren(items);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tresults.offer(packet.okResult(query, 0));\n\t}\n\n\tprivate void stopUpdatesChecker() {\n\t\tif (updates_checker != null) {\n\t\t\tupdates_checker.interrupt();\n\t\t\tupdates_checker = null;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate ServerComponent[] getComponentsForLocalDomain(String domain) {\n\t\treturn vHostManager.getComponentsForLocalDomain(domain);\n\t}\n\n\tprivate ServerComponent[] getComponentsForNonLocalDomain(String domain) {\n\t\treturn vHostManager.getComponentsForNonLocalDomain(domain);\n\t}\n\n\tprivate ServerComponent getLocalComponent(JID jid) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Called for : {0}\", jid);\n\t\t}\n\n\t\t// Fast lookup in the server components to find a candidate\n\t\t// by the component ID (JID). If the packet is addressed directly\n\t\t// to the component ID then this is where the processing must happen.\n\t\t// Normally the component id is: component name + \"@\" + default hostname\n\t\t// However the component may \"choose\" to have any ID.\n\t\tServerComponent comp = components_byId.get(jid);\n\n\t\tif (comp != null) {\n\t\t\treturn comp;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log( Level.FINEST, \"No componentID matches (fast lookup against exact address): \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t + \"{0}, for map: {1}; trying VHost lookup\",\n\t\t\t\t\t\t\t new Object[] { jid, components_byId.keySet() } );\n\t\t}\n\n\t\t// Note, component ID consists of the component name + default hostname\n\t\t// which can be different from a virtual host. There might be many\n\t\t// virtual hosts and the packet can be addressed to the component by\n\t\t// the component name + virtual host name\n\t\t// Code below, tries to find a destination by the component name + any\n\t\t// active virtual hostname.\n\t\tif (jid.getLocalpart() != null) {\n\t\t\tcomp = components.get(jid.getLocalpart());\n\t\t\tif ((comp != null) && (isLocalDomain(jid.getDomain()) || jid.getDomain().equals(\n\t\t\t\t\tgetDefHostName().getDomain()))) {\n\t\t\t\treturn comp;\n\t\t\t}\n\t\t}\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t \"No component name matches (VHost lookup against component name): \"\n\t\t\t\t\t\t\t + \"{0}, for map: {1}, for all VHosts: {2}; trying other forms of addressing\",\n\t\t\t\t\t\t\t new Object[] { jid, components.keySet(), vHostManager.getAllVHosts() } );\n\t\t}\n\n\t\t// Instead of a component ID built of: component name + \"@\" domain name\n\t\t// Some components have an ID of: component name + \".\" domain name\n\t\t// Code below tries to find a packet receiver if the address have the other\n\t\t// type of form.\n\t\tint idx = jid.getDomain().indexOf('.');\n\n\t\tif (idx > 0) {\n\t\t\tString cmpName  = jid.getDomain().substring(0, idx);\n\t\t\tString basename = jid.getDomain().substring(idx + 1);\n\n\t\t\tcomp = components.get(cmpName);\n\t\t\tif ((comp != null) && (isLocalDomain(basename) || basename.equals(getDefHostName()\n\t\t\t\t\t.getDomain()))) {\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t\t \"Component matched: {0}, for comp: {1}, basename: {3}\",\n\t\t\t\t\t\t\t\t\t new Object[] { jid, components.keySet(), comp, basename } );\n\t\t\t\t}\n\t\t\t\treturn comp;\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t \"Component match failed: {0}, for comp: {1}, basename: {3}\",\n\t\t\t\t\t\t\t\t new Object[] { jid, components.keySet(), comp, basename } );\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate ServerComponent[] getServerComponentsForRegex(String id) {\n\t\tLinkedHashSet<ServerComponent> comps = new LinkedHashSet<ServerComponent>();\n\n\t\tfor (MessageReceiver mr : receivers.values()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Checking routings for: \" + mr.getName());\n\t\t\t}\n\t\t\tif (mr.isInRegexRoutings(id)) {\n\t\t\t\tcomps.add(mr);\n\t\t\t}\n\t\t}\n\t\tif (comps.size() > 0) {\n\t\t\treturn comps.toArray(new ServerComponent[comps.size()]);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate boolean isDiscoDisabled(ServerComponent comp, JID to) {\n\t\tif (comp != null) {\n\t\t\treturn (comp instanceof DisableDisco);\n\t\t} else {\n\t\t\tServerComponent[] comps = getComponentsForLocalDomain(to.getDomain());\n\n\t\t\tif (comps != null) {\n\t\t\t\tfor (ServerComponent c : comps) {\n\t\t\t\t\tif (c instanceof DisableDisco) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate boolean isLocalDiscoRequest(Packet packet) {\n\t\tboolean         result = false;\n\t\tJID             to     = packet.getStanzaTo();\n\t\tServerComponent comp   = (to == null)\n\t\t\t\t? null\n\t\t\t\t: getLocalComponent(to);\n\n\t\tresult = packet.isServiceDisco() && (packet.getType() == StanzaType.get) && (packet\n\t\t\t\t.getStanzaFrom() != null) && ((packet.getStanzaTo() == null) || (((comp !=\n\t\t\t\tnull) || isLocalDomain(packet.getStanzaTo().toString())) &&!isDiscoDisabled(comp,\n\t\t\t\tto)));\n\n//  .getStanzaFrom() != null) && ((packet.getStanzaTo() == null) || ((comp != null) &&\n//  !(comp instanceof DisableDisco)) || isLocalDomain(packet.getStanzaTo()\n//  .toString()))) {\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/10/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/MessageRouterConfig.java",
    "content": "/*\n * MessageRouterConfig.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.annotations.TigaseDeprecatedComponent;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.util.DNSResolverFactory;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.conf.Configurable.*;\n\n/**\n * Describe class MessageRouterConfig here.\n *\n *\n * Created: Fri Jan  6 14:54:21 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MessageRouterConfig {\n\t/** Field description */\n\tpublic static final String DISCO_NAME_PROP_KEY = \"disco-name\";\n\n\t/** Field description */\n\tpublic static final String DISCO_SHOW_VERSION_PROP_KEY = \"disco-show-version\";\n\n\t/** Field description */\n\tpublic static final String LOCAL_ADDRESSES_PROP_KEY = \"hostnames\";\n\n\t/** Field description */\n\tpublic static final String MSG_RECEIVERS_PROP_KEY = \"components/msg-receivers/\";\n\n\t/** Field description */\n\tpublic static final String REGISTRATOR_PROP_KEY = \"components/registrators/\";\n\n\t/** Field description */\n\tpublic static final String UPDATES_CHECKING_INTERVAL_PROP_KEY =\n\t\t\t\"updates-checking-interval\";\n\n\t/** Field description */\n\tpublic static final long UPDATES_CHECKING_INTERVAL_PROP_VAL = 7;\n\n\t/** Field description */\n\tpublic static final String    UPDATES_CHECKING_PROP_KEY        = \"updates-checking\";\n\tprivate static String[]       LOCAL_ADDRESSES_PROP_VALUE = { \"localhost\", \"hostname\" };\n\tprivate static final Logger   log = Logger.getLogger(\n\t\t\t\"tigase.server.MessageRouterConfig\");\n\tprivate static final String[] DEF_MSG_RECEIVERS_NAMES_PROP_VAL = {\n\t\tDEF_C2S_NAME, DEF_S2S_NAME, DEF_SM_NAME, DEF_BOSH_NAME, DEF_MONITOR_NAME,\n\t\tDEF_AMP_NAME, DEF_WS2S_NAME, DEF_EVENTBUS_NAME\n\t};\n\tprivate static final String[] ALL_MSG_RECEIVERS_NAMES_PROP_VAL = {\n\t\tDEF_C2S_NAME, DEF_S2S_NAME, DEF_SM_NAME, DEF_SSEND_NAME, DEF_SRECV_NAME,\n\t\tDEF_BOSH_NAME, DEF_MONITOR_NAME, DEF_WS2S_NAME, DEF_EVENTBUS_NAME\n\t};\n\n\t/** Field description */\n\tpublic static final String MSG_RECEIVERS_NAMES_PROP_KEY = MSG_RECEIVERS_PROP_KEY +\n\t\t\t\"id-names\";\n\tprivate static final String[] SM_MSG_RECEIVERS_NAMES_PROP_VAL = { DEF_EXT_COMP_NAME,\n\t\t\tDEF_SM_NAME, DEF_MONITOR_NAME, DEF_AMP_NAME, DEF_EVENTBUS_NAME };\n\tprivate static final String[] DEF_REGISTRATOR_NAMES_PROP_VAL = { DEF_VHOST_MAN_NAME,\n\t\t\tDEF_STATS_NAME };\n\tprivate static final String[] CS_MSG_RECEIVERS_NAMES_PROP_VAL = {\n\t\tDEF_C2S_NAME, DEF_S2S_NAME, DEF_EXT_COMP_NAME, DEF_BOSH_NAME, DEF_MONITOR_NAME,\n\t\tDEF_AMP_NAME, DEF_WS2S_NAME, DEF_EVENTBUS_NAME\n\t};\n\tprivate static final Map<String, String> COMPONENT_CLASSES = new LinkedHashMap<String,\n\t\t\tString>();\n\tprivate static final String[] COMP_MSG_RECEIVERS_NAMES_PROP_VAL = { DEF_COMP_PROT_NAME,\n\t\t\tDEF_MONITOR_NAME, DEF_AMP_NAME };\n\tprivate static final Map<String, String> COMP_CLUS_MAP = new LinkedHashMap<String,\n\t\t\tString>();\n\tprivate static final String[] CLUSTER_REGISTRATOR_NAMES_PROP_VAL = { DEF_VHOST_MAN_NAME,\n\t\t\tDEF_STATS_NAME, DEF_CLUST_CONTR_NAME };\n\n\t/** Field description */\n\tpublic static final Boolean UPDATES_CHECKING_PROP_VAL = true;\n\n\t/** Field description */\n\tpublic static final String REGISTRATOR_NAMES_PROP_KEY = REGISTRATOR_PROP_KEY +\n\t\t\t\"id-names\";\n\n\t/** Field description */\n\tpublic static final boolean DISCO_SHOW_VERSION_PROP_VAL = true;\n\n\t/** Field description */\n\tpublic static final String DISCO_NAME_PROP_VAL = tigase.server.XMPPServer.NAME;\n\n\t//~--- static initializers --------------------------------------------------\n\n\tstatic {\n\t\tCOMPONENT_CLASSES.put(DEF_C2S_NAME, C2S_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_S2S_NAME, S2S_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_EXT_COMP_NAME, EXT_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_COMP_PROT_NAME, COMP_PROT_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_CL_COMP_NAME, CL_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_SM_NAME, SM_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_SSEND_NAME, SSEND_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_SRECV_NAME, SRECV_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_BOSH_NAME, BOSH_COMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_STATS_NAME, STATS_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_CLUST_CONTR_NAME, CLUSTER_CONTR_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_VHOST_MAN_NAME, VHOST_MAN_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_MONITOR_NAME, MONITOR_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_AMP_NAME, AMP_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_WS2S_NAME, WS2S_CLASS_NAME);\n\t\tCOMPONENT_CLASSES.put(DEF_EVENTBUS_NAME, EVENTBUS_CLASS_NAME);\n\t\tCOMP_CLUS_MAP.put(SM_COMP_CLASS_NAME, SM_CLUST_COMP_CLASS_NAME);\n\t\tCOMP_CLUS_MAP.put(C2S_COMP_CLASS_NAME, C2S_CLUST_COMP_CLASS_NAME);\n\t\tCOMP_CLUS_MAP.put(BOSH_COMP_CLASS_NAME, BOSH_CLUST_COMP_CLASS_NAME);\n\t\tCOMP_CLUS_MAP.put(WS2S_CLASS_NAME, WS2S_CLUST_CLASS_NAME);\n\t\tCOMP_CLUS_MAP.put(AMP_CLASS_NAME, AMP_CLUST_CLASS_NAME);\n\t}\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Map<String, Object> props = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param props\n\t */\n\tpublic MessageRouterConfig(Map<String, Object> props) {\n\t\tthis.props = props;\n\n\t\t// System.out.println(\"MessageRouterConfig() properties: \" + props.toString());\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cls_name\n\t * @param currCls\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic boolean componentClassEquals(String cls_name,\n\t\t\tClass<? extends ServerComponent> currCls) {\n\t\tClass<? extends ServerComponent> cls = null;\n\n\t\ttry {\n\t\t\tcls = ModulesManagerImpl.getInstance().getServerComponentClass(cls_name);\n\t\t\tif (((cls == null) && (!XMPPServer.isOSGi() || COMPONENT_CLASSES.containsValue(\n\t\t\t\t\tcls_name) || COMP_CLUS_MAP.containsValue(cls_name))) || EXT_COMP_CLASS_NAME\n\t\t\t\t\t.equals(cls_name) || \"tigase.cluster.VirtualComponent\".equals(cls_name)) {\n\t\t\t\tcls = (Class<? extends ServerComponent>) this.getClass().getClassLoader()\n\t\t\t\t\t\t.loadClass(cls_name);\n\t\t\t}\n\t\t} catch (Exception ex) {}\n\n\t\treturn (cls != null) && currCls.equals(cls);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param defs\n\t * @param params\n\t * @param comp_name\n\t */\n\tpublic static void getDefaults(Map<String, Object> defs, Map<String, Object> params,\n\t\t\tString comp_name) {\n\t\tboolean cluster_mode = isTrue((String) params.get(CLUSTER_MODE));\n\n\t\tlog.log(Level.CONFIG, \"Cluster mode: {0}\", params.get(CLUSTER_MODE));\n\t\tif (cluster_mode) {\n\t\t\tlog.config(\"Cluster mode is on, replacing known components with cluster\" +\n\t\t\t\t\t\" versions:\");\n\t\t\tfor (Map.Entry<String, String> entry : COMPONENT_CLASSES.entrySet()) {\n\t\t\t\tString cls = COMP_CLUS_MAP.get(entry.getValue());\n\n\t\t\t\tif (cls != null) {\n\t\t\t\t\tlog.log(Level.CONFIG, \"Replacing {0} with {1}\", new Object[] { entry.getValue(),\n\t\t\t\t\t\t\tcls });\n\t\t\t\t\tentry.setValue(cls);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.config(\"Cluster mode is off.\");\n\t\t}\n\n\t\tString   config_type = (String) params.get(\"config-type\");\n\t\tString[] rcv_names   = DEF_MSG_RECEIVERS_NAMES_PROP_VAL;\n\t\tObject   par_names   = params.get(comp_name + \"/\" + MSG_RECEIVERS_NAMES_PROP_KEY);\n\n\t\tif (par_names != null) {\n\t\t\trcv_names = (String[]) par_names;\n\t\t} else {\n\t\t\tif (config_type.equals(GEN_CONFIG_ALL)) {\n\t\t\t\trcv_names = ALL_MSG_RECEIVERS_NAMES_PROP_VAL;\n\t\t\t}\n\t\t\tif (config_type.equals(GEN_CONFIG_SM)) {\n\t\t\t\trcv_names = SM_MSG_RECEIVERS_NAMES_PROP_VAL;\n\t\t\t}\n\t\t\tif (config_type.equals(GEN_CONFIG_CS)) {\n\t\t\t\trcv_names = CS_MSG_RECEIVERS_NAMES_PROP_VAL;\n\t\t\t}\n\t\t\tif (config_type.equals(GEN_CONFIG_COMP)) {\n\t\t\t\trcv_names = COMP_MSG_RECEIVERS_NAMES_PROP_VAL;\n\t\t\t}\n\t\t}\n\t\tArrays.sort(rcv_names);\n\t\tlog.log(Level.CONFIG, \"Configured type: {0}, loading components: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {config_type, Arrays.asList( rcv_names )});\n\n\t\t// Now init defaults for all extra components:\n\t\tfor (String key : params.keySet()) {\n\n\t\t\t// XEP-0114 components\n\t\t\tif (key.startsWith(GEN_EXT_COMP)) {\n\t\t\t\tString new_comp_name = DEF_EXT_COMP_NAME + key.substring(GEN_EXT_COMP.length());\n\n\t\t\t\tif (Arrays.binarySearch(rcv_names, new_comp_name) < 0) {\n\t\t\t\t\trcv_names                       = Arrays.copyOf(rcv_names, rcv_names.length +\n\t\t\t\t\t\t\t1);\n\t\t\t\t\trcv_names[rcv_names.length - 1] = new_comp_name;\n\t\t\t\t\tArrays.sort(rcv_names);\n\t\t\t\t}\n\t\t\t}    // end of if (key.startsWith(GEN_EXT_COMP))\n\n\t\t\t// All other extra components, assuming class has been given\n\t\t\tif (key.startsWith(GEN_COMP_NAME)) {\n\t\t\t\tString comp_name_suffix = key.substring(GEN_COMP_NAME.length());\n\t\t\t\tString c_name           = (String) params.get(GEN_COMP_NAME + comp_name_suffix);\n\n\t\t\t\t// Make sure the component name is converted to lowercase\n\t\t\t\tc_name = c_name.toLowerCase();\n\n\t\t\t\tString c_class = (String) params.get(GEN_COMP_CLASS + comp_name_suffix);\n\n\t\t\t\tif (Arrays.binarySearch(rcv_names, c_name) < 0) {\n\t\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + c_name + \".class\", c_class);\n\t\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + c_name + \".active\", true);\n\t\t\t\t\trcv_names                       = Arrays.copyOf(rcv_names, rcv_names.length +\n\t\t\t\t\t\t\t1);\n\t\t\t\t\trcv_names[rcv_names.length - 1] = c_name;\n\t\t\t\t\tArrays.sort(rcv_names);\n\n\t\t\t\t\t// System.out.println(Arrays.toString(rcv_names));\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of for ()\n\n\t\t// Add XEP-0114 for cluster communication\n\t\tif (cluster_mode) {\n\t\t\tlog.config(\"In cluster mode I am setting up 1 listening xep-0114 component:\");\n\t\t\tif (Arrays.binarySearch(rcv_names, DEF_CL_COMP_NAME) < 0) {\n\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + DEF_CL_COMP_NAME + \".class\",\n\t\t\t\t\t\tCL_COMP_CLASS_NAME);\n\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + DEF_CL_COMP_NAME + \".active\", true);\n\t\t\t\trcv_names                       = Arrays.copyOf(rcv_names, rcv_names.length + 1);\n\t\t\t\trcv_names[rcv_names.length - 1] = DEF_CL_COMP_NAME;\n\t\t\t\tArrays.sort(rcv_names);\n\t\t\t}\n\t\t}\n\t\tdefs.put(MSG_RECEIVERS_NAMES_PROP_KEY, rcv_names);\n\t\tfor (String name : rcv_names) {\n\t\t\tif (defs.get(MSG_RECEIVERS_PROP_KEY + name + \".class\") == null) {\n\t\t\t\tString def_class = COMPONENT_CLASSES.get(name);\n\n\t\t\t\tif (def_class == null) {\n\t\t\t\t\tdef_class = EXT_COMP_CLASS_NAME;\n\t\t\t\t}\n\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + name + \".class\", def_class);\n\t\t\t\tdefs.put(MSG_RECEIVERS_PROP_KEY + name + \".active\", true);\n\t\t\t}\n\t\t}\n\n\t\tString[] registr = DEF_REGISTRATOR_NAMES_PROP_VAL;\n\n\t\tif (cluster_mode) {\n\t\t\tregistr = CLUSTER_REGISTRATOR_NAMES_PROP_VAL;\n\t\t}\n\t\tdefs.put(REGISTRATOR_NAMES_PROP_KEY, registr);\n\t\tfor (String reg : registr) {\n\t\t\tdefs.put(REGISTRATOR_PROP_KEY + reg + \".class\", COMPONENT_CLASSES.get(reg));\n\t\t\tdefs.put(REGISTRATOR_PROP_KEY + reg + \".active\", true);\n\t\t}\n\t\tif (params.get(GEN_VIRT_HOSTS) != null) {\n\t\t\tLOCAL_ADDRESSES_PROP_VALUE = ((String) params.get(GEN_VIRT_HOSTS)).split(\",\");\n\t\t} else {\n\t\t\tLOCAL_ADDRESSES_PROP_VALUE = DNSResolverFactory.getInstance().getDefaultHosts();\n\t\t}\n\t\tdefs.put(LOCAL_ADDRESSES_PROP_KEY, LOCAL_ADDRESSES_PROP_VALUE);\n\t\tdefs.put(DISCO_NAME_PROP_KEY, DISCO_NAME_PROP_VAL);\n\t\tdefs.put(DISCO_SHOW_VERSION_PROP_KEY, DISCO_SHOW_VERSION_PROP_VAL);\n\t\tdefs.put(UPDATES_CHECKING_PROP_KEY, UPDATES_CHECKING_PROP_VAL);\n\t\tdefs.put(UPDATES_CHECKING_INTERVAL_PROP_KEY, UPDATES_CHECKING_INTERVAL_PROP_VAL);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t */\n\tpublic String[] getMsgRcvActiveNames() {\n\t\tString[]     names          = (String[]) props.get(MSG_RECEIVERS_NAMES_PROP_KEY);\n\t\tList<String> availableNames = new ArrayList<String>();\n\n\t\tfor (String name : names) {\n\t\t\tif (hasClassForServerComponent(name) && ((props.get(MSG_RECEIVERS_PROP_KEY + name +\n\t\t\t\t\t\".active\") != null) && (Boolean) props.get(MSG_RECEIVERS_PROP_KEY + name +\n\t\t\t\t\t\".active\"))) {\n\t\t\t\tavailableNames.add(name);\n\t\t\t}\n\t\t}\n\t\tnames = availableNames.toArray(new String[availableNames.size()]);\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"active message receivers = {0}\", Arrays.toString(names));\n\t\t}\n\n\t\treturn names;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t */\n\tpublic String[] getMsgRcvInactiveNames() {\n\t\tString[]          names = (String[]) props.get(MSG_RECEIVERS_NAMES_PROP_KEY);\n\t\tArrayList<String> al    = new ArrayList<String>();\n\n\t\tfor (String name : names) {\n\t\t\tif ((props.get(MSG_RECEIVERS_PROP_KEY + name + \".active\") == null) ||\n\t\t\t\t\t!(Boolean) props.get(MSG_RECEIVERS_PROP_KEY + name + \".active\")) {\n\t\t\t\tal.add(name);\n\t\t\t}\n\t\t\tif (hasClassForServerComponent(name)) {\n\t\t\t\tal.add(name);\n\t\t\t}\n\t\t}    // end of for (String name: names)\n\t\tnames = al.toArray(new String[al.size()]);\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.log(Level.FINE, \"inactive message receivers = {0}\", Arrays.toString(names));\n\t\t}\n\n\t\treturn names;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>ServerComponent</code>\n\t * @throws ClassNotFoundException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t */\n\tpublic ServerComponent getMsgRcvInstance(String name)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException {\n\t\tString          cls_name = (String) props.get(MSG_RECEIVERS_PROP_KEY + name +\n\t\t\t\t\".class\");\n\t\tServerComponent cls = null;\n\n\t\tcls = ModulesManagerImpl.getInstance().getServerComponent(cls_name);\n\t\tif (((cls == null) && (!XMPPServer.isOSGi() || COMPONENT_CLASSES.containsValue(\n\t\t\t\tcls_name) || COMP_CLUS_MAP.containsValue(cls_name))) || EXT_COMP_CLASS_NAME\n\t\t\t\t.equals(cls_name)  || \"tigase.cluster.VirtualComponent\".equals(cls_name)) {\n\t\t\tcls = (ServerComponent) this.getClass().getClassLoader().loadClass(cls_name)\n\t\t\t\t\t.newInstance();\n\t\t}\n\n\t\tif ( cls != null && cls.getClass().isAnnotationPresent( TigaseDeprecatedComponent.class ) ){\n\t\t\tTigaseDeprecatedComponent annotation = cls.getClass().getAnnotation( TigaseDeprecatedComponent.class );\n\t\t\tlog.log( Level.WARNING, \"Deprecated Component: \" + cls.getClass().getCanonicalName()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \", INFO: \" + annotation.note() + \"\\n\" );\n\t\t}\n\n\n\t\treturn cls;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>ComponentRegistrator</code>\n\t * @throws ClassNotFoundException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t */\n\tpublic ComponentRegistrator getRegistrInstance(String name)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException {\n\t\tString cls_name = (String) props.get(REGISTRATOR_PROP_KEY + name + \".class\");\n\n\t\t// I changed location for the XMPPServiceCollector class\n\t\t// to avoid problems with old configuration files let's detect it here\n\t\t// and silently convert it to new package name:\n\t\tif (cls_name.equals(\"tigase.server.XMPPServiceCollector\") || cls_name.equals(\n\t\t\t\t\"tigase.disco.XMPPServiceCollector\")) {\n\t\t\tlog.warning(\n\t\t\t\t\t\"This class is not used anymore. Correct your configuration please. Remove \" +\n\t\t\t\t\t\"all references to class: XMPPServiceCollector.\");\n\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (ComponentRegistrator) this.getClass().getClassLoader().loadClass(cls_name)\n\t\t\t\t.newInstance();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t */\n\tpublic String[] getRegistrNames() {\n\t\tString[] names = (String[]) props.get(REGISTRATOR_NAMES_PROP_KEY);\n\n\t\tlog.config(Arrays.toString(names));\n\n\t\tArrayList<String> al = new ArrayList<String>();\n\n\t\tfor (String name : names) {\n\n\t\t\t// System.out.println(\"Checking: '\" + REGISTRATOR_PROP_KEY + name + \".active'\");\n\t\t\tif ((Boolean) props.get(REGISTRATOR_PROP_KEY + name + \".active\")) {\n\t\t\t\tal.add(name);\n\t\t\t}    // end of if ((Boolean)props.get())\n\t\t}      // end of for (String name: names)\n\n\t\treturn al.toArray(new String[al.size()]);\n\t}\n\n\t/**\n\t * Check if class exists for server component\n\t *\n\t * @param name\n\t *\n\t */\n\tprivate boolean hasClassForServerComponent(String name) {\n\t\ttry {\n\t\t\tString cls_name = (String) props.get(MSG_RECEIVERS_PROP_KEY + name + \".class\");\n\n\t\t\tif (cls_name == null) {\n\t\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't load component \" + name + \": Class is not defined in config.\");\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// first check if there is registered class in ModuleManagerImpl as\n\t\t\t// it is easy\n\t\t\tif (ModulesManagerImpl.getInstance().hasClassForServerComponent(cls_name)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (XMPPServer.isOSGi()\n\t\t\t\t\t&& !(COMPONENT_CLASSES.containsValue(cls_name) || COMP_CLUS_MAP.containsValue(cls_name) \n\t\t\t\t\t|| EXT_COMP_CLASS_NAME.equals(cls_name) || \"tigase.cluster.VirtualComponent\".equals(cls_name))) {\n\t\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't load component \" + name + \": \" + cls_name + \" is external class.\");\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// it is dirty but should work\n\t\t\tthis.getClass().getClassLoader().loadClass(cls_name);\n\n\t\t\treturn true;\n\t\t} catch (Exception ex) {\n\t\t\tif (log.isLoggable(Level.WARNING))\n\t\t\t\tlog.log(Level.WARNING, \"Can't load component \" + name + \": \" + ex.getMessage());\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate static boolean isTrue(String val) {\n\t\tif (val == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tString value = val.toLowerCase();\n\n\t\treturn (value.equals(\"true\") || value.equals(\"yes\") || value.equals(\"on\") || value\n\t\t\t\t.equals(\"1\"));\n\t}\n}    // MessageRouterConfig\n\n\n//~ Formatted in Tigase Code Convention on 13/10/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/MessageRouterIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\nimport tigase.conf.ConfigurationException;\nimport tigase.conf.ConfiguratorAbstract;\n\n/**\n * Created: Dec 7, 2009 5:20:56 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface MessageRouterIfc extends ServerComponent {\n\n\tvoid setConfig(ConfiguratorAbstract config) throws ConfigurationException;\n\n\tvoid start();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Packet.java",
    "content": "/*\n * Packet.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.server;\n\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Objects of this class carry a single XMPP packet (stanza).\n * The XMPP stanza is carried as an XML element in DOM structure by the\n * Packet object which contains some extra information and convenience methods\n * to quickly access the most important stanza information.<br>\n * The stanza is accessible directly through the <code>getElement()</code> method\n * and then it can be handles as an XML object. <br>\n * <strong>Please note! Even though the <code>Packet</code> object and carried the\n * stanza <code>Element</code> is not unmodifiable it should be treated as such. This\n * particular <code>Packet</code> can be processed concurrently at the same time in\n * different components or plugins of the Tigase server. Modifying it may lead to\n * unexpected and hard to diagnose behaviors. Every time you want to change or\n * update the object you should obtaina a copy of it using one of the utility methods:\n * <code>copyElementOnly()</code>, <code>swapFromTo(...)</code>,\n * <code>errorResult(...)</code>, <code>okResult(...)</code>,\n * <code>swapStanzaFromTo(...)</code></strong><br>\n * There are no public constructors for the class, instead you have to use factory\n * methods: <code>packetInstance(...)</code> which return instance of one of the\n * classes: <code>Iq</code>, <code>Message</code> or <code>Presence</code>.\n * While creating a new <code>Packet</code> instance JIDs are parsed and processed\n * through the stringprep. Hence some of the factory methods may throw\n * <code>TigaseStringprepException</code> exception. You can avoid this by using\n * the methods which accept preparsed JIDs. Reusing preparsed JIDs is highly\n * recommended.\n * <br>\n * There are 3 kinds of addresses available from the <code>Packet</code> object:\n * <em>PacketFrom/To</em>, <em>StanzaFrom/To</em> and <em>From/To</em>.<br>\n * <em>Stanza</em> addresses are the normal XMPP addresses parsed from the XML\n * stanza and as a convenience are available through methods as JID objects. This is\n * not only convenient to the developer but also this is important for performance\n * reasons as parsing JID and processing it through stringprep is quite expensive\n * operation so it is better to do it once and reuse the parsed objects. Please note\n * that any of them can be null. Note also. You should avoid parsing stanza JIDs\n * from the XML element in your code as this may impact the server performance.\n * Reuse the JIDs provided from the <code>Packet</code> methods.<br>\n * <em>Packet</em> addresses are also JID objects but they may contain a different\n * values from the <em>Stanza</em> addresses. These are the Tigase internal\n * addresses used by the server and they usually contain Tigase component source\n * and destination address. In most cases they are used between connection managers\n * and session managers and can be ignored by other code. One advantage of setting\n * <code>PacketFrom</code> address to address of your component\n * (<code>getComponentId()</code>) address is that if there is a packet delivery problem\n * it will be returned back to the sender with apropriate error message.<br>\n * <em>Simple From/To</em> addresses contains values following the logic: If\n * PacketFrom/To is not null then it contains PacketFrom/To values otherwise it\n * contains StanzaFrom/To values. This is because the Tigase server tries always\n * to deliver and process the <code>Packet</code> using PacketFrom/To addresses if\n * they are null then Stanza addresses are used instead. So these are just convenience\n * methods which allow avoiding extra <code>IFs</code> in the program code and also\n * save some CPU cycles.\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Packet {\n\t/** Field description */\n\tpublic static final String CLIENT_XMLNS = \"jabber:client\";\n\n\t/** Field description */\n\tpublic static final String FROM_ATT = \"from\";\n\n\t/** Field description */\n\tpublic static final String ID_ATT = \"id\";\n\n\t/** Field description */\n\tpublic static final String PERM_ATT = \"perm\";\n\n\t/** Field description */\n\tpublic static final String PRIORITY_ATT = \"pr\";\n\n\t/** Field description */\n\tpublic static final String TO_ATT = \"to\";\n\n\t/** Field description */\n\tpublic static final String TYPE_ATT = \"type\";\n\n\t/** Field description */\n\tpublic static final String XMLNS_ATT = \"xmlns\";\n\n\t/**\n\t *\n\t */\n\tprivate static final String ERROR_NS = \"urn:ietf:params:xml:ns:xmpp-stanzas\";\n\n\t/**\n\t * The variable control whether the toStringSecure() hides all the CData information\n\t * from stanzas printed to logs or logs the full, detailed stanza content. By default\n\t * the variable is set to 'false' to protect users' privacy and not reveal chat content.\n\t * This is the value to be used in all production/live systems. For the debug purposes\n\t * on the test or development system it can be set to 'true' to help diagnose run-time\n\t * problems.<br>\n\t * You can change value of the field by setting system property:\n\t * <code>'packet.debug.full'</code> to <code>'true'</code>.\n\t */\n\tpublic static boolean FULL_DEBUG = Boolean.getBoolean(\"packet.debug.full\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected Element elem;\n\tprivate JID packetFrom              = null;\n\tprivate JID packetTo                = null;\n\tprivate String packetToString       = null;\n\tprivate String packetToStringSecure = null;\n\tprivate Set<String> processorsIds   = new LinkedHashSet<String>(4, 0.9f);\n\tprivate LinkedHashSet<String> skippedProcessorsIds   = new LinkedHashSet<String>(4, 0.9f);\n\tprivate JID stanzaFrom              = null;\n\tprivate String stanzaId             = null;\n\tprivate JID stanzaTo                = null;\n\tprivate Priority priority           = Priority.NORMAL;\n\tprivate Permissions permissions     = Permissions.NONE;\n\tprivate boolean routed;\n\tprivate StanzaType type;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * A constructor creating the <code>Packet</code> instance. This is not part of\n\t * the public API, please use <code>packetInstance(...)</code> instead.\n\t *\n\t * @param elem is XML element with a single XMPP stanza.\n\t * @throws TigaseStringprepException exception is thrown if the stanza source or\n\t * destination address stringprep processing failed.\n\t */\n\tprotected Packet(final Element elem) throws TigaseStringprepException {\n\t\tsetElem(elem);\n\t\tinitVars();\n\t}\n\n\t/**\n\t * A constructor creating the <code>Packet</code> instance. This is not part of\n\t * the public API, please use <code>packetInstance(...)</code> instead.\n\t *\n\t * @param elem is XML element with a single XMPP stanza.\n\t * @param stanzaFrom is a source JID address of the stanza passed as the\n\t * constructor parameter.\n\t * @param stanzaTo is a destination JID address of the stanza passed as the\n\t * constructor parameter.\n\t */\n\tprotected Packet(final Element elem, JID stanzaFrom, JID stanzaTo) {\n\t\tsetElem(elem);\n\t\tinitVars(stanzaFrom, stanzaTo);\n\t}\n\n\t/**\n\t * Method trims {@link Element} stanza to 1024 characters and returns String\n\t * representation of the element\n\t *\n\t * @param el Element which should be converted\n\t * @return\n\t */\n\tpublic static String elemToString(Element el) {\n\t\tString elemData = el.toString();\n\t\tint size        = elemData.length();\n\n\t\tif (size > 1024) {\n\t\t\telemData = elemData.substring(0, 1024) + \" ... \";\n\t\t}\n\n\t\treturn elemData;\n\t}\n\n\t/**\n\t * Method trims {@link Element} stanza to 1024 characters and returns String\n\t * representation of the element. This version uses secure representation of\n\t * CData of the elements.\n\t *\n\t * @param el Element which should be converted\n\t * @return\n\t */\n\tpublic static String elemToStringSecure(Element el) {\n\t\tString elemData = el.toStringSecure();\n\t\tint size        = elemData.length();\n\n\t\tif (size > 1024) {\n\t\t\telemData = elemData.substring(0, 1024) + \" ... \";\n\t\t}\n\n\t\treturn elemData;\n\t}\n\n\t/**\n\t * The method returns <code>Packet</code> instance.\n\t * More specifically it returns instance of one of the following classes:\n\t * <code>Iq</code>, <code>Message</code> or <code>Presence</code>. It takes stanza XML\n\t * element as an arguments, parses some the most commonly used data and created an\n\t * object.\n\t * Pre-parsed information are: stanza from/to addresses, stanza id, type and presets\n\t * the <code>Packet</code> priority.<br>\n\t * If there is a stringprep processing error for either the stanza source or destination\n\t * address <code>TigaseStringprepException</code> exception is thrown.\n\t * @param elem is a stanza XML <code>Element</code>\n\t * @return a <code>Packet</code> instance, more specifically instance of one of the\n\t * following classes: <code>Iq</code>, <code>Message</code> or <code>Presence</code>.\n\t * @throws TigaseStringprepException if there is stanza from or to address parsing\n\t * error.\n\t */\n\tpublic static Packet packetInstance(Element elem) throws TigaseStringprepException {\n\t\tPacket result = null;\n\n\t\tif (elem.getName() == Message.ELEM_NAME) {\n\t\t\tresult = new Message(elem);\n\t\t}\n\t\tif (elem.getName() == Presence.ELEM_NAME) {\n\t\t\tresult = new Presence(elem);\n\t\t}\n\t\tif (elem.getName() == Iq.ELEM_NAME) {\n\t\t\tresult = new Iq(elem);\n\t\t}\n\t\tif (result == null) {\n\t\t\tresult = new Packet(elem);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method returns <code>Packet</code> instance.\n\t * More specifically it returns instance of one of the following classes:\n\t * <code>Iq</code>, <code>Message</code> or <code>Presence</code>. It takes stanza XML\n\t * element as an arguments and pre-parsed stanza from and to addresses. The method\n\t * parses some other, the most commonly used data and created an object.\n\t * Pre-parsed information are: stanza id, type and presets the <code>Packet</code>\n\t * priority.<br>\n\t * This method does not parses stanza from and stanza to address from the given XML\n\t * document, hence it does not throw <code>TigaseStringprepException</code>. Even\n\t * though reusing parsed from and to address is highly recommended an extra care\n\t * is needed to pass correct parameters as stanza JIDs or the packet may be\n\t * incorrectly routed or processed.\n\t *\n\t * @param elem is the stanza XML <code>Element</code>\n\t * @param stanzaFrom is a pre-parsed <code>JID</code> instance from the given stanza\n\t * XML element.\n\t * @param stanzaTo is a pre-parsed <code>JID</code> instance from the given stanza\n\t * XML element.\n\t * @return a <code>Packet</code> instance, more specifically instance of one of the\n\t * following classes: <code>Iq</code>, <code>Message</code> or <code>Presence</code>.\n\t */\n\tpublic static Packet packetInstance(Element elem, JID stanzaFrom, JID stanzaTo) {\n\t\tPacket result = null;\n\n\t\tif (elem.getName() == Message.ELEM_NAME) {\n\t\t\tresult = new Message(elem, stanzaFrom, stanzaTo);\n\t\t}\n\t\tif (elem.getName() == Presence.ELEM_NAME) {\n\t\t\tresult = new Presence(elem, stanzaFrom, stanzaTo);\n\t\t}\n\t\tif (elem.getName() == Iq.ELEM_NAME) {\n\t\t\tresult = new Iq(elem, stanzaFrom, stanzaTo);\n\t\t}\n\t\tif (result == null) {\n\t\t\tresult = new Packet(elem, stanzaFrom, stanzaTo);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method creates XML stanza from given parameters and returns\n\t * <code>Packet</code> instance for this XML stanza.\n\t * More specifically it returns instance of one of the following classes:\n\t * <code>Iq</code>, <code>Message</code> or <code>Presence</code>. <br>\n\t * The method first builds an XML stanza from given parameters: element name,\n\t * from and to addresses and stanza type, then it creates a Packet instance for the\n\t * stanza. It also runs all the parsing and stringprep processing, hence it throws\n\t * an exception if any error is found.\n\t * @param el_name XML stanza element name as <code>String</code>.\n\t * @param from is the stanza <strong>from</strong> address as <code>String</code>\n\t * @param to is the stanza <strong>to</strong> address as <code>String</code>.\n\t * @param type is one of the stanza types: <strong>set</strong>, <strong>get</strong>,\n\t * <strong>result</strong>, .... as <code>StanzaType</code> instance.\n\t * @return a <code>Packet</code> instance, more specifically instance of one of the\n\t * following classes: <code>Iq</code>, <code>Message</code> or <code>Presence</code>.\n\t * @throws TigaseStringprepException if there is stanza from or to address parsing\n\t * error.\n\t */\n\tpublic static Packet packetInstance(String el_name, String from, String to,\n\t\t\t\t\tStanzaType type)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tElement elem = new Element(el_name, new String[] { FROM_ATT, TO_ATT, TYPE_ATT },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { from,\n\t\t\t\t\t\tto, type.toString() });\n\n\t\treturn packetInstance(elem);\n\t}\n\n\t/**\n\t * <code>copyElementOnly</code> method creates a copy of the packet with stanza\n\t * information copied only. The <code>Packet</code> specific information stays\n\t * blank (NULL): (packetFrom, packetTo, etc...).<br>\n\t * This method should be used to obtain a copy of the packet without setting\n\t * packet specific fields (packetFrom or packetTo). The method reuses preparsed\n\t * stanza JIDs and does not throw any exception.\n\t * @return a new copy of the packet with packet specific fields set to NULL.\n\t */\n\tpublic Packet copyElementOnly() {\n\t\tElement res_elem = elem.clone();\n\t\tPacket result    = packetInstance(res_elem, getStanzaFrom(), getStanzaTo());\n\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method returns a string representation of all the data enclosed by the\n\t * <code>Packet</code> instance. All stanza XML element and all fields are converted\n\t * to the <code>String</code> representation for debugging. Please note, this may\n\t * be resources consuming process so use it only when experiencing problems with\n\t * <code>Packet</code> content.\n\t *\n\t *\n\t * @return <code>String</code> representation of the packet with all its fields.\n\t */\n\tpublic String debug() {\n\t\treturn toString() + \", stanzaFrom=\" + stanzaFrom + \", stanzaTo=\" + stanzaTo;\n\t}\n\n\t/**\n\t * Method returns a modified copy of the <code>Packet</code> with its stanza as\n\t * stanza error used for reporting errors. It is recommended not to use this\n\t * method directly as there is a utility class which makes generating error responses\n\t * much simpler. An example call (which uses this method underneath) looks like this\n\t * example:\n\t * <pre>\n\t * import tigase.xmpp.Authorization;\n\t * Authorization.BAD_REQUEST.getResponseMessage(packet, \"Error message\", true/false);\n\t * </pre>\n\t * This utility class and it's method acts not only as a convenience but also provides\n\t * some additional checking and control.\n\t *\n\t *\n\t * @param errorType is a <code>String</code> representation of the error type defined\n\t * in the XMPP RFC-3920.\n\t * @param errorCode is an integer error code defined in the XMPP RFC for backward\n\t * compatibility with old Jabber implementations.\n\t * @param errorCondition is a <code>String</code> representation of the error condition\n\t * defined in the XMPP RFC-3920.\n\t * @param errorText human readable error message.\n\t * @param includeOriginalXML a boolean parameter indicating whether stanza top element\n\t * children should be included in the error message.\n\t *\n\t * @return a new <code>Packet</code> instance with an error type stanza which\n\t * is a response to this <code>Packet</code> instance.\n\t */\n\tpublic Packet errorResult(final String errorType, final Integer errorCode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal String errorCondition, final String errorText,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfinal boolean includeOriginalXML) {\n\t\tElement reply = new Element(elem.getName());\n\n\t\treply.setAttribute(TYPE_ATT, StanzaType.error.toString());\n\t\tif (getStanzaId() != null) {\n\t\t\treply.setAttribute(ID_ATT, getStanzaId());\n\t\t}    // end of if (getElemId() != null)\n\t\tif (includeOriginalXML) {\n\t\t\treply.addChildren(elem.getChildren());\n\t\t}    // end of if (includeOriginalXML)\n\t\tif (getXMLNS() != null) {\n\t\t\treply.setXMLNS(getXMLNS());\n\t\t}\n\n\t\tElement error = new Element(\"error\");\n\n\t\tif (errorCode != null) {\n\t\t\terror.setAttribute(\"code\", errorCode.toString());\n\t\t}\n\t\terror.setAttribute(TYPE_ATT, errorType);\n\n\t\tElement cond = new Element(errorCondition);\n\n\t\tcond.setXMLNS(ERROR_NS);\n\t\terror.addChild(cond);\n\t\tif (errorText != null) {\n\t\t\tElement t = new Element(\"text\", errorText, new String[] { \"xml:lang\", \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"en\",\n\t\t\t\t\t\t\tERROR_NS });\n\n\t\t\terror.addChild(t);\n\t\t}    // end of if (text != null && text.length() > 0)\n\t\treply.addChild(error);\n\n\t\treturn swapFromTo(reply, getStanzaTo(), getStanzaFrom());\n\t}\n\n\t/**\n\t * A convenience method for accessing stanza top element attributes. This call is\n\t * equal to the call:\n\t * <pre>\n\t * packet.getElement().getAttribute(key);\n\t * </pre>\n\t *\n\t *\n\t * @param key is an attribute key.\n\t *\n\t * @return an attribute value or NULL if there is no such attribute.\n\t * @deprecated Consider using {@link #getAttributeStaticStr(java.lang.String) } instead.\n\t */\n\t@Deprecated\n\tpublic String getAttribute(String key) {\n\t\treturn elem.getAttribute(key);\n\t}\n\n\t/**\n\t * A convenience method for accessing stanza top element attributes. This call is\n\t * equal to the call:\n\t * <pre>\n\t * packet.getElement().getAttribute(key);\n\t * </pre>\n\t *\n\t * @param key is an attribute key.\n\t *\n\t * @return an attribute value or NULL if there is no such attribute.\n\t */\n\tpublic String getAttributeStaticStr(String key) {\n\t\treturn elem.getAttributeStaticStr(key);\n\t}\n\n\t/**\n\t * A convenience method for accessing stanza top level or any of it's children\n\t * attribute. This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getAttribute(xmlPath, key);\n\t * </pre>\n\t * <strong>Please note! This method can only be used with static strings or with\n\t * strings processed through <code>String.intern()</code> call. It uses \"==\" for\n\t * string comparison for performance reasons. If you pass dynamically built\n\t * <code>String[]</code> to the method call, use\n\t * {@link #getAttribute(java.lang.String[], java.lang.String) } instead.</strong>\n\t *\n\t * @param path is XML path for the stanza element or stanza child for which attribute\n\t * is retrieved.\n\t * @param key is an attribute key.\n\t *\n\t * @return value of the requested attribute or NULL if the attribute is not set.\n\t */\n\tpublic String getAttributeStaticStr(String[] path, String key) {\n\t\treturn elem.getAttributeStaticStr(path, key);\n\t}\n\n\t/**\n\t * A convenience method for accessing stanza top level or any of it's children\n\t * attribute. This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getAttribute(xmlPath, key);\n\t * </pre>\n\t * <strong>For performance reasons please consider using\n\t * {@link #getAttributeStaticStr(java.lang.String[], java.lang.String) }\n\t * instead.</strong>\n\t *\n\t * @param path\n\t * @param key\n\t * @return value of the requested attribute or NULL if the attribute is not set.\n\t * @deprecated use {@link #getAttributeStaticStr(java.lang.String[], java.lang.String)}\n\t * instead, if possible, if not, contact us so we preserve the API.\n\t */\n\t@Deprecated\n\tpublic String getAttribute(String[] path, String key) {\n\t\treturn elem.getAttribute(path, key);\n\t}\n\n\t/**\n\t * A convenience method for accessing stanza top level or any of it's children\n\t * attribute. This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getAttribute(xmlPath, key);\n\t * </pre>\n\t *\n\t * @param path is XML path for the stanza element or stanza child for which attribute\n\t * is retrieved.\n\t * @param key is an attribute key.\n\t *\n\t * @return value of the requested attribute or NULL if the attribute is not set.\n\t * @deprecated use {@link #getAttributeStaticStr(java.lang.String[], java.lang.String)}\n\t * instead, if possible, or {@link #getAttribute(java.lang.String[], java.lang.String)}\n\t */\n\t@Deprecated\n\tpublic String getAttribute(String path, String key) {\n\t\treturn elem.getAttribute(path, key);\n\t}\n\n\t/**\n\t * The method always returns NULL. It is overwritten in the {@link Iq} class\n\t * where it returns a command identifier if the {@code iq} stanza represents an\n\t * ad-hoc command. It is provided here is a convenience so the developer does not\n\t * have to cast the packet to IQ before retrieving the command id.\n\t *\n\t *\n\t * @return the method always returns a NULL.\n\t */\n\tpublic Command getCommand() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method returns character data from the enclosed stanza for a given stanza element\n\t * or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getCData(xmlPath);\n\t * </pre>\n\t * <strong>Please note! This method can only be used with static strings or with\n\t * strings processed through <code>String.intern()</code> call. It uses \"==\" for\n\t * string comparison for performance reasons. If you pass dynamically built\n\t * <code>String[]</code> to the method call, use\n\t * {@link #getElemCData(java.lang.String[])} instead.</strong>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which CData is retrieved.\n\t *\n\t * @return CData for a given element or NULL if the element does not exist or there is\n\t * no CData for the element.\n\t */\n\tpublic String getElemCDataStaticStr(String[] xmlPath) {\n\t\treturn elem.getCDataStaticStr(xmlPath);\n\t}\n\n\t/**\n\t * Method returns character data from the enclosed stanza for a given stanza element\n\t * or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getCData(xmlPath);\n\t * </pre>\n\t * <strong>For performance reasons please consider using\n\t * {@link #getElemCDataStaticStr(java.lang.String[])} instead.</strong>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which CData is retrieved.\n\t *\n\t * @return CData for a given element or NULL if the element does not exist or there is\n\t * no CData for the element.\n\t * @deprecated use {@link #getElemCDataStaticStr(java.lang.String[]) } instead,\n\t * if possible, if not, contact us so we preserve the API.\n\t */\n\t@Deprecated\n\tpublic String getElemCData(String[] xmlPath) {\n\t\treturn elem.getCData(xmlPath);\n\t}\n\n\t/**\n\t * Method returns character data from the enclosed stanza for a given stanza element\n\t * or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getCData(xmlPath);\n\t * </pre>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which CData is retrieved.\n\t *\n\t * @return CData for a given element or NULL if the element does not exist or there is\n\t * no CData for the element.\n\t * @deprecated use {@link #getElemCDataStaticStr(java.lang.String[])} instead,\n\t * if possible, or {@link #getElemCData(java.lang.String[])}\n\t */\n\t@Deprecated\n\tpublic String getElemCData(String xmlPath) {\n\t\treturn elem.getCData(xmlPath);\n\t}\n\n\t/**\n\t * Method return character data for the stanza top element.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getCData();\n\t * </pre>\n\t *\n\t *\n\t * @return CData or from the stanza top element or NULL if there is no CData for the\n\t * element.\n\t */\n\tpublic String getElemCData() {\n\t\treturn elem.getCData();\n\t}\n\n\t/**\n\t * Method returns a list of all XML children from the enclosed stanza for a given\n\t * stanza element or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getChildrenStaticStr(xmlPath);\n\t * </pre>\n\t * <strong>Please note! This method can only be used with static strings or with\n\t * strings processed through <code>String.intern()</code> call. It uses \"==\" for\n\t * string comparison for performance reasons. If you pass dynamically built\n\t * <code>String[]</code> to the method call, use\n\t * {@link #getElemChildren(java.lang.String[]) } instead.</strong>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which children are\n\t * retrieved.\n\t *\n\t * @return children list for a given element or NULL if the element does not exist\n\t * or there is no children for the element.\n\t */\n\tpublic List<Element> getElemChildrenStaticStr(String[] xmlPath) {\n\t\treturn elem.getChildrenStaticStr(xmlPath);\n\t}\n\n\t/**\n\t * Method returns a list of all XML children from the enclosed stanza for a given\n\t * stanza element or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getChildren(xmlPath);\n\t * </pre>\n\t * <strong>For performance reasons please consider using\n\t * {@link #getElemChildrenStaticStr(java.lang.String[]) } instead.</strong>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which children are\n\t * retrieved.\n\t *\n\t * @return children list for a given element or NULL if the element does not exist\n\t * or there is no children for the element.\n\t * @deprecated use {@link #getElemChildrenStaticStr(java.lang.String[])} instead,\n\t * if possible, if not, contact us so we preserve the API.\n\t */\n\t@Deprecated\n\tpublic List<Element> getElemChildren(String[] xmlPath) {\n\t\treturn elem.getChildren(xmlPath);\n\t}\n\n\t/**\n\t * Method returns a list of all XML children from the enclosed stanza for a given\n\t * stanza element or child pointed by the <code>xmlPath</code> parameter.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getChildren(xmlPath);\n\t * </pre>\n\t *\n\t * @param xmlPath is an XML path to the stanza element for which children are\n\t * retrieved.\n\t *\n\t * @return children list for a given element or NULL if the element does not exist\n\t * or there is no children for the element.\n\t * @deprecated use {@link #getElemChildrenStaticStr(java.lang.String[]) } instead,\n\t * if possible, or {@link #getElemChildren(java.lang.String[]) }.\n\t */\n\t@Deprecated\n\tpublic List<Element> getElemChildren(String xmlPath) {\n\t\treturn elem.getChildren(xmlPath);\n\t}\n\n\t/**\n\t * Method returns a <code>String</code> representation of the stanza source address.\n\t * Use of this method is not recommended, the API is depreciated in favor of API\n\t * operating on <code>JID</code> class.\n\t * @return a <code>String</code> representation of the stanza source address or NULL\n\t * if the source address has not been set.\n\t * @deprecated use getStanzaFrom() instead.\n\t */\n\t@Deprecated\n\tpublic String getElemFrom() {\n\t\treturn (stanzaFrom != null)\n\t\t\t\t\t ? stanzaFrom.toString()\n\t\t\t\t\t : null;\n\t}\n\n\t/**\n\t * Convenience method for retrieving the stanza top element name.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getName();\n\t * </pre>\n\t *\n\t * @return the stanza top element name.\n\t */\n\tpublic String getElemName() {\n\t\treturn elem.getName();\n\t}\n\n\t/**\n\t * Method returns a <code>String</code> representation of the stanza destination\n\t * address.\n\t * Use of this method is not recommended, the API is depreciated in favor of API\n\t * operating on <code>JID</code> class.\n\t * @return a <code>String</code> representation of the stanza destination address or\n\t * NULL if the destination address has not been set..\n\t * @deprecated use getStanzaTo() instead\n\t */\n\t@Deprecated\n\tpublic String getElemTo() {\n\t\treturn (stanzaTo != null)\n\t\t\t\t\t ? stanzaTo.toString()\n\t\t\t\t\t : null;\n\t}\n\n\t/**\n\t * Method returns the stanza XML element in DOM format.\n\t *\n\t * @return the stanza XML element in DOM format.\n\t */\n\tpublic Element getElement() {\n\t\treturn elem;\n\t}\n\n\t/**\n\t * Method parses the stanza and returns the error condition if there is any.\n\t *\n\t * @return parsed stanza error condition or NULL if there is not error condition.\n\t */\n\tpublic String getErrorCondition() {\n\t\tList<Element> children = elem.getChildrenStaticStr(getElNameErrorPath());\n\n\t\tif (children != null) {\n\t\t\tfor (Element cond : children) {\n\t\t\t\tif (!cond.getName().equals(\"text\")) {\n\t\t\t\t\treturn cond.getName();\n\t\t\t\t}    // end of if (!cond.getName().equals(\"text\"))\n\t\t\t}      // end of for (Element cond: children)\n\t\t}        // end of if (children == null) else\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * A convenience method to provide XML path as <code>String[]</code> to error element.\n\t * This method should be override by all classes extending this class.\n\t *\n\t * @return XML path to error element.\n\t */\n\tprotected String[] getElNameErrorPath() {\n\t\treturn new String[] { elem.getName(), \"error\" };\n\t}\n\n\t/**\n\t * Returns the packet source address. The method works as a following code:\n\t * <pre>\n\t * return (packetFrom != null) ? packetFrom : stanzaFrom;\n\t * </pre>\n\t *\n\t * @return a <code>JID</code> instance of the packet source address or NULL if\n\t * neither the packet source address is set nor the stanza source address is set.\n\t */\n\tpublic JID getFrom() {\n\t\treturn (packetFrom != null)\n\t\t\t\t\t ? packetFrom\n\t\t\t\t\t : stanzaFrom;\n\t}\n\n\t/**\n\t * Returns the packet internal source address.\n\t *\n\t * @return a {@link JID} instance of the packet internal source address or\n\t * NULL if the packet internal source address has not been set\n\t */\n\tpublic JID getPacketFrom() {\n\t\treturn this.packetFrom;\n\t}\n\n\t/**\n\t * Returns the packet internal destination address.\n\t *\n\t *\n\t * @return a {@link JID} instance of the packet internal destination address or\n\t * NULL if the packet internal destination address has not been set.\n\t */\n\tpublic JID getPacketTo() {\n\t\treturn this.packetTo;\n\t}\n\n\t/**\n\t * Method returns permissions set of the user who has sent the packet. Some packets\n\t * carry ad-hoc commands which can change server parameters, configuration or\n\t * can contains other administration commands. Such commands are not executed if\n\t * the packet sender does not have enough permissions.\n\t *\n\t *\n\t * @return a sender permissions set.\n\t */\n\tpublic Permissions getPermissions() {\n\t\treturn permissions;\n\t}\n\n\t/**\n\t * Method returns the packet priority. For more details please refer to {@link Priority}\n\t * enumeration.\n\t *\n\t *\n\t * @return the packet priority.\n\t */\n\tpublic Priority getPriority() {\n\t\treturn priority;\n\t}\n\n\t/**\n\t * Method returns a set of all processor IDs which processed the packet. Each\n\t * session manager processor which handles the packet can mark the packet as\n\t * processed. This is used internally by the session manager to detect packets\n\t * which hasn't been processed by any processor, hence a default action is\n\t * applied to the packet if possible.\n\t *\n\t *\n\t * @return a <code>Set</code> of stanza processor IDs which handled the packet.\n\t */\n\tpublic Set<String> getProcessorsIds() {\n\t\treturn processorsIds;\n\t}\n\n\t/**\n\t * Method returns a set of all processor IDs which skipped processing packets.\n\t *\n\t * @return a <code>Set</code> of stanza processor IDs which skipped the packet.\n\t */\n\tpublic Set<String> getSkippedProcessorsIds() {\n\t\treturn skippedProcessorsIds;\n\t}\n\n\t/**\n\t * Method returns source address of the stanza enclosed by this packet.\n\t * @return a <code>JID</code> instance of the stanza source address or NULL if the\n\t * source address has not been set for the stanza.\n\t */\n\tpublic JID getStanzaFrom() {\n\t\treturn stanzaFrom;\n\t}\n\n\t/**\n\t * Method returns the stanza ID if set.\n\t *\n\t *\n\t * @return a <code>String</code> representation of the stanza ID or NULL if the ID has\n\t * not been set for the stanza.\n\t */\n\tpublic String getStanzaId() {\n\t\treturn stanzaId;\n\t}\n\n\t/**\n\t * Method returns destination address of the stanza enclosed by this packet.\n\t * @return a <code>JID</code> instance of the stanza destination address or NULL if\n\t * the destination address has not been set for the stanza.\n\t */\n\tpublic JID getStanzaTo() {\n\t\treturn stanzaTo;\n\t}\n\n\t/**\n\t * Returns the packet destination address. The method works as a following code:\n\t * <pre>\n\t * return (packetTo != null) ? packetTo : stanzaTo;\n\t * </pre>\n\t *\n\t * @return a <code>JID</code> instance of the packet destination address or NULL if\n\t * neither the packet destination address is set nor the stanza destination address\n\t * is set.\n\t */\n\tpublic JID getTo() {\n\t\treturn (packetTo != null)\n\t\t\t\t\t ? packetTo\n\t\t\t\t\t : stanzaTo;\n\t}\n\n\t/**\n\t * Method returns the stanza type parsed from the top XML element of the enclosed\n\t * stanza.\n\t *\n\t *\n\t * @return a <code>StanzaType</code> instance of the stanza type parsed from the\n\t * top XML element of the enclosed stanza or NULL of the type has not been set.\n\t */\n\tpublic StanzaType getType() {\n\t\treturn type;\n\t}\n\n\t/**\n\t * Returns the enclosed stanza top element XMLNS.\n\t * This call is equal to the call:\n\t * <pre>\n\t * packet.getElement().getXMLNS();\n\t * </pre>\n\t *\n\t * @return a <code>String</code> instance of the stanza top element XMLNS.\n\t */\n\tpublic String getXMLNS() {\n\t\treturn elem.getXMLNS();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method allows for re-syncing stanza JIDs stored in the packet with the\n\t * attributes of the stanza if they have been changed for any reason.\n\t * <strong>Method mostly used internally only.</strong> Normally stanza carried by this\n\t * Packet instance\n\t * must not be changed, however there are rare occasions when it has to be changed.\n\t * RFC requires that the server adds missing <em>'from'</em> attribute to every\n\t * packet sent by the user. It would be highly inefficient to create a new instance\n\t * of the data just to add the missing from address. In such a case SM adds missing\n\t * attribute but then stanza preparsed JIDs stored in the packet are out of sync with\n\t * the enclosed stanza. This method allows for setting correct stanza JIDs for the\n\t * packet fields without a need to reparse the stanza.\n\t *\n\t *\n\t * @param stanzaFrom is a parsed source address JID from the stanza enclosed by this\n\t * packet.\n\t * @param stanzaTo is a parsed destination address JID from the stanza enclosed by\n\t * this packet.\n\t */\n\tpublic void initVars(JID stanzaFrom, JID stanzaTo) {\n\t\tif (this.stanzaFrom != stanzaFrom) {\n\t\t\tthis.stanzaFrom = stanzaFrom;\n\t\t\tif (stanzaFrom == null) {\n\t\t\t\telem.removeAttribute(FROM_ATT);\n\t\t\t} else {\n\t\t\t\telem.setAttribute(FROM_ATT, stanzaFrom.toString());\n\t\t\t}\n\t\t}\n\t\tif (this.stanzaTo != stanzaTo) {\n\t\t\tthis.stanzaTo = stanzaTo;\n\t\t\tif (stanzaTo == null) {\n\t\t\t\telem.removeAttribute(TO_ATT);\n\t\t\t} else {\n\t\t\t\telem.setAttribute(TO_ATT, stanzaTo.toString());\n\t\t\t}\n\t\t}\n\t\tstanzaId             = elem.getAttributeStaticStr(ID_ATT);\n\t\tpacketToString       = null;\n\t\tpacketToStringSecure = null;\n\t}\n\n\t/**\n\t * The method allows for re-syncing/parsing stanza JIDs stored in the packet with the\n\t * attributes of the stanza if they have been changed for any reason.\n\t * <strong>Method mostly used internally only.</strong> Normally stanza carried by this\n\t * Packet instance\n\t * must not be changed, however there are rare occasions when it is needed.\n\t * RFC requires that the server adds missing <em>'from'</em> attribute to every\n\t * packet sent by the user. It would be highly inefficient to create a new instance\n\t * of the data just to add the missing from address. In such a case SM adds missing\n\t * attribute but then stanza pre-parsed JIDs stored in the packet are out of sync with\n\t * the enclosed stanza. This method causes stanza JIDs re-parsing and setting the packet\n\t * variables.\n\t *\n\t *\n\t * @throws TigaseStringprepException if the stringprep error occurs during the stanza\n\t * JIDs parsing.\n\t */\n\tpublic void initVars() throws TigaseStringprepException {\n\t\tString tmp = elem.getAttributeStaticStr(TO_ATT);\n\n\t\tif (tmp != null) {\n\t\t\tstanzaTo = JID.jidInstance(tmp);\n\t\t} else {\n\t\t\tstanzaTo = null;\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(FROM_ATT);\n\t\tif (tmp != null) {\n\t\t\tstanzaFrom = JID.jidInstance(tmp);\n\t\t} else {\n\t\t\tstanzaFrom = null;\n\t\t}\n\t\tstanzaId             = elem.getAttributeStaticStr(ID_ATT);\n\t\tpacketToString       = null;\n\t\tpacketToStringSecure = null;\n\t\ttmp                  = elem.getAttributeStaticStr(PRIORITY_ATT);\n\t\tif (tmp != null) {\n\t\t\tpriority = Priority.valueOf(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(PERM_ATT);\n\t\tif (tmp != null) {\n\t\t\tpermissions = Permissions.valueOf(tmp);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * The method checks whether the stanza enclosed by this <code>Packet</code>\n\t * instance is an ad-hoc command.\n\t * This is a generic method which in fact always returns <code>false</code>. It\n\t * is overwritten in the <code>Iq</code> class where the real checking is\n\t * performed. This class has been provided as a convenience method to perform\n\t * the check without a need for casting the <code>Packet</code> instance to\n\t * the <code>Iq</code> class.\n\t *\n\t * @return a <code>boolean</code> value <code>true</code> if the stanza is\n\t * an ad-hoc command and <code>false</code> otherwise.\n\t */\n\tpublic boolean isCommand() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * The method checks whether the enclosed stanza is a specific XML element.\n\t * That is, it checks whether the stanza element name and XMLNS is exactly\n\t * the same as given parameters.\n\t * This is a convenience method which logic is equal to the code below:\n\t * {@code\n\t * return packet.getElement().getName() == name\n\t *             && packet.getElement().getXMLNS() == xmlns;\n\t * }\n\t *\n\t * @param name is a <code>String</code> representing the XML element name.\n\t * @param xmlns is a <code>String</code> representing the XML xmlns value.\n\t * @return {@code true} if stanza element name and XMLNS is exactly\n\t * the same as given parameters, {@code false} otherwise.\n\t */\n\tpublic boolean isElement(String name, String xmlns) {\n\t\treturn (elem.getName() == name) && (xmlns == elem.getXMLNS());\n\t}\n\n\t/**\n\t * Method determines whether the stanza represents so called <em>routed</em>\n\t * packet.\n\t * A routed packet is a packet created by a component responsible for\n\t * Communication with external components. In certain work mode it can send\n\t * over the link the whole packet information with all internal states and\n\t * addresses. Such a packet also encloses original stanza with all it's attributes.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if the packet is\n\t * routed and <code>false</code> otherwise.\n\t */\n\tpublic boolean isRouted() {\n\t\treturn routed;\n\t}\n\n\t/**\n\t * A convenience method which checks whether the enclosed stanza is a service\n\t * discovery query.\n\t * This is a generic method which in fact always returns <code>false</code>. It\n\t * is overwritten in the <code>Iq</code> class where the real checking is\n\t * performed. This class has been provided as a convenience method to perform\n\t * the check without a need for casting the <code>Packet</code> instance to\n\t * the <code>Iq</code> class.\n\t *\n\t * @return a <code>boolean</code> value <code>true</code> if the stanza is\n\t * a a service discovery query and <code>false</code> otherwise.\n\t */\n\tpublic boolean isServiceDisco() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * The method checks whether the enclosed stanza contains an XML element and\n\t * XML child element for a given element path and XMLNS.\n\t * The <code>elementPath</code> is directory path like string.\n\t * <strong>Please note! This method can only be used with static strings or with\n\t * strings processed through <code>String.intern()</code> call. It uses \"==\" for\n\t * string comparison for performance reasons. If you pass dynamically built\n\t * <code>String[]</code> to the method call, use\n\t * {@link #isXMLNS(java.lang.String[], java.lang.String)} instead.</strong>\n\t *\n\t * @param elementPath is a <code>String[]</code> value which represents XML\n\t * element path to a desired child element.\n\t * @param xmlns is a <code>String</code> value which represents XML XMLNS.\n\t *\n\t * @return a <code>true</code> is element given in parameters is found in the packet\n\t * stanza, otherwise <code>false</code>\n\t */\n\tpublic boolean isXMLNSStaticStr(String[] elementPath, String xmlns) {\n\t\tString this_xmlns = elem.getXMLNSStaticStr(elementPath);\n\n\t\treturn (this_xmlns == xmlns);\n\t}\n\n\t/**\n\t * The method checks whether the enclosed stanza contains an XML element and\n\t * XML child element for a given element path and xmlns.\n\t * The <code>elementPath</code> is a String array with path elements.\n\t * <strong>For performance reasons please consider using\n\t * {@link #isXMLNSStaticStr(java.lang.String[], java.lang.String)} instead.</strong>\n\t *\n\t * @param elementPath is a <code>String[]</code> value which represents XML\n\t * element path to a desired child element.\n\t * @param xmlns is a <code>String</code> value which represents XML XMLNS.\n\t *\n\t * @return a <code>true</code> is element given in parameters is found in the packet\n\t * stanza, otherwise <code>false</code>\n\t * @deprecated use {@link #isXMLNSStaticStr(String[], String)} instead,\n\t * if possible, if not contact us so we preserve the API.\n\t */\n\t@Deprecated\n\tpublic boolean isXMLNS(String[] elementPath, String xmlns) {\n\t\tString this_xmlns = elem.getXMLNS(elementPath);\n\n\t\treturn (this_xmlns == xmlns);\n\t}\n\n\t/**\n\t * Checks whether the XML stanza contains XML element with given XML path and\n\t * element name and XMLNS. This is inefficient method and highly recommended not to use.\n\t * Please use the other methods which accept <code>String[]</code> instead.\n\t *\n\t *\n\t * @param elementPath is a string with XML path in form of: \"/root/child1/child2\"\n\t * @param xmlns is a valid XML namespace.\n\t *\n\t * @return a <code>true</code> is element given in parameters is found in the packet\n\t * stanza, otherwise <code>false</code>\n\t * @deprecated use {@link #isXMLNSStaticStr(String[], String)} instead,\n\t * if possible, or {@link #isXMLNS(String[], String)}\n\t */\n\t@Deprecated\n\tpublic boolean isXMLNS(String elementPath, String xmlns) {\n\t\tString this_xmlns = elem.getXMLNS(elementPath);\n\n\t\treturn (this_xmlns == xmlns);\n\t}\n\n\t/**\n\t * The method marks that the packet has NOT been processed by a packet processor\n\t * with a given ID.\n\t *\n\t * @param id is a <code>String</code> instance of the packet processer identifier.\n\t */\n\tpublic void notProcessedBy(String id) {\n\t\tskippedProcessorsIds.add(id);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method allows to set-force XMLNS for the element. This is mostly used in cases\n\t * where there is no XMLNS provided for the element (by the client for example) and\n\t * then a default one is used. However, in some contexts a default XMLNS might be\n\t * confusing such as when the packet is passed between s2s to c2s connection and\n\t * the default XMLNS changes.\n\t *\n\t * @param xmlns a valid XMLNS string for the element.\n\t */\n\tpublic void setXMLNS(String xmlns) {\n\t\telem.setXMLNS(xmlns);\n\t\tpacketToString       = null;\n\t\tpacketToStringSecure = null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method returns a modified copy of the <code>Packet</code> with its stanza as\n\t * stanza <code>result</code> used for reporting <em>IQ</em> stanza results.\n\t * The method preserves all the attributes of the original stanza, swaps stanza\n\t * source and destination addresses and can optionally add more child XML\n\t * elements and can preserve existing children elements up to given depth.\n\t *\n\t * @param includeXML is an XML content serialized to <code>String</code> or just\n\t * character data as <code>String</code> which has to be added to response\n\t * stanza.\n\t * @param originalXML parameter specified whether and if so to what depth the\n\t * original stanza child elements have to be preserved in the response packet.\n\t * @return a new <code>Packet</code> instance with an OK (result) type stanza\n\t * which is a response to this <code>Packet</code> instance.\n\t */\n\tpublic Packet okResult(final String includeXML, final int originalXML) {\n\t\tElement reply = new Element(elem.getName());\n\n\t\tif (getXMLNS() != null) {\n\t\t\treply.setXMLNS(getXMLNS());\n\t\t}\n\t\treply.setAttribute(TYPE_ATT, StanzaType.result.toString());\n\t\tif (getStanzaId() != null) {\n\t\t\treply.setAttribute(ID_ATT, getStanzaId());\n\t\t}    // end of if (getElemId() != null)\n\n\t\tElement old_child = elem;\n\t\tElement new_child = reply;\n\n\t\tfor ( int i = 0 ; i < originalXML ; i++ ) {\n\t\t\tfinal List<Element> old_children = old_child.getChildren();\n\t\t\tif ( old_children != null && old_children.size() > 0 ){\n\t\t\t\told_child = old_children.get( 0 );\n\t\t\t\tElement tmp = new Element( old_child.getName() );\n\t\t\t\ttmp.setAttributes( old_child.getAttributes() );\n\t\t\t\tnew_child.addChild( tmp );\n\t\t\t\tnew_child = tmp;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}    // end of for (int i = 0; i < originalXML; i++)\n\t\tif (includeXML != null) {\n\t\t\tnew_child.setCData(includeXML);\n\t\t}    // end of if (includeOriginalXML)\n\n\t\tPacket result = swapFromTo(reply, getStanzaTo(), getStanzaFrom());\n\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method returns a modified copy of the <code>Packet</code> with its stanza as\n\t * stanza <code>result</code> used for reporting <em>IQ</em> stanza results.\n\t * The method preserves all the attributes of the original stanza, swaps stanza\n\t * source and destination addresses and can optionally add more child XML\n\t * elements and can preserve existing children elements up to given depth.\n\t *\n\t * @param includeXML is an XML content which has to be added to the response\n\t * stanza.\n\t * @param originalXML parameter specified whether and if so to what depth the\n\t * original stanza child elements have to be preserved in the response packet.\n\t * @return a new <code>Packet</code> instance with an OK (result) type stanza\n\t * which is a response to this <code>Packet</code> instance.\n\t */\n\tpublic Packet okResult( Element includeXML, int originalXML ) {\n\t\tElement reply = new Element( elem.getName() );\n\n\t\tif ( getXMLNS() != null ){\n\t\t\treply.setXMLNS( getXMLNS() );\n\t\t}\n\t\treply.setAttribute( TYPE_ATT, StanzaType.result.toString() );\n\t\tif ( getStanzaId() != null ){\n\t\t\treply.setAttribute( ID_ATT, getStanzaId() );\n\t\t}    // end of if (getElemId() != null)\n\n\t\tElement old_child = elem;\n\t\tElement new_child = reply;\n\n\t\tfor ( int i = 0 ; i < originalXML ; i++ ) {\n\t\t\tfinal List<Element> old_children = old_child.getChildren();\n\t\t\tif ( old_children != null && old_children.size() > 0 ){\n\t\t\t\told_child = old_children.get( 0 );\n\t\t\t\tElement tmp = new Element( old_child.getName() );\n\t\t\t\ttmp.setAttributes( old_child.getAttributes() );\n\t\t\t\tnew_child.addChild( tmp );\n\t\t\t\tnew_child = tmp;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}    // end of for (int i = 0; i < originalXML; i++)\n\t\tif ( includeXML != null ){\n\t\t\tnew_child.addChild( includeXML );\n\t\t}    // end of if (includeOriginalXML)\n\n\t\tPacket result = swapFromTo( reply, getStanzaTo(), getStanzaFrom() );\n\n\t\tresult.setPriority( priority );\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns a new <code>Packet</code> instance with stanza <em>routed</em>\n\t * which means an original stanza has been enclosed inside a <code>route</code>\n\t * XML element which contains additional information taken from\n\t * <code>Packet</code> packet instance internal attributes.\n\t *\n\t * @return a new <code>Packet</code> instance with <code>route</code> stanza.\n\t */\n\tpublic Packet packRouted() {\n\t\tElement routedp = new Element(\"route\", new String[] { TO_ATT, FROM_ATT, PRIORITY_ATT,\n\t\t\t\t\t\tPERM_ATT }, new String[] { getTo().toString(), getFrom().toString(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t priority.toString(), permissions.toString() });\n\n\t\troutedp.addChild(elem);\n\n\t\treturn packetInstance(routedp, getFrom(), getTo());\n\t}\n\n\t/**\n\t * The method marks that the packet has been processed by a packet processor\n\t * with a given ID.\n\t *\n\t * @param id is a <code>String</code> instance of the packet processer identifier.\n\t */\n\tpublic void processedBy(String id) {\n\t\tprocessorsIds.add(id);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * The method sets a source address for the <code>Packet</code> instance.\n\t *\n\t * @param from is a <code>JID</code> instance of the packet new source address.\n\t */\n\tpublic void setPacketFrom(JID from) {\n\t\tthis.packetFrom = from;\n\t}\n\n\t/**\n\t * The method sets a destination address for the <code>Packet</code> instance.\n\t *\n\t * @param to is a <code>JID</code> instance of the packet new destination\n\t * address.\n\t */\n\tpublic void setPacketTo(JID to) {\n\t\tthis.packetTo = to;\n\t}\n\n\t/**\n\t * The method sets permissions for the packet of a user who sent the stanza.\n\t *\n\t *\n\t * @param perm is <code>Permissions</code> instance of the stanza sender\n\t * permissions calculated by the session manager.\n\t */\n\tpublic void setPermissions(Permissions perm) {\n\t\tpacketToString       = null;\n\t\tpacketToStringSecure = null;\n\t\tpermissions          = perm;\n\t}\n\n\t/**\n\t * The method sets the packet priority. Depending on the priority the packet\n\t * is put to a queue with corresponding priority. This matter only on system\n\t * which experience overload and some packets may be delivered with a delay\n\t * if they are low priority packets.\n\t *\n\t * @param priority is a new <code>Priority</code> instance set for the packet.\n\t */\n\tpublic void setPriority(Priority priority) {\n\t\tthis.priority = priority;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * The method left for compatibility with an old API reasons. Use\n\t * <code>swapStanzaFromTo()</code> instead.\n\t *\n\t * @return a new packet instance with a copy of the stanza element with\n\t * swapped source and destination addresses.\n\t * @deprecated Use <code>swapStanzaFromTo()</code> instead.\n\t */\n\t@Deprecated\n\tpublic Packet swapElemFromTo() {\n\t\treturn swapStanzaFromTo();\n\t}\n\n\t/**\n\t * The method left for compatibility with an old API reasons. Use\n\t * <code>swapStanzaFromTo()</code> instead.\n\t *\n\t * @param type a new stanza type which has to be set to the generated\n\t * stanza copy.\n\t * @return a new packet instance with a copy of the stanza element with\n\t * swapped source and destination addresses.\n\t * @deprecated Use <code>swapStanzaFromTo()</code> instead.\n\t */\n\t@Deprecated\n\tpublic Packet swapElemFromTo(final StanzaType type) {\n\t\treturn swapStanzaFromTo(type);\n\t}\n\n\t/**\n\t * The method creates a new instance of the <code>Packet</code> class with the\n\t * packet source and destination addresses swapped and sets the given stanza\n\t * element plus source and destination addresses for the new stanza.\n\t * This method gives you slightly more flexibility as you can set any source\n\t * and destination address for the new stanza.\n\t * This method is rarely used in packet processors which don't sent a simple\n\t * \"ok result\" response. Some data flow requires a completely new packet\n\t * to be send as a response to the original call, but the response has to be\n\t * delivered to the original sends. As an example are the SASL authentication\n\t * and TLS handshaking.\n\t *\n\t * @param el is an XML element set for the new packet.\n\t * @param stanzaFrom is the stanza source address\n\t * @param stanzaTo is the stanza destination address\n\t *\n\t * @return a new <code>Packet</code> instance.\n\t */\n\tpublic Packet swapFromTo(Element el, JID stanzaFrom, JID stanzaTo) {\n\t\tPacket packet = packetInstance(el, stanzaFrom, stanzaTo);\n\n\t\tpacket.setPacketTo(getFrom());\n\t\tpacket.setPacketFrom(getTo());\n\t\tpacket.setPriority(priority);\n\n\t\treturn packet;\n\t}\n\n\t/**\n\t * Creates a new <code>Packet</code> instance with swapped packet source and\n\t * destination addresses. Please note the new packet contains unchanged copy of the\n\t * original stanza. Stanza source and destination addresses are no swapped.\n\t *\n\t * @return a new {@link Packet} instance.\n\t */\n\tpublic Packet swapFromTo() {\n\t\tElement el    = elem.clone();\n\t\tPacket packet = packetInstance(el, getStanzaFrom(), getStanzaTo());\n\n\t\tpacket.setPacketTo(getFrom());\n\t\tpacket.setPacketFrom(getTo());\n\t\tpacket.setPriority(priority);\n\n\t\treturn packet;\n\t}\n\n\t/**\n\t * The method creates a new <code>Packet</code> instance with a stanza copy\n\t * with swapped source and destination addresses. The packet source and\n\t * destination addresses are set to null.\n\t *\n\t *\n\t * @return a new <code>Packet</code> instance.\n\t */\n\tpublic Packet swapStanzaFromTo() {\n\t\tElement copy  = elem.clone();\n\t\tPacket result = packetInstance(copy, getStanzaTo(), getStanzaFrom());\n\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method creates a new <code>Packet</code> instance with a stanza copy\n\t * with swapped source and destination addresses and the given type set.\n\t * The packet source and destination addresses are set to null.\n\t *\n\t *\n\t * @param type is a new type for the stanza copy to set.\n\t * @return a new <code>Packet</code> instance.\n\t */\n\tpublic Packet swapStanzaFromTo(final StanzaType type) {\n\t\tElement copy = elem.clone();\n\n\t\tcopy.setAttribute(TYPE_ATT, type.toString());\n\n\t\tPacket result = packetInstance(copy, getStanzaTo(), getStanzaFrom());\n\n\t\tresult.setPriority(priority);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method converts the <code>Packet</code> instance to a <code>String</code>\n\t * representation. The stanza XML element is presented as the string and all packet\n\t * attributes are also added to the string.\n\t * The method is for a debugging purposes to log the whole packet content to\n\t * the debug file for further analysis. It is recommended to use\n\t * <code>toStringSecure()</code> instead as it removes all the CData from the\n\t * stanza avoiding exposing user chat message content. The secure method\n\t * also preserves you from flooding your log files in case of a huge chunks of\n\t * data are sent in packets (user photos in vCards or files).\n\t *\n\t * @return a <code>String</code> representation of the packet instance.\n\t */\n\tpublic String toStringFull() {\n\t\tif (packetToString == null) {\n\t\t\tString elemData = elemToString(elem);\n\n\t\t\tpacketToString = calcToString(elemData);\n\t\t}\n\n\t\treturn \"from=\" + packetFrom + \", to=\" + packetTo + packetToString;\n\t}\n\n\t/**\n\t * Provides human-readable string presentation of the <code>Packet</code> object. It is\n\t * not a XMPP stanza only, it also contains some Tigase specific meta-data.\n\t * \n\t * @return human-readable string presentation of the <code>Packet</code> object.\n\t */\n\t@Override\n\tpublic String toString() {\n\t\treturn toString(FULL_DEBUG);\n\t}\n\n\t/**\n\t * Is a convenience method which allows you to call always the same method\n\t * but change (configure) whether you want to get a secure packet string\n\t * representation or full representation.\n\t *\n\t * @param secure parameter specifies whether the secure packet representation\n\t * should be returned (<code>true</code> value) or the full one\n\t * (<code>false</code>).\n\t *\n\t * @return a <code>String</code> representation of the packet instance.\n\t */\n\tpublic String toString(boolean secure) {\n\t\tString result;\n\n\t\tif (secure) {\n\t\t\tresult = toStringSecure();\n\t\t} else {\n\t\t\tresult = toStringFull();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method returns a <code>String</code> representation of the packet with\n\t * all CData content replaced with text: <em>\"CData size: NN\"</em>. This is a\n\t * preferable method to log the packets for debuging purposes.\n\t *\n\t * @return a <code>String</code> representation of the packet instance.\n\t */\n\tpublic String toStringSecure() {\n\t\tif (FULL_DEBUG) {\n\t\t\treturn toStringFull();\n\t\t} else {\n\t\t\tif (packetToStringSecure == null) {\n\t\t\t\tString elemData = elemToStringSecure(elem);\n\n\t\t\t\tpacketToStringSecure = calcToString(elemData);\n\t\t\t}\n\n\t\t\treturn \"from=\" + packetFrom + \", to=\" + packetTo + packetToStringSecure;\n\t\t}\n\t}\n\n\t/**\n\t * The method unpacks the original packet and stanza from <code>route</code>\n\t * stanza.\n\t * This is the opposite action to the <code>packRouted()</code> method.\n\t *\n\t *\n\t * @return a new instance of the <code>Packet</code> class with unpacket\n\t * packet and stanza from <code>route</code> stanza.\n\t *\n\t * @throws TigaseStringprepException if there was a problem with addresses\n\t * stringprep processing.\n\t */\n\tpublic Packet unpackRouted() throws TigaseStringprepException {\n\t\tPacket result = packetInstance(elem.getChildren().get(0));\n\n\t\tresult.setPacketTo(getTo());\n\t\tresult.setPacketFrom(getFrom());\n\t\tresult.setPriority(priority);\n\t\tresult.setPermissions(permissions);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * The method determines whether the packet has been processed by any of\n\t * the packet processors.\n\t * In fact it says whether there has been called method\n\t * <code>processedBy(...)</code> on the packet.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> of the packet was\n\t * processed by any processor and <code>false</code> otherwise.\n\t */\n\tpublic boolean wasProcessed() {\n\t\treturn processorsIds.size() > 0;\n\t}\n\n\t/**\n\t * The method determines whether the packet was directed to processing by any packet processor,\n\t * but it wasn't processed by them because of internal queue full.\n\t *\n\t * @return <code>true</code> if packet was skipped by any processor.\n\t */\n\tpublic boolean wasSkipped() {\n\t\treturn skippedProcessorsIds.size() > 0;\n\t}\n\n\t/**\n\t * The method checks whether the packet has been processed by a\n\t * packet processor with the specified ID.\n\t *\n\t * @param id is a <code>String</code> instance of the packet processor identifier.\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> of the packet was\n\t * processed by a processor with specified ID and <code>false</code> otherwise.\n\t */\n\tpublic boolean wasProcessedBy(String id) {\n\t\treturn processorsIds.contains(id);\n\t}\n\n\t/**\n\t * Common method for creating debugging string representation of {@code Packet}\n\t * objects pre-processed either by regular or secure {@code toString()} {@link Element}\n\t * methods\n\t *\n\t * @param elemData string representation of the Element\n\t * @return debug string representation with additional data.\n\t */\n\tprivate String calcToString(String elemData) {\n\t\treturn \", DATA=\" + elemData + \", SIZE=\" + elem.toString().length() + \", XMLNS=\" +\n\t\t\t\t\t elem.getXMLNS() + \", PRIORITY=\" + priority + \", PERMISSION=\" + permissions +\n\t\t\t\t\t \", TYPE=\" + type;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprivate void setElem(Element elem) {\n\t\tif (elem == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}    // end of if (elem == null)\n\t\tthis.elem = elem;\n\t\tif (elem.getAttributeStaticStr(TYPE_ATT) != null) {\n\t\t\ttype = StanzaType.valueof(elem.getAttributeStaticStr(TYPE_ATT));\n\t\t} else {\n\t\t\ttype = null;\n\t\t}    // end of if (elem.getAttribute(\"type\") != null) else\n\t\tif (elem.getName() == \"cluster\") {\n\t\t\tsetPriority(Priority.CLUSTER);\n\t\t} else {\n\t\t\tif ((elem.getName() == \"presence\") &&\n\t\t\t\t\t((type == null) || (type == StanzaType.available) ||\n\t\t\t\t\t (type == StanzaType.unavailable) || (type == StanzaType.probe))) {\n\t\t\t\tsetPriority(Priority.PRESENCE);\n\t\t\t} else {\n\t\t\t\tif (elem.getName() == \"route\") {\n\t\t\t\t\trouted = true;\n\t\t\t\t} else {\n\t\t\t\t\trouted = false;\n\t\t\t\t}    // end of if (elem.getName().equals(\"route\")) else\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/PacketFilterIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\nimport tigase.stats.StatisticsList;\n\n/**\n * An interface for loadable packet filters to the Tigase server. Every Tigase component\n * can have an independent list of packet filters for outgoing and incoming traffic.\n * A filter can make any change to the processed packet or can block the packet from\n * further processing. Please refer to the <code>filter()</code> method for more details.\n *\n * Created: Jun 8, 2009 1:29:49 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface PacketFilterIfc {\n\n\t/**\n\t * The method initializes the filter. It is always called only once after an instance\n\t * of the filter has been created.\n\t * @param name is a component name which loaded and initialized the filter. This is\n\t * the name of the component which uses the filter.\n\t * @param qType is a packet queue type, differnt one for outgoing traffic and different\n\t * for incoming. A filter may want to treat the traffic differently depending on the\n\t * direction it flows.\n\t */\n\tvoid init(String name, QueueType qType);\n\n\t/**\n\t * This is the actual packet filtering method. It receives a packet as a parameter\n\t * and may make any change to the packet it wishes, remove or add specific payloads\n\t * or redirect the packet to specific destination. <strong>Please note!</strong> it is\n\t * recommended not to modify the actual packet itself. If the filter needs to make\n\t * any changes to the packet it should create a copy of the object, then make\n\t * any changes on the copy and return the copy as the result.\n\t * It may also optionally block the packet from further processing. This means\n\t * that the packet is effectivelly dropped and forgotten.\n\t *\n\t * If the method returns a <code>Packet</code> as a result. It is normally recommended\n\t * not to modify the existing packet as it maybe processed simultanuously by other\n\t * components/threads at the same time. Modifying packet while it is being processed\n\t * may lead to unpredictable results. Therefore, if the filter wants to modify the\n\t * packet it should create a copy of the packet and return modified copy from\n\t * the method.\n\t * If the filter decided to block the packet it just has to return null. In most cases,\n\t * however the method returns the packet it received as a parameter to method call.\n\t * @param packet for the filter processing.\n\t *\n\t * Please note, the packet filtering may affect performance significantly therefore\n\t * this method should be carefully tested and optimized under a high load.\n\t *\n\t * @return a Packet object which is further processed by the system. If the\n\t * method decided to block the packet it returns null. If the method want the\n\t * packet to be processed without any modifications it returns the same object\n\t * it received as a parameter. It may also return a modified copy of the Packet.\n\t */\n\tPacket filter(Packet packet);\n\n\t/**\n\t * A filter may optionally return some processing statistics. Please note the method\n\t * may be called quite frequently (once a second) therefore no expensive calculation\n\t * should be performed inside the method.\n\t * @param list of statistics created by the master object. The packet instance should\n\t * add its statistics to the list.\n\t */\n\tvoid getStatistics(StatisticsList list);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Permissions.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server;\n\n/**\n * Describe class Permissions here.\n *\n *\n * Created: Tue Jan 23 22:52:45 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum Permissions {\n\n\tNONE,     // Unknown user JID\n  ANONYM,   // Anonymous user\n  REMOTE,   // Packet from a user from a different XMPP installation\n\tLOCAL,    // This is local user JID but not authenticated yet\n\tAUTH,     // Local authenticated and authorized user\n\tTRUSTED,  // Trusted account, can broadcast packets\n\tADMIN;    // Admin account already authenticated\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/PolicyViolationException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server;\n\npublic class PolicyViolationException extends Exception {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic PolicyViolationException() {\n\t\tsuper();\n\t}\n\n\tpublic PolicyViolationException( String message ) {\n\t\tsuper( message );\n\t}\n\n\tpublic PolicyViolationException( String message, Throwable cause ) {\n\t\tsuper( message, cause );\n\t}\n\n\tpublic PolicyViolationException( Throwable cause ) {\n\t\tsuper( cause );\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Presence.java",
    "content": "/*\n * Presence.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 31, 2009 8:42:05 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Presence\n\t\t\t\textends Packet {\n\t/** Field description */\n\tpublic static final String ELEM_NAME = \"presence\";\n\n\t/** Field description */\n\tpublic static final String[] PRESENCE_ERROR_PATH = { ELEM_NAME, \"error\" };\n\n\t/** Field description */\n\tpublic static final String[] PRESENCE_PRIORITY_PATH = { ELEM_NAME, \"priority\" };\n\tpublic static final String[] PRESENCE_SHOW_PATH = { ELEM_NAME, \"show\" };\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic Presence(Element elem) throws TigaseStringprepException {\n\t\tsuper(elem);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param elem\n\t * @param stanzaFrom\n\t * @param stanzaTo\n\t */\n\tpublic Presence(Element elem, JID stanzaFrom, JID stanzaTo) {\n\t\tsuper(elem, stanzaFrom, stanzaTo);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected String[] getElNameErrorPath() {\n\t\treturn PRESENCE_ERROR_PATH;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/Priority.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\n/**\n * Created: Feb 13, 2009 9:44:53 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum Priority {\n\n\tSYSTEM,\n\tCLUSTER,\n\tHIGH,\n\tNORMAL,\n\tLOW,\n\tPRESENCE,\n\tLOWEST;\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/QueueType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\n/**\n * Created: Jun 8, 2009 1:53:38 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum QueueType {\n\tIN_QUEUE, OUT_QUEUE;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ReceiverTimeoutHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\n/**\n * Created: Feb 16, 2009 1:44:46 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ReceiverTimeoutHandler {\n\n\tvoid timeOutExpired(Packet data);\n\n\tvoid responseReceived(Packet data, Packet response);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ServerComponent.java",
    "content": "/*\n * ServerComponent.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n/**\n * Interface ServerComponent\n *\n * Object of this type can be managed by MessageRouter. All classes which are\n * loaded by MessageRouter must inherit this interface.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ServerComponent {\n\t/**\n\t * Method is called by <code>MessageRouter</code> when all the startup components of\n\t * the server have been loaded and configured through setProperties(...) call.\n\t * At this point the whole server should be loaded and functional, except\n\t * initializations taking place in this routine.\n\t *\n\t */\n\tvoid initializationCompleted();\n\n\t/**\n\t * <code>processPacket</code> is a blocking processing method implemented\n\t * by all components. This method processes packet and returns results\n\t * instantly without waiting for any resources.\n\t *\n\t * @param packet a <code>Packet</code> value\n\t * @param results\n\t */\n\tvoid processPacket(Packet packet, Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tvoid release();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tJID getComponentId();\n\n\t/**\n\t * Allows to obtain various informations about components\n\t *\n\t * @return information about particular component\n\t */\n\tComponentInfo getComponentInfo();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tString getName();\n\n\t/**\n\t * Method returns information about whether the initialization process\n\t * (initializationCompleted()) method has been called.\n\t * @return <code>true</code> if initialization of the object has been completed\n\t * <code>false</code> otherwise\n\t */\n\tboolean isInitializationComplete();\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t */\n\tvoid setName(String name);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/06/08\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ServiceChecker.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPIOService;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface ServiceChecker here.\n *\n *\n * Created: Sat Jun 21 22:45:52 2008\n *\n * @param <IO>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ServiceChecker<IO extends XMPPIOService<?>> {\n\tvoid check(IO service);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ThreadExceptionHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server;\n\nimport java.util.logging.Logger;\nimport java.util.logging.Level;\n\n/**\n * Class ThreadExceptionHandler.java is responsible helper class used to catch\n * all unhandled exception from all threads.\n * This is default handler which sends exception stack trace to log system. If\n * necessary other server packages can use own custom handlers and do something\n * else with unhandled exceptions. This handler is only implemented to avoid\n * hidden exception causing bugs.\n *\n * <p>\n * Created: Thu Sep 30 22:24:24 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n\npublic class ThreadExceptionHandler\n  implements Thread.UncaughtExceptionHandler {\n\n  private static final Logger log =\n    Logger.getLogger(\"tigase.server.ThreadExceptionHandler\");\n\n  public void uncaughtException(final Thread t, final Throwable e) {\n    log.log(Level.SEVERE,\n      \"Uncaught thread: \\\"\" + t.getName() + \"\\\" exception\", e);\n  }\n\n}// ThreadExceptionHandler\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/XMPPServer.java",
    "content": "/*\n * @(#)XMPPServer.java   2010.01.15 at 08:51:06 PST\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.conf.ConfigurationException;\nimport tigase.conf.ConfiguratorAbstract;\nimport tigase.util.ClassUtil;\nimport tigase.xml.XMLUtils;\n\n//~--- classes ----------------------------------------------------------------\n/**\n * Describe class XMPPServer here.\n *\n *\n * Created: Wed Nov 23 07:04:18 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic final class XMPPServer {\n\n\t@SuppressWarnings(\"PMD\")\n\t/** property allowing setting up configurator implementation of\n\t * {@link tigase.conf.ConfiguratorAbstract} used in Tigase.\n\t */\n\tpublic static final String CONFIGURATOR_PROP_KEY = \"tigase-configurator\";\n\n\t/** default configurator implementation of\n\t * {@link tigase.conf.ConfiguratorAbstract} used in Tigase, which is\n\t * tigase.conf.Configurator. */\n\tprivate static final String DEF_CONFIGURATOR = \"tigase.conf.Configurator\";\n\tpublic static final String HARDENED_MODE_KEY = \"hardened-mode\";\n\n\tpublic static boolean isHardenedModeEnabled() {\n\t\treturn System.getProperty( XMPPServer.HARDENED_MODE_KEY ) == null ? false\n\t\t\t\t\t : Boolean.getBoolean( XMPPServer.HARDENED_MODE_KEY );\n\t}\n\n\t/** Field description */\n\tpublic static final String NAME = \"Tigase\";\n\tprivate static String serverName = \"message-router\";\n\n\tprivate static MessageRouterIfc router = null;\n\tprivate static ConfiguratorAbstract config = null;\n\tprivate static boolean inOSGi = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\t/**\n\t * Creates a new <code>XMPPServer</code> instance.\n\t */\n\tprivate XMPPServer() {\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic static String getImplementationVersion() {\n\t\tString version = ComponentInfo.getImplementationVersion( XMPPServer.class );\n\t\treturn ( version.isEmpty() ? \"0.0.0-0\" : version );\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\t/**\n\t * Returns help regarding command line parameters\n\t */\n\tpublic static String help() {\n\t\treturn \"\\n\" + \"Parameters:\\n\"\n\t\t\t\t\t + \" -h               this help message\\n\"\n\t\t\t\t\t + \" -v               prints server version info\\n\"\n\t\t\t\t\t + \" -n server-name    sets server name\\n\";\n\t}\n\n\t/**\n\t * Describe <code>main</code> method here.\n\t *\n\t * @param args a <code>String[]</code> value\n\t */\n\t@SuppressWarnings(\"PMD\")\n\tpublic static void main( final String[] args ) {\n\n\t\tparseParams( args );\n\n\t\tSystem.out.println( ( new ComponentInfo( XMLUtils.class ) ).toString() );\n\t\tSystem.out.println( ( new ComponentInfo( ClassUtil.class ) ).toString() );\n\t\tSystem.out.println( ( new ComponentInfo( XMPPServer.class ) ).toString() );\n\t\tstart( args );\n\t}\n\n\tpublic static void start( String[] args ) {\n\t\tThread.setDefaultUncaughtExceptionHandler( new ThreadExceptionHandler() );\n\n\t\tif ( !isOSGi() ){\n\t\t\tString initial_config\n\t\t\t\t\t\t = \"tigase.level=ALL\\n\" + \"tigase.xml.level=INFO\\n\"\n\t\t\t\t\t\t\t + \"handlers=java.util.logging.ConsoleHandler\\n\"\n\t\t\t\t\t\t\t + \"java.util.logging.ConsoleHandler.level=ALL\\n\"\n\t\t\t\t\t\t\t + \"java.util.logging.ConsoleHandler.formatter=tigase.util.LogFormatter\\n\";\n\n\t\t\tConfiguratorAbstract.loadLogManagerConfig( initial_config );\n\t\t}\n\n\t\ttry {\n\t\t\tString config_class_name = System.getProperty( CONFIGURATOR_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t DEF_CONFIGURATOR );\n\n\t\t\tconfig = (ConfiguratorAbstract) Class.forName( config_class_name ).newInstance();\n\t\t\tconfig.init( args );\n\n\t\t\t// config = new ConfiguratorOld(config_file, args);\n\t\t\tconfig.setName( \"basic-conf\" );\n\n\t\t\tString mr_class_name = config.getMessageRouterClassName();\n\t\t\trouter = (MessageRouterIfc) Class.forName( mr_class_name ).newInstance();\n\n\t\t\trouter.setName( serverName );\n\t\t\trouter.setConfig( config );\n\t\t\trouter.start();\n\t\t} catch ( ConfigurationException e ) {\n\t\t\tSystem.err.println( \"\" );\n\t\t\tSystem.err.println( \"  --------------------------------------\" );\n\t\t\tSystem.err.println( \"  ERROR! Terminating the server process.\" );\n\t\t\tSystem.err.println( \"  Invalid configuration data: \" + e );\n\t\t\tSystem.err.println( \"  Please fix the problem and start the server again.\" );\n\t\t\tSystem.exit( 1 );\n\t\t} catch ( Exception e ) {\n\t\t\tSystem.err.println( \"\" );\n\t\t\tSystem.err.println( \"  --------------------------------------\" );\n\t\t\tSystem.err.println( \"  ERROR! Terminating the server process.\" );\n\t\t\tSystem.err.println( \"  Problem initializing the server: \" + e );\n\t\t\tSystem.err.println( \"  Please fix the problem and start the server again.\" );\n\t\t\te.printStackTrace();\n\t\t\tSystem.exit( 1 );\n\t\t}\n\t}\n\n\tpublic static void setOSGi( boolean val ) {\n\t\tinOSGi = val;\n\t}\n\n\tpublic static boolean isOSGi() {\n\t\treturn inOSGi;\n\t}\n\n\tpublic static void stop() {\n\t\t( (AbstractMessageReceiver) router ).stop();\n\t}\n\n\t/**\n\t * Allows obtaining {@link tigase.conf.ConfiguratorAbstract} implementation\n\t * used by Tigase to handle all configuration of the server.\n\t *\n\t * @return implementation of {@link tigase.conf.ConfiguratorAbstract}\n\t *         interface.\n\t */\n\tpublic static ConfiguratorAbstract getConfigurator() {\n\t\treturn config;\n\t}\n\n\tpublic static MessageReceiver getComponent( String name ) {\n\t\treturn (MessageReceiver) config.getComponent( name );\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t */\n\t@SuppressWarnings(\"PMD\")\n\tpublic static void parseParams( final String[] args ) {\n\t\tif ( ( args != null ) && ( args.length > 0 ) ){\n\t\t\tfor ( int i = 0 ; i < args.length ; i++ ) {\n\t\t\t\tif ( args[i].equals( \"-h\" ) ){\n\t\t\t\t\tSystem.out.print( help() );\n\t\t\t\t\tSystem.exit( 0 );\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif ( args[i].equals( \"-v\" ) ){\n\t\t\t\t\tSystem.out.print( version() );\n\t\t\t\t\tSystem.exit( 0 );\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif ( args[i].equals( \"-n\" ) ){\n\t\t\t\t\tif ( i + 1 == args.length ){\n\t\t\t\t\t\tSystem.out.print( help() );\n\t\t\t\t\t\tSystem.exit( 1 );\n\t\t\t\t\t} // end of if (i+1 == args.length)\n\t\t\t\t\telse {\n\t\t\t\t\t\tserverName = args[++i];\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (args[i].equals(\"-h\"))\n\n\t\t\t}        // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic static String version() {\n\t\treturn \"\\n\" + \"-- \\n\" + NAME + \" XMPP Server, version: \" + getImplementationVersion()\n\t\t\t\t\t + \"\\n\" + \"Author:  Artur Hefczyc <artur.hefczyc@tigase.org>\\n\" + \"-- \\n\";\n\t}\n}    // XMPPServer\n\n//~ Formatted in Sun Code Convention on 2010.01.15 at 08:51:06 PST\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/ActionAbstract.java",
    "content": "/*\n * ActionAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\nimport tigase.db.UserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterElement;\nimport tigase.xmpp.impl.roster.RosterFlat;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Created: May 1, 2010 7:44:17 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class ActionAbstract\n\t\t\t\timplements ActionIfc {\n\t/** Field description */\n\tpublic static final String AMP_SECURITY_LEVEL = \"--amp-security-level\";\n\n\t/** Field description */\n\tpublic static final String AMP_SECURITY_LEVEL_DEFAULT = \"STRICT\";\n\n\t/** Field description */\n\tpublic static final String SECURITY_PROP_KEY = \"security-level\";\n\tprivate static Logger log                    =\n\t\tLogger.getLogger(ActionAbstract.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected ActionResultsHandlerIfc resultsHandler = null;\n\tprivate SECURITY security                        = SECURITY.STRICT;\n\tprivate UserRepository user_repository           = null;\n\tRosterFlat rosterUtil                            = new RosterFlat();\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate enum SECURITY {\n\n\t\tNONE, PERFORMANCE, STRICT\n\t};\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = new LinkedHashMap<String, Object>();\n\t\tString sec_str           = (String) params.get(AMP_SECURITY_LEVEL);\n\n\t\tif (null == sec_str) {\n\t\t\tsec_str = AMP_SECURITY_LEVEL_DEFAULT;\n\t\t}\n\t\ttry {\n\t\t\tSECURITY sec = SECURITY.valueOf(sec_str.toUpperCase());\n\n\t\t\tsecurity = sec;\n\t\t} catch (Exception e) {}\n\t\tdefs.put(SECURITY_PROP_KEY, security.name());\n\n\t\treturn defs;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tActionResultsHandlerIfc resultsHandler) {\n\t\tthis.resultsHandler = resultsHandler;\n\n\t\tString sec_str = (String) props.get(SECURITY_PROP_KEY);\n\n\t\ttry {\n\t\t\tSECURITY sec = SECURITY.valueOf(sec_str.toUpperCase());\n\n\t\t\tsecurity = sec;\n\t\t} catch (NullPointerException e) {\n\n\t\t\t// Ignore, this is expected here\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Incorrect amp security settings, using defaults: \" + security, e);\n\t\t}\n\n\t\t// Is there shared user repository instance? If so I want to use it:\n\t\tuser_repository = (UserRepository) props.get(RepositoryFactory.SHARED_USER_REPO_PROP_KEY);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param rule\n\t *\n\t * \n\t *\n\t * @throws PacketErrorTypeException\n\t */\n\tprotected Packet prepareAmpPacket(Packet packet, Element rule)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tboolean error_result = false;\n\n\t\tswitch (security) {\n\t\tcase NONE :\n\t\t\tbreak;\n\n\t\tcase PERFORMANCE :\n\t\t\terror_result = true;\n\n\t\t\tbreak;\n\n\t\tcase STRICT :\n\t\t\terror_result = !checkUserRoster(packet.getStanzaTo(), packet.getStanzaFrom());\n\n\t\t\tbreak;\n\t\t}\n\n\t\tPacket result = null;\n\n\t\tif (error_result) {\n\t\t\tresult = Authorization.NOT_ACCEPTABLE.getResponseMessage(packet, \"Subscription between users not valid\", false);\n\t\t} else {\n\t\t\tJID old_from        = packet.getStanzaFrom();\n\t\t\tJID old_to          = packet.getStanzaTo();\n\t\t\tString from_conn_id = packet.getAttributeStaticStr(FROM_CONN_ID);\n\t\t\tJID new_from        = null;\n\n\t\t\tif (from_conn_id != null) {\n\t\t\t\tnew_from = JID.jidInstanceNS(old_from.getDomain());\n\t\t\t} else {\n\t\t\t\tnew_from = JID.jidInstanceNS(old_to.getDomain());\n\t\t\t}\n\n\t\t\t// Packet result = Packet.packetInstance(packet.getElement(), new_from, old_from);\n\t\t\tresult = packet.copyElementOnly();\n\t\t\tresult.initVars(new_from, old_from);\n\n\t\t\tElement amp = result.getElement().getChild(\"amp\", AMP_XMLNS);\n\n\t\t\tresult.getElement().removeChild(amp);\n\t\t\tamp = new Element(\"amp\", new Element[] { rule }, new String[] { \"from\", \"to\",\n\t\t\t\t\t\t\t\"xmlns\", \"status\" }, new String[] { old_from.toString(), old_to.toString(),\n\t\t\t\t\t\t\tAMP_XMLNS, getName() });\n\t\t\tresult.getElement().addChild(amp);\n\t\t\tremoveTigasePayload(result);\n\t\t\tif (from_conn_id != null) {\n\t\t\t\tresult.setPacketTo(JID.jidInstanceNS(from_conn_id));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tprotected void removeTigasePayload(Packet packet) {\n\t\tpacket.getElement().removeAttribute(TO_CONN_ID);\n\t\tpacket.getElement().removeAttribute(TO_RES);\n\t\tpacket.getElement().removeAttribute(OFFLINE);\n\t\tpacket.getElement().removeAttribute(FROM_CONN_ID);\n\t\tpacket.getElement().removeAttribute(SESSION_JID);\n\t\tpacket.getElement().removeAttribute(EXPIRED);\n\t}\n\n\tprivate boolean checkUserRoster(JID user, JID contact) {\n\n\t\tif ( user.getBareJID().equals( contact.getBareJID() ) ){\n\t\t\t// this is the same user, no point in checking sub\n\t\t\treturn true;\n\t\t}\n\n\t\ttry {\n\t\t\tString roster_str = user_repository.getData(user.getBareJID(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tRosterAbstract.ROSTER);\n\n\t\t\tif (roster_str != null) {\n\t\t\t\tMap<BareJID, RosterElement> roster = new LinkedHashMap<BareJID, RosterElement>();\n\n\t\t\t\tRosterFlat.parseRosterUtil(roster_str, roster, null);\n\n\t\t\t\tRosterElement re = roster.get(contact.getBareJID());\n\n\t\t\t\tif (re != null) {\n\t\t\t\t\treturn rosterUtil.isSubscribedFrom(re.getSubscription());\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.INFO, \"Problem retrieving user roster: \" + user, ex);\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/ActionIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Apr 26, 2010 5:05:58 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ActionIfc extends AmpFeatureIfc {\n\tboolean execute(Packet packet, Element rule);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tMap<String, Object> getDefaults(Map<String, Object> params);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tvoid setProperties(Map<String, Object> props, ActionResultsHandlerIfc resultsHandler);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/ActionResultsHandlerIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: May 1, 2010 3:26:50 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ActionResultsHandlerIfc {\n\tboolean addOutPacket(Packet packet);\n\n\tboolean addOutPackets(Queue<Packet> packets);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/AmpComponent.java",
    "content": "/*\n * AmpComponent.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.ConfigurationException;\nimport tigase.disco.XMPPService;\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.server.ServerComponent;\nimport tigase.server.XMPPServer;\nimport tigase.server.amp.action.Alert;\nimport tigase.server.amp.action.Broadcast;\nimport tigase.server.amp.action.Drop;\nimport tigase.server.amp.action.Notify;\nimport tigase.server.amp.action.Store;\nimport tigase.server.amp.cond.Deliver;\nimport tigase.server.amp.cond.ExpireAt;\nimport tigase.server.amp.cond.MatchResource;\nimport tigase.server.xmppsession.SessionManager;\nimport tigase.server.xmppsession.SessionManagerHandler;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Apr 26, 2010 3:22:06 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AmpComponent\n\t\t\t\textends AbstractMessageReceiver\n\t\t\t\timplements ActionResultsHandlerIfc {\n\tprivate static final String AMP_NODE     = \"http://jabber.org/protocol/amp\";\n\tprivate static final Logger log          =\n\t\tLogger.getLogger(AmpComponent.class.getName());\n\tprivate static final String AMP_XMLNS    = AMP_NODE;\n\tprivate static final Element top_feature = new Element(\"feature\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { AMP_NODE });\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate Map<String, ActionIfc> actions       = new ConcurrentSkipListMap<String,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ActionIfc>();\n\tprivate Map<String, ConditionIfc> conditions = new ConcurrentSkipListMap<String,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ConditionIfc>();\n\n\tprotected final Broadcast broadcast = new Broadcast();\n\t//~--- methods --------------------------------------------------------------\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutPacket(Packet packet) {\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\t@Override\n\tpublic boolean addOutPackets(Queue<Packet> packets) {\n\t\treturn super.addOutPackets(packets);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\t\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\t\tActionIfc action         = new Drop();\n\n\t\tactions.put(action.getName(), action);\n\t\taction = new tigase.server.amp.action.Error();\n\t\tactions.put(action.getName(), action);\n\t\taction = new Notify();\n\t\tactions.put(action.getName(), action);\n\t\taction = new tigase.server.amp.action.Deliver();\n\t\tactions.put(action.getName(), action);\n\t\taction = new Store();\n\t\tactions.put(action.getName(), action);\n\t\taction = new Alert();\n\t\tactions.put(action.getName(), action);\n\n\t\tConditionIfc condition = new Deliver();\n\n\t\tconditions.put(condition.getName(), condition);\n\t\tcondition = new ExpireAt();\n\t\tconditions.put(condition.getName(), condition);\n\t\tcondition = new MatchResource();\n\t\tconditions.put(condition.getName(), condition);\n\t\tfor (ActionIfc a : actions.values()) {\n\t\t\tMap<String, Object> d = a.getDefaults(params);\n\n\t\t\tif (d != null) {\n\t\t\t\tdefs.putAll(d);\n\t\t\t}\n\t\t}\n\n\t\tMap<String,Object> d = broadcast.getDefaults(params);\n\t\tif (d != null) {\n\t\t\tdefs.putAll(d);\n\t\t}\n\t\t\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"generic\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"IM AMP Support\";\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tElement query = super.getDiscoInfo(node, jid, from);\n\n\t\tif ((jid != null) &&\n\t\t\t\t(getName().equals(jid.getLocalpart()) || isLocalDomain(jid.toString())) &&\n\t\t\t\t(AMP_NODE.equals(node))) {\n\t\t\tif (query == null) {\n\t\t\t\tquery = new Element(\"query\");\n\t\t\t\tquery.setXMLNS(XMPPService.INFO_XMLNS);\n\t\t\t}\n\t\t\tquery.addChild(new Element(\"identity\", new String[] { \"name\", \"category\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { getDiscoDescription(),\n\t\t\t\t\t\t\t\"im\", getDiscoCategoryType() }));\n\t\t\tquery.addChild(top_feature);\n\t\t\tfor (ActionIfc action : actions.values()) {\n\t\t\t\tquery.addChild(new Element(\"feature\", new String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t AMP_NODE + \"?action=\" + action.getName() }));\n\t\t\t}\n\t\t\tfor (ConditionIfc cond : conditions.values()) {\n\t\t\t\tquery.addChild(new Element(\"feature\", new String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t AMP_NODE + \"?condition=\" + cond.getName() }));\n\t\t\t}\n\n\t\t\t// for (ProcessingThreads<ProcessorWorkerThread> proc_t :\n\t\t\t// processors.values()) {\n\t\t\t// Element[] discoFeatures =\n\t\t\t// proc_t.getWorkerThread().processor.supDiscoFeatures(null);\n\t\t\t//\n\t\t\t// if (discoFeatures != null) {\n\t\t\t// query.addChildren(Arrays.asList(discoFeatures));\n\t\t\t// } // end of if (discoFeatures != null)\n\t\t\t// }\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Found disco info: \" + ((query != null)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? query.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : null));\n\t\t}\n\n\t\treturn query;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"My packet: \" + packet);\n\t\t}\n\n\t\tif (broadcast.preprocess(packet)) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tActionIfc def = null;\n\n\t\tif (packet.getAttributeStaticStr(AmpFeatureIfc.OFFLINE) == null) {\n\t\t\tdef = actions.get(\"deliver\");\n\t\t} else {\n\t\t\tdef = actions.get(\"store\");\n\t\t}\n\n\t\tboolean exec_def = true;\n\t\tElement amp      = packet.getElement().getChild(\"amp\", AMP_XMLNS);\n\n\t\tif (amp != null) {\n\t\t\tList<Element> rules = amp.getChildren();\n\n\t\t\tif ((rules != null) && (rules.size() > 0)) {\n\t\t\t\tfor (Element rule : rules) {\n\t\t\t\t\tif (matchCondition(packet, rule)) {\n\t\t\t\t\t\texec_def = executeAction(packet, rule);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.warning(\"AMP packet but empty rule-set! \" + packet);\n\n\t\t\t\t// In case of such error, let's just drop the packet\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"Not an AMP packet! \" + packet);\n\n\t\t\t// In case of such error, let's just drop the packet\n\t\t\treturn;\n\t\t}\n\t\tif (exec_def) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Executing default action: \" + def.getName());\n\t\t\t}\n\t\t\tdef.execute(packet, null);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\t\tfor (ActionIfc a : actions.values()) {\n\t\t\ta.setProperties(props, this);\n\t\t}\n\n\t\tbroadcast.setProperties(props, this);\n\t\t// for (ConditionIfc c : conditions.values()) {\n\t\t// c.setProperties(props, this);\n\t\t// }\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// ~--- methods --------------------------------------------------------------\n\tprivate boolean executeAction(Packet packet, Element rule) {\n\t\tString act = rule.getAttributeStaticStr(AmpFeatureIfc.ACTION_ATT);\n\n\t\tif (act != null) {\n\t\t\tActionIfc action = actions.get(act);\n\n\t\t\tif (action != null) {\n\t\t\t\tboolean result = action.execute(packet, rule);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Matched action: \" + action.getName() + \", result: \" + result);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t} else {\n\t\t\t\tlog.fine(\"No action found for act: \" + act);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.fine(\"No actionset for rule: \" + rule);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate boolean matchCondition(Packet packet, Element rule) {\n\t\tString cond = rule.getAttributeStaticStr(AmpFeatureIfc.CONDITION_ATT);\n\n\t\tif (cond != null) {\n\t\t\tConditionIfc condition = conditions.get(cond);\n\n\t\t\tif (condition != null) {\n\t\t\t\tboolean result = condition.match(packet, rule);;\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Matched condition: \" + condition.getName() + \", result: \" + result);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t} else {\n\t\t\t\tlog.fine(\"No condition found for cond: \" + cond);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.fine(\"No condition set for rule: \" + rule);\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/AmpFeatureIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Apr 28, 2010 5:38:24 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface AmpFeatureIfc {\n\n\t/** Field description */\n\tpublic static final String AMP_MSG_REPO_CLASS_PROP_KEY = \"amp-repo-class\";\n\t\n\t/** Field description */\n\tpublic static final String AMP_MSG_REPO_CLASS_PARAM = \"--amp-repo-class\";\n\t\n\t/** Field description */\n\tpublic static final String AMP_MSG_REPO_URI_PARAM = \"--amp-repo-uri\";\n\n\t/** Field description */\n\tpublic static final String AMP_MSG_REPO_URI_PROP_KEY = \"amp-repo-uri\";\n\n\t/** Field description */\n\tpublic static final String AMP_XMLNS = \"http://jabber.org/protocol/amp\";\n\t\n\t/** Field description */\n\tpublic static final String FROM_CONN_ID = \"from-conn-id\";\n\n\tpublic static final String SESSION_JID = \"from-session-jid\";\n\n\t/** Field description */\n\tpublic static final String TO_CONN_ID = \"to-conn-id\";\n\n\t/** Field description */\n\tpublic static final String TO_RES = \"to-res\";\n\n\t/** Field description */\n\tpublic static final String EXPIRED = \"expired\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE = \"offline\";\n\n\t/** Field description */\n\tpublic static final String MSG_OFFLINE_PROP_KEY = \"msg-offline\";\n\n\t/** Field description */\n\tpublic static final String CONDITION_ATT = \"condition\";\n\n\t/** Field description */\n\tpublic static final String ACTION_ATT = \"action\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tString getName();\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/ConditionIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Apr 26, 2010 5:06:13 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ConditionIfc extends AmpFeatureIfc {\n\tboolean match(Packet packet, Element rule);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/JDBCMsgRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.amp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.DataRepository.dbTypes;\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.util.Algorithms;\nimport tigase.util.SimpleCache;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\n\nimport java.security.NoSuchAlgorithmException;\nimport java.sql.DataTruncation;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Timestamp;\nimport java.sql.Types;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.NonAuthUserRepositoryImpl;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: May 3, 2010 5:28:02 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Repository.Meta( isDefault=true, supportedUris = { \"jdbc:[^:]+:.*\" } )\npublic class JDBCMsgRepository extends MsgRepository<Long> {\n\tprivate static final Logger log = Logger.getLogger(JDBCMsgRepository.class.getName());\n\tprivate static final String MSG_TABLE = \"msg_history\";\n\tprivate static final String MSG_ID_COLUMN = \"msg_id\";\n\tprivate static final String MSG_TIMESTAMP_COLUMN = \"ts\";\n\tprivate static final String MSG_EXPIRED_COLUMN = \"expired\";\n\tprivate static final String MSG_FROM_UID_COLUMN = \"sender_uid\";\n\tprivate static final String MSG_TO_UID_COLUMN = \"receiver_uid\";\n\tprivate static final String MSG_TYPE_COLUMN = \"msg_type\";\n\tprivate static final String MSG_BODY_COLUMN = \"message\";\n\tprivate static final String HISTORY_FLAG_COLUMN = \"history_enabled\";\n\tprivate static final String JID_TABLE = \"user_jid\";\n\tprivate static final String JID_ID_COLUMN = \"jid_id\";\n\tprivate static final String JID_SHA_COLUMN = \"jid_sha\";\n\tprivate static final String JID_COLUMN = \"jid\";\n\tprivate static final int StatementsCount = 2;\n\t/* @formatter:off */\n\tprivate static final String MYSQL_CREATE_MSG_TABLE =\n\t\t\t\t\t\t\t\"create table \" + MSG_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ MSG_ID_COLUMN + \" serial,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TIMESTAMP_COLUMN + \" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_EXPIRED_COLUMN + \" DATETIME,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_FROM_UID_COLUMN + \" bigint unsigned,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TO_UID_COLUMN + \" bigint unsigned NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TYPE_COLUMN + \" int NOT NULL default 0,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_BODY_COLUMN + \" varchar(4096) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ \" key (\" + MSG_EXPIRED_COLUMN + \"), \"\n\t\t\t\t\t\t\t+ \" key (\" + MSG_FROM_UID_COLUMN + \", \" + MSG_TO_UID_COLUMN + \"),\"\n\t\t\t\t\t\t\t+ \" key (\" + MSG_TO_UID_COLUMN + \", \" + MSG_FROM_UID_COLUMN + \"))\"\n\t\t\t\t\t\t\t+ \" ENGINE=InnoDB default character set utf8 ROW_FORMAT=DYNAMIC;\";\n\tprivate static final String PGSQL_CREATE_MSG_TABLE =\n\t\t\t\t\t\t\t\"create table \" + MSG_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ MSG_ID_COLUMN + \" serial,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TIMESTAMP_COLUMN + \" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_EXPIRED_COLUMN + \" TIMESTAMP,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_FROM_UID_COLUMN + \" bigint,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TO_UID_COLUMN + \" bigint NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TYPE_COLUMN + \" int NOT NULL default 0,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_BODY_COLUMN + \" varchar(4096) NOT NULL);\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_EXPIRED_COLUMN + \" on \" + MSG_TABLE\n\t\t\t\t\t\t\t+ \" (\" + MSG_EXPIRED_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_FROM_UID_COLUMN + \"_\" + MSG_TO_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_FROM_UID_COLUMN + \",\" + MSG_TO_UID_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_TO_UID_COLUMN + \"_\" + MSG_FROM_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_TO_UID_COLUMN + \",\" + MSG_FROM_UID_COLUMN + \");\";\n\tprivate static final String SQLSERVER_CREATE_MSG_TABLE =\n\t\t\t\t\t\t\t\"create table \" + MSG_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ MSG_ID_COLUMN + \" [bigint] IDENTITY(1,1),\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TIMESTAMP_COLUMN + \" [datetime] DEFAULT getdate() ,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_EXPIRED_COLUMN + \" [datetime] ,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_FROM_UID_COLUMN + \" bigint,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TO_UID_COLUMN + \" bigint NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TYPE_COLUMN + \" int NOT NULL default 0,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_BODY_COLUMN + \" nvarchar(4000) NOT NULL);\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_EXPIRED_COLUMN + \" on \" + MSG_TABLE\n\t\t\t\t\t\t\t+ \" (\" + MSG_EXPIRED_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_FROM_UID_COLUMN + \"_\" + MSG_TO_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_FROM_UID_COLUMN + \",\" + MSG_TO_UID_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_TO_UID_COLUMN + \"_\" + MSG_FROM_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_TO_UID_COLUMN + \",\" + MSG_FROM_UID_COLUMN + \");\";\n\tprivate static final String DERBY_CREATE_MSG_TABLE =\n\t\t\t\t\t\t\t\"create table \" + MSG_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ MSG_ID_COLUMN + \" bigint generated by default as identity not null,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TIMESTAMP_COLUMN + \" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_EXPIRED_COLUMN + \" TIMESTAMP,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_FROM_UID_COLUMN + \" bigint,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TO_UID_COLUMN + \" bigint NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_TYPE_COLUMN + \" int NOT NULL default 0,\" + \"  \"\n\t\t\t\t\t\t\t+ MSG_BODY_COLUMN + \" varchar(4096) NOT NULL);\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_EXPIRED_COLUMN + \" on \" + MSG_TABLE\n\t\t\t\t\t\t\t+ \" (\" + MSG_EXPIRED_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_FROM_UID_COLUMN + \"_\" + MSG_TO_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_FROM_UID_COLUMN + \",\" + MSG_TO_UID_COLUMN + \");\"\n\t\t\t\t\t\t\t+ \"create index index_\" + MSG_TO_UID_COLUMN + \"_\" + MSG_FROM_UID_COLUMN\n\t\t\t\t\t\t\t+ \" on \" + MSG_TABLE + \"(\" + MSG_TO_UID_COLUMN + \",\" + MSG_FROM_UID_COLUMN + \");\";\n\tprivate static final String MYSQL_CREATE_JID_TABLE =\n\t\t\t\t\t\t\t\"create table \" + JID_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ JID_ID_COLUMN + \" serial,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_SHA_COLUMN + \" char(128) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_COLUMN + \" varchar(2049) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ HISTORY_FLAG_COLUMN + \" int default 0,\"\n\t\t\t\t\t\t\t+ \" primary key (\" + JID_ID_COLUMN + \"),\"\n\t\t\t\t\t\t\t+ \" unique key \" + JID_SHA_COLUMN + \" (\" + JID_SHA_COLUMN + \"),\"\n\t\t\t\t\t\t\t+ \" key \" + JID_COLUMN + \" (\" + JID_COLUMN + \"(255)))\";\n\tprivate static final String PGSQL_CREATE_JID_TABLE =\n\t\t\t\t\t\t\t\"create table \" + JID_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ JID_ID_COLUMN + \" serial,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_SHA_COLUMN + \" char(128) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_COLUMN + \" varchar(2049) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ HISTORY_FLAG_COLUMN + \" int default 0,\"\n\t\t\t\t\t\t\t+ \" primary key (\" + JID_ID_COLUMN + \")); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_SHA_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_SHA_COLUMN + \"); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_COLUMN + \"); \";\n\tprivate static final String SQLSERVER_CREATE_JID_TABLE =\n\t\t\t\t\t\t\t\"create table \" + JID_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ JID_ID_COLUMN + \" [bigint] IDENTITY(1,1),\" + \"  \"\n\t\t\t\t\t\t\t+ JID_SHA_COLUMN + \" char(128) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_COLUMN + \" nvarchar(2049) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ HISTORY_FLAG_COLUMN + \" int default 0,\"\n\t\t\t\t\t\t\t+ \" primary key (\" + JID_ID_COLUMN + \")); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_SHA_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_SHA_COLUMN + \"); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_COLUMN + \"); \";\n\tprivate static final String DERBY_CREATE_JID_TABLE =\n\t\t\t\t\t\t\t\"create table \" + JID_TABLE + \" ( \" + \"  \"\n\t\t\t\t\t\t\t+ JID_ID_COLUMN + \" bigint generated by default as identity not null,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_SHA_COLUMN + \" char(128) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ JID_COLUMN + \" varchar(2049) NOT NULL,\" + \"  \"\n\t\t\t\t\t\t\t+ HISTORY_FLAG_COLUMN + \" int default 0,\"\n\t\t\t\t\t\t\t+ \" primary key (\" + JID_ID_COLUMN + \")); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_SHA_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_SHA_COLUMN + \"); \"\n\t\t\t\t\t\t\t+ \"create unique index index_\" + JID_COLUMN + \" on \" + JID_TABLE\n\t\t\t\t\t\t\t+ \" (\" + JID_COLUMN + \"); \";\n\tprivate static final String MSG_INSERT_QUERY =\n\t\t\t\t\t\t\t\"insert into \" + MSG_TABLE + \" ( \"\n\t\t\t\t\t\t\t+ MSG_EXPIRED_COLUMN + \", \"\n\t\t\t\t\t\t\t+ MSG_FROM_UID_COLUMN + \", \"\n\t\t\t\t\t\t\t+ MSG_TO_UID_COLUMN + \", \"\n\t\t\t\t\t\t\t+ MSG_TYPE_COLUMN + \", \"\n\t\t\t\t\t\t\t+ MSG_BODY_COLUMN + \") values (?, ?, ?, ?, ?)\";\n\tprivate static final String MSG_SELECT_TO_JID_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"select * from \" + MSG_TABLE + \" where \" + MSG_TO_UID_COLUMN + \" = ?\";\n\tprivate static final String MSG_SELECT_IDS_TO_JID_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMSG_SELECT_TO_JID_QUERY + \" AND \"+ MSG_ID_COLUMN + \" IN ( \";\n\tprivate static final String MSG_SELECT_COUNT_TO_JID_QUERY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t= \"select \" + MSG_TYPE_COLUMN + \" , count(\" + MSG_TYPE_COLUMN + \") from \" + MSG_TABLE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" where \" + MSG_TO_UID_COLUMN + \" = ? \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" group by \" + MSG_TYPE_COLUMN;\n\tprivate static final String MSG_SELECT_LIST_TO_JID_QUERY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t= \"select \" + MSG_ID_COLUMN + \",\"+ MSG_TYPE_COLUMN + \",\"+ JID_COLUMN + \" from \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ MSG_TABLE + \"  left join \" + JID_TABLE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" ON \" + MSG_TABLE + \".\" + MSG_FROM_UID_COLUMN + \"=\" +  JID_TABLE + \".\" + JID_ID_COLUMN\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" where \" + MSG_TO_UID_COLUMN + \" = ? \";\n\tprivate static final String MSG_DELETE_TO_JID_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"delete from \" + MSG_TABLE + \" where \" + MSG_TO_UID_COLUMN + \" = ?\";\n\tprivate static final String MSG_DELETE_IDS_TO_JID_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMSG_DELETE_TO_JID_QUERY + \" AND \" + MSG_ID_COLUMN + \" IN ( \";\n\tprivate static final String MSG_DELETE_ID_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"delete from \" + MSG_TABLE + \" where \" + MSG_ID_COLUMN + \" = ?\";\n\tprivate static final String MSG_SELECT_EXPIRED_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"select * from \" + MSG_TABLE + \" where expired is not null order by expired\";\n\tprivate static final String MSG_SELECT_EXPIRED_BEFORE_QUERY =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"select * from \" + MSG_TABLE + \" where expired is not null and expired <= ? order by expired\";\n\n\tprivate static final String MYSQL_CREATE_BROADCAST_MSGS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"expired datetime NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"msg varchar(4096) NOT NULL, \"\n\t\t\t\t\t\t\t+ \" primary key (id))\";\n\tprivate static final String PGSQL_CREATE_BROADCAST_MSGS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"expired timestamp NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"msg varchar(4096) NOT NULL, \"\n\t\t\t\t\t\t\t+ \" primary key (id))\";\n\tprivate static final String SQLSERVER_CREATE_BROADCAST_MSGS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"expired datetime NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"msg nvarchar(4000) NOT NULL, \"\n\t\t\t\t\t\t\t+ \" primary key (id))\";\n\tprivate static final String DERBY_CREATE_BROADCAST_MSGS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"expired timestamp NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"msg varchar(4096) NOT NULL, \"\n\t\t\t\t\t\t\t+ \" primary key (id))\";\n\t\n\tprivate static final String MYSQL_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs_recipients ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"msg_id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"jid_id bigint unsigned NOT NULL,  \"\n\t\t\t\t\t\t\t+ \" primary key (msg_id, jid_id))\";\n\tprivate static final String PGSQL_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs_recipients ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"msg_id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"jid_id bigint NOT NULL,  \"\n\t\t\t\t\t\t\t+ \" primary key (msg_id, jid_id))\";\n\tprivate static final String SQLSERVER_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs_recipients ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"msg_id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"jid_id bigint NOT NULL,  \"\n\t\t\t\t\t\t\t+ \" primary key (msg_id, jid_id))\";\n\tprivate static final String DERBY_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE =\n\t\t\t\t\t\t\t\"create table broadcast_msgs_recipients ( \" + \"  \"\n\t\t\t\t\t\t\t+ \"msg_id varchar(128) NOT NULL,  \"\n\t\t\t\t\t\t\t+ \"jid_id bigint NOT NULL,  \"\n\t\t\t\t\t\t\t+ \" primary key (msg_id, jid_id))\";\t\n\t\n\tprivate static final String MSG_SELECT_MESSAGES_TO_BROADCAST = \n\t\t\t\"select id, expired, msg from broadcast_msgs where expired >= ?\";\n\tprivate static final String SQLSERVER_MSG_INSERT_MESSAGE_TO_BROADCAST =\n\t\t\t\"insert into broadcast_msgs (id, expired, msg) values (?, ?, ?) where not exists (select 1 from broadcast_msgs where id = ?)\";\n\tprivate static final String SQL_MSG_INSERT_MESSAGE_TO_BROADCAST =\n\t\t\t\"insert into broadcast_msgs (id, expired, msg) select ?, ?, ? from (select 1) x where not exists (select 1 from broadcast_msgs where id = ?)\";\n\tprivate static final String DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST1 = \n\t\t\t\"select id from broadcast_msgs where id = ?\";\n\tprivate static final String DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST2 = \n\t\t\t\"insert into broadcast_msgs (id, expired, msg) values (?,?,?)\";\n\tprivate static final String MSG_SELECT_BROADCAST_RECIPIENTS = \n\t\t\t\"select j.\" + JID_COLUMN + \" from broadcast_msgs_recipients r join \" + JID_TABLE + \" j on j.\" + JID_ID_COLUMN + \" = r.jid_id where r.msg_id = ?\";\n\tprivate static final String SQLSERVER_MSG_ENSURE_BROADCAT_RECIPIETN = \n\t\t\t\"insert into broadcast_msgs_recipients (msg_id, jid_id) values (?, ?) where not exists (select 1 from broadcast_msgs_recipients where msg_id = ? and jid_id = ?)\";\n\tprivate static final String SQL_MSG_ENSURE_BROADCAT_RECIPIETN = \n\t\t\t\"insert into broadcast_msgs_recipients (msg_id, jid_id) select ?, ? from (select 1) x where not exists (select 1 from broadcast_msgs_recipients where msg_id = ? and jid_id = ?)\";\n\tprivate static final String DERBY_MSG_ENSURE_BROADCAT_RECIPIETN1 = \n\t\t\t\"select 1 from broadcast_msgs_recipients where msg_id = ? and jid_id = ?\";\n\tprivate static final String DERBY_MSG_ENSURE_BROADCAT_RECIPIETN2 = \n\t\t\t\"insert into broadcast_msgs_recipients (msg_id, jid_id) values (?, ?)\";\n\t\n\tprivate static final String GET_USER_UID_DEF_QUERY =\n\t\t\"select \" + \n\t\t  JID_ID_COLUMN + \", \" + \n\t\t  JID_COLUMN + \n\t\t\" from \" + JID_TABLE + \" where \" + JID_SHA_COLUMN + \" = ?\";\n        private static final String MSG_COUNT_FOR_TO_AND_FROM_QUERY_DEF =\n                \"select count(*) from \" + MSG_TABLE + \" where \" + MSG_TO_UID_COLUMN + \" = ? and \" + MSG_FROM_UID_COLUMN + \" = ?\";\n\tprivate static final String ADD_USER_JID_ID_QUERY =\n\t\t\"insert into \" + JID_TABLE + \" ( \" + JID_SHA_COLUMN + \", \" + JID_COLUMN + \") select ?, ? \"\n\t\t+ \"WHERE NOT EXISTS (SELECT 1 FROM \" + JID_TABLE+ \" WHERE \" + JID_SHA_COLUMN + \" = ? AND \" + JID_COLUMN +\" = ? )\";\n\tprivate static final String ADD_USER_JID_ID_QUERY_MYSQL =\n\t\t\"insert into \" + JID_TABLE + \" ( \" + JID_SHA_COLUMN + \", \" + JID_COLUMN + \") select ?, ? \"\n\t\t+ \"from dual \"\n\t\t+ \"WHERE NOT EXISTS (SELECT 1 FROM \" + JID_TABLE+ \" WHERE \" + JID_SHA_COLUMN + \" = ? AND \" + JID_COLUMN +\" = ? )\";\n\tprivate static final String ADD_USER_JID_ID_QUERY_DERBY =\n\t\t\"insert into \" + JID_TABLE + \" ( \" + JID_SHA_COLUMN + \", \" + JID_COLUMN + \") select ?, ? \"\n\t\t+ \"FROM SYSIBM.SYSDUMMY1 \"\n\t\t+ \"WHERE NOT EXISTS (SELECT 1 FROM \" + JID_TABLE+ \" WHERE \" + JID_SHA_COLUMN + \" = ? AND \" + JID_COLUMN +\" = ? )\";\n\t/* @formatter:on */\n\tprivate static final String GET_USER_UID_PROP_KEY = \"user-uid-query\";\n\tprivate static final String MSGS_COUNT_LIMIT_PROP_KEY = \"count-limit-query\";\n\tprivate static final int MAX_UID_CACHE_SIZE = 100000;\n\tprivate static final long MAX_UID_CACHE_TIME = 3600000;\n//\tprivate static final Map<String, JDBCMsgRepository> repos =\n//\t\t\tnew ConcurrentSkipListMap<String, JDBCMsgRepository>();\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\tprivate String uid_query = GET_USER_UID_DEF_QUERY;\n\tprivate String msg_count_for_limit_query = MSG_COUNT_FOR_TO_AND_FROM_QUERY_DEF;\n\tprivate String msg_insert_message_to_broadcast = SQL_MSG_INSERT_MESSAGE_TO_BROADCAST;\n\tprivate String msg_ensure_broadcast_recipient = SQL_MSG_ENSURE_BROADCAT_RECIPIETN;\n\tprivate String add_user_jid_id = ADD_USER_JID_ID_QUERY;\n\tprivate boolean initialized = false;\n\tprivate Map<BareJID, Long> uids_cache = Collections\n\t\t\t.synchronizedMap(new SimpleCache<BareJID, Long>(MAX_UID_CACHE_SIZE,\n\t\t\t\t\tMAX_UID_CACHE_TIME));\n\n\t@Override\n\tpublic void initRepository(String conn_str, Map<String, String> map)\n\t\t\tthrows DBInitException {\n\t\tif (initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\tinitialized = true;\n\t\tlog.log(Level.INFO, \"Initializing dbAccess for db connection url: {0}\", conn_str);\n\n\t\tif (map != null) {\n\t\t\tString query = map.get(GET_USER_UID_PROP_KEY);\n\n\t\t\tif (query != null) {\n\t\t\t\tuid_query = query;\n\t\t\t}\n\n\t\t\tquery = map.get(JDBCMsgRepository.MSGS_COUNT_LIMIT_PROP_KEY);\n\n\t\t\tif (query != null) {\n\t\t\t\tmsg_count_for_limit_query = query;\n\t\t\t}\n\t\t}\n\n\t\tsuper.initRepository(conn_str, map);\n\t\t\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, map);\n\t\t\tswitch (data_repo.getDatabaseType()) {\n\t\t\t\tcase sqlserver:\n\t\t\t\t\tmsg_ensure_broadcast_recipient = SQLSERVER_MSG_ENSURE_BROADCAT_RECIPIETN;\n\t\t\t\t\tmsg_insert_message_to_broadcast = SQLSERVER_MSG_INSERT_MESSAGE_TO_BROADCAST;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tmsg_ensure_broadcast_recipient = SQL_MSG_ENSURE_BROADCAT_RECIPIETN;\n\t\t\t\t\tmsg_insert_message_to_broadcast = SQL_MSG_INSERT_MESSAGE_TO_BROADCAST;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tswitch (data_repo.getDatabaseType()) {\n\t\t\t\tcase mysql:\n\t\t\t\t\tadd_user_jid_id = ADD_USER_JID_ID_QUERY_MYSQL;\n\t\t\t\t\tbreak;\n\t\t\t\tcase derby:\n\t\t\t\t\tadd_user_jid_id = ADD_USER_JID_ID_QUERY_DERBY;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tadd_user_jid_id = ADD_USER_JID_ID_QUERY;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Check if DB is correctly setup and contains all required tables.\n\t\t\tcheckDB();\n\t\t\tdata_repo.initPreparedStatement(uid_query, uid_query);\n\t\t\tdata_repo.initPreparedStatement(MSG_INSERT_QUERY, MSG_INSERT_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_TO_JID_QUERY, MSG_SELECT_TO_JID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_COUNT_TO_JID_QUERY, MSG_SELECT_COUNT_TO_JID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_LIST_TO_JID_QUERY, MSG_SELECT_LIST_TO_JID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_DELETE_TO_JID_QUERY, MSG_DELETE_TO_JID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_DELETE_ID_QUERY, MSG_DELETE_ID_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_EXPIRED_QUERY, MSG_SELECT_EXPIRED_QUERY);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_EXPIRED_BEFORE_QUERY,\n\t\t\t\t\tMSG_SELECT_EXPIRED_BEFORE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(msg_count_for_limit_query,\n\t\t\t\t\tmsg_count_for_limit_query);\n\t\t\tdata_repo.initPreparedStatement(add_user_jid_id, add_user_jid_id);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_BROADCAST_RECIPIENTS, MSG_SELECT_BROADCAST_RECIPIENTS);\n\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_MESSAGES_TO_BROADCAST, MSG_SELECT_MESSAGES_TO_BROADCAST);\n\t\t\tif (data_repo.getDatabaseType() == dbTypes.derby) {\n\t\t\t\tdata_repo.initPreparedStatement(DERBY_MSG_ENSURE_BROADCAT_RECIPIETN1, DERBY_MSG_ENSURE_BROADCAT_RECIPIETN1);\n\t\t\t\tdata_repo.initPreparedStatement(DERBY_MSG_ENSURE_BROADCAT_RECIPIETN2, DERBY_MSG_ENSURE_BROADCAT_RECIPIETN2);\n\t\t\t\tdata_repo.initPreparedStatement(DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST1, DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST1);\n\t\t\t\tdata_repo.initPreparedStatement(DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST2, DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST2);\n\t\t\t} else {\n\t\t\t\tdata_repo.initPreparedStatement(msg_ensure_broadcast_recipient, msg_ensure_broadcast_recipient);\n\t\t\t\tdata_repo.initPreparedStatement(msg_insert_message_to_broadcast, msg_insert_message_to_broadcast);\n\t\t\t}\n\n\t\t\tfor (int i=1; i<= StatementsCount; i++) {\n\t\t\t\tStringBuilder select = new StringBuilder().append(MSG_DELETE_IDS_TO_JID_QUERY);\n\t\t\t\tfor (int j=1; j<=i; j++) {\n\t\t\t\t\tif (j > 1)\n\t\t\t\t\t\tselect.append(\" , \");\n\t\t\t\t\tselect.append(\" ? \");\n\t\t\t\t}\n\t\t\t\tselect.append(\")\");\n\n\t\t\t\tdata_repo.initPreparedStatement(MSG_DELETE_IDS_TO_JID_QUERY + \"_\" + i, select.toString());\n\t\t\t}\n\n\t\t\tfor (int i=1; i<= StatementsCount; i++) {\n\t\t\t\tStringBuilder select = new StringBuilder().append(MSG_SELECT_IDS_TO_JID_QUERY);\n\t\t\t\tfor (int j=1; j<=i; j++) {\n\t\t\t\t\tif (j > 1)\n\t\t\t\t\t\tselect.append(\" , \");\n\t\t\t\t\tselect.append(\" ? \");\n\t\t\t\t}\n\t\t\t\tselect.append(\")\");\n\t\t\t\tdata_repo.initPreparedStatement(MSG_SELECT_IDS_TO_JID_QUERY + \"_\" + i, select.toString());\n\t\t\t}\n\n\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"MsgRepository not initialized due to exception\", e);\n\t\t\t// Ignore for now....\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<Enum,Long> getMessagesCount(JID to) throws UserNotFoundException {\n\n\t\tMap<Enum,Long> result = new HashMap<>(MSG_TYPES.values().length);\n\n\t\ttry {\n\n\t\t\tResultSet rs = null;\n\n\t\t\tlong to_uid = getUserUID( to.getBareJID() );\n\n\t\t\tif ( to_uid < 0 ){\n\t\t\t\tthrow new UserNotFoundException( \"User: \" + to + \" was not found in database.\" );\n\t\t\t}\n\n\t\t\t// get number of messages\n\t\t\tPreparedStatement number_of_messages\n\t\t\t\t\t\t\t\t\t\t\t\t= data_repo.getPreparedStatement( to.getBareJID(), MSG_SELECT_COUNT_TO_JID_QUERY );\n\n\t\t\tsynchronized ( number_of_messages ) {\n\t\t\t\tnumber_of_messages.setLong( 1, to_uid );\n\t\t\t\trs = number_of_messages.executeQuery();\n\n\t\t\t\twhile ( rs.next() ) {\n\t\t\t\t\tint msgType = rs.getInt( 1 );\n\t\t\t\t\tlong msgCount = rs.getLong( 2 );\n\t\t\t\t\tresult.put( MSG_TYPES.getFromInt( msgType ), msgCount );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch ( SQLException e ) {\n\t\t\tlog.log( Level.WARNING, \"Problem getting offline messages for user: \" + to, e );\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic List<Element> getMessagesList( JID to) throws UserNotFoundException {\n\t\t\tList<Element> result = new LinkedList<Element>();\n\t\t\tResultSet rs = null;\n\n\t\t\ttry {\n\t\t\t\tlong to_uid = getUserUID( to.getBareJID() );\n\n\t\t\t\tif ( to_uid < 0 ){\n\t\t\t\t\tthrow new UserNotFoundException( \"User: \" + to + \" was not found in database.\" );\n\t\t\t\t}\n\n\t\t\t\tPreparedStatement select_messages_list\n\t\t\t\t\t\t\t\t\t\t\t\t\t= data_repo.getPreparedStatement( to.getBareJID(), MSG_SELECT_LIST_TO_JID_QUERY );\n\n\t\t\t\tsynchronized (select_messages_list) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tselect_messages_list.setLong(1, to_uid);\n\n\t\t\t\t\t\trs = select_messages_list.executeQuery();\n\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tlong msgId = rs.getLong(MSG_ID_COLUMN);\n\t\t\t\t\t\t\tint mType = rs.getInt(MSG_TYPE_COLUMN);\n\t\t\t\t\t\t\tMSG_TYPES messageType = MSG_TYPES.getFromInt(mType);\n\t\t\t\t\t\t\tString sender = rs.getString(JID_COLUMN);\n\n\t\t\t\t\t\t\tif (msgId != 0 && messageType != MSG_TYPES.none && sender != null) {\n\t\t\t\t\t\t\t\tElement item = new Element(\"item\",\n\t\t\t\t\t\t\t\t\t\tnew String[]{\"jid\", \"node\", \"type\", \"name\"},\n\t\t\t\t\t\t\t\t\t\tnew String[]{to.getBareJID().toString(), String.valueOf(msgId),\n\t\t\t\t\t\t\t\t\t\t\tmessageType.name(), sender});\n\t\t\t\t\t\t\t\tresult.add(item);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} catch ( SQLException e ) {\n\t\t\t\tlog.log( Level.WARNING, \"Problem getting offline messages for user: \" + to, e );\n\t\t\t}\n\t\t\treturn result;\n\n\t}\n\n\t@Override\n\tpublic Queue<Element> loadMessagesToJID( List<String> db_ids, XMPPResourceConnection session, boolean delete, OfflineMessagesProcessor proc) throws UserNotFoundException {\n\n\t\t\tQueue<Element> result = null;\n\t\t\tBareJID to = null;\n\t\t\n\t\t\ttry {\n\t\t\t\tto = session.getBareJID();\t\t\n\t\t\t\tlong to_uid = getUserUID( to );\n\n\t\t\t\tif ( to_uid < 0 ){\n\t\t\t\t\tthrow new UserNotFoundException( \"User: \" + to + \" was not found in database.\" );\n\t\t\t\t}\n\n\t\t\t\tif ( db_ids == null || db_ids.size() == 0 ){\n\t\t\t\t\t// fetch\n\t\t\t\t\treturn loadMessagesToJID( session, delete, proc );\n\t\t\t\t} else {\n\t\t\t\t\tResultSet rs = null;\n\t\t\t\t\tresult = new LinkedList<Element>();\n\n\t\t\t\t\tIterator<String> ids = db_ids.iterator();\n\n\t\t\t\t\tint iters = ( db_ids.size() / StatementsCount ) + 1;\n\t\t\t\t\tfor ( int i = 0 ; i < iters ; i++ ) {\n\t\t\t\t\t\tint params = ( i == ( iters - 1 ) ) ? db_ids.size() % StatementsCount : StatementsCount;\n\t\t\t\t\t\tif (params == 0 ) continue;\n\t\t\t\t\t\tPreparedStatement select_ids_to_jid_st = data_repo.getPreparedStatement( to,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t MSG_SELECT_IDS_TO_JID_QUERY + \"_\" + params );\n\n\t\t\t\t\t\tsynchronized ( select_ids_to_jid_st ) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tselect_ids_to_jid_st.setLong(1, to_uid);\n\t\t\t\t\t\t\t\tfor (int j = 0; j < params; j++) {\n\t\t\t\t\t\t\t\t\tString id = ids.next();\n\t\t\t\t\t\t\t\t\tselect_ids_to_jid_st.setString(j + 2, id);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trs = select_ids_to_jid_st.executeQuery();\n\t\t\t\t\t\t\t\tresult.addAll(parseLoadedMessages(proc, rs));\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( delete ){\n\t\t\t\t\tdeleteMessagesToJID( null, session );\n\t\t\t\t}\n\t\t\t} catch ( SQLException e ) {\n\t\t\t\tlog.log( Level.WARNING, \"Problem getting offline messages for user: \" + to, e );\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Session not authorized yet!\", ex);\t\t\t\t\n\t\t\t}\n\t\t\treturn result;\n\n\t}\n\n\t@Override\n\tpublic int deleteMessagesToJID( List<String> db_ids, XMPPResourceConnection session ) throws UserNotFoundException {\n\n\t\tint affectedRows = 0;\n\t\tBareJID to = null;\n\t\t\n\t\ttry {\n\t\t\tto = session.getBareJID();\n\t\t\t\n\t\t\tlong to_uid = getUserUID( to );\n\n\t\t\tif ( to_uid < 0 ){\n\t\t\t\tthrow new UserNotFoundException( \"User: \" + to + \" was not found in database.\" );\n\t\t\t}\n\n\t\t\tif ( db_ids == null || db_ids.size() == 0 ){\n\t\t\t\t// purge\n\t\t\t\tPreparedStatement delete_to_jid_st\n\t\t\t\t\t\t\t\t\t\t\t\t\t= data_repo.getPreparedStatement( to, MSG_DELETE_TO_JID_QUERY );\n\n\t\t\t\tsynchronized ( delete_to_jid_st ) {\n\t\t\t\t\tdelete_to_jid_st.setLong( 1, to_uid );\n\t\t\t\t\taffectedRows += delete_to_jid_st.executeUpdate();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tIterator<String> ids = db_ids.iterator();\n\n\t\t\t\tint iters = ( db_ids.size() / StatementsCount ) + 1;\n\t\t\t\t\tfor ( int i = 0 ; i < iters ; i++ ) {\n\t\t\t\t\t\tint params = ( i == ( iters - 1 ) ) ? db_ids.size() % StatementsCount : StatementsCount;\n\t\t\t\t\t\tif (params == 0 ) continue;\n\t\t\t\t\tPreparedStatement delete_to_jid_st = data_repo.getPreparedStatement( to,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t MSG_DELETE_IDS_TO_JID_QUERY + \"_\" + params );\n\n\t\t\t\t\tsynchronized ( delete_to_jid_st ) {\n\t\t\t\t\t\tdelete_to_jid_st.setLong( 1, to_uid );\n\t\t\t\t\t\tfor ( int j = 0 ; j < params ; j++ ) {\n\t\t\t\t\t\t\tString id = ids.next();\n\t\t\t\t\t\t\tdelete_to_jid_st.setString( j + 2, id );\n\t\t\t\t\t\t}\n\t\t\t\t\t\taffectedRows = affectedRows + delete_to_jid_st.executeUpdate();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( SQLException e ) {\n\t\t\tlog.log( Level.WARNING, \"Problem getting offline messages for user: \" + to, e );\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\tlog.log(Level.WARNING, \"Session not authorized yet!\", ex);\t\t\t\n\t\t}\n\t\treturn affectedRows;\n\t}\n\n\n\t@Override\n\tpublic Queue<Element> loadMessagesToJID( XMPPResourceConnection session, boolean delete )\n\t\t\tthrows UserNotFoundException {\n\t\treturn loadMessagesToJID( session, delete, null );\n\t}\n\n\tpublic Queue<Element> loadMessagesToJID(XMPPResourceConnection session, boolean delete, OfflineMessagesProcessor proc)\n\t\t\tthrows UserNotFoundException {\n\t\tQueue<Element> result = null;\n\t\tBareJID to = null;\n\t\t\n\t\ttry {\n\t\t\tto = session.getBareJID();\n\t\t\tlong to_uid = getUserUID(to);\n\n\t\t\tif (to_uid < 0) {\n\t\t\t\tthrow new UserNotFoundException(\"User: \" + to + \" was not found in database.\");\n\t\t\t}\n\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement select_to_jid_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(to, MSG_SELECT_TO_JID_QUERY);\n\n\t\t\tsynchronized (select_to_jid_st) {\n\t\t\t\ttry {\n\t\t\t\t\tselect_to_jid_st.setLong(1, to_uid);\n\t\t\t\t\trs = select_to_jid_st.executeQuery();\n\n\t\t\t\t\tStringBuilder sb = new StringBuilder(1000);\n\n\t\t\t\t\tresult = parseLoadedMessages(proc, rs);\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (delete) {\n\t\t\t\tPreparedStatement delete_to_jid_st =\n\t\t\t\t\t\tdata_repo.getPreparedStatement(to, MSG_DELETE_TO_JID_QUERY);\n\n\t\t\t\tsynchronized (delete_to_jid_st) {\n\t\t\t\t\tdelete_to_jid_st.setLong(1, to_uid);\n\t\t\t\t\tdelete_to_jid_st.executeUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting offline messages for user: \" + to, e);\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\tlog.log(Level.WARNING, \"Session not authorized yet!\", ex);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprotected Queue<Element> parseLoadedMessages( OfflineMessagesProcessor proc, ResultSet rs) throws SQLException {\n\t\tStringBuilder sb = new StringBuilder( 1000 );\n\t\tQueue<Element> result = new LinkedList<Element>();\n\t\tif ( proc == null ){\n\t\t\twhile ( rs.next() ) {\n\t\t\t\tsb.append( rs.getString( MSG_BODY_COLUMN ) );\n\t\t\t}\n\n\t\t\tif ( sb.length() > 0 ){\n\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\t\t\tparser.parse( domHandler, sb.toString().toCharArray(), 0, sb.length() );\n\t\t\t\tresult = domHandler.getParsedElements();\n\t\t\t}\n\t\t} else {\n\t\t\tresult = new LinkedList<Element>();\n\t\t\twhile ( rs.next() ) {\n\t\t\t\tfinal String msg = rs.getString( MSG_BODY_COLUMN );\n\t\t\t\tfinal long msgId = rs.getLong( MSG_ID_COLUMN );\n\n\t\t\t\tif ( msg != null ){\n\t\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\t\t\t\tparser.parse( domHandler, msg.toCharArray(), 0, msg.length() );\n\t\t\t\t\tfinal Queue<Element> parsedElements = domHandler.getParsedElements();\n\t\t\t\t\tElement msgEl = parsedElements.poll();\n\t\t\t\t\tif ( msgEl != null && msgId > 0 ){\n\n\t\t\t\t\t\tproc.stamp( msgEl, String.valueOf( msgId ) );\n\n\t\t\t\t\t\tresult.add( msgEl );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean storeMessage(JID from, JID to, Date expired, Element msg, NonAuthUserRepository userRepo)\n\t\t\tthrows UserNotFoundException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Storring expired: {0} message: {1}\", new Object[] { expired,\n\t\t\t\t\tPacket.elemToString(msg) });\n\t\t}\n\n\t\ttry {\n\t\t\tlong from_uid = getUserUID(from.getBareJID());\n\n\t\t\tif (from_uid < 0) {\n\t\t\t\tfrom_uid = addUserJID(from.getBareJID());\n\t\t\t}\n\n\t\t\tlong to_uid = getUserUID(to.getBareJID());\n\n\t\t\tif (to_uid < 0) {\n\t\t\t\tto_uid = addUserJID(to.getBareJID());\n\t\t\t}\n\n\t\t\tlong count = 0;\n\t\t\t\n\t\t\tlong msgs_store_limit = getMsgsStoreLimit(to.getBareJID(), userRepo);\n\t\t\t// If the msgs_store_limit is set to 0, skip the select because the message will be saved anyway\n\t\t\tif (msgs_store_limit != 0) {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement count_msgs_st\n\t\t\t\t\t\t= data_repo.getPreparedStatement(to.getBareJID(), msg_count_for_limit_query);\n\n\t\t\t\tsynchronized (count_msgs_st) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcount_msgs_st.setLong(1, to_uid);\n\t\t\t\t\t\tcount_msgs_st.setLong(2, from_uid);\n\n\t\t\t\t\t\trs = count_msgs_st.executeQuery();\n\n\t\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\t\tcount = rs.getLong(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// The insertion will be skipped if the msgs_store_limit is higher than 0 and it was passed\n\t\t\tif (msgs_store_limit != 0 && msgs_store_limit <= count) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Message store limit ({0}) exceeded for message: {1}\",\n\t\t\t\t\t\t\tnew Object[] { msgs_store_limit, Packet.elemToString(msg) });\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tPreparedStatement insert_msg_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(to.getBareJID(), MSG_INSERT_QUERY);\n\n\t\t\tsynchronized (insert_msg_st) {\n\t\t\t\tif (expired == null) {\n\t\t\t\t\tinsert_msg_st.setNull(1, Types.TIMESTAMP);\n\t\t\t\t} else {\n\t\t\t\t\tTimestamp time = new Timestamp(expired.getTime());\n\n\t\t\t\t\tinsert_msg_st.setTimestamp(1, time);\n\t\t\t\t}\n\n\t\t\t\tif (from_uid <= 0) {\n\t\t\t\t\tinsert_msg_st.setNull(2, Types.BIGINT);\n\t\t\t\t} else {\n\t\t\t\t\tinsert_msg_st.setLong(2, from_uid);\n\t\t\t\t}\n\n\t\t\t\tinsert_msg_st.setLong(3, to_uid);\n\n\t\t\t\tint msg_type;\n\t\t\t\ttry {\n\t\t\t\t\tfinal String name = msg.getName();\n\t\t\t\t\tfinal MSG_TYPES valueOf = MSG_TYPES.valueOf(name);\n\t\t\t\t\tmsg_type = valueOf.ordinal();\n\t\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\t\tmsg_type = Integer.MAX_VALUE;\n\t\t\t\t}\n\n\t\t\t\tinsert_msg_st.setLong(4, msg_type);\n\t\t\t\t// TODO: deal with messages bigger than the database can fit....\n\t\t\t\tinsert_msg_st.setString(5, msg.toString());\n\t\t\t\tinsert_msg_st.executeUpdate();\n\t\t\t}\n\n\t\t\tif (expired != null) {\n\t\t\t\tif (expired.getTime() < earliestOffline) {\n\t\t\t\t\tearliestOffline = expired.getTime();\n\t\t\t\t}\n\n\t\t\t\tif (expiredQueue.size() == 0) {\n\t\t\t\t\tloadExpiredQueue(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (DataTruncation dte) {\n\t\t\tlog.log(Level.FINE, \"Data truncated for message from {0} to {1}\", new Object[] {\n\t\t\t\t\tfrom, to });\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem adding new entry to DB: \", e);\n\t\t}\n\t\treturn true;\n\t}\n\t\n\t@Override\n\tpublic void loadMessagesToBroadcast() {\n\t\ttry {\n\t\t\tSet<String> oldMessages = new HashSet<String>(broadcastMessages.keySet());\n\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement stmt = data_repo.getPreparedStatement(null, MSG_SELECT_MESSAGES_TO_BROADCAST);\n\n\t\t\tsynchronized (stmt) {\n\t\t\t\ttry {\n\t\t\t\t\tstmt.setTimestamp(1, new Timestamp(System.currentTimeMillis()));\n\t\t\t\t\trs = stmt.executeQuery();\n\n\t\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tString msgId = rs.getString(1);\n\t\t\t\t\t\toldMessages.remove(msgId);\n\t\t\t\t\t\tif (broadcastMessages.containsKey(msgId))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tDate expire = rs.getTimestamp(2);\n\t\t\t\t\t\tchar[] msgChars = rs.getString(3).toCharArray();\n\n\t\t\t\t\t\tparser.parse(domHandler, msgChars, 0, msgChars.length);\n\n\t\t\t\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\t\t\t\t\t\tElement msg = elems.poll();\n\t\t\t\t\t\tif (msg == null)\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tbroadcastMessages.put(msgId, new BroadcastMsg(null, msg, expire));\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tfor (String id : oldMessages) {\n\t\t\t\tbroadcastMessages.remove(id);\n\t\t\t}\n\t\t\t\n\t\t\trs = null;\n\t\t\t\n\t\t\tfor (String id : broadcastMessages.keySet()) {\n\t\t\t\tBroadcastMsg bmsg = broadcastMessages.get(id);\n\t\t\t\tstmt = data_repo.getPreparedStatement(null, MSG_SELECT_BROADCAST_RECIPIENTS);\n\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\t\trs = stmt.executeQuery();\n\t\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\t\tBareJID jid = BareJID.bareJIDInstanceNS(rs.getString(1));\n\t\t\t\t\t\t\tbmsg.addRecipient(jid);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem with retrieving broadcast messages\", ex);\n\t\t}\n\t}\n\t\n\t@Override\n\tprotected void insertBroadcastMessage(String id, Element msg, Date expire, BareJID recipient) {\n\t\ttry {\n\t\t\tif (data_repo.getDatabaseType() == dbTypes.derby) {\n\t\t\t\tboolean exists = false;\n\t\t\t\tPreparedStatement stmt = data_repo.getPreparedStatement(recipient, DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST1);\n\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\tResultSet rs = stmt.executeQuery();\n\t\t\t\t\texists = rs.next();\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t\tif (!exists) {\n\t\t\t\t\tstmt = data_repo.getPreparedStatement(recipient, DERBY_MSG_INSERT_MESSAGE_TO_BROADCAST2);\n\t\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\t\tstmt.setTimestamp(2, new Timestamp(expire.getTime()));\n\t\t\t\t\t\tstmt.setString(3, msg.toString());\n\t\t\t\t\t\tstmt.executeUpdate();\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t} else {\t\t\t\n\t\t\t\tPreparedStatement stmt = data_repo.getPreparedStatement(recipient, msg_insert_message_to_broadcast);\n\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\tstmt.setTimestamp(2, new Timestamp(expire.getTime()));\n\t\t\t\t\tstmt.setString(3, msg.toString());\n\t\t\t\t\tstmt.setString(4, id);\n\t\t\t\t\tstmt.executeUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem with updating broadcast message\", ex);\n\t\t}\n\t}\n\t\n\t@Override\n\tprotected void ensureBroadcastMessageRecipient(String id, BareJID recipient) {\n\t\ttry {\n\t\t\tlong uid = getUserUID(recipient);\n\t\t\tif (uid == -1) {\n\t\t\t\tuid = addUserJID(recipient);\n\t\t\t}\n\t\t\t\n\t\t\tif (data_repo.getDatabaseType() == dbTypes.derby) {\n\t\t\t\tboolean exists = false;\n\t\t\t\tPreparedStatement stmt = data_repo.getPreparedStatement(recipient, DERBY_MSG_ENSURE_BROADCAT_RECIPIETN1);\n\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\tstmt.setLong(2, uid);\n\t\t\t\t\tResultSet rs = stmt.executeQuery();\n\t\t\t\t\texists = rs.next();\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t\tif (!exists) {\n\t\t\t\t\tstmt = data_repo.getPreparedStatement(recipient, DERBY_MSG_ENSURE_BROADCAT_RECIPIETN2);\n\t\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\t\tstmt.setLong(2, uid);\n\t\t\t\t\t\tstmt.executeUpdate();\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tPreparedStatement stmt = data_repo.getPreparedStatement(recipient, msg_ensure_broadcast_recipient);\n\t\t\t\tsynchronized (stmt) {\n\t\t\t\t\tstmt.setString(1, id);\n\t\t\t\t\tstmt.setLong(2, uid);\n\t\t\t\t\tstmt.setString(3, id);\n\t\t\t\t\tstmt.setLong(4, uid);\n\t\t\t\t\tstmt.executeUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem with updating broadcast message\", ex);\n\t\t}\n\t}\n\n\tprivate long addUserJID(BareJID bareJID) throws SQLException, UserNotFoundException {\n\t\ttry {\n\t\t\tString jid_sha = Algorithms.hexDigest(bareJID.toString(), \"\", \"SHA\");\n\t\t\tPreparedStatement add_jid_id_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(bareJID, add_user_jid_id);\n\n\t\t\tsynchronized (add_jid_id_st) {\n\t\t\t\tadd_jid_id_st.setString(1, jid_sha);\n\t\t\t\tadd_jid_id_st.setString(2, bareJID.toString());\n\t\t\t\tadd_jid_id_st.setString( 3, jid_sha );\n\t\t\t\tadd_jid_id_st.setString( 4, bareJID.toString() );\n\t\t\t\tadd_jid_id_st.executeUpdate();\n\t\t\t}\n\n\t\t} catch (NoSuchAlgorithmException ex) {\n\t\t\tlog.log(Level.WARNING, \"Configuration error or code bug: \", ex);\n\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn getUserUID(bareJID);\n\t}\n\n\t/**\n\t * Performs database check, creates missing schema if necessary\n\t *\n\t * @throws SQLException\n\t */\n\tprivate void checkDB() throws SQLException {\n\n\t\tStatement stmt = null;\n\n\t\ttry {\n\t\t\tDataRepository.dbTypes databaseType = data_repo.getDatabaseType();\n\t\t\tswitch ( databaseType ) {\n\t\t\t\tcase mysql:\n\t\t\t\t\tdata_repo.checkTable( JID_TABLE, MYSQL_CREATE_JID_TABLE );\n\t\t\t\t\tdata_repo.checkTable( MSG_TABLE, MYSQL_CREATE_MSG_TABLE );\n\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs\", MYSQL_CREATE_BROADCAST_MSGS_TABLE );\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs_recipients\", MYSQL_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE );\n\t\t\t\t\tbreak;\n\t\t\t\tcase postgresql:\n\t\t\t\t\tdata_repo.checkTable( JID_TABLE, PGSQL_CREATE_JID_TABLE );\n\t\t\t\t\tdata_repo.checkTable( MSG_TABLE, PGSQL_CREATE_MSG_TABLE );\n\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs\", PGSQL_CREATE_BROADCAST_MSGS_TABLE );\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs_recipients\", PGSQL_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE );\n\t\t\t\t\tbreak;\n\t\t\t\tcase derby:\n\t\t\t\t\tdata_repo.checkTable( JID_TABLE, DERBY_CREATE_JID_TABLE );\n\t\t\t\t\tdata_repo.checkTable( MSG_TABLE, DERBY_CREATE_MSG_TABLE );\n\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs\", DERBY_CREATE_BROADCAST_MSGS_TABLE );\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs_recipients\", DERBY_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE );\n\t\t\t\t\tbreak;\n\t\t\t\tcase jtds:\n\t\t\t\tcase sqlserver:\n\t\t\t\t\tdata_repo.checkTable( JID_TABLE, SQLSERVER_CREATE_JID_TABLE );\n\t\t\t\t\tdata_repo.checkTable( MSG_TABLE, SQLSERVER_CREATE_MSG_TABLE );\n\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs\", SQLSERVER_CREATE_BROADCAST_MSGS_TABLE );\n\t\t\t\t\tdata_repo.checkTable( \"broadcast_msgs_recipients\", SQLSERVER_CREATE_BROADCAST_MSGS_RECIPIENTS_TABLE );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstmt = data_repo.createStatement( null );\n\t\t\t\tstmt.executeQuery( \"select \" + MSG_TYPE_COLUMN + \" from \" + MSG_TABLE + \" where \" + MSG_ID_COLUMN + \" = 0\" );\n\t\t\t} catch ( SQLException ex ) {\n\t\t\t\tlog.log( Level.INFO, MSG_TABLE + \" table was in old version, performing update to add missing column\" );\n\t\t\t\t// if this happens then we have issue with old database schema and missing body columns in MSGS_TABLE\n\t\t\t\tString alterTable = null;\n\t\t\t\ttry {\n\t\t\t\t\talterTable = \"alter table \" + MSG_TABLE + \" add \" + MSG_TYPE_COLUMN + \" int NOT NULL default 0\";\n\t\t\t\t\tif ( stmt == null ){\n\t\t\t\t\t\tstmt = data_repo.createStatement( null );\n\t\t\t\t\t}\n\t\t\t\t\tstmt.execute( alterTable );\n\t\t\t\t} catch ( SQLException ex1 ) {\n\t\t\t\t\tlog.log( Level.SEVERE, \"could not alter table \" + MSG_TABLE + \" to add missing column by SQL:\\n\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + alterTable, ex1 );\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tdata_repo.release( stmt, null );\n\t\t}\n\n\t}\n\n\t@Override\n\tprotected void deleteMessage(Long msg_id) {\n\t\ttry {\n\t\t\tPreparedStatement delete_id_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, MSG_DELETE_ID_QUERY);\n\n\t\t\tsynchronized (delete_id_st) {\n\t\t\t\tdelete_id_st.setLong(1, msg_id);\n\t\t\t\tdelete_id_st.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem removing entry from DB: \", e);\n\t\t}\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\tprivate long getUserUID(BareJID user_id) throws SQLException, UserNotFoundException {\n\t\tLong cache_res = uids_cache.get(user_id);\n\n\t\tif (cache_res != null) {\n\t\t\treturn cache_res.longValue();\n\t\t} // end of if (result != null)\n\n\t\tlong result = -1;\n\t\tString jid_sha;\n\n\t\ttry {\n\t\t\tjid_sha = Algorithms.hexDigest(user_id.toString(), \"\", \"SHA\");\n\t\t} catch (NoSuchAlgorithmException ex) {\n\t\t\tlog.log(Level.WARNING, \"Configuration error or code bug: \", ex);\n\n\t\t\treturn -1;\n\t\t}\n\n\t\tResultSet rs = null;\n\t\tPreparedStatement uid_st = data_repo.getPreparedStatement(user_id, uid_query);\n\n\t\tsynchronized (uid_st) {\n\t\t\ttry {\n\t\t\t\tuid_st.setString(1, jid_sha);\n\t\t\t\trs = uid_st.executeQuery();\n\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\tBareJID res_jid = BareJID.bareJIDInstanceNS(rs.getString(JID_COLUMN));\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Found entry for JID: {0}, DB JID: {1}\", new Object[] {\n\t\t\t\t\t\t\tuser_id, res_jid });\n\t\t\t\t\t}\n\n\t\t\t\t\t// There is a slight chance that there is the same SHA for 2 different\n\t\t\t\t\t// JIDs.\n\t\t\t\t\t// Even though it is impossible to store messages for both JIDs right\n\t\t\t\t\t// now\n\t\t\t\t\t// we have to make sure we don't send offline messages to incorrect\n\t\t\t\t\t// person\n\t\t\t\t\tif (user_id.equals(res_jid)) {\n\t\t\t\t\t\tresult = rs.getLong(JID_ID_COLUMN);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"JIDs don't match, SHA conflict? JID: {0}, DB JID: {1}\", new Object[] {\n\t\t\t\t\t\t\t\t\t\tuser_id, res_jid });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"No entry for JID: {0}\", user_id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\n\t\t\t// if (result <= 0) {\n\t\t\t// throw new UserNotFoundException(\"User does not exist: \" + user_id);\n\t\t\t// } // end of if (isnext) else\n\n\t\tif (result > 0) {\n\t\t\tuids_cache.put(user_id, result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void loadExpiredQueue(int min_elements) {\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement select_expired_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, MSG_SELECT_EXPIRED_QUERY);\n\n\t\t\tsynchronized (select_expired_st) {\n\t\t\t\ttry {\n\t\t\t\t\trs = select_expired_st.executeQuery();\n\n\t\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\t\tint counter = 0;\n\n\t\t\t\t\twhile (rs.next()\n\t\t\t\t\t\t\t&& ((expiredQueue.size() < MAX_QUEUE_SIZE) || (counter++ < min_elements))) {\n\t\t\t\t\t\tString msg_str = rs.getString(MSG_BODY_COLUMN);\n\n\t\t\t\t\t\tparser.parse(domHandler, msg_str.toCharArray(), 0, msg_str.length());\n\n\t\t\t\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\t\t\t\t\t\tElement msg = elems.poll();\n\n\t\t\t\t\t\tif (msg == null) {\n\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\"Something wrong, loaded offline message from DB but parsed no \"\n\t\t\t\t\t\t\t\t\t+ \"XML elements: {0}\", msg_str);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tTimestamp ts = rs.getTimestamp(MSG_EXPIRED_COLUMN);\n\t\t\t\t\t\t\tMsgDBItem item = new MsgDBItem(rs.getLong(MSG_ID_COLUMN), msg, ts);\n\n\t\t\t\t\t\t\texpiredQueue.offer(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting offline messages from db: \", e);\n\t\t}\n\n\t\tearliestOffline = Long.MAX_VALUE;\n\t}\n\n\t@Override\n\tprotected void loadExpiredQueue(Date expired) {\n\t\ttry {\n\t\t\tif (expiredQueue.size() > 100 * MAX_QUEUE_SIZE) {\n\t\t\t\texpiredQueue.clear();\n\t\t\t}\n\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement select_expired_before_st =\n\t\t\t\t\tdata_repo.getPreparedStatement(null, MSG_SELECT_EXPIRED_BEFORE_QUERY);\n\n\t\t\tsynchronized (select_expired_before_st) {\n\t\t\t\ttry {\n\t\t\t\t\tselect_expired_before_st.setTimestamp(1, new Timestamp(expired.getTime()));\n\t\t\t\t\trs = select_expired_before_st.executeQuery();\n\n\t\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\t\tint counter = 0;\n\n\t\t\t\t\twhile (rs.next() && (counter++ < MAX_QUEUE_SIZE)) {\n\t\t\t\t\t\tString msg_str = rs.getString(MSG_BODY_COLUMN);\n\n\t\t\t\t\t\tparser.parse(domHandler, msg_str.toCharArray(), 0, msg_str.length());\n\n\t\t\t\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\t\t\t\t\t\tElement msg = elems.poll();\n\n\t\t\t\t\t\tif (msg == null) {\n\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\"Something wrong, loaded offline message from DB but parsed no \"\n\t\t\t\t\t\t\t\t\t+ \"XML elements: {0}\", msg_str);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tTimestamp ts = rs.getTimestamp(MSG_EXPIRED_COLUMN);\n\t\t\t\t\t\t\tMsgDBItem item = new MsgDBItem(rs.getLong(MSG_ID_COLUMN), msg, ts);\n\n\t\t\t\t\t\t\texpiredQueue.offer(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting offline messages from db: \", e);\n\t\t}\n\n\t\tearliestOffline = Long.MAX_VALUE;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/JidResourceMap.java",
    "content": "/*\n * JidResourceMap.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.server.amp;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\n/**\n * Generic utility class to allow storage of any value for particular JID (including resource).\n * \n * @author andrzej\n * @param <T>\n */\npublic class JidResourceMap<T> {\n\t\n\tprivate final ConcurrentHashMap<BareJID,Map<String,T>> usersMap = new ConcurrentHashMap<BareJID,Map<String,T>>();\n\t\n\tpublic JidResourceMap() {\n\t\t\n\t}\n\t\n\tpublic boolean containsKey(BareJID jid) {\n\t\treturn usersMap.containsKey(jid);\n\t}\n\t\n\tpublic boolean containsKey(JID jid) {\n\t\tMap<String,T> resources = usersMap.get(jid.getBareJID());\n\t\treturn resources != null && resources.containsKey(jid.getResource());\n\t}\n\t\n\tpublic T get(JID jid) {\n\t\tMap<String,T> resources = usersMap.get(jid.getBareJID());\n\t\tif (resources == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tsynchronized (resources) {\n\t\t\t\treturn resources.get(jid.getResource());\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic T put(JID jid, T value) {\n\t\tif (value == null) {\n\t\t\treturn remove(jid);\n\t\t}\n\t\t\n\t\tMap<String,T> resources = usersMap.get(jid.getBareJID());\n\t\t\n\t\tif (resources == null) {\n\t\t\tresources = new HashMap<String,T>();\n\t\t\t\n\t\t\tMap<String,T> oldResources = usersMap.putIfAbsent(jid.getBareJID(), resources);\n\t\t\t\n\t\t\tif (oldResources != null) {\n\t\t\t\tresources = oldResources;\n\t\t\t}\n\t\t}\n\t\tif (jid.getResource() != null) {\n\t\t\tsynchronized (resources) {\n\t\t\t\treturn resources.put(jid.getResource(), value);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\t\n\tpublic T remove(JID jid) {\n\t\tMap<String,T> resources = usersMap.get(jid.getBareJID());\n\t\t\n\t\tif (resources == null) \n\t\t\treturn null;\n\t\t\n\t\tsynchronized (resources) {\n\t\t\treturn resources.remove(jid.getResource());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/MsgRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.amp;\n\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.DelayQueue;\nimport java.util.concurrent.Delayed;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.DBInitException;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic abstract class MsgRepository<T> implements MsgRepositoryIfc {\n\n\tpublic static final String OFFLINE_MSGS_KEY = \"offline-msgs\";\n\tprivate static final long MSGS_STORE_LIMIT_VAL = 100;\n\tpublic static final String MSGS_STORE_LIMIT_KEY = \"store-limit\";\n\tprivate static final String MSGS_USER_STORE_LIMIT_ENABLE_KEY = \"user-store-limit-enable\";\n\t\n\tprotected static final int MAX_QUEUE_SIZE = 1000;\n\t\n\tprivate static final Map<String, MsgRepositoryIfc> repos =\n\t\t\tnew ConcurrentSkipListMap<String, MsgRepositoryIfc>();\n\t\n\tpublic enum MSG_TYPES { none(0), message(1), presence(2);\n\n    private final int numVal;\n\n    MSG_TYPES(int numVal) {\n        this.numVal = numVal;\n    }\n\n    public int getNumVal() {\n        return numVal;\n    }\n\n    public static MSG_TYPES getFromInt(int type) {\n        switch (type) {\n        case 1:\n            return message;\n        case 2:\n            return presence;\n        case 0:\n\t\t\t\tdefault:\n            return none;\n        }\n\t\t}\n\n\t};\n\n\tpublic static MsgRepositoryIfc getInstance(String cls, String id_string) throws TigaseDBException {\n\t\ttry {\n\t\t\tif (cls == null) {\n\t\t\t\tcls = RepositoryFactory.getRepoClassName(MsgRepositoryIfc.class, id_string);\n\t\t\t}\n\t\t\tString key = cls + \"#\" + id_string;\n\t\t\tMsgRepositoryIfc result = repos.get(key);\n\n\t\t\tif (result == null) {\n\t\t\t\tresult = (MsgRepositoryIfc) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t\trepos.put(key, result);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} catch (Exception ex) {\n\t\t\tthrow new TigaseDBException(\"Could not create instance of \" + cls + \" for uri \" + id_string, ex);\n\t\t}\n\t}\n\n\tprotected SimpleParser parser = SingletonFactory.getParserInstance();\t\n\tprotected long earliestOffline = Long.MAX_VALUE;\n\tprotected DelayQueue<MsgDBItem> expiredQueue = new DelayQueue<MsgDBItem>();\n\tprotected long broadcastMessagesLastCleanup = 0;\n\tprotected Map<String,BroadcastMsg> broadcastMessages = new ConcurrentHashMap<String,BroadcastMsg>();\n\n\tprivate long msgs_store_limit = MSGS_STORE_LIMIT_VAL;\n\tprivate boolean msgs_user_store_limit = false;\n\t\n\tprotected abstract void loadExpiredQueue(int max);\n\tprotected abstract void loadExpiredQueue(Date expired);\n\tprotected abstract void deleteMessage(T db_id);\n\t\n\tpublic abstract void loadMessagesToBroadcast();\n\tprotected abstract void ensureBroadcastMessageRecipient(String id, BareJID recipient);\n\tprotected abstract void insertBroadcastMessage(String id, Element msg, Date expire, BareJID recipient);\n\n\tpublic abstract Map<Enum,Long> getMessagesCount(JID to)  throws UserNotFoundException;\n\tpublic abstract List<Element> getMessagesList(JID to)  throws UserNotFoundException;\n\tpublic abstract\tQueue<Element> loadMessagesToJID(List<String> db_ids,  XMPPResourceConnection session, boolean delete,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOfflineMessagesProcessor proc ) throws UserNotFoundException;\n\tpublic abstract\tint deleteMessagesToJID( List<String> db_ids, XMPPResourceConnection session) throws UserNotFoundException;\n\n\t@Override\n\tpublic void initRepository(String conn_str, Map<String, String> map)\n\t\t\tthrows DBInitException {\n\t\t\n\t\tif (map != null) {\n\t\t\tString msgs_store_limit_str = map.get(MSGS_STORE_LIMIT_KEY);\n\t\t\t\n\t\t\tif (msgs_store_limit_str != null) {\n\t\t\t\tmsgs_store_limit = Long.parseLong(msgs_store_limit_str);\n\t\t\t}\n\t\t\t\n\t\t\tString msgs_user_store_limit_enable = map.get(MSGS_USER_STORE_LIMIT_ENABLE_KEY);\n\t\t\tif (msgs_user_store_limit_enable != null) {\n\t\t\t\tmsgs_user_store_limit = Boolean.parseBoolean(msgs_user_store_limit_enable);\n\t\t\t}\t\t\t\n\t\t}\n\t}\t\n\n\tprotected long getMsgsStoreLimit(BareJID userJid, NonAuthUserRepository userRepo) {\n\t\tif (msgs_user_store_limit) {\n\t\t\ttry {\n\t\t\t\tString limitStr = userRepo.getPublicData(userJid, OFFLINE_MSGS_KEY, MSGS_STORE_LIMIT_KEY, null);\n\t\t\t\tif (limitStr != null) {\n\t\t\t\t\tlong limit = Long.parseLong(limitStr);\n\t\t\t\t\t// in case of 0 we need to disable offline storage - not to save all as in case of store-limit\n\t\t\t\t\tif (limit == 0)\n\t\t\t\t\t\tlimit = -1;\n\t\t\t\t\treturn limit;\n\t\t\t\t}\n\t\t\t} catch (UserNotFoundException ex) {\n\t\t\t\t// should not happen\n\t\t\t}\n\t\t}\n\t\treturn msgs_store_limit;\n\t}\n\n\tpublic BroadcastMsg getBroadcastMsg(String id) {\n\t\treturn broadcastMessages.get(id);\n\t}\n\t\n\tpublic String dumpBroadcastMessageKeys() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (String key : broadcastMessages.keySet()) {\n\t\t\tif (sb.length() == 0)\n\t\t\t\tsb.append(\"[\");\n\t\t\telse\n\t\t\t\tsb.append(\",\");\n\t\t\tsb.append(key);\n\t\t}\n\t\treturn sb.append(\"]\").toString();\n\t}\n\t\n\tpublic Collection<BroadcastMsg> getBroadcastMessages() { \n\t\tlong now = System.currentTimeMillis();\n\t\tif (now - broadcastMessagesLastCleanup > 60 * 1000) {\n\t\t\tbroadcastMessagesLastCleanup = now;\n\t\t\tList<String> toRemove = new ArrayList<String>();\n\t\t\tfor (Map.Entry<String,BroadcastMsg> e : broadcastMessages.entrySet()) {\n\t\t\t\tif (e.getValue().getDelay(TimeUnit.MILLISECONDS) < 0) {\n\t\t\t\t\ttoRemove.add(e.getKey());\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (String key : toRemove)\n\t\t\t\tbroadcastMessages.remove(key);\n\t\t}\n\t\treturn Collections.unmodifiableCollection(broadcastMessages.values());\n\t}\n\t\n\tpublic boolean updateBroadcastMessage(String id, Element msg, Date expire, BareJID recipient) {\n\t\tboolean isNew = false;\n\t\tsynchronized (broadcastMessages) {\n\t\t\tMsgRepository.BroadcastMsg bmsg = broadcastMessages.get(id);\n\t\t\tif (bmsg == null) {\n\t\t\t\tbmsg = new MsgRepository.BroadcastMsg(null, msg, expire);\n\t\t\t\tbroadcastMessages.put(id, bmsg);\n\t\t\t\tisNew = true;\n\t\t\t\tinsertBroadcastMessage(id, msg, expire, recipient);\n\t\t\t}\n\t\t\tif (bmsg.addRecipient(recipient)) {\n\t\t\t\tensureBroadcastMessageRecipient(id, recipient);\n\t\t\t}\n\t\t\treturn isNew;\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic Element getMessageExpired(long time, boolean delete) {\n\t\tif (expiredQueue.size() == 0) {\n\n\t\t\t// If the queue is empty load it with some elements\n\t\t\tloadExpiredQueue(MAX_QUEUE_SIZE);\n\t\t} else {\n\n\t\t\t// If the queue is not empty, check whether recently saved off-line\n\t\t\t// message\n\t\t\t// is due to expire sooner then the head of the queue.\n\t\t\tMsgDBItem item = expiredQueue.peek();\n\n\t\t\tif ((item != null) && (earliestOffline < item.expired.getTime())) {\n\n\t\t\t\t// There is in fact off-line message due to expire sooner then the head\n\t\t\t\t// of the\n\t\t\t\t// queue. Load all off-line message due to expire sooner then the first\n\t\t\t\t// element\n\t\t\t\t// in the queue.\n\t\t\t\tloadExpiredQueue(item.expired);\n\t\t\t}\n\t\t}\n\n\t\tMsgDBItem item = null;\n\n\t\twhile (item == null) {\n\t\t\ttry {\n\t\t\t\titem = expiredQueue.take();\n\t\t\t} catch (InterruptedException ex) {\n\t\t\t}\n\t\t}\n\n\t\tif (delete) {\n\t\t\tdeleteMessage(item.db_id);\n\t\t}\n\n\t\treturn item.msg;\n\t}\n\n\tpublic String getStanzaTo() {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\"); //To change body of generated methods, choose Tools | Templates.\n\t}\n\t\n\t// ~--- inner classes --------------------------------------------------------\n\n\tprotected class MsgDBItem implements Delayed {\n\t\tpublic final T db_id;\n\t\tpublic final Date expired;\n\t\tpublic final Element msg;\n\n\t\t// ~--- constructors -------------------------------------------------------\n\n\t\tpublic MsgDBItem(T db_id, Element msg, Date expired) {\n\t\t\tthis.db_id = db_id;\n\t\t\tthis.msg = msg;\n\t\t\tthis.expired = expired;\n\t\t}\n\n\t\t// ~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic int compareTo(Delayed o) {\n\t\t\treturn (int) (getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS));\n\t\t}\n\n\t\t// ~--- get methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic long getDelay(TimeUnit unit) {\n\t\t\treturn unit.convert(expired.getTime() - System.currentTimeMillis(),\n\t\t\t\t\tTimeUnit.MILLISECONDS);\n\t\t}\n\t}\t\n\t\t\n\tpublic class BroadcastMsg extends MsgDBItem {\n\t\t\n\t\tprivate JidResourceMap<Boolean> recipients = new JidResourceMap<Boolean>();\n\t\t\n\t\tpublic BroadcastMsg(T db_id, Element msg, Date expired) {\n\t\t\tsuper(db_id, msg, expired);\n\t\t}\n\t\t\t\t\n\t\tprotected boolean addRecipient(BareJID jid) {\n\t\t\tif (recipients.containsKey(jid))\n\t\t\t\treturn false;\n\t\t\trecipients.put(JID.jidInstance(jid), Boolean.TRUE);\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tpublic boolean needToSend(JID jid) {\n\t\t\treturn recipients.containsKey(jid.getBareJID()) \n\t\t\t\t\t&& (jid.getResource() == null || !recipients.containsKey(jid));\n\t\t}\n\t\t\n\t\tpublic void markAsSent(JID jid) {\n\t\t\trecipients.put(jid, Boolean.TRUE);\n\t\t}\n\t\t\n\t}\n\n\tpublic interface OfflineMessagesProcessor {\n\t\tpublic void stamp(Element msg, String msgID);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Alert.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.amp.ActionAbstract;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.PacketErrorTypeException;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: May 1, 2010 1:39:07 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Alert extends ActionAbstract {\n\tprivate static final String name = \"alert\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\ttry {\n\t\t\tPacket result = prepareAmpPacket(packet, rule);\n\n\t\t\tresultsHandler.addOutPacket(result);\n\t\t} catch (PacketErrorTypeException ex) {\n\n\t\t\t// Ignore....\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Broadcast.java",
    "content": "/*\n * Broadcast.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.server.amp.action;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TimeZone;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.server.Presence;\nimport tigase.server.amp.ActionAbstract;\nimport tigase.server.amp.ActionResultsHandlerIfc;\nimport tigase.server.amp.AmpFeatureIfc;\nimport static tigase.server.amp.AmpFeatureIfc.AMP_MSG_REPO_CLASS_PARAM;\nimport static tigase.server.amp.AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY;\nimport static tigase.server.amp.AmpFeatureIfc.AMP_MSG_REPO_URI_PARAM;\nimport static tigase.server.amp.AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY;\nimport static tigase.server.amp.AmpFeatureIfc.AMP_XMLNS;\nimport static tigase.server.amp.AmpFeatureIfc.CONDITION_ATT;\nimport tigase.server.amp.MsgRepository;\nimport static tigase.server.amp.cond.ExpireAt.NAME;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n *\n * @author andrzej\n */\npublic class Broadcast implements AmpFeatureIfc {\n\t\n\tprivate static final Logger log  = Logger.getLogger(Broadcast.class.getName());\n\tprivate static final String name = \"broadcast\";\n\t\n\tprivate MsgRepository repo = null;\n\t\n\tprivate final SimpleDateFormat formatter;\n\tprivate final SimpleDateFormat formatter2;\n\tprivate ActionResultsHandlerIfc resultsHandler;\n\t{\n\t\tformatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tformatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t\tformatter2 = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss'Z'\" );\n\t\tformatter2.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\t\n\t\n\tpublic boolean preprocess(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"processing packet = {0}\", packet.toString());\n\t\t}\n\t\tif (packet.getElemName() == Presence.ELEM_NAME) {\n\t\t\tsendBroadcastMessage(packet.getStanzaFrom());\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tElement broadcast = packet.getElement().getChild(\"broadcast\", \"http://tigase.org/protocol/broadcast\");\n\t\tif (broadcast == null || packet.getAttributeStaticStr(FROM_CONN_ID) != null) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"processing broadcast packet = {0}\", packet);\n\t\t}\n\t\t\n\t\tif (repo != null) {\n\t\t\tif (packet.getStanzaTo().getResource() == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"setting broadcast request for user {0}\", packet.getStanzaTo());\n\t\t\t\t}\n\t\t\t\tElement amp = packet.getElement().getChild(\"amp\", AMP_XMLNS);\n\t\t\t\tElement rule = null;\n\t\t\t\tfor (Element elem : amp.getChildren()) {\n\t\t\t\t\tif (\"rule\".equals(elem.getName()) && \"expire-at\".equals(elem.getAttributeStaticStr(CONDITION_ATT))) {\n\t\t\t\t\t\trule = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (rule != null) {\n\t\t\t\t\tString value = rule.getAttributeStaticStr(\"value\");\n\t\t\t\t\tDate expire = null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (value != null) {\n\t\t\t\t\t\t\tif (value.contains(\".\")) {\n\t\t\t\t\t\t\t\tsynchronized (formatter) {\n\t\t\t\t\t\t\t\t\texpire = formatter.parse(value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsynchronized (formatter2) {\n\t\t\t\t\t\t\t\t\texpire = formatter2.parse(value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tpacket.getElement().removeAttribute(TO_CONN_ID);\n\t\t\t\t\t\t\tpacket.getElement().removeAttribute(TO_RES);\n\t\t\t\t\t\t\tpacket.getElement().removeAttribute(OFFLINE);\n\t\t\t\t\t\t\tpacket.getElement().removeAttribute(FROM_CONN_ID);\n\t\t\t\t\t\t\tpacket.getElement().removeAttribute(EXPIRED);\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\tElement msg = packet.getElement().clone();\n\t\t\t\t\t\t\tmsg.removeAttribute(\"to\");\n\n\t\t\t\t\t\t\tString msgId = packet.getAttributeStaticStr(\"id\");\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tMsgRepository.BroadcastMsg bmsg = repo.getBroadcastMsg(msgId);\n\t\t\t\t\t\t\tboolean needToBroadcast = bmsg == null || !bmsg.needToSend(packet.getStanzaTo());\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\trepo.updateBroadcastMessage(msgId, msg, expire, packet.getStanzaTo().getBareJID());\n\n\t\t\t\t\t\t\tif (needToBroadcast) {\n\t\t\t\t\t\t\t\tPacket broadcastCmd = Command.BROADCAST_TO_ONLINE.getPacket(packet.getPacketTo(),\n\t\t\t\t\t\t\t\t\t\tJID.jidInstanceNS(\"sess-man\", packet.getPacketTo().getDomain(), null), StanzaType.get, name);\n\t\t\t\t\t\t\t\tCommand.addFieldValue(broadcastCmd, \"to\", packet.getStanzaTo().toString());\n\t\t\t\t\t\t\t\tmsg = packet.getElement().clone();\n\t\t\t\t\t\t\t\tmsg.removeAttribute(\"to\");\n\t\t\t\t\t\t\t\tmsg.setAttribute(\"xmlns\", \"http://tigase.org/protocol/broadcast\");\n\t\t\t\t\t\t\t\tbroadcastCmd.getElement().addChild(msg);\n\n\t\t\t\t\t\t\t\tresultsHandler.addOutPacket(broadcastCmd);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (ParseException ex) {\n\t\t\t\t\t\tlog.info(\"Incorrect \" + NAME + \" condition value for rule: \" + rule);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tString msgId = packet.getAttributeStaticStr(\"id\");\n\t\t\t\tMsgRepository.BroadcastMsg msg = repo.getBroadcastMsg(msgId);\n\t\t\t\tif (msg != null) {\n\t\t\t\t\tpacket.getElement().removeChild(broadcast);\n\t\t\t\t\tmsg.markAsSent(packet.getStanzaTo());\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"marking broadcast of message = {0} for user {1} as done, result = {2}\", \n\t\t\t\t\t\t\t\tnew Object[]{msgId, packet.getStanzaTo(), msg.needToSend(packet.getStanzaTo())});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"not found broadcast request with id = {0} for user {1}, keys = {2}\", new Object[]{msgId, packet.getStanzaTo(), repo.dumpBroadcastMessageKeys()});\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\treturn packet.getPacketTo() == null || !packet.getPacketTo().getDomain().equals(packet.getPacketFrom().getDomain());\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.FINEST, \"repository is NULL !!\");\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void sendBroadcastMessage(JID jid) {\n\t\tif (repo != null) {\n\t\t\tfor (Object o : repo.getBroadcastMessages()) {\n\t\t\t\tMsgRepository.BroadcastMsg msg = (MsgRepository.BroadcastMsg) o;\n\t\t\t\tif (msg.getDelay(TimeUnit.MILLISECONDS) > 0 && msg.needToSend(jid)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsendBroadcastMessage(jid, msg);\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"should not happen, contact developer\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\n\t}\n\t\n\tpublic void sendBroadcastMessage(JID jid, MsgRepository.BroadcastMsg msg) throws TigaseStringprepException {\n\t\tElement msgEl = msg.msg.clone();\n\t\tmsgEl.setAttribute(\"to\", jid.toString());\n\t\tPacket p = Packet.packetInstance(msgEl);\n\t\tresultsHandler.addOutPacket(p);\n\t}\n\t\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param params\n\t *\n\t * \n\t */\n\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = new HashMap<String,Object>();\n\t\tString db_uri            = (String) params.get(AMP_MSG_REPO_URI_PARAM);\n\t\tString db_cls\t\t\t = (String) params.get(AMP_MSG_REPO_CLASS_PARAM);\n\n\t\tif (db_uri == null) {\n\t\t\tdb_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t}\n\t\tif (db_uri != null) {\n\t\t\tdefs.put(AMP_MSG_REPO_URI_PROP_KEY, db_uri);\n\t\t}\n\t\tif (db_cls != null) {\n\t\t\tdefs.put(AMP_MSG_REPO_CLASS_PROP_KEY, db_cls);\n\t\t}\n\n\t\treturn defs;\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param props\n\t * @param handler\n\t */\n\n\tpublic void setProperties(Map<String, Object> props, ActionResultsHandlerIfc handler) {\n\t\tthis.resultsHandler = handler;\n\t\tString db_uri = (String) props.get(AMP_MSG_REPO_URI_PROP_KEY);\n\t\tString db_cls = (String) props.get(AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t\n\t\tif (db_uri != null) {\n\t\t\ttry {\n\t\t\t\trepo = (MsgRepository) MsgRepository.getInstance(db_cls, db_uri);\n\t\t\t\tMap<String, String> db_props = new HashMap<String, String>(4);\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\n\t\t\t\t\t// Entry happens to be null for (shared-user-repo-params, null)\n\t\t\t\t\t// TODO: Not sure if this is supposed to happen, more investigation is needed.\n\t\t\t\t\tif (entry.getValue() != null) {\n\t\t\t\t\t\tlog.log(Level.CONFIG,\n\t\t\t\t\t\t\t\t\t\t\"Reading properties: (\" + entry.getKey() + \", \" + entry.getValue() +\n\t\t\t\t\t\t\t\t\t\t\")\");\n\t\t\t\t\t\tdb_props.put(entry.getKey(), entry.getValue().toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Initialization of repository can be done here and in MessageAmp\n\t\t\t\t// class so repository related parameters for JDBCMsgRepository\n\t\t\t\t// should be specified for AMP plugin and AMP component\n\t\t\t\trepo.initRepository(db_uri, db_props);\n\t\t\t\t\n\t\t\t\trepo.loadMessagesToBroadcast();\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\trepo = null;\n\t\t\t\tlog.log(Level.WARNING, \"Problem initializing connection to DB: \", ex);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Deliver.java",
    "content": "/*\n * Deliver.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.List;\nimport tigase.server.amp.ActionAbstract;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\n\n/**\n * Created: May 1, 2010 11:28:40 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Deliver\n\t\t\t\textends ActionAbstract {\n\tprivate static final String name = \"deliver\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\tPacket result     = packet.copyElementOnly();\n\t\tif (packet.getAttributeStaticStr(FROM_CONN_ID) == null)\n\t\t\tresult.setPacketFrom(packet.getPacketTo());\t\n\t\tremoveTigasePayload(result);\t\n\t\tresultsHandler.addOutPacket(result);\n\t\treturn true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Drop.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.amp.ActionAbstract;\n\nimport tigase.xml.Element;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 27, 2010 5:35:33 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Drop extends ActionAbstract {\n\tprivate static final String name = \"drop\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Error.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.amp.ActionAbstract;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.PacketErrorTypeException;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 27, 2010 5:35:45 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Error extends ActionAbstract {\n\tprivate static final String name = \"error\";\n\tprivate static final String FAILED_RULES_PATH = \"error/failed-rules\";\n\tprivate static final Element UNDEF_CONDITION = new Element(\"undefined-condition\",\n\t\tnew String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-stanzas\" });\n\tprivate static final Element FAILED_RULES = new Element(\"failed-rules\",\n\t\tnew String[] { \"xmlns\" }, new String[] { \"http://jabber.org/protocol/amp#errors\" });\n\tprivate static final Element ERROR_TEMPLATE = new Element(\"error\",\n\t\tnew Element[] { UNDEF_CONDITION }, new String[] { \"type\",\n\t\t\t\"code\" }, new String[] { \"modify\", \"500\" });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\ttry {\n\t\t\tPacket result = prepareAmpPacket(packet, rule);\n\t\t\tElement error = ERROR_TEMPLATE.clone();\n\t\t\tElement failed_rules = FAILED_RULES.clone();\n\n\t\t\tfailed_rules.addChild(rule);\n\t\t\terror.addChild(failed_rules);\n\t\t\tresult.getElement().addChild(error);\n\t\t\tresultsHandler.addOutPacket(result);\n\t\t} catch (PacketErrorTypeException ex) {\n\n\t\t\t// Ignore\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Notify.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.amp.ActionAbstract;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.PacketErrorTypeException;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 27, 2010 5:36:03 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Notify extends ActionAbstract {\n\tprivate static final String name = \"notify\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\ttry {\n\t\t\tif (packet.getStanzaFrom() != null && packet.getStanzaFrom().getBareJID().getLocalpart() != null ) {\n\t\t\t\tPacket result = prepareAmpPacket(packet, rule);\n\t\t\t\tresultsHandler.addOutPacket(result);\n\t\t\t}\n\n\t\t} catch (PacketErrorTypeException ex) {\n\n\t\t\t// Ignore\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/action/Store.java",
    "content": "/*\n * Store.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp.action;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.sql.SQLException;\nimport java.text.SimpleDateFormat;\n\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.NonAuthUserRepositoryImpl;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\nimport tigase.db.UserRepository;\nimport tigase.server.Packet;\nimport tigase.server.amp.ActionAbstract;\nimport tigase.server.amp.ActionResultsHandlerIfc;\nimport tigase.server.amp.JDBCMsgRepository;\nimport tigase.server.amp.MsgRepository;\nimport tigase.server.amp.cond.ExpireAt;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\n/**\n * Created: May 1, 2010 11:32:59 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Store\n\t\t\t\textends ActionAbstract {\n\tprivate static final Logger log  = Logger.getLogger(Store.class.getName());\n\tprivate static final String name = \"store\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate Thread expiredProcessor          = null;\n\tprivate MsgRepositoryIfc repo               = null;\n\tprivate final SimpleDateFormat formatter;\n\tprivate final SimpleDateFormat formatter2;\n\tprivate NonAuthUserRepositoryImpl nonAuthUserRepo;\n\n\t{\n\t\tformatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tformatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t\tformatter2 = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss'Z'\" );\n\t\tformatter2.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean execute(Packet packet, Element rule) {\n\t\tif (repo != null) {\n\t\t\tDate expired = null;\n\t\t\tString stamp = null;\n\n\t\t\tif (packet.getAttributeStaticStr(EXPIRED) == null) {\n\t\t\t\tif (rule == null) {\n\t\t\t\t\trule = getExpireAtRule(packet);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremoveExpireAtRule(packet);\n\t\t\t\trule = null;\n\t\t\t}\n\t\t\tif (rule != null) {\n\t\t\t\ttry {\n\t\t\t\t\tString value = rule.getAttributeStaticStr(\"value\");\n\t\t\t\t\tif (value != null) {\n\t\t\t\t\t\tif (value.contains(\".\")) {\n\t\t\t\t\t\t\tsynchronized (formatter) {\n\t\t\t\t\t\t\t\texpired = formatter.parse(value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsynchronized (formatter2) {\n\t\t\t\t\t\t\t\texpired = formatter2.parse(value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\"Incorrect expire-at value: \" + rule.getAttributeStaticStr(\"value\"),\n\t\t\t\t\t\t\t\t\te);\n\t\t\t\t\texpired = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsynchronized (formatter) {\n\t\t\t\tstamp = formatter.format(new Date());\n\t\t\t}\n\t\t\tremoveTigasePayload(packet);\n\t\t\ttry {\n\t\t\t\tElement elem = packet.getElement();\n\n\t\t\t\tif (elem.getChild(\"delay\", \"urn:xmpp:delay\") == null) {\n\t\t\t\t\tElement x = new Element(\"delay\", \"Offline Storage\", new String[] { \"from\",\n\t\t\t\t\t\t\t\t\t\"stamp\", \"xmlns\" }, new String[] { packet.getStanzaTo().getDomain(),\n\t\t\t\t\t\t\t\t\tstamp, \"urn:xmpp:delay\" });\n\n\t\t\t\t\telem.addChild(x);\n\t\t\t\t}\n\t\t\t\trepo.storeMessage(packet.getStanzaFrom(), packet.getStanzaTo(), expired, elem, nonAuthUserRepo);\n\t\t\t} catch (UserNotFoundException ex) {\n\t\t\t\tlog.info(\"User not found for offline message: \" + packet);\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\t\tString db_uri            = (String) params.get(AMP_MSG_REPO_URI_PARAM);\n\t\tString db_cls\t\t\t = (String) params.get(AMP_MSG_REPO_CLASS_PARAM);\n\n\t\tif (db_uri == null) {\n\t\t\tdb_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t}\n\t\tif (db_uri != null) {\n\t\t\tdefs.put(AMP_MSG_REPO_URI_PROP_KEY, db_uri);\n\t\t}\n\t\tif (db_cls != null) {\n\t\t\tdefs.put(AMP_MSG_REPO_CLASS_PROP_KEY, db_cls);\n\t\t}\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props, ActionResultsHandlerIfc handler) {\n\t\tsuper.setProperties(props, handler);\n\n\t\tUserRepository user_repository = (UserRepository) props.get(RepositoryFactory.SHARED_USER_REPO_PROP_KEY);\n\t\tnonAuthUserRepo = new NonAuthUserRepositoryImpl(user_repository, null, true);\n\t\t\n\t\tString db_uri = (String) props.get(AMP_MSG_REPO_URI_PROP_KEY);\n\t\tString db_cls = (String) props.get(AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t\n\t\tif (db_uri != null) {\n\t\t\ttry {\n\t\t\t\trepo = MsgRepository.getInstance(db_cls, db_uri);\n\t\t\t\tMap<String, String> db_props = new HashMap<String, String>(4);\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\n\t\t\t\t\t// Entry happens to be null for (shared-user-repo-params, null)\n\t\t\t\t\t// TODO: Not sure if this is supposed to happen, more investigation is needed.\n\t\t\t\t\tif (entry.getValue() != null) {\n\t\t\t\t\t\tlog.log(Level.CONFIG,\n\t\t\t\t\t\t\t\t\t\t\"Reading properties: (\" + entry.getKey() + \", \" + entry.getValue() +\n\t\t\t\t\t\t\t\t\t\t\")\");\n\t\t\t\t\t\tdb_props.put(entry.getKey(), entry.getValue().toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Initialization of repository can be done here and in MessageAmp\n\t\t\t\t// class so repository related parameters for JDBCMsgRepository\n\t\t\t\t// should be specified for AMP plugin and AMP component\n\t\t\t\trepo.initRepository(db_uri, db_props);\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\trepo = null;\n\t\t\t\tlog.log(Level.WARNING, \"Problem initializing connection to DB: \", ex);\n\t\t\t}\n\t\t}\t\n\t\tif ((repo != null) && (expiredProcessor == null)) {\n\t\t\texpiredProcessor = new Thread(\"expired-processor\") {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tElement elem = repo.getMessageExpired(0, true);\n\n\t\t\t\t\t\tif (elem != null) {\n\t\t\t\t\t\t\telem.addAttribute(OFFLINE, \"1\");\n\t\t\t\t\t\t\telem.addAttribute(EXPIRED, \"1\");\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tresultsHandler.addOutPacket(Packet.packetInstance(elem));\n\t\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\t\tlog.info(\"Stringprep error for offline message loaded from DB: \" + elem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\texpiredProcessor.setDaemon(true);\n\t\t\texpiredProcessor.start();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t// ~--- get methods ----------------------------------------------------------\n\tprivate Element getExpireAtRule(Packet packet) {\n\t\tElement amp         = packet.getElement().getChild(\"amp\", AMP_XMLNS);\n\t\tList<Element> rules = amp.getChildren();\n\t\tElement rule        = null;\n\n\t\tif ((rules != null) && (rules.size() > 0)) {\n\t\t\tfor (Element r : rules) {\n\t\t\t\tString cond = r.getAttributeStaticStr(CONDITION_ATT);\n\n\t\t\t\tif ((cond != null) && cond.equals(ExpireAt.NAME)) {\n\t\t\t\t\trule = r;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn rule;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// ~--- methods --------------------------------------------------------------\n\tprivate void removeExpireAtRule(Packet packet) {\n\t\tElement amp         = packet.getElement().getChild(\"amp\", AMP_XMLNS);\n\t\tList<Element> rules = amp.getChildren();\n\n\t\tif ((rules != null) && (rules.size() > 0)) {\n\t\t\tfor (Element r : rules) {\n\t\t\t\tString cond = r.getAttributeStaticStr(CONDITION_ATT);\n\n\t\t\t\tif ((cond != null) && cond.equals(ExpireAt.NAME)) {\n\t\t\t\t\tamp.removeChild(r);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trules = amp.getChildren();\n\t\tif ((rules == null) || (rules.size() == 0)) {\n\t\t\tpacket.getElement().removeChild(amp);\n\t\t}\n\t}\n}\n\n\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/cond/Deliver.java",
    "content": "/*\n * Deliver.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp.cond;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.amp.ConditionIfc;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Created: Apr 27, 2010 5:36:27 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Deliver\n\t\t\t\timplements ConditionIfc {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log        = Logger.getLogger(Deliver.class.getName());\n\tprivate static final String name = \"deliver\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate boolean offline_storage = true;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate enum MatchValue {\n\t\tdirect, forward, gateway, none, stored;\n\t}\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic Deliver() {\n\t\tString off_val = System.getProperty(MSG_OFFLINE_PROP_KEY);\n\n\t\toffline_storage = (off_val == null) || Boolean.parseBoolean(off_val);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean match(Packet packet, Element rule) {\n\t\tString value   = rule.getAttributeStaticStr(\"value\");\n\t\tboolean result = false;\n\n\t\tif (value != null) {\n\t\t\ttry {\n\t\t\t\tMatchValue m_val = MatchValue.valueOf(value);\n\n\t\t\t\tswitch (m_val) {\n\t\t\t\tcase direct :\n\t\t\t\t\tresult = (packet.getAttributeStaticStr(OFFLINE) == null) &&\n\t\t\t\t\t\t\t\t\t (packet.getAttributeStaticStr(FROM_CONN_ID) == null);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase forward :\n\n\t\t\t\t\t// Forwarding not supported in Tigase yet\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase gateway :\n\n\t\t\t\t\t// This can be only determined by the gateway itself\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase none :\n\t\t\t\t\tresult = (packet.getAttributeStaticStr(OFFLINE) != null) &&!offline_storage;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase stored :\n\t\t\t\t\tresult = (packet.getAttributeStaticStr(OFFLINE) != null) && offline_storage;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.info(\"Incorrect \" + name + \" condition value for rule: \" + rule);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.info(\"No value set for rule: \" + rule);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/cond/ExpireAt.java",
    "content": "/*\n * ExpireAt.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp.cond;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.amp.ConditionIfc;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\n\nimport java.util.Date;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.TimeZone;\n\n/**\n * Created: Apr 27, 2010 5:36:39 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ExpireAt\n\t\t\t\timplements ConditionIfc {\n\t/** Field description */\n\tpublic static final String NAME = \"expire-at\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(ExpireAt.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate final SimpleDateFormat formatter;\n\tprivate final SimpleDateFormat formatter2;\n\t{\n\t\tformatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tformatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t\tformatter2 = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss'Z'\" );\n\t\tformatter2.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn NAME;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean match(Packet packet, Element rule) {\n\t\tString value = rule.getAttributeStaticStr(\"value\");\n\n\t\tif (value != null) {\n\t\t\ttry {\n\t\t\t\tDate val_date = null;\n\n\t\t\t\tif (value.contains(\".\")) {\n\t\t\t\t\tsynchronized (formatter) {\n\t\t\t\t\t\tval_date = formatter.parse(value);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsynchronized (formatter2) {\n\t\t\t\t\t\tval_date = formatter2.parse(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn val_date.before(new Date());\n\t\t\t} catch (ParseException ex) {\n\t\t\t\tlog.info(\"Incorrect \" + NAME + \" condition value for rule: \" + rule);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.info(\"No value set for rule: \" + rule);\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/amp/cond/MatchResource.java",
    "content": "/*\n * MatchResource.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.amp.cond;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.amp.ConditionIfc;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.JID;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Created: Apr 27, 2010 5:36:54 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MatchResource\n\t\t\t\timplements ConditionIfc {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log        = Logger.getLogger(MatchResource.class.getName());\n\tprivate static final String name = \"match-resource\";\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate enum MatchValue { any, exact, other; }\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean match(Packet packet, Element rule) {\n\t\tString value   = rule.getAttributeStaticStr(\"value\");\n\t\tboolean result = false;\n\n\t\tif (value != null) {\n\t\t\ttry {\n\t\t\t\tMatchValue m_val       = MatchValue.valueOf(value);\n\t\t\t\tString jid_resource    = (packet.getStanzaTo() != null)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? packet.getStanzaTo().getResource()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : null;\n\t\t\t\tString target_resource = packet.getAttributeStaticStr(TO_RES);\n\t\t\t\tString from_session_jid_string = packet.getAttributeStaticStr(SESSION_JID);\n\t\t\t\tJID from_original_jid = from_session_jid_string != null ? \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tJID.jidInstance( from_session_jid_string)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\tswitch (m_val) {\n\t\t\t\tcase any :\n\t\t\t\t\tresult = true;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase other :\n\t\t\t\t\tresult = ( ( jid_resource != null ) && ( target_resource != null )\n\t\t\t\t\t\t\t\t\t\t && !jid_resource.equals( target_resource ) )\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t || ( from_original_jid == null && target_resource == null )\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase exact :\n\t\t\t\t\tresult = (jid_resource != null) && jid_resource.equals(target_resource);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.info(\"Incorrect \" + name + \" condition value for rule: \" + rule);\n\t\t\t}\n\t\t} else {\n\t\t\tlog.info(\"No value set for rule: \" + rule);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshConnectionManager.java",
    "content": "/*\n * BoshConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.bosh;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.ReceiverTimeoutHandler;\nimport tigase.server.xmppclient.ClientConnectionManager;\nimport tigase.server.xmppclient.SeeOtherHostIfc.Phase;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPIOService;\n\nimport tigase.conf.ConfigurationException;\nimport tigase.stats.StatisticsList;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.io.IOException;\nimport java.util.ArrayDeque;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.FileHandler;\nimport java.util.logging.Filter;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\n\nimport static tigase.server.bosh.Constants.*;\nimport tigase.xmpp.StreamError;\n\n/**\n * Describe class BoshConnectionManager here.\n *\n *\n * Created: Sat Jun 2 12:24:29 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BoshConnectionManager\n\t\t\t\textends ClientConnectionManager\n\t\t\t\timplements BoshSessionTaskHandler {\n\tprivate static final int DEF_PORT_NO = 5280;\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(BoshConnectionManager.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int[]                  PORTS               = { DEF_PORT_NO };\n\tprivate long                   min_polling         = MIN_POLLING_PROP_VAL;\n\tprivate long                   max_wait            = MAX_WAIT_DEF_PROP_VAL;\n\tprivate long                   max_pause           = MAX_PAUSE_PROP_VAL;\n\tprivate long                   max_inactivity      = MAX_INACTIVITY_PROP_VAL;\n\tprivate int                    hold_requests       = HOLD_REQUESTS_PROP_VAL;\n\tprivate int                    concurrent_requests = CONCURRENT_REQUESTS_PROP_VAL;\n\tprivate ReceiverTimeoutHandler stoppedHandler      = newStoppedHandler();\n\tprivate ReceiverTimeoutHandler startedHandler      = newStartedHandler();\n\tprivate int                    max_batch_size      = MAX_BATCH_SIZE_VAL;\n\tprivate long                   bosh_session_close_delay =\n\t\t\tBOSH_SESSION_CLOSE_DELAY_DEF_VAL;\n\tprivate long                   batch_queue_timeout = BATCH_QUEUE_TIMEOUT_VAL;\n\tprivate int\t\t\t\t\t   maxSessionWaitingPackets = MAX_SESSION_WAITING_PACKETS_VAL;\n\tprivate boolean\t\t\t\t   sendNodeHostname\t   = SEND_NODE_HOSTNAME_VAL;\n\n\tprotected enum BOSH_OPERATION_TYPE {\n\n\t\tCREATE, REMOVE, INVALID_SID,\n\t\tTIMER;\n\n\t\tprivate static final Map<String, BOSH_OPERATION_TYPE> nameToValueMap\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t= new HashMap<String, BOSH_OPERATION_TYPE>();\n\n\t\tstatic {\n\t\t\tfor ( BOSH_OPERATION_TYPE value : EnumSet.allOf( BOSH_OPERATION_TYPE.class ) ) {\n\t\t\t\tnameToValueMap.put( value.name(), value );\n\t\t\t}\n\t\t}\n\n\t\tpublic static BOSH_OPERATION_TYPE forName( String name ) {\n\t\t\treturn nameToValueMap.get( name );\n\t\t}\n\n\t};\n\n\tprivate static Handler sidFilehandler;\n\n\t// This should be actually a multi-thread save variable.\n\t// Changing it to\n\n\t/** Field description */\n\tprotected final Map<UUID, BoshSession> sessions = new ConcurrentSkipListMap<UUID,\n\t\t\tBoshSession>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutStreamClosed(Packet packet, BoshSession bs, boolean withTimeout) {\n\t\tpacket.setPacketFrom(getFromAddress(bs.getSid().toString()));\n\t\tpacket.setPacketTo(bs.getDataReceiver());\n\t\tpacket.initVars(packet.getPacketFrom(), packet.getPacketTo());\n\t\tbs.close();\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.REMOVE, bs.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Closing bosh session\" } );\n\t\t}\n\n\t\tsessions.remove(bs.getSid());\n\n\t\tif ( withTimeout ){\n\t\t\treturn addOutPacketWithTimeout( packet, stoppedHandler, 15l, TimeUnit.SECONDS );\n\t\t} else {\n\t\t\treturn addOutPacket( packet );\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean addOutStreamOpen(Packet packet, BoshSession bs) {\n\t\tpacket.initVars(getFromAddress(bs.getSid().toString()), bs.getDataReceiver());\n\n\t\treturn addOutPacketWithTimeout(packet, startedHandler, 15l, TimeUnit.SECONDS);\n\t}\n\n\t@Override\n\tpublic void cancelSendQueueTask(BoshSendQueueTask tt) {\n\t\ttt.cancel();\n\t}\n\n\t@Override\n\tpublic void cancelTask(BoshTask tt) {\n\t\ttt.cancel();\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet.toString());\n\t\t}\n\t\tsuper.processPacket(packet);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\tprotected static void setupSidlogger( Level lvl ) {\n\t\tif ( !Level.OFF.equals( lvl ) ){\n\t\t\tFilter bslf = new BoshSidLoggerFilter();\n\n\t\t\tLogger BoshConnectionManagerLogger = Logger.getLogger(BoshConnectionManager.class.getName());\n\t\t\tLogger BoshSessionLogger = Logger.getLogger(BoshSession.class.getName());\n\n\t\t\tif (BoshConnectionManagerLogger.getLevel() == null || BoshSessionLogger.getLevel() == null\n\t\t\t\t\t|| BoshConnectionManagerLogger.getLevel().intValue() < lvl.intValue()) {\n\t\t\t\tBoshConnectionManagerLogger.setLevel( lvl );\n\t\t\t\tBoshConnectionManagerLogger.setFilter( bslf );\n\t\t\t\tBoshSessionLogger.setLevel( lvl );\n\t\t\t\tBoshSessionLogger.setFilter( bslf );\n\n\t\t\t\tBoshConnectionManagerLogger.getParent().setFilter( bslf );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif ( null == sidFilehandler ){\n\t\t\t\t\tsidFilehandler = new FileHandler( \"logs/bosh_sid.log\", 10000000, 5, false );\n\t\t\t\t\tsidFilehandler.setLevel( lvl );\n\t\t\t\t\tsidFilehandler.setFilter( bslf );\n\t\t\t\t\tBoshConnectionManagerLogger.getParent().addHandler( sidFilehandler );\n\t\t\t\t}\n\t\t\t} catch ( IOException ex ) {\n\t\t\t\tlog.log( Level.CONFIG, \"Error creating BOSH SID logger\" + ex );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void setupWatchdogThread() {\n\t\t// having watchdog for bosh connections is not needed\n\t}\n\n\tprotected Map<String,String> preBindSession(Map<String,String> attr) {\n\t\tString hostname = attr.get( TO_ATTR );\n\n\t\tQueue<Packet> out_results = new ArrayDeque<Packet>( 2 );\n\n\t\tBoshSession bs = new BoshSession( getDefVHostItem().getDomain(),\n\t\t\t\tJID.jidInstanceNS( routings.computeRouting( hostname ) ), \n\t\t\t\tthis, sendNodeHostname ? getDefHostName().getDomain() : null,\n\t\t\t\tmaxSessionWaitingPackets);\n\n\t\tString jid = attr.get( FROM_ATTR );\n\t\tString uuid = UUID.randomUUID().toString();\n\t\tJID userId = JID.jidInstanceNS( jid );\n\t\tif ( null == userId.getResource() ){\n\t\t\tuserId = userId.copyWithResourceNS( uuid );\n\t\t\tattr.put( FROM_ATTR, userId.toString() );\n\t\t\tbs.setUserJid( jid );\n\t\t}\n\t\tlong rid = (long) (Math.random() * 10000000);\n\n\t\tattr.put( RID_ATTR, Long.toString( rid ) );\n\n\t\tUUID sid = bs.getSid();\n\t\tsessions.put( sid, bs );\n\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.CREATE, bs.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Pre-bind\" } );\n\t\t}\n\n\t\tattr.put( SID_ATTR, sid.toString() );\n\n\t\tPacket p = null;\n\t\ttry {\n\t\t\tElement el = new Element( \"body\" );\n\t\t\tel.setAttributes( attr );\n\t\t\tp = Packet.packetInstance( el );\n\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\tLogger.getLogger( BoshConnectionManager.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\t\tbs.init( p, null, max_wait, min_polling, max_inactivity,\n\t\t\t\t\t\t concurrent_requests, hold_requests, max_pause, max_batch_size,\n\t\t\t\t\t\t batch_queue_timeout, out_results, true );\n\t\taddOutPackets( out_results, bs );\n\n\t\tattr.put( \"hostname\", getDefHostName().toString() );\n\n\t\treturn attr;\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(XMPPIOService<Object> srv) {\n\t\tBoshIOService serv = (BoshIOService) srv;\n\t\tPacket        p    = null;\n\n\t\twhile ((p = serv.getReceivedPackets().poll()) != null) {\n\t\t\tQueue<Packet> out_results = new ArrayDeque<Packet>(2);\n\t\t\tBoshSession   bs          = null;\n\t\t\tString        sid_str     = null;\n\n\t\t\tsynchronized (sessions) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Processing packet: {0}, type: {1}\", new Object[] { p\n\t\t\t\t\t\t\t.getElemName(),\n\t\t\t\t\t\t\tp.getType() });\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Processing socket data: {0}\", p);\n\t\t\t\t}\n\t\t\t\tsid_str = p.getAttributeStaticStr(SID_ATTR);\n\n\t\t\t\tUUID sid = null;\n\n\t\t\t\tif (sid_str == null) {\n\t\t\t\t\tString hostname = p.getAttributeStaticStr(Packet.TO_ATT);\n\n\t\t\t\t\tif ((hostname != null) && isLocalDomain(hostname)) {\n\t\t\t\t\t\tif (!isAllowed(srv, hostname)) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINE, \"Policy violation. Closing connection: {0}\", p);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tserv.sendErrorAndStop(Authorization.NOT_ALLOWED, StreamError.PolicyViolation, p, \"Policy violation.\");\n\t\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t\"Problem sending invalid hostname error for sid =  \" + sid, e);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbs = new BoshSession(getDefVHostItem().getDomain(), JID.jidInstanceNS(routings\n\t\t\t\t\t\t\t\t.computeRouting(hostname)), this, sendNodeHostname ? getDefHostName().getDomain() : null,\n\t\t\t\t\t\t\t\tmaxSessionWaitingPackets);\n\t\t\t\t\t\t\tsid = bs.getSid();\n\t\t\t\t\t\t\tsessions.put(sid, bs);\n\n\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.CREATE, sid, \"Socket bosh session\" } );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tserv.sendErrorAndStop(Authorization.NOT_ALLOWED, \n\t\t\t\t\t\t\t\t\thostname == null ? StreamError.ImproperAddressing : StreamError.HostUnknown, p, \"Invalid hostname.\");\n\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\"Problem sending invalid hostname error for sid =  \" + sid, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsid = UUID.fromString( sid_str );\n\t\t\t\t\t\tbs = sessions.get( sid );\n\t\t\t\t\t} catch ( IllegalArgumentException e ) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem processing socket data, sid =  \" + sid_str\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + \" does not conform to the UUID string representation.\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (bs != null) {\n\t\t\t\t\tsynchronized (bs) {\n\t\t\t\t\t\tif (sid_str == null) {\n\t\t\t\t\t\t\tbs.init(p, serv, max_wait, min_polling, max_inactivity,\n\t\t\t\t\t\t\t\t\tconcurrent_requests, hold_requests, max_pause, max_batch_size,\n\t\t\t\t\t\t\t\t\tbatch_queue_timeout, out_results);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbs.processSocketPacket(p, serv, out_results);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.INVALID_SID, sid_str, \"Invalid SID\" } );\n\t\t\t\t\t}\n\t\t\t\t\tserv.sendErrorAndStop(Authorization.ITEM_NOT_FOUND, null, p, \"Invalid SID\");\n\t\t\t\t}\n\t\t\t\taddOutPackets(out_results, bs);\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem processing socket data for sid =  \" + sid_str, e);\n\t\t\t}\n\n\t\t\t// addOutPackets(out_results);\n\t\t}    // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic BoshSendQueueTask scheduleSendQueueTask(final BoshSession bs, long delay) {\n\t\tBoshSendQueueTask bt = new BoshSendQueueTask(bs);\n\n\t\taddTimerTask(bt, delay);\n\n\t\t// boshTasks.schedule(bt, delay);\n\t\treturn bt;\n\t}\n\n\t@Override\n\tpublic BoshTask scheduleTask(BoshSession bs, long delay) {\n\t\tBoshTask bt = new BoshTask(bs, this);\n\n\t\taddTimerTask(bt, delay);\n\n\t\t// boshTasks.schedule(bt, delay);\n\t\treturn bt;\n\t}\n\n\t@Override\n\tpublic void serviceStarted(XMPPIOService<Object> service) {\n\t\tsuper.serviceStarted(service);\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService<Object> xmppService) {\n\t\tBoshIOService service = (BoshIOService) xmppService;\n\t\tboolean result = super.serviceStopped(service);\n\n\t\tUUID sid = service.getSid();\n\n\t\tif (sid != null) {\n\t\t\tBoshSession bs = sessions.get(sid);\n\n\t\t\tif (bs != null) {\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.REMOVE, bs.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Closing bosh session\" } );\n\t\t\t\t}\n\n\t\t\t\tbs.disconnected(service);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void writeRawData(BoshIOService ios, String data) {\n\t\tsuper.writeRawData(ios, data);\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(XMPPIOService<Object>  serv) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Stream closed.\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic String xmppStreamOpened(XMPPIOService<Object> serv, Map<String, String> attribs) {\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.fine(\n\t\t\t\t\t\"Ups, what just happened? Stream open. Hey, this is a Bosh connection manager.\" +\n\t\t\t\t\t\" c2s and s2s are not supported on the same port as Bosh yet.\");\n\t\t}\n\n\t\treturn \"<?xml version='1.0'?><stream:stream\" + \" xmlns='jabber:client'\" +\n\t\t\t\t\" xmlns:stream='http://etherx.jabber.org/streams'\" + \" id='1'\" + \" from='\" +\n\t\t\t\tgetDefVHostItem() + \"'\" + \" version='1.0' xml:lang='en'>\" + \"<stream:error>\" +\n\t\t\t\t\"<invalid-namespace xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\" +\n\t\t\t\t\"<text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='langcode'>\" +\n\t\t\t\t\"Ups, what just happened? Stream open. Hey, this is a Bosh connection manager. \" +\n\t\t\t\t\"c2s and s2s are not supported on the same port... yet.\" + \"</text>\" +\n\t\t\t\t\"</stream:error>\" + \"</stream:stream>\";\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tprops.put(MAX_WAIT_DEF_PROP_KEY, MAX_WAIT_DEF_PROP_VAL);\n\t\tprops.put(MIN_POLLING_PROP_KEY, MIN_POLLING_PROP_VAL);\n\t\tprops.put(MAX_INACTIVITY_PROP_KEY, MAX_INACTIVITY_PROP_VAL);\n\t\tprops.put(CONCURRENT_REQUESTS_PROP_KEY, CONCURRENT_REQUESTS_PROP_VAL);\n\t\tprops.put(HOLD_REQUESTS_PROP_KEY, HOLD_REQUESTS_PROP_VAL);\n\t\tprops.put(MAX_PAUSE_PROP_KEY, MAX_PAUSE_PROP_VAL);\n\t\tprops.put(MAX_BATCH_SIZE_KEY, MAX_BATCH_SIZE_VAL);\n\t\tprops.put(BATCH_QUEUE_TIMEOUT_KEY, BATCH_QUEUE_TIMEOUT_VAL);\n\t\tprops.put(MAX_SESSION_WAITING_PACKETS_KEY, MAX_SESSION_WAITING_PACKETS_VAL);\n\t\tprops.put(SEND_NODE_HOSTNAME_KEY, SEND_NODE_HOSTNAME_VAL );\n\t\tprops.put(SID_LOGGER_KEY, SID_LOGGER_VAL);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"c2s\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Bosh connection manager\";\n\t}\n\n\t/**\n\t * Returns full jid of passed BoshSession instance\n\t * \n\t * @param bs {@link BoshSession} for which JID should be retrieved\n\t * \n\t * @return JID address related to particular {@link BoshSession}\n\t */\n\t@Override\n\tpublic JID getJidForBoshSession(BoshSession bs) {\n\t\treturn getFromAddress(bs.getSid().toString());\n\t}\n\n\t@Override\n\tpublic Element getSeeOtherHostError( Packet packet, BareJID destination) {\n\n\t\tXMPPIOService<Object> xmppioService = getXMPPIOService( packet );\n\n\t\tInteger redirect_port = (Integer) xmppioService.getSessionData().get( FORCE_REDIRECT_TO_KEY );\n\n\t\treturn see_other_host_strategy.getStreamError( \"urn:ietf:params:xml:ns:xmpp-streams\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdestination, redirect_port );\n\n\t}\n\n\t@Override\n\tpublic BareJID getSeeOtherHostForJID(Packet packet, BareJID fromJID, Phase ph) {\n\t\tif (see_other_host_strategy == null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"no see-other-host implementation set\");\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t\tif (!see_other_host_strategy.isEnabled(vHostManager.getVHostItem( fromJID.getDomain()), ph)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"see-other-host not enabled for the Phase: \" + ph.toString());\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tBareJID see_other_host = see_other_host_strategy.findHostForJID(fromJID,\n\t\t\t\tgetDefHostName());\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"using = \" + see_other_host_strategy.getClass().getCanonicalName() +\n\t\t\t\t\t\"for jid = \" + fromJID.toString() + \" got = \" + ((see_other_host != null)\n\t\t\t\t\t? see_other_host.toString()\n\t\t\t\t\t: \"null\") + \" in phase: \" + ph.toString());\n\t\t}\n\n\t\tXMPPIOService<Object> xmppioService = getXMPPIOService( packet );\n\t\tInteger redirect_port = (Integer) xmppioService.getSessionData().get( FORCE_REDIRECT_TO_KEY );\n\n\t\treturn ( ( see_other_host != null )\n\t\t\t\t\t\t && ( redirect_port != null\n\t\t\t\t\t\t\t\t\t|| see_other_host_strategy.isRedirectionRequired( getDefHostName(), see_other_host ) ) )\n\t\t\t\t\t ? see_other_host\n\t\t\t\t\t : null;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tif (list.checkLevel(Level.FINEST)) {\n\n\t\t\t// Be careful here, the size() for this map is expensive to count\n\t\t\tlist.add(getName(), \"Bosh sessions\", sessions.size(), Level.FINEST);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.get(MAX_WAIT_DEF_PROP_KEY) != null) {\n\t\t\tmax_wait = (Long) props.get(MAX_WAIT_DEF_PROP_KEY);\n\t\t\tlog.info(\"Setting max_wait to: \" + max_wait);\n\t\t}\n\t\tif (props.get(MIN_POLLING_PROP_KEY) != null) {\n\t\t\tmin_polling = (Long) props.get(MIN_POLLING_PROP_KEY);\n\t\t\tlog.info(\"Setting min_polling to: \" + min_polling);\n\t\t}\n\t\tif (props.get(MAX_INACTIVITY_PROP_KEY) != null) {\n\t\t\tmax_inactivity = (Long) props.get(MAX_INACTIVITY_PROP_KEY);\n\t\t\tlog.info(\"Setting max_inactivity to: \" + max_inactivity);\n\t\t}\n\t\tif (props.get(CONCURRENT_REQUESTS_PROP_KEY) != null) {\n\t\t\tconcurrent_requests = (Integer) props.get(CONCURRENT_REQUESTS_PROP_KEY);\n\t\t\tlog.info(\"Setting concurrent_requests to: \" + concurrent_requests);\n\t\t}\n\t\tif (props.get(HOLD_REQUESTS_PROP_KEY) != null) {\n\t\t\thold_requests = (Integer) props.get(HOLD_REQUESTS_PROP_KEY);\n\t\t\tlog.info(\"Setting hold_requests to: \" + hold_requests);\n\t\t}\n\t\tif (props.get(MAX_PAUSE_PROP_KEY) != null) {\n\t\t\tmax_pause = (Long) props.get(MAX_PAUSE_PROP_KEY);\n\t\t\tlog.info(\"Setting max_pause to: \" + max_pause);\n\t\t}\n\t\tif (props.get(MAX_BATCH_SIZE_KEY) != null) {\n\t\t\tmax_batch_size = (Integer) props.get(MAX_BATCH_SIZE_KEY);\n\t\t\tlog.info(\"Setting max_batch_size to: \" + max_batch_size);\n\t\t}\n\t\tif (props.get(BATCH_QUEUE_TIMEOUT_KEY) != null) {\n\t\t\tbatch_queue_timeout = (Long) props.get(BATCH_QUEUE_TIMEOUT_KEY);\n\t\t\tlog.info(\"Setting batch_queue_timeout to: \" + batch_queue_timeout);\n\t\t}\n\t\tif (props.get(MAX_SESSION_WAITING_PACKETS_KEY) != null) {\n\t\t\tmaxSessionWaitingPackets = (Integer) props.get(MAX_SESSION_WAITING_PACKETS_KEY);\n\t\t\tlog.info(\"Setting max session waiting packets to: \" + maxSessionWaitingPackets);\n\t\t}\n\t\tif (props.get(SEND_NODE_HOSTNAME_KEY) != null) {\n\t\t\tsendNodeHostname = (Boolean) props.get(SEND_NODE_HOSTNAME_KEY);\n\t\t}\n\t\tif (props.size() == 1 && props.get(SID_LOGGER_KEY) != null) {\n\t\t\tLevel lvl = Level.parse( (String)props.get(SID_LOGGER_KEY) );\n\t\t\tsetupSidlogger( lvl );\n\t\t\tlog.info(\"Setting SID log level to: \" + lvl);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method adds packets to the output queue stamping it with the appropriate\n\t * {@link BoshSession} data\n\t *\n\t * @param out_results collection of {@link Packet} objects to be added to queue\n\t * @param bs related {@link BoshSession}\n\t */\n\tprotected void addOutPackets(Queue<Packet> out_results, BoshSession bs) {\n\t\tfor (Packet res : out_results) {\n\t\t\tres.setPacketFrom(getFromAddress(bs.getSid().toString()));\n\t\t\tres.setPacketTo(bs.getDataReceiver());\n\t\t\tif (res.getCommand() != null) {\n\t\t\t\tswitch (res.getCommand()) {\n\t\t\t\tcase STREAM_CLOSED :\n\t\t\t\tcase GETFEATURES :\n\t\t\t\t\tres.initVars(res.getPacketFrom(), res.getPacketTo());\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\n\t\t\t\t// Do nothing...\n\t\t\t\t}\n\t\t\t}\n\t\t\taddOutPacket(res);\n\t\t}\n\t\tout_results.clear();\n\t}\n\n\t@Override\n\tprotected JID changeDataReceiver(Packet packet, JID newAddress,\n\t\t\tString command_sessionId, XMPPIOService<Object> serv) {\n\t\tBoshSession session = getBoshSession(packet.getTo());\n\n\t\tif (session != null) {\n\t\t\tString sessionId = session.getSessionId();\n\n\t\t\tif (sessionId.equals(command_sessionId)) {\n\t\t\t\tJID old_receiver = session.getDataReceiver();\n\n\t\t\t\tsession.setDataReceiver(newAddress);\n\n\t\t\t\treturn old_receiver;\n\t\t\t} else {\n\t\t\t\tlog.info(\"Incorrect session ID, ignoring data redirect for: \" + newAddress);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected ReceiverTimeoutHandler newStartedHandler() {\n\t\treturn new StartedHandler();\n\t}\n\n\t@Override\n\tprotected void processCommand(Packet packet) {\n\t\tBoshSession session = getBoshSession(packet.getTo());\n\n\t\tswitch (packet.getCommand()) {\n\t\tcase USER_LOGIN :\n\t\t\tString jid = Command.getFieldValue(packet, \"user-jid\");\n\n\t\t\tif (jid != null) {\n\t\t\t\tif (session != null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tBareJID fromJID = BareJID.bareJIDInstance(jid);\n\t\t\t\t\t\tBareJID hostJid = getSeeOtherHostForJID( packet, fromJID, Phase.LOGIN );\n\n\t\t\t\t\t\tif (hostJid != null) {\n\n\t\t\t\t\t\t\tXMPPIOService<Object> xmppioService = getXMPPIOService( packet );\n\t\t\t\t\t\t\tInteger port = (Integer) xmppioService.getSessionData().get( FORCE_REDIRECT_TO_KEY );\n\n\t\t\t\t\t\t\tElement streamErrorElement = see_other_host_strategy.getStreamError(\n\t\t\t\t\t\t\t\t\t\"urn:ietf:params:xml:ns:xmpp-streams\", hostJid, port);\n\t\t\t\t\t\t\tPacket redirectPacket = Packet.packetInstance(streamErrorElement);\n\n\t\t\t\t\t\t\tredirectPacket.setPacketTo(packet.getTo());\n\t\t\t\t\t\t\twritePacketToSocket(redirectPacket);\n\t\t\t\t\t\t\tsession.sendWaitingPackets();\n\t\t\t\t\t\t\tsession.close();\n\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.REMOVE, session.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"See other host\" } );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsessions.remove(session.getSid());\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsession.setUserJid(jid);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"user JID violates RFC6122 (XMPP:Address Format): \",\n\t\t\t\t\t\t\t\tex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"Missing XMPPIOService for USER_LOGIN command: {0}\",\n\t\t\t\t\t\t\t\tpacket);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.log(Level.WARNING, \"Missing user-jid for USER_LOGIN command: {0}\", packet);\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase CLOSE :\n\t\t\tif (session != null) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Closing session for command CLOSE: {0}\", session\n\t\t\t\t\t\t\t.getSid());\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tList<Element> err_el = packet.getElement().getChildrenStaticStr(Iq\n\t\t\t\t\t\t\t.IQ_COMMAND_PATH);\n\n\t\t\t\t\tif ((err_el != null) && (err_el.size() > 0)) {\n\t\t\t\t\t\tElement error = new Element(\"stream:error\");\n\n\t\t\t\t\t\terror.addChild(err_el.get(0));\n\n\t\t\t\t\t\tPacket condition = Packet.packetInstance(error);\n\n\t\t\t\t\t\tcondition.setPacketTo(packet.getTo());\n\t\t\t\t\t\twritePacketToSocket(condition);\n\t\t\t\t\t\tsession.sendWaitingPackets();\n\t\t\t\t\t\tbosh_session_close_delay = 100;\n\t\t\t\t\t}\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tLogger.getLogger(BoshConnectionManager.class.getName()).log(Level.SEVERE, null,\n\t\t\t\t\t\t\tex);\n\t\t\t\t}\n\t\t\t\tif (bosh_session_close_delay > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(bosh_session_close_delay);\n\t\t\t\t\t} catch (InterruptedException ex) {\n\n\t\t\t\t\t\t// Intentionally left blank\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsession.close();\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.REMOVE, session.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Closing session for command CLOSE\" } );\n\t\t\t\t}\n\t\t\t\tsessions.remove(session.getSid());\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE, \"Session does not exist for packet: {0}\", packet)\n\t\t\t\t\t;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase CHECK_USER_CONNECTION :\n\t\t\tif (session != null) {\n\n\t\t\t\t// It's ok, the session has been found, respond with OK.\n\t\t\t\taddOutPacket(packet.okResult((String) null, 0));\n\t\t\t} else {\n\n\t\t\t\t// Session is no longer active, respond with an error.\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Connection gone.\", false));\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t\t\t// Hm, error already, ignoring...\n\t\t\t\t\tlog.log(Level.INFO, \"Error packet is not really expected here: {0}\", packet);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tsuper.processCommand(packet);\n\n\t\t\tbreak;\n\t\t}    // end of switch (pc.getCommand())\n\t}\n\n\t@Override\n\tprotected boolean writePacketToSocket(Packet packet) {\n\t\tBoshSession session = getBoshSession(packet.getTo());\n\n\t\tif (session != null) {\n\t\t\tsynchronized (session) {\n\t\t\t\tQueue<Packet> out_results = new ArrayDeque<Packet>();\n\n\t\t\t\tsession.processPacket(packet, out_results);\n\t\t\t\taddOutPackets(out_results, session);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\tlog.info(\"Session does not exist for packet: \" + packet.toString());\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method retrieves {@link BoshSession} related to the particular user address\n\t *\n\t * @param jid address for which {@link BoshSession} should be returned\n\t *\n\t * @return a value of {@link BoshSession}\n\t */\n\tprotected BoshSession getBoshSession(JID jid) {\n\t\tString res = jid.getResource();\n\n\t\tif (res != null) {\n\t\t\tUUID sid = UUID.fromString(res);\n\n\t\t\treturn sessions.get(sid);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn PORTS;\n\t}\n\n\t@Override\n\tprotected int[] getDefSSLPorts() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method <code>getMaxInactiveTime</code> returns max keep-alive time for\n\t * inactive connection. For Bosh it does not make sense to keep the idle\n\t * connection longer than 10 minutes.\n\t *\n\t * @return a <code>long</code> value\n\t */\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 10 * MINUTE;\n\n\t}\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(\"boshCM\", this);\n\t}\n\n\t@Override\n\tprotected BoshIOService getXMPPIOServiceInstance() {\n\t\treturn new BoshIOService();\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\tprivate JID getFromAddress(String id) {\n\t\treturn JID.jidInstanceNS(getName(), getDefHostName().getDomain(), id);\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\t// ~--- inner classes --------------------------------------------------------\n\tprivate class StartedHandler\n\t\t\t\t\timplements ReceiverTimeoutHandler {\n\t\t@Override\n\t\tpublic void responseReceived( Packet packet, Packet response ) {\n\t\t\tString pb = Command.getFieldValue( packet, PRE_BIND_ATTR );\n\t\t\tboolean prebind = Boolean.valueOf( pb );\n\n\t\t\tString sessionId = Command.getFieldValue( packet, SESSION_ID_ATTR );\n\t\t\tString userID = Command.getFieldValue( packet, USER_ID_ATTR );\n\n\t\t\tif ( prebind ){\n\t\t\t\t// we are doing pre-bind, send user-login command, bind resource\n\t\t\t\tPacket packetOut\n\t\t\t\t\t\t\t = Command.USER_STATUS.getPacket( packet.getFrom(), packet.getTo(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tStanzaType.get, UUID.randomUUID().toString() );\n\n//\t\t\t\tElement presence = new Element( \"presence\" );\n\t\t\t\tCommand.addFieldValue( packetOut, USER_ID_ATTR, userID );\n\t\t\t\tif ( null != sessionId ){\n\t\t\t\t\tCommand.addFieldValue( packetOut, SESSION_ID_ATTR, sessionId );\n\t\t\t\t}\n\t\t\t\tCommand.addFieldValue( packetOut, PRE_BIND_ATTR, String.valueOf( prebind ) );\n\n\t\t\t\taddOutPacket( packetOut );\n\t\t\t} else {\n\n\t\t\t\t// We are now ready to ask for features....\n\t\t\t\taddOutPacket( Command.GETFEATURES.getPacket( packet.getFrom(), packet.getTo(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.get, UUID.randomUUID().toString(), null ) );\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void timeOutExpired(Packet packet) {\n\n\t\t\t// If we still haven't received confirmation from the SM then\n\t\t\t// the packet either has been lost or the server is overloaded\n\t\t\t// In either case we disconnect the connection.\n\t\t\tlog.warning(\"No response within time limit received for a packet: \" + packet\n\t\t\t\t\t.toString());\n\n\t\t\tBoshSession session = getBoshSession(packet.getFrom());\n\n\t\t\tif ( session != null ){\n\t\t\t\tlog.fine( \"Closing session for timeout: \" + session.getSid() );\n\t\t\t\tsession.close();\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t new Object[] { BOSH_OPERATION_TYPE.REMOVE, session.getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Closing session for timeout\" } );\n\t\t\t\t}\n\t\t\t\tsessions.remove( session.getSid() );\n\t\t\t} else {\n\t\t\t\tlog.info(\"Session does not exist for packet: \" + packet.toString());\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshIOService.java",
    "content": "/*\n * BoshIOService.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.bosh;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.IOException;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.UUID;\nimport tigase.server.xmppclient.XMPPIOProcessor;\nimport tigase.xmpp.StreamError;\n\n/**\n * Describe class BoshIOService here.\n *\n *\n * Created: Tue Jun 5 22:33:18 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BoshIOService\n\t\t\t\textends XMPPIOService<Object> {\n\t/** Field description */\n\tpublic static final String BOSH_CLOSE_CONNECTION_PROP_KEY = \"bosh-close-connection\";\n\n\t/** Field description */\n\tpublic static final String BOSH_EXTRA_HEADERS_FILE_PROP_KEY = \"bosh-extra-headers-file\";\n\n\t/** Field description */\n\tpublic static final String BOSH_EXTRA_HEADERS_FILE_PROP_VAL =\n\t\t\t\"etc/bosh-extra-headers.txt\";\n\n\t/** Field description */\n\tpublic static final String CLIENT_ACCESS_POLICY_FILE_PROP_KEY =\n\t\t\t\"client-access-policy-file\";\n\n\t/** Field description */\n\tpublic static final String CLIENT_ACCESS_POLICY_FILE_PROP_VAL =\n\t\t\t\"etc/client-access-policy.xml\";\n\tprivate static String       client_access_policy = null;\n\tprivate static final String CONNECTION           = \"Connection: \";\n\tprivate static final String CONTENT_TYPE_HEADER  = \"Content-Type: \";\n\tprivate static final String CONTENT_TYPE_LENGTH  = \"Content-Length: \";\n\tprivate static final String EOL                  = \"\\r\\n\";\n\tprivate static String       extra_headers        = null;\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(BoshIOService.class.getName());\n\tprivate static final String HTTP_OK_RESPONSE = \"HTTP/1.1 200 OK\" + EOL;\n\tprivate static final String SERVER = \"Server: Tigase Bosh/\" + tigase.server.XMPPServer\n\t\t\t.getImplementationVersion();\n\tprivate static final char[] HTTP_CLIENT_ACCESS_POLICY_REQUEST_HEADER =\n\t\t\t\"GET /clientaccesspolicy.xml\".toCharArray();\n\tprivate static Boolean closeConnections;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String   content_type                = \"text/xml; charset=utf-8\";\n\tprivate long     rid                         = -1;\n\tprivate UUID     sid                         = null;\n\tprivate BoshTask waitTimer                   = null;\n\tprivate boolean  firstPassCORS               = true;\n\tprivate boolean  firstPassClientAccessPolicy = true;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic BoshIOService() {\n\t\tsuper();\n\t\tif (closeConnections == null) {\n\t\t\tcloseConnections = Boolean.parseBoolean(System.getProperty(\n\t\t\t\t\tBOSH_CLOSE_CONNECTION_PROP_KEY, \"false\"));\n\t\t}\n\t\tif (extra_headers == null) {\n\t\t\tString file_name = System.getProperty(BOSH_EXTRA_HEADERS_FILE_PROP_KEY,\n\t\t\t\t\tBOSH_EXTRA_HEADERS_FILE_PROP_VAL);\n\n\t\t\ttry {\n\t\t\t\tBufferedReader br   = new BufferedReader(new FileReader(file_name));\n\t\t\t\tString         line = br.readLine();\n\t\t\t\tStringBuilder  sb   = new StringBuilder();\n\n\t\t\t\twhile (line != null) {\n\t\t\t\t\tsb.append(line).append(EOL);\n\t\t\t\t\tline = br.readLine();\n\t\t\t\t}\n\t\t\t\tbr.close();\n\t\t\t\textra_headers = sb.toString();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem reading Bosh extra headers file: \" + file_name,\n\t\t\t\t\t\tex);\n\t\t\t}\n\t\t}\n\t\tif (client_access_policy == null) {\n\t\t\tString file_name = System.getProperty(CLIENT_ACCESS_POLICY_FILE_PROP_KEY,\n\t\t\t\t\tCLIENT_ACCESS_POLICY_FILE_PROP_VAL);\n\n\t\t\ttry {\n\t\t\t\tBufferedReader br   = new BufferedReader(new FileReader(file_name));\n\t\t\t\tString         line = br.readLine();\n\t\t\t\tStringBuilder  sb   = new StringBuilder();\n\n\t\t\t\twhile (line != null) {\n\t\t\t\t\tsb.append(line).append(EOL);\n\t\t\t\t\tline = br.readLine();\n\t\t\t\t}\n\t\t\t\tbr.close();\n\t\t\t\tclient_access_policy = sb.toString();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem reading client access policy file: \" + file_name,\n\t\t\t\t\t\tex);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getRid() {\n\t\treturn this.rid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic UUID getSid() {\n\t\treturn this.sid;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param timer\n\t */\n\tpublic void setWaitTimer(BoshTask timer) {\n\t\twaitTimer = timer;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic BoshTask getWaitTimer() {\n\t\treturn waitTimer;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param errorCode\n\t * @param packet\n\t * @param errorMsg\n\t *\n\t * @throws IOException\n\t */\n\tpublic void sendErrorAndStop(Authorization errorCode, StreamError streamError, Packet packet, String errorMsg)\n\t\t\t\t\tthrows IOException {\n\t\tfor (XMPPIOProcessor proc  : processors) {\n\t\t\tproc.streamError(this, streamError);\n\t\t}\n\t\tString code = \"<body type='terminate'\" + \" condition='\" + (streamError != null ? streamError.getCondition() : errorCode.getCondition()) + \"'\" +\n\t\t\t\t\" xmlns='http://jabber.org/protocol/httpbind'/>\";\n\n\t\ttry {\n\t\t\tPacket error = errorCode.getResponseMessage(packet, errorMsg, false);\n\n\t\t\tcode = error.getElement().toString();\n\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t// ignore\n\t\t}\n\n\t\tStringBuilder sb = new StringBuilder(200);\n\n\t\tsb.append(\"HTTP/1.1 \").append(errorCode.getErrorCode()).append(\" \");\n\t\tsb.append(errorMsg).append(EOL);\n\t\tsb.append(CONTENT_TYPE_HEADER).append(content_type).append(EOL);\n\t\tsb.append(CONTENT_TYPE_LENGTH).append(code.getBytes().length).append(EOL);\n\t\tif (extra_headers != null) {\n\t\t\tsb.append(extra_headers);\n\t\t}\n\n\t\t// sb.append(\"X-error-code\").append(code).append(EOL);\n\t\tsb.append(CONNECTION + \"close\" + EOL);\n\t\tsb.append(SERVER).append(EOL);\n\t\tsb.append(EOL);\n\t\tsb.append(code);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Writing to socket:\\n{0}\", sb.toString());\n\t\t}\n\t\tsuper.writeRawData(sb.toString());\n\t\tstop();\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ct\n\t */\n\tpublic void setContentType(String ct) {\n\t\tthis.content_type = ct;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param rid\n\t */\n\tpublic void setRid(long rid) {\n\t\tthis.rid = rid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sid\n\t */\n\tpublic void setSid(UUID sid) {\n\t\tthis.sid = sid;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * \n\t */\n\tpublic StringBuilder prepareHeaders(String data) {\n\t\tStringBuilder sb = new StringBuilder(200);\n\n\t\tsb.append(HTTP_OK_RESPONSE);\n\t\tsb.append(CONTENT_TYPE_HEADER).append(content_type).append(EOL);\n\t\tif (data != null) {\n\t\t\tsb.append(CONTENT_TYPE_LENGTH).append(data.getBytes().length).append(EOL);\n\t\t}\n\t\telse {\n\t\t\tsb.append(CONTENT_TYPE_LENGTH).append(\"0\").append(EOL);\n\t\t}\n\t\tif (extra_headers != null) {\n\t\t\tsb.append(extra_headers);\n\t\t}\n\t\tsb.append(SERVER).append(EOL);\n\t\tsb.append(EOL);\n\n\t\treturn sb;\n\t}\n\n\t@Override\n\tpublic void writeRawData(String data) throws IOException {\n\t\tif ((data != null) && data.startsWith(\"<body\")) {\n\t\t\tStringBuilder sb = prepareHeaders(data);\n\n\t\t\tsb.append(data);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Writing to socket:\\n{0}\", sb.toString());\n\t\t\t}\n\t\t\tsuper.writeRawData(sb.toString());\n\t\t} else {\n\t\t\tsuper.writeRawData(data);\n\t\t}\n\t\tif (closeConnections) {\n\t\t\tstop();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean checkData(char[] data) throws IOException {\n\t\t// we need to check this every time as Webkit based browser are reusing\n\t\t// existing connections and repeat this CORS request every 10 minutes\n\t\t//if (firstPassCORS && \n\t\tif ((data != null) && (data.length > 7)) {\n\t\t\tif ((data[0] == 'O') && (data[1] == 'P') && (data[2] == 'T') && (data[3] == 'I') &&\n\t\t\t\t\t(data[4] == 'O') && (data[5] == 'N') && (data[6] == 'S')) {\n\n\t\t\t\t// responding with headers - needed for Chrome browser\n\t\t\t\tthis.writeRawData(prepareHeaders(null).toString());\n\n\t\t\t\t// connection needs to be closed as in other case data headers are not sent to browser\n\t\t\t\t// until connection is closed and for OPTIONS request we are not sending any data\n\t\t\t\t//firstPassCORS = false;\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//firstPassCORS = false;\n\t\t}\n\t\tif (firstPassClientAccessPolicy && (data != null) && (data.length >=\n\t\t\t\tHTTP_CLIENT_ACCESS_POLICY_REQUEST_HEADER.length)) {\n\t\t\tif ((data[0] == 'G') && (data[1] == 'E') && (data[2] == 'T')) {\n\t\t\t\tboolean ok = true;\n\t\t\t\tint     i  = 3;\n\n\t\t\t\twhile (ok && (i < HTTP_CLIENT_ACCESS_POLICY_REQUEST_HEADER.length)) {\n\t\t\t\t\tok &= (data[i] == HTTP_CLIENT_ACCESS_POLICY_REQUEST_HEADER[i]);\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tif (ok) {\n\t\t\t\t\tthis.writeRawData(prepareHeaders(client_access_policy).toString() +\n\t\t\t\t\t\t\tclient_access_policy);\n\n\t\t\t\t\t// connection needs to be closed as in other case data headers are not sent to browser\n\t\t\t\t\t// until connection is closed\n\t\t\t\t\tfirstPassClientAccessPolicy = false;\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfirstPassClientAccessPolicy = false;\n\t\t}\n\n\t\t// by default do nothing and return false\n\t\treturn false;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/19\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshSendQueueTask.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\npackage tigase.server.bosh;\n\nimport tigase.util.TimerTask;\n\n/**\n *\n * @author andrzej\n */\npublic class BoshSendQueueTask extends TimerTask {\n\n\tprivate final BoshSession bs;\n\n\tpublic BoshSendQueueTask( BoshSession bs ) {\n\t\tthis.bs = bs;\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\tbs.sendWaitingPackets();\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshSession.java",
    "content": "/*\n * BoshSession.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.bosh;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.bosh.Constants.CacheAction;\nimport tigase.server.xmppclient.SeeOtherHostIfc.Phase;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.util.TimerTask;\nimport tigase.xml.Element;\n\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.regex.Pattern;\n\nimport static tigase.server.bosh.Constants.*;\n\n\n/**\n * Describe class BoshSession here.\n *\n *\n * Created: Tue Jun 5 18:07:23 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BoshSession {\n\tprivate static final String IQ_ELEMENT_NAME = \"iq\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger              log = Logger.getLogger(BoshSession.class\n\t\t\t.getName());\n\tprivate static final String              MESSAGE_ELEMENT_NAME  = \"message\";\n\tprivate static final String              PRESENCE_ELEMENT_NAME = \"presence\";\n\tprivate static final long                SECOND                = 1000;\n\tprivate static final TimerTaskComparator timerTaskComparator =\n\t\t\tnew TimerTaskComparator();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate BoshSessionCache cache                = null;\n\tprivate long             cache_reload_counter = 0;\n\n\t/**\n\t * <code>current_rid</code> is the table with body rids which are waiting for\n\t * replies.\n\t */\n\tprivate long[]                 currentRids           = null;\n\tprivate JID                    dataReceiver          = null;\n\tprivate String                 domain                = null;\n\tprivate String                 hostname              = null;\n\tprivate BoshSessionTaskHandler handler               = null;\n\tprivate int[]                  hashCodes             = null;\n\tprivate BoshTask               inactivityTimer       = null;\n\tprivate long                   previous_received_rid = -1;\n\tprivate BoshSendQueueTask      queueTask             = null;\n\tprivate String[]               replace_with = {\n\t\t\t\"$1&lt;a href=\\\"http://$2\\\" target=\\\"_blank\\\"&gt;$2&lt;/a&gt;\",\n\t\t\t\"$1&lt;a href=\\\"$2\\\" target=\\\"_blank\\\"&gt;$2&lt;/a&gt;\", };\n\tprivate int    rids_head = 0;\n\tprivate int    rids_tail = 0;\n\tprivate String sessionId = null;\n\tprivate UUID   sid       = null;\n\n\t// Old connections which might be reused in keep-alive mode.\n\t// Requests have been responded to so in most cases the connection should\n\t// be closed unless it is reused in keep-alive mode.\n\t// Normally there should be no more than max 2 elements in the queue.\n\tprivate Queue<BoshIOService> old_connections = new LinkedBlockingQueue<BoshIOService>(\n\t\t\t4);\n\n\t// Active connections with pending requests received\n\tprivate ConcurrentSkipListMap<BoshTask, BoshIOService> connections =\n\t\t\tnew ConcurrentSkipListMap<BoshTask, BoshIOService>(timerTaskComparator);\n\tprivate JID userJid = null;\n\n\t// private enum TimedTask { EMPTY_RESP, STOP };\n\t// private Map<TimerTask, TimedTask> task_enum =\n\t// new LinkedHashMap<TimerTask, TimedTask>();\n\t// private EnumMap<TimedTask, TimerTask> enum_task =\n\t// new EnumMap<TimedTask, TimerTask>(TimedTask.class);\n\tprivate Set<BoshTask> waitTimerSet = new ConcurrentSkipListSet<BoshTask>(\n\t\t\ttimerTaskComparator);\n\tprivate Queue<Element> waiting_packets = null;//new ConcurrentLinkedQueue<Element>();\n\tprivate boolean        terminate       = false;\n\tprivate long           min_polling     = MIN_POLLING_PROP_VAL;\n\tprivate long           max_wait        = MAX_WAIT_DEF_PROP_VAL;\n\tprivate long           max_pause       = MAX_PAUSE_PROP_VAL;\n\tprivate long           max_inactivity  = MAX_INACTIVITY_PROP_VAL;\n\tprivate int            max_batch_size  = MAX_BATCH_SIZE_VAL;\n\tprivate Pattern[]      links_regexs = { Pattern.compile(\"([^>/\\\";]|^)(www\\\\.[^ ]+)\",\n\t\t\tPattern.CASE_INSENSITIVE),\n\t\t\tPattern.compile(\"([^\\\">;]|^)(http://[^ ]+)\", Pattern.CASE_INSENSITIVE), };\n\tprivate int     hold_requests       = HOLD_REQUESTS_PROP_VAL;\n\tprivate String  content_type        = CONTENT_TYPE_DEF;\n\tprivate int     concurrent_requests = CONCURRENT_REQUESTS_PROP_VAL;\n\tprivate boolean cache_on            = false;\n\tprivate long    batch_queue_timeout = BATCH_QUEUE_TIMEOUT_VAL;\n\tprivate long    last_send_time;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>BoshSession</code> instance.\n\t *\n\t *\n\t * @param def_domain\n\t * @param dataReceiver\n\t * @param handler\n\t */\n\tpublic BoshSession(String def_domain, JID dataReceiver,\n\t\t\tBoshSessionTaskHandler handler, String hostname, int maxWaitingPackets) {\n\t\tthis.sid            = UUID.randomUUID();\n\t\tthis.domain         = def_domain;\n\t\tthis.dataReceiver   = dataReceiver;\n\t\tthis.handler        = handler;\n\t\tthis.last_send_time = System.currentTimeMillis();\n\t\tthis.hostname       = hostname;\n\t\tthis.waiting_packets = new LinkedBlockingQueue(maxWaitingPackets);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void close() {\n\t\tterminate = true;\n\t\tprocessPacket(null, null);\n\t\tcloseAllConnections();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param bios\n\t */\n\tpublic void disconnected(BoshIOService bios) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Disconnected called for: \" + bios.getUniqueId());\n\t\t}\n\t\tif ((bios != null) && (bios.getWaitTimer() != null)) {\n\t\t\thandler.cancelTask(bios.getWaitTimer());\n\t\t\tconnections.remove(bios.getWaitTimer());\n\t\t}\n\t\tif (inactivityTimer != null) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER, getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Canceling inactivityTimer: \" + bios != null ? bios.getUniqueId() : \"n/a\" } );\n\t\t\t}\n\t\t}\n\t\tif (connections.isEmpty()) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER, getSid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Setting inactivityTimer for \" + max_inactivity\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" on: \" + bios != null ? bios.getUniqueId() : \"n/a\"} );\n\t\t\t}\n\n\t\t\tinactivityTimer = handler.scheduleTask(this, max_inactivity * SECOND);\n\t\t}\n\t}\n\tpublic void init(Packet packet, BoshIOService service, long max_wait, long min_polling,\n\t\t\tlong max_inactivity, int concurrent_requests, int hold_requests, long max_pause,\n\t\t\tint max_batch_size, long batch_queue_timeout, Queue<Packet> out_results) {\n\n\t\tinit( packet, service, max_wait, min_polling, max_inactivity,\n\t\t\t\t\tconcurrent_requests, hold_requests, max_pause, max_batch_size,\n\t\t\t\t\tbatch_queue_timeout, out_results, false );\n\t}\n\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param service\n\t * @param max_wait\n\t * @param min_polling\n\t * @param max_inactivity\n\t * @param concurrent_requests\n\t * @param hold_requests\n\t * @param max_pause\n\t * @param max_batch_size\n\t * @param batch_queue_timeout\n\t * @param out_results\n\t */\n\tprotected void init(Packet packet, BoshIOService service, long max_wait, long min_polling,\n\t\t\tlong max_inactivity, int concurrent_requests, int hold_requests, long max_pause,\n\t\t\tint max_batch_size, long batch_queue_timeout, Queue<Packet> out_results,\n\t\t\tboolean preBindEnabled) {\n\t\tString cache_action = packet.getAttributeStaticStr(CACHE_ATTR);\n\n\t\tif ((cache_action != null) && cache_action.equals(CacheAction.on.toString())) {\n\t\t\tcache    = new BoshSessionCache();\n\t\t\tcache_on = true;\n\t\t\tlog.fine(\"BoshSessionCache set to ON\");\n\t\t}\n\t\thashCodes   = new int[(this.concurrent_requests + 1) * 5];\n\t\tcurrentRids = new long[(this.concurrent_requests + 1) * 5];\n\t\tfor (int i = 0; i < currentRids.length; i++) {\n\t\t\tcurrentRids[i] = -1;\n\t\t\thashCodes[i]   = -1;\n\t\t}\n\n\t\tlong   wait_l = max_wait;\n\t\tString wait_s = packet.getAttributeStaticStr(WAIT_ATTR);\n\n\t\tif (wait_s != null) {\n\t\t\ttry {\n\t\t\t\twait_l = Long.parseLong(wait_s);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\twait_l = max_wait;\n\t\t\t}\n\t\t}\n\t\tthis.max_wait = Math.min(wait_l, max_wait);\n\n\t\t// this.max_wait = wait_l;\n\t\tint    hold_i  = hold_requests;\n\t\tString tmp_str = packet.getAttributeStaticStr(HOLD_ATTR);\n\n\t\tif (tmp_str != null) {\n\t\t\ttry {\n\t\t\t\thold_i = Integer.parseInt(tmp_str);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\thold_i = hold_requests;\n\t\t\t}\n\t\t}\n\t\ttmp_str = packet.getAttributeStaticStr(RID_ATTR);\n\t\tif (tmp_str != null) {\n\t\t\ttry {\n\t\t\t\tprevious_received_rid    = Long.parseLong(tmp_str);\n\t\t\t\tcurrentRids[rids_head++] = previous_received_rid;\n\t\t\t} catch (NumberFormatException e) {}\n\t\t}\n\t\tthis.hold_requests = Math.max(hold_i, hold_requests);\n\t\tif (packet.getAttributeStaticStr(TO_ATTR) != null) {\n\t\t\tthis.domain = packet.getAttributeStaticStr(TO_ATTR);\n\t\t}\n\t\tthis.max_batch_size      = max_batch_size;\n\t\tthis.batch_queue_timeout = batch_queue_timeout;\n\t\tthis.min_polling         = min_polling;\n\t\tthis.max_inactivity      = max_inactivity;\n\t\tthis.concurrent_requests = concurrent_requests;\n\t\tthis.max_pause           = max_pause;\n\t\tif (packet.getAttributeStaticStr(CONTENT_ATTR) != null) {\n\t\t\tcontent_type = packet.getAttributeStaticStr(CONTENT_ATTR);\n\t\t}\n\n\t\tString lang = packet.getAttributeStaticStr(LANG_ATTR);\n\n\t\tif (lang == null) {\n\t\t\tlang = \"en\";\n\t\t}\n\n\t\tElement body = new Element(BODY_EL_NAME, new String[] {\n\t\t\tWAIT_ATTR, INACTIVITY_ATTR, POLLING_ATTR, REQUESTS_ATTR, HOLD_ATTR, MAXPAUSE_ATTR,\n\t\t\tSID_ATTR, VER_ATTR, FROM_ATTR, SECURE_ATTR, \"xmpp:version\", \"xmlns:xmpp\",\n\t\t\t\"xmlns:stream\"\n\t\t}, new String[] {\n\t\t\tLong.toString(this.max_wait),\n\t\t\tLong.toString(this.max_inactivity),\n\t\t\tLong.toString(this.min_polling),\n\t\t\tInteger.toString(this.concurrent_requests),\n\t\t\tInteger.valueOf(this.hold_requests).toString(),\n\t\t\tLong.valueOf(this.max_pause).toString(), this.sid.toString(), BOSH_VERSION,\n\t\t\tthis.domain, \"true\", \"1.0\", \"urn:xmpp:xbosh\", \"http://etherx.jabber.org/streams\"\n\t\t});\n\t\t\n\t\tif (this.hostname != null) {\n\t\t\tbody.addAttribute(HOST_ATTR, this.hostname);\n\t\t}\n\n\t\tsessionId = UUID.randomUUID().toString();\n\t\tbody.setAttribute(AUTHID_ATTR, sessionId);\n\t\tif (getCurrentRidTail() > 0) {\n\t\t\tbody.setAttribute(ACK_ATTR, \"\" + takeCurrentRidTail());\n\t\t}\n\t\tJID userId = null;\n\t\ttry {\n\t\t\tuserId = (packet.getAttributeStaticStr(Packet.FROM_ATT) != null)\n\t\t\t\t\t? JID.jidInstance(packet.getAttributeStaticStr(Packet.FROM_ATT))\n\t\t\t\t\t: null;\n\n\t\t\tif (userId != null) {\n\t\t\t\tBareJID hostJid = handler.getSeeOtherHostForJID(packet, userId.getBareJID(), Phase.OPEN);\n\n\t\t\t\tif (hostJid != null) {\n\t\t\t\t\tElement error        = new Element(\"stream:error\");\n\t\t\t\t\tElement seeOtherHost = handler.getSeeOtherHostError( packet, hostJid);\n\n\t\t\t\t\tseeOtherHost.setXMLNS(\"urn:ietf:params:xml:ns:xmpp-streams\");\n\t\t\t\t\terror.addChild(seeOtherHost);\n\t\t\t\t\tbody.addChild(error);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(BoshSession.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t\tbody.setXMLNS(BOSH_XMLNS);\n\t\t// we are just doing session pre-bind, ignore sending back\n\n\n\t\t// service.writeRawData(body.toString());\n\t\tPacket streamOpen = Command.STREAM_OPENED.getPacket(handler.getJidForBoshSession(this),\n\t\t\t\tnull, StanzaType.set, UUID.randomUUID().toString(), Command.DataType.submit);\n\n\t\tCommand.addFieldValue(streamOpen, SESSION_ID_ATTR, sessionId);\n\t\tCommand.addFieldValue(streamOpen, \"hostname\", domain);\n\t\tCommand.addFieldValue(streamOpen, LANG_ATTR, lang);\n\n\t\tif (null != service ) {\n\t\t\tservice.setContentType(content_type);\n\t\t\tsendBody(service, body);\n\t\t}\n\t\tif ( preBindEnabled ){\n\n\t\t\tinactivityTimer = handler.scheduleTask(this, max_inactivity * SECOND);\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Setting inactivityTimer for \" + max_inactivity\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" on \" + service } );\n\t\t\t}\n\n\t\t\t\n\t\t\tif ( null != userId ){\n\t\t\t\tCommand.addFieldValue( streamOpen, USER_ID_ATTR, userId.toString() );\n\t\t\t}\n\t\t\tString ridString = packet.getAttributeStaticStr( RID_ATTR );\n\t\t\tif ( null != ridString ){\n\t\t\t\tlong rid = Long.valueOf( ridString );\n\t\t\t\tprocessRid( rid, null );\n\t\t\t}\n\t\t\tCommand.addFieldValue( streamOpen, PRE_BIND_ATTR, String.valueOf( preBindEnabled ) );\n\t\t}\n\n\t\thandler.addOutStreamOpen(streamOpen, this);\n\n\t\t// out_results.offer(streamOpen);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param out_results\n\t */\n\tpublic synchronized void processPacket(Packet packet, Queue<Packet> out_results) {\n\t\tif (packet != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"[\" + connections.size() + \"] Processing packet: \" + packet\n\t\t\t\t\t\t.toString());\n\t\t\t}\n\t\t\tif (filterInPacket(packet)) {\n\t\t\t\tif (!waiting_packets.offer(packet.getElement())) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.log(Level.INFO, \"waiting_packets queue exceeded, dropping packet: \" + packet.toString());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"[\" + connections.size() + \"] In packet filtered: \" + packet\n\t\t\t\t\t\t\t.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ((!connections.isEmpty()) && ((!waiting_packets.isEmpty()) || terminate)) {\n\t\t\tlong currentTime = System.currentTimeMillis();\n\n\t\t\tif (terminate || (waiting_packets.size() >= max_batch_size) || (currentTime -\n\t\t\t\t\tlast_send_time) > batch_queue_timeout) {\n\t\t\t\tMap.Entry<BoshTask, BoshIOService> entry = connections.pollFirstEntry();\n\t\t\t\tBoshIOService                      serv  = entry.getValue();\n\n\t\t\t\tsendBody(serv, null);\n\t\t\t} else {\n\n\t\t\t\t// @todo - change it to use value from settings\n\t\t\t\tif (queueTask == null) {\n\t\t\t\t\tqueueTask = handler.scheduleSendQueueTask(this, batch_queue_timeout);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param service\n\t * @param out_results\n\t */\n\tpublic synchronized void processSocketPacket(Packet packet, BoshIOService service,\n\t\t\tQueue<Packet> out_results) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"[\" + connections.size() + \"] Processing socket packet: \" + packet\n\t\t\t\t\t.toString());\n\t\t}\n\n\t\tBoshTask waitTimer = service.getWaitTimer();\n\n\t\tif (waitTimer != null) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Canceling waitTimer: \" + service.getUniqueId() } );\n\t\t\t}\n\t\t\thandler.cancelTask(waitTimer);\n\t\t}\n\t\tif (inactivityTimer != null) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Canceling inactivityTimer: \" + service.getUniqueId() } );\n\t\t\t}\n\t\t\thandler.cancelTask(inactivityTimer);\n\t\t}\n\t\tif ((packet.getElemName() == BODY_EL_NAME) && (packet.getXMLNS() == BOSH_XMLNS)) {\n\t\t\tList<Element> children  = packet.getElemChildrenStaticStr(BODY_EL_PATH);\n\t\t\tboolean       duplicate = false;\n\n\t\t\tif (packet.getAttributeStaticStr(RID_ATTR) != null) {\n\t\t\t\ttry {\n\t\t\t\t\tlong rid = Long.parseLong(packet.getAttributeStaticStr(RID_ATTR));\n\n\t\t\t\t\tif (isDuplicateRid(rid, children)) {\n\t\t\t\t\t\tlog.info(\"Discovered duplicate client connection, trying to close the \" +\n\t\t\t\t\t\t\t\t\"old one with RID: \" + rid);\n\n\t\t\t\t\t\tElement body = getBodyElem();\n\n\t\t\t\t\t\tbody.setAttribute(\"type\", StanzaType.terminate.toString());\n\t\t\t\t\t\tsendBody(service, body);\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tservice.setRid(rid);\n\t\t\t\t\tduplicate = isDuplicateMessage(rid, children);\n\t\t\t\t\tif (!duplicate) {\n\t\t\t\t\t\tprocessRid(rid, children);\n\t\t\t\t\t}\n\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\tlog.warning(\"Incorrect RID value: \" + packet.getAttributeStaticStr(RID_ATTR));\n\t\t\t\t}\n\t\t\t}\n\t\t\tservice.setContentType(content_type);\n\t\t\tservice.setSid(sid);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Setting waitTimer for \" + max_wait + \": \" + getSid());\n\t\t\t}\n\t\t\twaitTimer = handler.scheduleTask(this, max_wait * SECOND);\n\t\t\tservice.setWaitTimer(waitTimer);\n\t\t\tconnections.put(waitTimer, service);\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Scheduling waitTimer: \" + service.getUniqueId() } );\n\t\t\t}\n\t\t\tif (!duplicate) {\n\t\t\t\tif ((packet.getType() != null) && (packet.getType() == StanzaType.terminate)) {\n\n\t\t\t\t\t// We are preparing for session termination.\n\t\t\t\t\t// Some client send IQ stanzas with private data to store some\n\t\t\t\t\t// settings so some confirmation stanzas might be sent back\n\t\t\t\t\t// let's give the client a few secs for session termination\n\t\t\t\t\tmax_inactivity = 2;    // Max pause changed to 2 secs\n\t\t\t\t\tterminate      = true;\n\n\t\t\t\t\tPacket command = Command.STREAM_CLOSED.getPacket(handler.getJidForBoshSession(this),\n\t\t\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\t\tif (userJid != null) {\n\t\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t\t\t}\t\n\t\t\t\t\thandler.addOutStreamClosed(command, this, true);\n\n\t\t\t\t\t// out_results.offer(command);\n\t\t\t\t}\n\t\t\t\tif ((packet.getAttributeStaticStr(RESTART_ATTR) != null) && packet\n\t\t\t\t\t\t.getAttributeStaticStr(RESTART_ATTR).equals(\"true\")) {\n\t\t\t\t\tlog.fine(\"Found stream restart instruction: \" + packet.toString());\n\t\t\t\t\tout_results.offer(Command.GETFEATURES.getPacket(null, null, StanzaType.get,\n\t\t\t\t\t\t\t\"restart1\", null));\n\t\t\t\t}\n\t\t\t\tif (packet.getAttributeStaticStr(CACHE_ATTR) != null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tCacheAction action = CacheAction.valueOf(packet.getAttributeStaticStr(\n\t\t\t\t\t\t\t\tCACHE_ATTR));\n\n\t\t\t\t\t\tif (cache_on || (action == CacheAction.on)) {\n\t\t\t\t\t\t\tprocessCache(action, packet);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\t\t\tlog.warning(\"Incorrect cache action: \" + packet.getAttributeStaticStr(\n\t\t\t\t\t\t\t\tCACHE_ATTR));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (children != null) {\n\t\t\t\t\t\tfor (Element el : children) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (el.getXMLNS().equals(BOSH_XMLNS)) {\n\t\t\t\t\t\t\t\t\tel.setXMLNS(XMLNS_CLIENT_VAL);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tPacket result = Packet.packetInstance(el);\n\n\t\t\t\t\t\t\t\tif (filterOutPacket(result)) {\n\t\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\t\tlog.finest(\"Sending out packet: \" + result.toString());\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tout_results.offer(result);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\t\tlog.finest(\"Out packet filtered: \" + result.toString());\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\t\tlog.warning(\n\t\t\t\t\t\t\t\t\t\t\"Packet addressing problem, stringprep processing failed, dropping: \" +\n\t\t\t\t\t\t\t\t\t\tel);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (terminate) {\n\t\t\t\t\tPacket command = Command.STREAM_CLOSED.getPacket(handler.getJidForBoshSession(this),\n\t\t\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\t\tif (userJid != null) {\n\t\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t\t\t}\n\t\t\t\t\thandler.addOutStreamClosed(command, this, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.info(\"Duplicated packet: \" + packet.toString());\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"[\" + connections.size() + \"] Unexpected packet from the network: \" +\n\t\t\t\t\tpacket.toString());\n\n\t\t\tString er_msg = \"Invalid body element\";\n\n\t\t\tif (packet.getElemName() != BODY_EL_NAME) {\n\t\t\t\ter_msg += \", incorrect root element name, use \" + BODY_EL_NAME;\n\t\t\t}\n\t\t\tif (packet.getXMLNS() != BOSH_XMLNS) {\n\t\t\t\ter_msg += \", incorrect xmlns, use \" + BOSH_XMLNS;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tPacket error = Authorization.BAD_REQUEST.getResponseMessage(packet, er_msg, true);\n\n\t\t\t\tif (!waiting_packets.offer(error.getElement())) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.log(Level.INFO, \"waiting_packets queue exceeded, dropping packet: \" + error.toString());\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tterminate = true;\n\n\t\t\t\tPacket command = Command.STREAM_CLOSED.getPacket(handler.getJidForBoshSession(this),\n\t\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\tif (userJid != null) {\n\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t\t}\t\n\t\t\t\thandler.addOutStreamClosed(command, this, true);\n\n\t\t\t\tcommand = Command.STREAM_FINISHED.getPacket(handler.getJidForBoshSession(this),\n\t\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\tif (userJid != null) {\n\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t\t}\t\n\t\t\t\thandler.addOutStreamClosed(command, this, false);\n\t\t\t\t\n\t\t\t\t// out_results.offer(command);\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.info(\"Error type and incorrect from bosh client? Ignoring...\");\n\t\t\t}\n\t\t}\n\n\t\t// Send packets waiting in queue...\n\t\tprocessPacket(null, out_results);\n\t\tif (connections.size() > hold_requests) {\n\t\t\tBoshIOService serv = connections.pollFirstEntry().getValue();\n\n\t\t\tsendBody(serv, null);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic synchronized void sendWaitingPackets() {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"trying to send waiting packets from queue of \" + getSid() +\n\t\t\t\t\t\" after timer = \" + waiting_packets.size());\n\t\t}\n\t\tif (!waiting_packets.isEmpty()) {\n\t\t\tMap.Entry<BoshTask, BoshIOService> entry = connections.pollFirstEntry();\n\n\t\t\tif (entry == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tBoshIOService serv = entry.getValue();\n\n\t\t\tsendBody(serv, null);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param out_results\n\t * @param tt\n\t *\n\t * \n\t */\n\tpublic boolean task(Queue<Packet> out_results, TimerTask tt) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"task called for {0}, inactivityTimer = {1}, tt = {2}\", new Object[] { getSid(), inactivityTimer, tt });\n\t\t}\n\t\tif (tt == inactivityTimer) {\n\t\t\tif (connections.size() > 0) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tString conns = \"\";\n\t\t\t\t\tfor (BoshIOService serv : connections.values()) {\n\t\t\t\t\t\tif (!conns.isEmpty()) {\n\t\t\t\t\t\t\tconns += \", \";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconns += \"[\" + serv.toString() + \"]\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"ignoring inactivityTimer\" } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"inactivityTimer fired\" } );\n\t\t\t}\n\t\t\tfor (BoshTask waitTimer : waitTimerSet) {\n\t\t\t\tif (waitTimer != null) {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.TIMER,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Canceling waitTimer\" } );\n\t\t\t\t\t}\n\n\t\t\t\t\thandler.cancelTask(waitTimer);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"{0} : {1} ({2})\",\n\t\t\t\t\t\t\t\t new Object[] { BoshConnectionManager.BOSH_OPERATION_TYPE.REMOVE,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetSid(), \"Closing session, inactivity timeout expired\" } );\n\t\t\t}\n\t\t\t// we need to set packetFrom as it is later used as packet from and to\n\t\t\t// pick thread on which it will be processed\n\t\t\tPacket command = Command.STREAM_CLOSED.getPacket(handler.getJidForBoshSession(this), \n\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\tif (userJid != null) {\n\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t}\t\t\t\n\n\t\t\thandler.addOutStreamClosed(command, this, true);\n\n\t\t\tfor (Element packet : waiting_packets) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Do not send stream:features back with an error\n\t\t\t\t\tif (packet.getName() != \"stream:features\") {\n//\t\t\t\t\t\tout_results.offer(Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(\n//\t\t\t\t\t\t\t\tPacket.packetInstance(packet), \"Bosh = disconnected\", true));\n\t\t\t\t\t\tPacket p = Packet.packetInstance(packet);\n\t\t\t\t\t\t// we need to set packetTo as it is later used as packet from and to\n\t\t\t\t\t\t// pick thread on which it will be processed\n\t\t\t\t\t\tp.setPacketTo(handler.getJidForBoshSession(this));\n\t\t\t\t\t\tp.setPacketFrom(getDataReceiver());\n\t\t\t\t\t\thandler.processUndeliveredPacket(p, null, \"Bosh = disconnected\");\n\t\t\t\t\t}\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.warning(\n\t\t\t\t\t\t\t\"Packet addressing problem, stringprep processing failed, dropping: \" +\n\t\t\t\t\t\t\tpacket);\n//\t\t\t\t} catch (PacketErrorTypeException e) {\n//\t\t\t\t\tlog.info(\"Packet processing exception: \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tcommand = Command.STREAM_FINISHED.getPacket(handler.getJidForBoshSession(this), \n\t\t\t\t\tgetDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\tif (userJid != null) {\n\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid.toString());\n\t\t\t}\t\t\t\n\n\t\t\thandler.addOutStreamClosed(command, this, false);\n\t\t\t\n\t\t\tcloseAllConnections();\n\n\t\t\t// out_results.offer(command);\n\t\t\treturn true;\n\t\t}\n\n\t\tBoshIOService serv = connections.remove(tt);\n\n\t\tif (serv != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"waitTimer fired: \" + getSid());\n\t\t\t}\n\t\t\tsendBody(serv, null);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void terminateBoshSession() {\n\t\tterminate = true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic JID getDataReceiver() {\n\t\treturn dataReceiver;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getDomain() {\n\t\treturn domain;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getSessionId() {\n\t\treturn sessionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic UUID getSid() {\n\t\treturn sid;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param dataReceiver\n\t */\n\tpublic void setDataReceiver(JID dataReceiver) {\n\t\tthis.dataReceiver = dataReceiver;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t */\n\tpublic void setUserJid(String jid) {\n\t\tuserJid = JID.jidInstanceNS(jid);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate Element applyFilters(Element packet) {\n\t\tElement result = packet.clone();\n\n\t\tif (result.getName() == MESSAGE_ELEMENT_NAME) {\n\t\t\tString body = result.getCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\t\tif (body != null) {\n\t\t\t\tint count = 0;\n\n\t\t\t\t// for (Pattern reg: links_regexs) {\n\t\t\t\t// body = reg.matcher(body).replaceAll(replace_with[count++]);\n\t\t\t\t// }\n\t\t\t\tresult.getChild(\"body\").setCData(body);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate void closeAllConnections() {\n\t\tfor (BoshIOService conn : old_connections) {\n\t\t\tconn.stop();\n\t\t}\n\t\tfor (BoshIOService conn : connections.values()) {\n\t\t\tconn.stop();\n\t\t}\n\t}\n\n\tprivate boolean filterInPacket(Packet packet) {\n\t\tif (cache_on) {\n\t\t\tprocessAutomaticCache(packet);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate boolean filterOutPacket(Packet packet) {\n\t\tif (cache_on && (packet.getElemName() == MESSAGE_ELEMENT_NAME)) {\n\t\t\tcache.addToMessage(packet.getElement());\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate void processAutomaticCache(Packet packet) {\n\t\tif (packet.getElemName() == PRESENCE_ELEMENT_NAME) {\n\t\t\tcache.addPresence(packet.getElement());\n\t\t}\n\t\tif (packet.getElemName() == MESSAGE_ELEMENT_NAME) {\n\t\t\tcache.addFromMessage(packet.getElement());\n\t\t}\n\t\tif (packet.isXMLNSStaticStr(Iq.IQ_QUERY_PATH, \"jabber:iq:roster\")) {\n\t\t\tcache.addRoster(packet.getElement());\n\t\t}\n\t\tif (packet.isXMLNSStaticStr(Iq.IQ_BIND_PATH, \"urn:ietf:params:xml:ns:xmpp-bind\")) {\n\t\t\tcache.set(BoshSessionCache.RESOURCE_BIND_ID, Collections.singletonList(packet\n\t\t\t\t\t.getElement()));\n\t\t}\n\t}\n\n\tprivate void processCache(CacheAction action, Packet packet) {\n\t\t++cache_reload_counter;\n\n\t\tint           packet_counter = 0;\n\t\tList<Element> children       = packet.getElemChildrenStaticStr(BODY_EL_PATH);\n\t\tString        cache_id       = packet.getAttributeStaticStr(CACHE_ID_ATTR);\n\t\tList<Element> cache_res      = null;\n\n\t\tswitch (action) {\n\t\tcase on :\n\t\t\tif (cache == null) {\n\t\t\t\tcache = new BoshSessionCache();\n\t\t\t}\n\t\t\tcache_on = true;\n\t\t\tlog.fine(\"BoshSessionCache set to ON\");\n\n\t\t\tbreak;\n\n\t\tcase off :\n\t\t\tcache_on = false;\n\t\t\tlog.fine(\"BoshSessionCache set to OFF\");\n\n\t\t\tbreak;\n\n\t\tcase set :\n\t\t\tcache.set(cache_id, children);\n\n\t\t\tbreak;\n\n\t\tcase add :\n\t\t\tcache.add(cache_id, children);\n\n\t\t\tbreak;\n\n\t\tcase get :\n\t\t\tcache_res = cache.get(cache_id);\n\n\t\t\tbreak;\n\n\t\tcase remove :\n\t\t\tcache.remove(cache_id);\n\n\t\t\tbreak;\n\n\t\tcase get_all :\n\t\t\tcache_res = cache.getAll();\n\t\t\tretireAllOldConnections();\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tlog.warning(\"Unknown cache action: \" + action.toString());\n\n\t\t\tbreak;\n\t\t}\n\t\tif (cache_res != null) {\n\t\t\tfor (Element elem : cache_res) {\n\t\t\t\telem.addAttribute(\"reload-counter\", \"\" + cache_reload_counter);\n\t\t\t\telem.addAttribute(\"packet-counter\", \"\" + (++packet_counter));\n\t\t\t\tif (!waiting_packets.offer(elem)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.log(Level.INFO, \"waiting_packets queue exceeded, dropping packet: \" + elem.toString());\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void processRid(long rid, List<Element> packets) {\n\t\tsynchronized (currentRids) {\n\t\t\tif ((previous_received_rid + 1) != rid) {\n\t\t\t\tlog.log(Level.FINER, \"Incorrect packet order, last_rid={0}, current_rid={1}\",\n\t\t\t\t\t\tnew Object[] { previous_received_rid,\n\t\t\t\t\t\trid });\n\t\t\t}\n\t\t\tif ((packets != null) && (!packets.isEmpty())) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\tfor (Element elem : packets) {\n\t\t\t\t\tsb.append(elem.toString());\n\t\t\t\t}\n\t\t\t\thashCodes[rids_head] = sb.toString().hashCode();\n\t\t\t} else {\n\t\t\t\thashCodes[rids_head] = -1;\n\t\t\t}\n\t\t\tprevious_received_rid    = rid;\n\t\t\tcurrentRids[rids_head++] = rid;\n\t\t\tif (rids_head >= currentRids.length) {\n\t\t\t\trids_head = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void retireAllOldConnections() {\n\t\twhile (connections.size() > 1) {\n\t\t\tMap.Entry<BoshTask, BoshIOService> entry = connections.pollFirstEntry();\n\n\t\t\thandler.cancelTask(entry.getKey());\n\n\t\t\tBoshIOService serv = entry.getValue();\n\n\t\t\tif (serv != null) {\n\t\t\t\tretireConnectionService(serv);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\t\tlog.warning(\"connections queue size is greater than 1 but poll returns null\" +\n\t\t\t\t\t\t\tgetSid());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void retireConnectionService(BoshIOService serv) {\n\t\tif (!old_connections.contains(serv)) {\n\t\t\twhile (!old_connections.offer(serv)) {\n\t\t\t\tBoshIOService old_serv = old_connections.poll();\n\n\t\t\t\tif (old_serv != null) {\n\t\t\t\t\told_serv.stop();\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\t\t\tlog.warning(\"old_connections queue is empty but can not add new element!: \" +\n\t\t\t\t\t\t\t\tgetSid());\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tserv.setSid(null);\n\t\tdisconnected(serv);\n\t}\n\n\tprivate synchronized void sendBody(BoshIOService serv, Element body_par) {\n\t\tif (queueTask != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Canceling queue timer: \" + getSid());\n\t\t\t}\n\t\t\thandler.cancelSendQueueTask(queueTask);\n\t\t\tqueueTask = null;\n\t\t}\n\t\tlast_send_time = System.currentTimeMillis();\n\n\t\tBoshTask timer = serv.getWaitTimer();\n\n\t\tif (timer != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Canceling waitTimer: \" + getSid());\n\t\t\t}\n\t\t\thandler.cancelTask(timer);\n\t\t} else {\n\t\t\tlog.fine(\"No waitTimer for the Bosh connection! \" + serv);\n\t\t}\n\n\t\tElement body = body_par;\n\n\t\tif (body == null) {\n\t\t\tbody = getBodyElem();\n\n\t\t\tlong rid = takeCurrentRidTail();\n\n\t\t\tif (rid > 0) {\n\t\t\t\tbody.setAttribute(ACK_ATTR, \"\" + rid);\n\t\t\t}\n\t\t\tif (!waiting_packets.isEmpty()) {\n\n\t\t\t\t// body.addChild(applyFilters(waiting_packets.poll()));\n\t\t\t\t// Make sure the XMLNS is set correctly for all stanzas to avoid\n\t\t\t\t// namespace confusion:\n\t\t\t\t// http://forum.ag-software.de/thread/969\n\t\t\t\tElement stanza = waiting_packets.poll();\n\n\t\t\t\tif (stanza.getXMLNS() == null) {\n\t\t\t\t\tstanza.setXMLNS(XMLNS_CLIENT_VAL);\n\t\t\t\t}\n\t\t\t\tbody.addChild(stanza);\n\t\t\t\twhile ((!waiting_packets.isEmpty()) && (body.getChildren().size() <\n\t\t\t\t\t\tmax_batch_size)) {\n\n\t\t\t\t\t// body.addChild(applyFilters(waiting_packets.poll()));\n\t\t\t\t\tstanza = waiting_packets.poll();\n\t\t\t\t\tif (stanza.getXMLNS() == null) {\n\t\t\t\t\t\tstanza.setXMLNS(XMLNS_CLIENT_VAL);\n\t\t\t\t\t}\n\t\t\t\t\tbody.addChild(stanza);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( body.getChild( \"stream:error\" ) != null ){\n\t\t\tbody.addAttribute( \"condition\", \"remote-stream-error\" );\n\t\t\tbody.addAttribute( \"type\", \"terminate\" );\n\t\t\tbody.addAttribute( \"xmlns:stream\", \"http://etherx.jabber.org/streams\" );\n\t\t\tthis.terminate = true;\n\t\t}\n\n\t\ttry {\n\t\t\tif (terminate) {\n\t\t\t\tbody.setAttribute(\"type\", StanzaType.terminate.toString());\n\t\t\t}\n\t\t\thandler.writeRawData(serv, body.toString());\n\t\t\tretireConnectionService(serv);\n\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"[\" + connections.size() +\n\t\t\t\t\t\"] Exception during writing to socket\", e);\n\t\t}\n\t}\n\n\tprivate long takeCurrentRidTail() {\n\t\tsynchronized (currentRids) {\n\t\t\tint idx = rids_tail++;\n\n\t\t\tif (rids_tail >= currentRids.length) {\n\t\t\t\trids_tail = 0;\n\t\t\t}\n\n\t\t\treturn currentRids[idx];\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate Element getBodyElem() {\n\t\tElement body = new Element(BODY_EL_NAME, new String[] { FROM_ATTR, SECURE_ATTR,\n\t\t\t\t\"xmpp:version\", \"xmlns:xmpp\", \"xmlns:stream\" }, new String[] { this.domain,\n\t\t\t\t\"true\", \"1.0\", \"urn:xmpp:xbosh\", \"http://etherx.jabber.org/streams\" });\n\n\t\tif (this.hostname != null) {\n\t\t\tbody.addAttribute(HOST_ATTR, this.hostname);\n\t\t}\n\t\t\n\t\tbody.setXMLNS(BOSH_XMLNS);\n\n\t\treturn body;\n\t}\n\n\tprivate long getCurrentRidTail() {\n\t\tsynchronized (currentRids) {\n\t\t\treturn currentRids[rids_tail];\n\t\t}\n\t}\n\n\tprivate boolean isDuplicateMessage(long rid, List<Element> packets) {\n\t\tsynchronized (currentRids) {\n\t\t\tint hashCode = -1;\n\n\t\t\tif ((packets != null) && (!packets.isEmpty())) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\tfor (Element elem : packets) {\n\t\t\t\t\tsb.append(elem.toString());\n\t\t\t\t}\n\t\t\t\thashCode = sb.toString().hashCode();\n\t\t\t}\n\t\t\tif (hashCode == -1) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (int i = 0; i < currentRids.length; ++i) {\n\t\t\t\tif (rid == currentRids[i]) {\n\t\t\t\t\treturn hashCode == hashCodes[i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate boolean isDuplicateRid(long rid, List<Element> packets) {\n\t\tsynchronized (currentRids) {\n\t\t\tint hashCode = -1;\n\n\t\t\tif ((packets != null) && (!packets.isEmpty())) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\tfor (Element elem : packets) {\n\t\t\t\t\tsb.append(elem.toString());\n\t\t\t\t}\n\t\t\t\thashCode = sb.toString().hashCode();\n\t\t\t}\n\t\t\tfor (int i = 0; i < currentRids.length; ++i) {\n\t\t\t\tif (rid == currentRids[i]) {\n\t\t\t\t\treturn hashCode != hashCodes[i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate static class TimerTaskComparator\n\t\t\t\t\timplements Comparator<BoshTask> {\n\t\t@Override\n\t\tpublic int compare(BoshTask o1, BoshTask o2) {\n\t\t\tif (o1.timerOrder > o2.timerOrder) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tif (o1.timerOrder < o2.timerOrder) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshSessionCache.java",
    "content": "/*\n * BoshSessionCache.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.bosh;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.text.SimpleDateFormat;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Describe class BoshSessionCache here.\n *\n *\n * Created: Mon Feb 25 23:54:57 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BoshSessionCache {\n\t/** Field description */\n\tpublic static final String DEF_ID = \"\";\n\n\t/** Field description */\n\tpublic static final String MESSAGE_ID = \"bosh-message\";\n\n\t/** Field description */\n\tpublic static final String RESOURCE_BIND_ID = \"bosh-resource-bind\";\n\n\t/** Field description */\n\tpublic static final String ROSTER_ID = \"bosh-roster\";\n\tprivate static final Logger log      =\n\t\tLogger.getLogger(\"tigase.server.bosh.BoshSessionCache\");\n\tprivate static final SimpleDateFormat sdf =\n\t\tnew SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * Cached time of the first message to/from some jid\n\t * to speedup message caching processing\n\t */\n\tprotected Map<String, Long> jid_msg_start = null;\n\n\t/**\n\t * Cache elements stored by the Bosh client. The cache elements are grouped\n\t * by IDs. There can be any number of Elements under each ID.\n\t */\n\tprivate Map<String, List<Element>> id_cache = null;\n\n\t/**\n\t * Cached presence elements automaticaly stored by the Bosh component.\n\t * There is only 1 presence element stored for each JID which means the\n\t * cache stores the last presence element for each JID.\n\t */\n\tprivate Map<String, Element> jid_presence = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>BoshSessionCache</code> instance.\n\t *\n\t */\n\tpublic BoshSessionCache() {\n\t\tid_cache      = new LinkedHashMap<String, List<Element>>();\n\t\tjid_presence  = new LinkedHashMap<String, Element>();\n\t\tjid_msg_start = new LinkedHashMap<String, Long>();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t * @param data\n\t */\n\tpublic void add(String id, List<Element> data) {\n\t\tif (id == null) {\n\t\t\tid = DEF_ID;\n\t\t}\n\n\t\tList<Element> cached_data = id_cache.get(id);\n\n\t\tif (cached_data == null) {\n\t\t\tcached_data = new ArrayList<Element>();\n\t\t\tid_cache.put(id, cached_data);\n\t\t}\n\t\tcached_data.addAll(data);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"ADD, id = \" + id + \", DATA: \" + data.toString());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param message\n\t */\n\tpublic void addFromMessage(Element message) {\n\t\tElement body = message.findChildStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tString jid = message.getAttributeStaticStr(Packet.FROM_ATT);\n\n\t\taddMsgBody(jid, Packet.FROM_ATT, body);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param presence\n\t */\n\tpublic void addPresence(Element presence) {\n\t\tString from = presence.getAttributeStaticStr(Packet.FROM_ATT);\n\n\t\tjid_presence.put(from, presence);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"ADD_PRESENCE, from = \" + from + \", PRESENCE: \" + presence.toString());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param roster\n\t */\n\tpublic void addRoster(Element roster) {\n\n\t\t// Pushing roster with 'result' packet type will not work\n\t\tElement roster_mod = roster.clone();\n\n\t\troster_mod.setAttribute(Packet.TYPE_ATT, \"set\");\n\t\tadd(ROSTER_ID, Arrays.asList(roster_mod));\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"ADD_ROSTER, ROSTER: \" + roster_mod.toString());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param message\n\t */\n\tpublic void addToMessage(Element message) {\n\t\tElement body = message.findChildStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tString jid = message.getAttributeStaticStr(Packet.TO_ATT);\n\n\t\taddMsgBody(jid, Packet.TO_ATT, body);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic List<Element> get(String id) {\n\t\tif (id == null) {\n\t\t\tid = DEF_ID;\n\t\t}\n\n\t\tList<Element> data = id_cache.get(id);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"GET, id = \" + id + \", DATA: \" + data.toString());\n\t\t}\n\n\t\treturn data;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic List<Element> getAll() {\n\t\tList<Element> result = new ArrayList<Element>();\n\n\t\tfor (List<Element> cache_data : id_cache.values()) {\n\t\t\tresult.addAll(cache_data);\n\t\t}\n\t\tresult.addAll(jid_presence.values());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"GET_ALL, DATA: \" + result.toString());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic List<Element> getAllPresences() {\n\t\treturn new ArrayList<Element>(jid_presence.values());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param from\n\t *\n\t * \n\t */\n\tpublic List<Element> getPresence(String... from) {\n\t\tList<Element> result = new ArrayList<Element>();\n\n\t\tfor (String f : from) {\n\t\t\tElement presence = jid_presence.get(f);\n\n\t\t\tif (presence != null) {\n\t\t\t\tresult.add(presence);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic List<Element> remove(String id) {\n\t\tif (id == null) {\n\t\t\tid = DEF_ID;\n\t\t}\n\n\t\tList<Element> data = id_cache.remove(id);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"REMOVED, id = \" + id + \", DATA: \" + data.toString());\n\t\t}\n\n\t\treturn data;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t * @param data\n\t */\n\tpublic void set(String id, List<Element> data) {\n\t\tif (id == null) {\n\t\t\tid = DEF_ID;\n\t\t}\n\n\t\tList<Element> cached_data = new ArrayList<Element>();\n\n\t\tid_cache.put(id, cached_data);\n\t\tcached_data.addAll(data);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"SET, id = \" + id + \", DATA: \" + data.toString());\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void addMsgBody(String jid, String direction, Element body) {\n\t\tlong start_time             = getMsgStartTime(jid);\n\t\tList<Element> msg_history_l = id_cache.get(MESSAGE_ID + jid);\n\t\tElement msg_history         = null;\n\n\t\tif (msg_history_l == null) {\n\t\t\tmsg_history = createMessageHistory(jid);\n\t\t\tadd(MESSAGE_ID + jid, Arrays.asList(msg_history));\n\t\t} else {\n\t\t\tmsg_history = msg_history_l.get(0);\n\t\t}\n\n\t\tlong current_secs = (System.currentTimeMillis() / 1000) - start_time;\n\n\t\tmsg_history.findChildStaticStr(Iq.IQ_CHAT_PATH).addChild(new Element(direction,\n\t\t\t\t\t\tnew Element[] { body }, new String[] { \"secs\" },\n\t\t\t\t\t\tnew String[] { \"\" + current_secs }));\n\t}\n\n\tprivate Element createMessageHistory(String jid) {\n\t\tString sdf_string = null;\n\n\t\tsynchronized (sdf) {\n\t\t\tsdf_string = sdf.format(new Date());\n\t\t}\n\n\t\treturn new Element(\"iq\", new Element[] { new Element(\"chat\", new String[] { \"xmlns\",\n\t\t\t\t\t\t\"with\", \"start\" }, new String[] { \"urn:xmpp:tmp:archive\", jid,\n\t\t\t\t\t\tsdf_string }) }, new String[] { \"type\",\n\t\t\t\t\t\t\"id\" }, new String[] { \"set\", \"\" + System.currentTimeMillis() });\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate long getMsgStartTime(String jid) {\n\t\tLong start_time = jid_msg_start.get(jid);\n\n\t\tif (start_time == null) {\n\t\t\tstart_time = (System.currentTimeMillis() / 1000);\n\t\t\tjid_msg_start.put(jid, start_time);\n\t\t}\n\n\t\treturn start_time;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshSessionTaskHandler.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.bosh;\n\nimport tigase.server.Packet;\nimport tigase.server.xmppclient.SeeOtherHostIfc;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.xml.Element;\n\n\n/**\n * Describe interface BoshSessionTaskHandler here.\n *\n *\n * Created: Sat Aug  4 10:39:21 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface BoshSessionTaskHandler {\n\n\tJID getJidForBoshSession(BoshSession bs);\n\t\n\tBoshTask scheduleTask( BoshSession bs, long delay );\n\n\tBoshSendQueueTask scheduleSendQueueTask( BoshSession tt, long delay );\n\n\tvoid cancelTask( BoshTask bs );\n\n\tvoid cancelSendQueueTask( BoshSendQueueTask bt );\n\n\tvoid writeRawData( BoshIOService ios, String data );\n\n\tboolean addOutStreamOpen( Packet packet, BoshSession bs );\n\n\tboolean addOutStreamClosed( Packet packet, BoshSession bs, boolean withTimeout );\n\n\tBareJID getDefHostName();\n\t\n\tBareJID getSeeOtherHostForJID( Packet packet, BareJID userId, SeeOtherHostIfc.Phase ph );\n\n\tElement getSeeOtherHostError( Packet packet, BareJID destination);\n\n\tboolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshSidLoggerFilter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.server.bosh;\n\nimport tigase.server.bosh.BoshConnectionManager.BOSH_OPERATION_TYPE;\n\nimport java.util.logging.Filter;\nimport java.util.logging.LogRecord;\n\n/**\n *\n * @author Wojciech Kapcia\n */\n\npublic class BoshSidLoggerFilter implements Filter {\n\n\t@Override\n\tpublic boolean isLoggable( LogRecord record ) {\n\t\tboolean matchTracker = false;\n\n\t\tObject[] parameters = record.getParameters();\n\t\tif ( parameters != null && parameters.length > 0 && parameters[0] != null\n\t\t\t\t && BOSH_OPERATION_TYPE.forName( parameters[0].toString()) != null ){\n\t\t\tmatchTracker = true;\n\t\t}\n\t\treturn matchTracker;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/BoshTask.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\npackage tigase.server.bosh;\n\nimport tigase.server.Packet;\n\nimport tigase.util.TimerTask;\n\nimport java.util.ArrayDeque;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Describe class BoshWaitTimer here.\n *\n *\n * Created: Tue Oct 30 16:38:15 2012\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev: $\n */\npublic class BoshTask extends TimerTask {\n\tprivate static final Logger log = Logger.getLogger(BoshTask.class.getName());\n\n\tprotected long timerOrder = System.currentTimeMillis();\n\tprivate BoshSession bs = null;\n\tprivate BoshConnectionManager manager = null;\n\t\n\t// ~--- constructors -------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t * \n\t * \n\t * @param bs\n\t */\n\tpublic BoshTask(BoshSession bs, BoshConnectionManager manager) {\n\t\tthis.bs = bs;\n\t\tthis.manager = manager;\n\t}\n\n\t// ~--- methods ------------------------------------------------------------\n\n\t@Override\n\tpublic void run() {\n\t\tQueue<Packet> out_results = new ArrayDeque<Packet>();\n\n\t\tif (bs.task(out_results, this)) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Closing session for BS task: \" + bs.getSid());\n\t\t\t}\n\t\t\tmanager.sessions.remove(bs.getSid());\n\t\t}\n\n\t\tmanager.addOutPackets(out_results, bs);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/bosh/Constants.java",
    "content": "/*\n * Constants.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.bosh;\n\nimport java.util.logging.Level;\n\n/**\n * Describe class Constants here.\n *\n *\n * Created: Tue Jun  5 22:22:09 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class Constants {\n\t/** Field description */\n\tpublic static final String BOSH_VERSION = \"1.6\";\n\n\t/** Field description */\n\tprotected static final String ACCEPT_ATTR = \"accept\";\n\n\t/** Field description */\n\tprotected static final String ACK_ATTR = \"ack\";\n\n\t/** Field description */\n\tprotected static final String AUTHID_ATTR = \"authid\";\n\n\t/** Field description */\n\tprotected static final String BATCH_QUEUE_TIMEOUT_KEY = \"batch-queue-timeout\";\n\n\t/** Field description */\n\tprotected static final long BATCH_QUEUE_TIMEOUT_VAL = 100;\n\n\t/** Field description */\n\tprotected static final String BODY_EL_NAME = \"body\";\n\n\t/** Field description */\n\tprotected static final String[] BODY_EL_PATH = { \"body\" };\n\n\t/** Field description */\n\tprotected static final long BOSH_SESSION_CLOSE_DELAY_DEF_VAL = 0;\n\n\t/** Field description */\n\tprotected static final String BOSH_SESSION_CLOSE_DELAY_PROP_KEY =\n\t\t\"bosh-session-close-delay\";\n\n\t/** Field description */\n\tprotected static final String BOSH_XMLNS = \"http://jabber.org/protocol/httpbind\";\n\n\t/** Field description */\n\tprotected static final String CACHE_ATTR = \"cache\";\n\n\t/** Field description */\n\tprotected static final String CACHE_ID_ATTR = \"cache-id\";\n\n\t/** Field description */\n\tprotected static final String CHARSETS_ATTR = \"charsets\";\n\n\t/** Field description */\n\tprotected static final String CONCURRENT_REQUESTS_PROP_KEY = \"concurrent-requests\";\n\n\t/** Field description */\n\tprotected static final int CONCURRENT_REQUESTS_PROP_VAL = 2;\n\n\t/** Field description */\n\tprotected static final String CONTENT_ATTR = \"content\";\n\n\t/** Field description */\n\tprotected static final String CONTENT_TYPE_DEF = \"text/xml; charset=utf-8\";\n\n\t/** Field description */\n\tprotected static final String FROM_ATTR = \"from\";\n\n\t/** Field description */\n\tprotected static final String HOLD_ATTR = \"hold\";\n\n\t/** Field description */\n\tprotected static final String HOLD_REQUESTS_PROP_KEY = \"hold-requests\";\n\n\t/** Field description */\n\tprotected static final int HOLD_REQUESTS_PROP_VAL = 1;\n\n\t/** Name of custom attribute to pass name of host to which \n\t * BOSH connection is established */\n\tprotected static final String HOST_ATTR = \"host\";\n\t\n\t/** Field description */\n\tprotected static final String INACTIVITY_ATTR = \"inactivity\";\n\n\t/** Field description */\n\tprotected static final String LANG_ATTR = \"xml:lang\";\n\n\tprotected static final String PRE_BIND_ATTR = \"prebind\";\n\tprotected static final String SESSION_ID_ATTR = \"session-id\";\n\tprotected static final String USER_ID_ATTR = \"jid\";\n\n\t/** Field description */\n\tprotected static final String MAX_BATCH_SIZE_KEY = \"max-batch-size\";\n\n\t/** Field description */\n\tprotected static final String MAX_INACTIVITY_PROP_KEY = \"max-inactivity\";\n\n\t/** Field description */\n\tprotected static final long MAX_INACTIVITY_PROP_VAL = 10;\n\n\t/** Field description */\n\tprotected static final int MAX_PACKETS = 15;\n\n\t/** Field description */\n\tprotected static final String MAX_PAUSE_PROP_KEY = \"max-inactivity\";\n\n\t/** Field description */\n\tprotected static final long MAX_PAUSE_PROP_VAL = 10;\n\t\n\tprotected static final String MAX_SESSION_WAITING_PACKETS_KEY = \"max-session-waiting-packets\";\n\t\n\tprotected static final int MAX_SESSION_WAITING_PACKETS_VAL = 100;\n\n\t/** Field description */\n\tprotected static final String MAX_WAIT_DEF_PROP_KEY = \"max-wait\";\n\n\t/** Field description */\n\tprotected static final long MAX_WAIT_DEF_PROP_VAL = 30;\n\n\t/** Field description */\n\tprotected static final String MAXPAUSE_ATTR = \"maxpause\";\n\n\t/** Field description */\n\tprotected static final String MIN_POLLING_PROP_KEY = \"min-polling\";\n\n\t/** Field description */\n\tprotected static final long MIN_POLLING_PROP_VAL = 10;\n\n\t/** Field description */\n\tprotected static final String POLLING_ATTR = \"polling\";\n\n\t/** Field description */\n\tprotected static final String REQUESTS_ATTR = \"requests\";\n\n\t/** Field description */\n\tprotected static final String RESTART_ATTR = \"xmpp:restart\";\n\n\t/** Field description */\n\tprotected static final String RID_ATTR = \"rid\";\n\n\t/** Field description */\n\tprotected static final String ROUTE_ATTR = \"route\";\n\n\t/** Field description */\n\tprotected static final String SECURE_ATTR = \"secure\";\n\t\n\t/**\tField description */\n\tprotected static final String SEND_NODE_HOSTNAME_KEY = \"send-node-hostname\";\n\t\n\t/** Field description */\n\tprotected static final boolean SEND_NODE_HOSTNAME_VAL = true;\n\n\t/** Field description */\n\tprotected static final String SID_ATTR = \"sid\";\n\n\t/** Field description */\n\tprotected static final String TO_ATTR = \"to\";\n\n\t/** Field description */\n\tprotected static final String VER_ATTR = \"ver\";\n\n\t/** Field description */\n\tprotected static final String WAIT_ATTR = \"wait\";\n\n\t/** Field description */\n\tprotected static final String XMLNS_CLIENT_VAL = \"jabber:client\";\n\n\t/** Field description */\n\tprotected static final int MAX_BATCH_SIZE_VAL = MAX_PACKETS;\n\n\tprotected static final String SID_LOGGER_KEY = \"sid-logger-level\";\n\tprotected static final String SID_LOGGER_VAL = Level.OFF.toString();\n\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tprotected enum CacheAction {\n\t\ton, off, set, add, get, get_all, remove;\n\t}\n\n//protected static final String CACHE_ON = \"on\";\n//protected static final String CACHE_OFF = \"off\";\n//protected static final String CACHE_SET = \"set\";\n//protected static final String CACHE_ADD = \"add\";\n//protected static final String CACHE_GET = \"get\";\n//protected static final String CACHE_GET_ALL = \"get-all\";\n//protected static final String CACHE_REMOVE = \"remove\";\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/CompConfigRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\nimport java.util.Map;\nimport tigase.db.DBInitException;\nimport tigase.db.comp.ConfigRepository;\n\n/**\n * Created: Oct 3, 2009 2:00:30 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CompConfigRepository extends ConfigRepository<CompRepoItem> {\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do\n\t}\n\t\n\t@Override\n\tpublic String[] getDefaultPropetyItems() {\n\t\treturn CompRepoDefaults.getDefaultPropetyItems();\n\t}\n\n\t@Override\n\tpublic String getPropertyKey() {\n\t\treturn CompRepoDefaults.getPropertyKey();\n\t}\n\n\t@Override\n\tpublic String getConfigKey() {\n\t\treturn CompRepoDefaults.getConfigKey();\n\t}\n\n\t@Override\n\tpublic CompRepoItem getItemInstance() {\n\t\treturn CompRepoDefaults.getItemInstance();\n\t}\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do\n\t}\n\n\t@Override\n\tpublic String validateItem(CompRepoItem item) {\n\t\tString result = super.validateItem(item);\n\t\tif (result == null) {\n\t\t\tresult = item.validate();\n\t\t}\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/CompDBRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Map;\nimport tigase.db.DBInitException;\nimport tigase.db.comp.UserRepoRepository;\n\nimport tigase.xmpp.BareJID;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 24, 2009 3:55:41 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class CompDBRepository extends UserRepoRepository<CompRepoItem> {\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to destroy here\n\t}\n\t\n\t@Override\n\tpublic String getConfigKey() {\n\t\treturn CompRepoDefaults.getConfigKey();\n\t}\n\n\t@Override\n\tpublic String[] getDefaultPropetyItems() {\n\t\treturn CompRepoDefaults.getDefaultPropetyItems();\n\t}\n\n\t@Override\n\tpublic CompRepoItem getItemInstance() {\n\t\treturn CompRepoDefaults.getItemInstance();\n\t}\n\n\t@Override\n\tpublic String getPropertyKey() {\n\t\treturn CompRepoDefaults.getPropertyKey();\n\t}\n\n\t@Override\n\tpublic BareJID getRepoUser() {\n\t\treturn CompRepoDefaults.getRepoUser();\n\t}\n\t\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do here\n\t}\n\n\t@Override\n\tpublic String validateItem(CompRepoItem item) {\n\t\tString result = super.validateItem(item);\n\t\tif (result == null) {\n\t\t\tresult = item.validate();\n\t\t}\n\t\treturn result;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/CompRepoDefaults.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.BareJID;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 24, 2009 3:57:36 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class CompRepoDefaults {\n\tprivate static final BareJID comp_user = BareJID.bareJIDInstanceNS(\"ext-comp-manager\");\n\tprivate static final String comp_list_pkey = \"ext-comp-lists\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getConfigKey() {\n\t\treturn \"comp-items\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String[] getDefaultPropetyItems() {\n\t\treturn new String[] { \"muc.domain.tld:passwd:listen:5277:accept\" };\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static CompRepoItem getItemInstance() {\n\t\treturn new CompRepoItem();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getItemsListPKey() {\n\t\treturn comp_list_pkey;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getPropertyKey() {\n\t\treturn \"--external\";\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static BareJID getRepoUser() {\n\t\treturn comp_user;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/CompRepoItem.java",
    "content": "/*\n * CompRepoItem.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.comp.RepositoryItemAbstract;\n\nimport tigase.net.ConnectionType;\n\nimport tigase.server.Command;\nimport tigase.server.ext.lb.LoadBalancerIfc;\nimport tigase.server.ext.lb.ReceiverBareJidLB;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Oct 3, 2009 4:39:51 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CompRepoItem\n\t\t\t\textends RepositoryItemAbstract {\n\t/** Field description */\n\tpublic static final String CONN_TYPE_ATTR = \"type\";\n\n\t/** Field description */\n\tpublic static final String CONNECTION_TYPE_LABEL = \"Connection type\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_ATTR = \"domain\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_NAME_LABEL = \"Domain name\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_PASS_LABEL = \"Domain password\";\n\n\t/** Field description */\n\tpublic static final String LB_CLASS_LABEL = \"Load balancer class\";\n\n\t/** Field description */\n\tpublic static final String LB_NAME_ATTR = \"lb-class\";\n\n\t/** Field description */\n\tpublic static final String PASSWORD_ATTR = \"pass\";\n\n\t/** Field description */\n\tpublic static final String PORT_NO_ATTR = \"port\";\n\n\t/** Field description */\n\tpublic static final String PORT_NO_LABEL = \"Port number\";\n\n\t/** Field description */\n\tpublic static final String PROTO_XMLNS_ATTR = \"proto-xmlns\";\n\n\t/** Field description */\n\tpublic static final String PROTO_XMLNS_LABEL = \"Protocol\";\n\n\t/** Field description */\n\tpublic static final String REMOTE_HOST_ATTR = \"remote\";\n\n\t/** Field description */\n\tpublic static final String REMOTE_HOST_LABEL = \"Remote host\";\n\n\t/** Field description */\n\tpublic static final String REPO_ITEM_ELEM_NAME = \"item\";\n\n\t/** Field description */\n\tpublic static final String ROUTINGS_ATTR = \"routings\";\n\n\t/** Field description */\n\tpublic static final String ROUTINGS_LABEL = \"(Optional) Routings\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(CompRepoItem.class.getName());\n\n\t/** Field description */\n\tpublic static final LoadBalancerIfc DEF_LB_CLASS = new ReceiverBareJidLB();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate String auth_pass = null;\n\n\t// \"accept:muc.domain.tld:5277:user:passwd\"\n\tprivate String domain       = null;\n\tprivate int port            = -1;\n\tprivate String prop_xmlns   = null;\n\tprivate String remoteHost   = null;\n\tprivate String[] routings   = null;\n\tprivate ConnectionType type = ConnectionType.accept;\n\tprivate String xmlns        = null;\n\tprivate LoadBalancerIfc lb  = DEF_LB_CLASS;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addCommandFields(Packet packet) {\n\t\tCommand.addFieldValue(packet, DOMAIN_NAME_LABEL, ((domain != null)\n\t\t\t\t\t\t? domain\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, DOMAIN_PASS_LABEL, ((auth_pass != null)\n\t\t\t\t\t\t? auth_pass\n\t\t\t\t\t\t: \"\"));\n\n\t\tString[] types = new String[ConnectionType.values().length];\n\t\tint i          = 0;\n\n\t\tfor (ConnectionType t : ConnectionType.values()) {\n\t\t\ttypes[i++] = t.name();\n\t\t}\n\t\tCommand.addFieldValue(packet, CONNECTION_TYPE_LABEL, type.name(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCONNECTION_TYPE_LABEL, types, types);\n\t\tCommand.addFieldValue(packet, PORT_NO_LABEL, ((port > 0)\n\t\t\t\t\t\t? \"\" + port\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, REMOTE_HOST_LABEL, ((remoteHost != null)\n\t\t\t\t\t\t? remoteHost\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, PROTO_XMLNS_LABEL, ((prop_xmlns != null)\n\t\t\t\t\t\t? prop_xmlns\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, LB_CLASS_LABEL, ((lb != null)\n\t\t\t\t\t\t? lb.getClass().getName()\n\t\t\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, ROUTINGS_LABEL, \"\");\n\t\tsuper.addCommandFields(packet);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getAuthPasswd() {\n\t\treturn auth_pass;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic ConnectionType getConnectionType() {\n\t\treturn type;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic LoadBalancerIfc getLoadBalancer() {\n\t\treturn lb;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getDomain() {\n\t\treturn domain;\n\t}\n\n\t@Override\n\tpublic String getElemName() {\n\t\treturn REPO_ITEM_ELEM_NAME;\n\t}\n\n\t@Override\n\tpublic String getKey() {\n\t\treturn domain;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getRemoteHost() {\n\t\treturn remoteHost;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String[] getRoutings() {\n\t\treturn routings;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getXMLNS() {\n\t\treturn xmlns;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initFromCommand(Packet packet) {\n\t\tsuper.initFromCommand(packet);\n\t\tdomain    = Command.getFieldValue(packet, DOMAIN_NAME_LABEL);\n\t\troutings  = new String[] { domain, \".*@\" + domain, \".*\\\\.\" + domain };\n\t\tauth_pass = Command.getFieldValue(packet, DOMAIN_PASS_LABEL);\n\n\t\tString tmp = Command.getFieldValue(packet, REMOTE_HOST_LABEL);\n\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tremoteHost = tmp;\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, CONNECTION_TYPE_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\ttype = parseConnectionType(tmp);\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, PORT_NO_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tport = parsePortNo(tmp);\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, PROTO_XMLNS_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\tprop_xmlns = tmp;\n\t\t\txmlns      = parseProtoXMLNS(prop_xmlns);\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, LB_CLASS_LABEL);\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\tlb = lbInstance(tmp);\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, ROUTINGS_LABEL);\n\t\tif ((tmp != null) &&!tmp.isEmpty()) {\n\t\t\troutings = tmp.split(\",\");\n\t\t}\n\t}\n\n\t/**\n\t * @param tmp\n\t * \n\t */\n\tprivate LoadBalancerIfc lbInstance(String cls_name) {\n\t\tString class_name = cls_name;\n\n//  if (!class_name.endsWith(\".class\")) {\n//    class_name = class_name + \".class\";\n//  }\n\t\tlog.log(Level.INFO, \"Activating load-balancer for domain: {0}, class: {1}\",\n\t\t\t\t\t\tnew Object[] { domain,\n\t\t\t\t\t\t\t\t\t\t\t\t\t class_name });\n\n\t\tLoadBalancerIfc result = null;\n\n\t\ttry {\n\t\t\tresult = (LoadBalancerIfc) Class.forName(class_name).newInstance();\n\t\t} catch (Exception ex1) {\n\t\t\tclass_name = \"tigase.server.ext.lb.\" + class_name;\n\t\t\tlog.log(Level.INFO, \"Cannot active load balancer for class: {0}, trying: {1}\",\n\t\t\t\t\t\t\tnew Object[] { cls_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t class_name });\n\t\t\ttry {\n\t\t\t\tresult = (LoadBalancerIfc) Class.forName(class_name).newInstance();\n\t\t\t} catch (Exception ex2) {\n\t\t\t\tlog.log(\n\t\t\t\t\t\tLevel.WARNING,\n\t\t\t\t\t\t\"Cannot active load balancer for class:\" +\n\t\t\t\t\t\t\" {0}, or: {1}, errors: {2} or {3}, using default LB: {4}\", new Object[] {\n\t\t\t\t\t\t\tcls_name,\n\t\t\t\t\t\t\tclass_name, ex1, ex2, DEF_LB_CLASS.getClass().getName() });\n\t\t\t\tresult = DEF_LB_CLASS;\n\t\t\t}\n\t\t}\n\t\tlog.log(Level.INFO, \"Activated load-balancer for domain: {0}, class: {1}\",\n\t\t\t\t\t\tnew Object[] { domain,\n\t\t\t\t\t\t\t\t\t\t\t\t\t result.getClass().getName() });\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void initFromElement(Element elem) {\n\t\tif (elem.getName() != REPO_ITEM_ELEM_NAME) {\n\t\t\tthrow new IllegalArgumentException(\"Incorrect element name, expected: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t REPO_ITEM_ELEM_NAME);\n\t\t}\n\t\tsuper.initFromElement(elem);\n\t\tsetDomain(elem.getAttributeStaticStr(DOMAIN_ATTR));\n\t\tauth_pass  = elem.getAttributeStaticStr(PASSWORD_ATTR);\n\t\tremoteHost = elem.getAttributeStaticStr(REMOTE_HOST_ATTR);\n\n\t\tString tmp = elem.getAttributeStaticStr(CONN_TYPE_ATTR);\n\n\t\tif (tmp != null) {\n\t\t\tsetConnectionType(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(PORT_NO_ATTR);\n\t\tif (tmp != null) {\n\t\t\tport = parsePortNo(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(PROTO_XMLNS_ATTR);\n\t\tif (tmp != null) {\n\t\t\tsetProtocol(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(LB_NAME_ATTR);\n\t\tif (tmp != null) {\n\t\t\tlb = lbInstance(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(ROUTINGS_ATTR);\n\t\tif (tmp != null) {\n\t\t\troutings = tmp.split(\",\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initFromPropertyString(String propString) {\n\t\tString[] props = propString.split(\":\");\n\n\t\tif (props.length > 0) {\n\t\t\tsetDomain(props[0]);\n\t\t}\n\t\tif (props.length > 1) {\n\t\t\tauth_pass = props[1];\n\t\t}\n\t\tif (props.length > 2) {\n\t\t\tsetConnectionType(props[2]);\n\t\t}\n\t\tif (props.length > 3) {\n\t\t\tport = parsePortNo(props[3]);\n\t\t}\n\t\tif (props.length > 4) {\n\t\t\tremoteHost = props[4];\n\t\t}\n\t\tif (props.length > 5) {\n\t\t\tsetProtocol(props[5]);\n\t\t}\n\t\tif (props.length > 6) {\n\t\t\tlb = lbInstance(props[6]);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t// ~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t */\n\tpublic void setDomain(String domain) {\n\t\tthis.domain = domain;\n\t\troutings    = new String[] { domain, \".*@\" + domain, \".*\\\\.\" + domain };\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Element toElement() {\n\t\tElement elem = super.toElement();\n\n\t\telem.addAttribute(DOMAIN_ATTR, domain);\n\t\telem.addAttribute(PASSWORD_ATTR, auth_pass);\n\t\tif ((remoteHost != null) &&!remoteHost.isEmpty()) {\n\t\t\telem.addAttribute(REMOTE_HOST_ATTR, remoteHost);\n\t\t}\n\t\telem.addAttribute(CONN_TYPE_ATTR, type.name());\n\t\tif (port > 0) {\n\t\t\telem.addAttribute(PORT_NO_ATTR, \"\" + port);\n\t\t}\n\t\tif (prop_xmlns != null)\n\t\t\telem.addAttribute(PROTO_XMLNS_ATTR, prop_xmlns);\n\t\telem.addAttribute(LB_NAME_ATTR, lb.getClass().getName());\n\n\t\tStringBuilder route = new StringBuilder();\n\n\t\tfor (String r : routings) {\n\t\t\tif (route.length() > 0) {\n\t\t\t\troute.append(',');\n\t\t\t}\n\t\t\troute.append(r);\n\t\t}\n\t\telem.addAttribute(ROUTINGS_ATTR, route.toString());\n\n\t\treturn elem;\n\t}\n\n\t@Override\n\tpublic String toPropertyString() {\n\t\treturn domain + \":\" + auth_pass + \":\" + type.name() + \":\" + port + \":\" + remoteHost +\n\t\t\t\t\t \":\" + prop_xmlns + \":\" + lb.getClass().getName();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn toPropertyString();\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param connection_type\n\t */\n\tvoid setConnectionType(String connection_type) {\n\t\tthis.type = parseConnectionType(connection_type);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param password\n\t */\n\tvoid setPassword(String password) {\n\t\tthis.auth_pass = password;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param port\n\t */\n\tvoid setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param protocol\n\t */\n\tvoid setProtocol(String protocol) {\n\t\tthis.prop_xmlns = protocol;\n\t\tthis.xmlns      = parseProtoXMLNS(protocol);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param remote_domain\n\t */\n\tvoid setRemoteDomain(String remote_domain) {\n\t\tthis.remoteHost = remote_domain;\n\t}\n\t\n\tString validate() {\n\t\tif (domain == null)\n\t\t\treturn \"Domain name is required\";\n\t\tif (auth_pass == null)\n\t\t\treturn \"Password is required\";\n\t\tif (prop_xmlns == null)\n\t\t\treturn \"Protocol is required\";\t\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// ~--- methods --------------------------------------------------------------\n\tprivate ConnectionType parseConnectionType(String input) {\n\t\tConnectionType result = ConnectionType.accept;\n\n\t\tif (input.equals(\"connect\")) {\n\t\t\tresult = ConnectionType.connect;\n\t\t}\n\t\tif (input.equals(\"accept\") || input.equals(\"listen\")) {\n\t\t\tresult = ConnectionType.accept;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate int parsePortNo(String input) {\n\t\tint result = -1;\n\n\t\ttry {\n\t\t\tresult = Integer.parseInt(input);\n\t\t} catch (Exception e) {\n\t\t\tresult = 5277;\n\t\t\tlog.warning(\"Incorrect port number, can't parse: \" + input);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate String parseProtoXMLNS(String input) {\n\t\tString result = input;\n\n\t\tif (input.equals(\"accept\")) {\n\t\t\tresult = \"jabber:component:accept\";\n\t\t}\n\t\tif (input.equals(\"client\")) {\n\t\t\tresult = \"jabber:client\";\n\t\t}\n\t\tif (input.equals(\"connect\")) {\n\t\t\tresult = \"jabber:component:connect\";\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/CompSQLRepository.java",
    "content": "/*\n * CompSQLRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.db.comp.RepositoryChangeListenerIfc;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\n/**\n * Created: Nov 7, 2009 11:26:10 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CompSQLRepository\n\t\t\t\timplements ComponentRepository<CompRepoItem> {\n\t/** Field description */\n\tpublic static final String REPO_URI_PROP_KEY = \"repo-uri\";\n\n\t/** Field description */\n\tpublic static final String  TABLE_NAME             = \"external_component\";\n\tprivate static final String CONNECTION_TYPE_COLUMN = \"connection_type\";\n\tprivate static final String DOMAIN_COLUMN          = \"domain\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(CompSQLRepository.class.getName());\n\tprivate static final String OTHER_DATA_COLUMN    = \"other_data\";\n\tprivate static final String PASSWORD_COLUMN      = \"password\";\n\tprivate static final String PORT_COLUMN          = \"port\";\n\tprivate static final String PROTOCOL_COLUMN      = \"protocol\";\n\tprivate static final String REMOTE_DOMAIN_COLUMN = \"remote_domain\";\n\tprivate static final String GET_ITEM_QUERY = \"select * from \" + TABLE_NAME +\n\t\t\t\" where \" + DOMAIN_COLUMN + \" = ?\";\n\tprivate static final String GET_ALL_ITEMS_QUERY = \"select * from \" + TABLE_NAME;\n\tprivate static final String DELETE_ITEM_QUERY = \"delete from \" + TABLE_NAME +\n\t\t\t\" where (\" + DOMAIN_COLUMN + \" = ?)\";\n\tprivate static final String CREATE_TABLE_QUERY = \"create table \" + TABLE_NAME + \" (\" +\n\t\t\t\"  \" + DOMAIN_COLUMN + \" varchar(255) NOT NULL,\" + \"  \" + PASSWORD_COLUMN +\n\t\t\t\" varchar(255) NOT NULL,\" + \"  \" + CONNECTION_TYPE_COLUMN + \" varchar(127),\" +\n\t\t\t\"  \" + PORT_COLUMN + \" int,\" + \"  \" + REMOTE_DOMAIN_COLUMN + \" varchar(255),\" +\n\t\t\t\"  \" + PROTOCOL_COLUMN + \" varchar(127),\" + \"  \" + OTHER_DATA_COLUMN +\n\t\t\t\" TEXT,\" + \"  primary key(\" + DOMAIN_COLUMN + \"))\";\n\tprivate static final String CHECK_TABLE_QUERY = \"select count(*) from \" + TABLE_NAME;\n\tprivate static final String ADD_ITEM_QUERY = \"insert into \" + TABLE_NAME + \" (\" +\n\t\t\tDOMAIN_COLUMN + \", \" + PASSWORD_COLUMN + \", \" + CONNECTION_TYPE_COLUMN + \", \" +\n\t\t\tPORT_COLUMN + \", \" + REMOTE_DOMAIN_COLUMN + \", \" + PROTOCOL_COLUMN + \", \" +\n//\t\t\tOTHER_DATA_COLUMN + \") \" + \" values (?, ?, ?, ?, ?, ?, ?)\";\n\t\t\tOTHER_DATA_COLUMN + \") \" + \" (select ?, ?, ?, ?, ?, ?, ? from \" + TABLE_NAME + \" where \" + DOMAIN_COLUMN + \" = ? HAVING count(*)=0) \";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo = null;\n\n\tprivate String               tableName  = TABLE_NAME;\n\tprivate CompConfigRepository configRepo = new CompConfigRepository();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addRepoChangeListener(\n\t\t\tRepositoryChangeListenerIfc<CompRepoItem> repoChangeListener) {\n\t\tconfigRepo.addRepoChangeListener(repoChangeListener);\n\t}\n\n\t@Override\n\tpublic void removeRepoChangeListener(\n\t\t\tRepositoryChangeListenerIfc<CompRepoItem> repoChangeListener) {\n\t\tconfigRepo.removeRepoChangeListener(repoChangeListener);\n\t}\n\n\t@Override\n\tpublic void addItemNoStore(CompRepoItem item) {\n\n\t}\n\n\t@Override\n\tpublic void addItem(CompRepoItem item) {\n\t\ttry {\n\t\t\tPreparedStatement addItemSt = data_repo.getPreparedStatement(null, ADD_ITEM_QUERY);\n\n\t\t\tsynchronized (addItemSt) {\n\t\t\t\tif ((item.getDomain() != null) &&!item.getDomain().isEmpty()) {\n\t\t\t\t\taddItemSt.setString(1, item.getDomain());\n\t\t\t\t\taddItemSt.setString(8, item.getDomain());\n\t\t\t\t} else {\n\t\t\t\t\tthrow new NullPointerException(\"Null or empty domain name is not allowed\");\n\t\t\t\t}\n\t\t\t\tif (item.getAuthPasswd() != null) {\n\t\t\t\t\taddItemSt.setString(2, item.getAuthPasswd());\n\t\t\t\t} else {\n\t\t\t\t\tthrow new NullPointerException(\"Null password is not allowed\");\n\t\t\t\t}\n\t\t\t\tif (item.getConnectionType() != null) {\n\t\t\t\t\taddItemSt.setString(3, item.getConnectionType().name());\n\t\t\t\t} else {\n\t\t\t\t\taddItemSt.setNull(3, Types.VARCHAR);\n\t\t\t\t}\n\t\t\t\tif (item.getPort() > 0) {\n\t\t\t\t\taddItemSt.setInt(4, item.getPort());\n\t\t\t\t} else {\n\t\t\t\t\taddItemSt.setNull(4, Types.INTEGER);\n\t\t\t\t}\n\t\t\t\tif ((item.getRemoteHost() != null) &&!item.getRemoteHost().isEmpty()) {\n\t\t\t\t\taddItemSt.setString(5, item.getRemoteHost());\n\t\t\t\t} else {\n\t\t\t\t\taddItemSt.setNull(5, Types.VARCHAR);\n\t\t\t\t}\n\t\t\t\tif (item.getXMLNS() != null) {\n\t\t\t\t\taddItemSt.setString(6, item.getXMLNS());\n\t\t\t\t} else {\n\t\t\t\t\taddItemSt.setNull(6, Types.VARCHAR);\n\t\t\t\t}\n\n\t\t\t\tString other_data = item.toElement().toString();\n\n\t\t\t\tif (other_data != null) {\n\t\t\t\t\taddItemSt.setString(7, other_data);\n\t\t\t\t} else {\n\t\t\t\t\taddItemSt.setNull(7, Types.VARCHAR);\n\t\t\t\t}\n\t\t\t\taddItemSt.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem adding a new item to DB: \" + item.toElement(), e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Collection<CompRepoItem> allItems() {\n\t\tList<CompRepoItem> result = new ArrayList<CompRepoItem>();\n\n\t\tresult.addAll(configRepo.allItems());\n\n\t\ttry {\n\t\t\tResultSet rs = null;\n\t\t\tPreparedStatement getAllItemsSt = data_repo.getPreparedStatement(null,\n\t\t\t\t\tGET_ALL_ITEMS_QUERY);\n\n\t\t\tsynchronized (getAllItemsSt) {\n\t\t\t\ttry {\n\t\t\t\t\trs = getAllItemsSt.executeQuery();\n\t\t\t\t\twhile (rs.next()) {\n\t\t\t\t\t\tresult.add(createItemFromRS(rs));\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem getting elements from DB: \", e);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean contains(String key) {\n\t\tboolean result = configRepo.contains(key);\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\t// This implementation of CompSQLRepository is using shared connection\n\t\t// pool to database which is cached by RepositoryFactory and maybe be used\n\t\t// in other places, so we can not destroy it.\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tconfigRepo.getDefaults(defs, params);\n\n\t\tString repo_uri = RepositoryFactory.DERBY_REPO_URL_PROP_VAL;\n\n\t\tif (params.get(RepositoryFactory.GEN_USER_DB_URI) != null) {\n\t\t\trepo_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t}\n\t\tdefs.put(REPO_URI_PROP_KEY, repo_uri);\n\t}\n\n\t@Override\n\tpublic CompRepoItem getItem(String key) {\n\t\tCompRepoItem result = configRepo.getItem(key);\n\n\t\tif (result == null) {\n\t\t\ttry {\n\t\t\t\tResultSet rs = null;\n\t\t\t\tPreparedStatement getItemSt = data_repo.getPreparedStatement(null,\n\t\t\t\t\t\tGET_ITEM_QUERY);\n\n\t\t\t\tsynchronized (getItemSt) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tgetItemSt.setString(1, key);\n\t\t\t\t\t\trs = getItemSt.executeQuery();\n\t\t\t\t\t\tif (rs.next()) {\n\t\t\t\t\t\t\tresult = createItemFromRS(rs);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdata_repo.release(null, rs);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem getting element from DB for domain: \" + key, e);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic CompRepoItem getItemInstance() {\n\t\treturn configRepo.getItemInstance();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initRepository(String conn_str, Map<String, String> params)\n\t\t\t\t\tthrows DBInitException {\n\t\ttry {\n\t\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, params);\n\t\t\tcheckDB();\n\t\t\tdata_repo.initPreparedStatement(CHECK_TABLE_QUERY, CHECK_TABLE_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_ITEM_QUERY, GET_ITEM_QUERY);\n\t\t\tdata_repo.initPreparedStatement(GET_ALL_ITEMS_QUERY, GET_ALL_ITEMS_QUERY);\n\t\t\tdata_repo.initPreparedStatement(ADD_ITEM_QUERY, ADD_ITEM_QUERY);\n\t\t\tdata_repo.initPreparedStatement(DELETE_ITEM_QUERY, DELETE_ITEM_QUERY);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem initializing database: \", e);\n\t\t} finally {\n\n\t\t\t// Check if DB is correctly setup and contains all required tables.\n\t\t}\n\t}\n\n\t@Override\n\tpublic Iterator<CompRepoItem> iterator() {\n\t\treturn allItems().iterator();\n\t}\n\n\t@Override\n\tpublic void reload() {\n\n\t\t// Do nothing, no caching, everything is read on demand from DB\n\t}\n\n\t@Override\n\tpublic void removeItem(String key) {\n\t\tconfigRepo.removeItem(key);\n\t\ttry {\n\t\t\tPreparedStatement deleteItemSt = data_repo.getPreparedStatement(null,\n\t\t\t\t\tDELETE_ITEM_QUERY);\n\n\t\t\tsynchronized (deleteItemSt) {\n\t\t\t\tdeleteItemSt.setString(1, key);\n\t\t\t\tdeleteItemSt.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't remove item: \" + key, e);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\t\tconfigRepo.setProperties(properties);\n\n\t\tString repo_uri = (String) properties.get(REPO_URI_PROP_KEY);\n\n\t\ttry {\n\t\t\tinitRepository(repo_uri, null);\n\t\t} catch (DBInitException ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem initializing database.\", ex);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int size() {\n\t\tint result = configRepo.size();\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void store() {\n\n\t\t// Do nothing everything is written on demand to DB\n\t}\n\n\t@Override\n\tpublic String validateItem(CompRepoItem item) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Performs database check, creates missing schema if necessary\n\t *\n\t * @throws SQLException\n\t */\n\tprivate void checkDB() throws SQLException {\n\t\tdata_repo.checkTable( tableName, CREATE_TABLE_QUERY );\n\t}\n\n\tprivate CompRepoItem createItemFromRS(ResultSet rs) throws SQLException {\n\t\tCompRepoItem result = getItemInstance();\n\n\t\t// First init from other parameters, some fixed fields may\n\t\t// overwrite fields initialized from other parametrs\n\t\tString other = rs.getString(OTHER_DATA_COLUMN);\n\n\t\tif ((other != null) &&!other.isEmpty()) {\n\t\t\tElement elem_item = parseElement(other);\n\n\t\t\tif (elem_item != null) {\n\t\t\t\tresult.initFromElement(elem_item);\n\t\t\t}\n\t\t}\n\n\t\tString domain = rs.getString(DOMAIN_COLUMN);\n\n\t\tif ((domain != null) &&!domain.isEmpty()) {\n\t\t\tresult.setDomain(domain);\n\t\t}\n\n\t\tString password = rs.getString(PASSWORD_COLUMN);\n\n\t\tif ((password != null) &&!password.isEmpty()) {\n\t\t\tresult.setPassword(password);\n\t\t}\n\n\t\tint port = rs.getInt(PORT_COLUMN);\n\n\t\tif (port > 0) {\n\t\t\tresult.setPort(port);\n\t\t}\n\n\t\tString remote_domain = rs.getString(REMOTE_DOMAIN_COLUMN);\n\n\t\tif ((remote_domain != null) &&!remote_domain.isEmpty()) {\n\t\t\tresult.setRemoteDomain(remote_domain);\n\t\t}\n\n\t\tString protocol = rs.getString(PROTOCOL_COLUMN);\n\n\t\tif ((protocol != null) &&!protocol.isEmpty()) {\n\t\t\tresult.setProtocol(protocol);\n\t\t}\n\n\t\tString connection_type = rs.getString(CONNECTION_TYPE_COLUMN);\n\n\t\tif ((connection_type != null) &&!connection_type.isEmpty()) {\n\t\t\tresult.setConnectionType(connection_type);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate Element parseElement(String data) {\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\tSimpleParser      parser     = SingletonFactory.getParserInstance();\n\n\t\tparser.parse(domHandler, data.toCharArray(), 0, data.length());\n\n\t\tQueue<Element> elems = domHandler.getParsedElements();\n\n\t\tif ((elems != null) && (elems.size() > 0)) {\n\t\t\treturn elems.poll();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setAutoloadTimer(long delay) {}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/ComponentConnection.java",
    "content": "/*\n * ComponentConnection.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext;\n\n/**\n * Created: Sep 30, 2009 9:20:22 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentConnection\n\t\t\t\timplements Comparable<ComponentConnection> {\n\tprivate String domain = null;\n\n//private List<String> resources     = new ArrayList<String>();\n\tprivate ComponentIOService service = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param domain\n\t * @param service\n\t */\n\tpublic ComponentConnection(String domain, ComponentIOService service) {\n\t\tthis.domain  = domain;\n\t\tthis.service = service;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int compareTo(ComponentConnection o) {\n\t\tif (o == null) {\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn service.getRemoteAddress().compareTo(o.service.getRemoteAddress());\n\n\t\t// return service.getUniqueId().compareTo(o.service.getUniqueId());\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getDomain() {\n\t\treturn domain;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic ComponentIOService getService() {\n\t\treturn service;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/ComponentIOService.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ext;\n\nimport tigase.net.ConnectionType;\nimport tigase.util.SizedCache;\nimport tigase.xmpp.XMPPIOService;\nimport tigase.xmpp.JID;\n\nimport java.util.List;\n\n/**\n * Created: Jun 14, 2010 12:05:41 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentIOService extends XMPPIOService<List<ComponentConnection>> {\n\tprivate static final int MAX_RECENT_JIDS = 10000;\n\tprivate static final long MAX_CACHE_TIME = 100000;\n\n\tprivate boolean authenticated = false;\n\tprivate String routings = null;\n\tprivate SizedCache<JID, JID> recentJIDs = new SizedCache<JID, JID>(MAX_RECENT_JIDS);\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * \n\t */\n\tpublic boolean isAuthenticated() {\n\t\treturn authenticated;\n\t}\n\n\tpublic String getRoutings() {\n\t\treturn routings;\n\t}\n\n\tpublic void addRecentJID(JID jid) {\n\t\t// We only save recent JIDs on the external component side\n\t\tif (connectionType() == ConnectionType.connect) {\n\t\t\trecentJIDs.put(jid, jid);\n\t\t}\n\t}\n\n\tpublic boolean isRecentJID(JID jid) {\n\t\treturn jid != null && recentJIDs.get(jid) != null;\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param authenticated\n\t */\n\tpublic void setAuthenticated(boolean authenticated) {\n\t\tthis.authenticated = authenticated;\n\t}\n\n\tpublic void setRoutings(String r) {\n\t\troutings = r;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/ComponentProtocol.java",
    "content": "/*\n * ComponentProtocol.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimerTask;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\n\nimport tigase.conf.ConfigurationException;\n\nimport tigase.db.comp.ComponentRepository;\n\nimport tigase.net.ConnectionType;\nimport tigase.net.SocketType;\n\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\nimport tigase.server.ext.handlers.BindProcessor;\nimport tigase.server.ext.handlers.ComponentAcceptStreamOpenHandler;\nimport tigase.server.ext.handlers.ComponentConnectStreamOpenHandler;\nimport tigase.server.ext.handlers.HandshakeProcessor;\nimport tigase.server.ext.handlers.JabberClientStreamOpenHandler;\nimport tigase.server.ext.handlers.SASLProcessor;\nimport tigase.server.ext.handlers.StartTLSProcessor;\nimport tigase.server.ext.handlers.StreamFeaturesProcessor;\nimport tigase.server.ext.handlers.UnknownXMLNSStreamOpenHandler;\nimport tigase.server.ext.lb.LoadBalancerIfc;\n\nimport tigase.stats.StatisticsList;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.PacketErrorTypeException;\n\nimport java.text.MessageFormat;\n\n/**\n * Created: Sep 30, 2009 8:28:13 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentProtocol\n\t\t\t\textends ConnectionManager<ComponentIOService>\n\t\t\t\timplements ComponentProtocolHandler {\n\t/** Field description */\n\tpublic static final String AUTHENTICATION_TIMEOUT_PROP_KEY = \"auth-timeout\";\n\n\t/** Field description */\n\tpublic static final String CLOSE_ON_SEQUENCE_ERROR_PROP_KEY = \"close-on-seq-error\";\n\n\t/** Field description */\n\tpublic static final String EXTCOMP_BIND_HOSTNAMES = \"--bind-ext-hostnames\";\n\n\t/** Field description */\n\tpublic static final String EXTCOMP_REPO_CLASS_PROP_KEY = \"repository-class\";\n\n\t/** Field description */\n\tpublic static final String EXTCOMP_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.server.ext.CompDBRepository\";\n\n\t/** Field description */\n\tpublic static final String EXTCOMP_REPO_CLASS_PROPERTY = \"--extcomp-repo-class\";\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_KEY = \"identity-type\";\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_VAL = \"generic\";\n\n\t/** Field description */\n\tpublic static final String MAX_AUTH_ATTEMPTS_PROP_KEY = \"max-auth-attempts\";\n\n\t/** Field description */\n\tpublic static final String PACK_ROUTED_KEY = \"pack-routed\";\n\n\t/** Field description */\n\tpublic static final String RETURN_SERVICE_DISCO_KEY = \"service-disco\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ComponentProtocol.class.getName());\n\n\t/** Field description */\n\tpublic static final boolean RETURN_SERVICE_DISCO_VAL = true;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tpublic boolean PACK_ROUTED_VAL = false;\n\n\t// In seconds\n\tprivate long authenticationTimeOut = 15;\n\n\t/**\n\t * A map keeping all active connections by a connection JID or domain name.\n\t * Since for each domain we can have 1..N connections the Map value is a List\n\t * of connections.\n\t */\n\tprivate Map<String, CopyOnWriteArrayList<ComponentConnection>> connections =\n\t\t\tnew ConcurrentHashMap<String, CopyOnWriteArrayList<ComponentConnection>>();\n\tprivate String[]                          hostnamesToBind           = null;\n\tprivate int                               maxAuthenticationAttempts = 1;\n\tprivate ComponentRepository<CompRepoItem> repo                      = null;\n\tprivate Map<String, StreamOpenHandler>    streamOpenHandlers =\n\t\t\tnew LinkedHashMap<String, StreamOpenHandler>();\n\n\t/**\n\t * List of processors which should handle all traffic incoming from the\n\t * network. In most cases if not all, these processors handle just protocol\n\t * traffic, all the rest traffic should be passed on to MR.\n\t */\n\tprivate Map<String, ExtProcessor> processors = new LinkedHashMap<String, ExtProcessor>(\n\t\t\t10);\n\tprivate UnknownXMLNSStreamOpenHandler unknownXMLNSHandler =\n\t\t\tnew UnknownXMLNSStreamOpenHandler();\n\tprivate String  identity_type = IDENTITY_TYPE_VAL;\n\tprivate boolean experimental  = false;\n\n\t// private ServiceEntity serviceEntity = null;\n\tprivate boolean closeOnSequenceError = true;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic ComponentProtocol() {\n\t\tsuper();\n\n\t\tStreamOpenHandler handler = new JabberClientStreamOpenHandler();\n\n\t\tif (handler.getXMLNSs() != null) {\n\t\t\tfor (String xmlns : handler.getXMLNSs()) {\n\t\t\t\tstreamOpenHandlers.put(xmlns, handler);\n\t\t\t}\n\t\t}\n\t\thandler = new ComponentAcceptStreamOpenHandler();\n\t\tif (handler.getXMLNSs() != null) {\n\t\t\tfor (String xmlns : handler.getXMLNSs()) {\n\t\t\t\tstreamOpenHandlers.put(xmlns, handler);\n\t\t\t}\n\t\t}\n\t\thandler = new ComponentConnectStreamOpenHandler();\n\t\tif (handler.getXMLNSs() != null) {\n\t\t\tfor (String xmlns : handler.getXMLNSs()) {\n\t\t\t\tstreamOpenHandlers.put(xmlns, handler);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void authenticated(ComponentIOService serv) {\n\t\tserv.setAuthenticated(true);\n\n\t\tString hostname = (String) serv.getSessionData().get(ComponentIOService.HOSTNAME_KEY);\n\n\t\tbindHostname(hostname, serv);\n\t\tif (hostnamesToBind != null) {\n\t\t\tserv.getSessionData().put(EXTCOMP_BIND_HOSTNAMES_PROP_KEY, hostnamesToBind);\n\n\t\t\tExtProcessor proc = getProcessor(\"bind\");\n\n\t\t\tif (proc != null) {\n\t\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\t\t\tproc.startProcessing(null, serv, this, results);\n\t\t\t\twritePacketsToSocket(serv, results);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void authenticationFailed(ComponentIOService serv, Packet packet) {\n\t\twritePacketToSocket(serv, packet);\n\n\t\tInteger fails = (Integer) serv.getSessionData().get(\"auth-fails\");\n\n\t\tif (fails == null) {\n\t\t\tfails = 1;\n\t\t} else {\n\t\t\tfails += 1;\n\t\t}\n\t\tif (fails >= maxAuthenticationAttempts) {\n\t\t\tserv.stop();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected String getDefTrafficThrottling() {\n\t\treturn \"xmpp:25m:0:disc,bin:20000m:0:disc\";\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void bindHostname(String hostname, ComponentIOService serv) {\n\t\tString[] routings = new String[] { hostname, \".*@\" + hostname, \".*\\\\.\" + hostname };\n\n\t\tif (serv.connectionType() == ConnectionType.connect) {\n\n\t\t\t// Most likely we have an external component here which doesn't have any\n\t\t\t// connections managers. In such a case the best routings settings would\n\t\t\t// be: .*\n\t\t\troutings = new String[] { \".*\" };\n\t\t}\n\t\tserv.setRoutings(routings[0]);\n\t\tupdateRoutings(routings, true);\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.fine(\"Authenticated: \" + hostname);\n\t\t}\n\t\tupdateServiceDiscoveryItem(hostname, null, \"ext-comp connected\", false);\n\n\t\t// Now kind of trick to allow access to the external component in a more\n\t\t// direct way. However, we have to careful here to avoid disaster.\n\t\tif (experimental) {\n\t\t\tupdateServiceDiscoForConnection(hostname, serv);\n\t\t}\n\t\taddComponentConnection(hostname, serv);\n\t\taddComponentDomain(hostname);\n\t}\n\n\tprivate void updateServiceDiscoForConnection(String hostname, ComponentIOService serv) {\n\n\t\t// Cut off the first, component part\n\t\tint    idx         = hostname.indexOf(\".\");\n\t\tString newhostname = hostname.substring(idx + 1);\n\n\t\tif (!isLocalDomain(newhostname)) {\n\t\t\tupdateServiceDiscoveryItem(newhostname, \"ext\", serv.getUniqueId(), true);\n\t\t} else {\n\n\t\t\t// We don't do the trick because this would break stuff\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic CompRepoItem getCompRepoItem(String hostname) {\n\t\treturn repo.getItem(hostname);\n\t}\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\n\t\texperimental = Boolean.parseBoolean((String) params.get(\"--experimental\"));\n\n\t\tString repo_class = (String) params.get(EXTCOMP_REPO_CLASS_PROPERTY);\n\n\t\tif (repo_class == null) {\n\t\t\trepo_class = EXTCOMP_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tdefs.put(EXTCOMP_REPO_CLASS_PROP_KEY, repo_class);\n\t\ttry {\n\t\t\trepo = (ComponentRepository<CompRepoItem>) Class.forName(repo_class).newInstance();\n\t\t\trepo.getDefaults(defs, params);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not instantiate items repository for class: \" +\n\t\t\t\t\trepo_class, e);\n\t\t}\n\t\tdefs.put(PACK_ROUTED_KEY, PACK_ROUTED_VAL);\n\t\tdefs.put(RETURN_SERVICE_DISCO_KEY, RETURN_SERVICE_DISCO_VAL);\n\t\tdefs.put(IDENTITY_TYPE_KEY, IDENTITY_TYPE_VAL);\n\n\t\tString bind_hostnames = (String) params.get(EXTCOMP_BIND_HOSTNAMES);\n\n\t\tif (bind_hostnames != null) {\n\t\t\tdefs.put(EXTCOMP_BIND_HOSTNAMES_PROP_KEY, bind_hostnames.split(\",\"));\n\t\t} else {\n\t\t\tdefs.put(EXTCOMP_BIND_HOSTNAMES_PROP_KEY, new String[] { \"\" });\n\t\t}\n\t\tdefs.put(CLOSE_ON_SEQUENCE_ERROR_PROP_KEY, closeOnSequenceError);\n\t\tdefs.put(MAX_AUTH_ATTEMPTS_PROP_KEY, maxAuthenticationAttempts);\n\t\tdefs.put(AUTHENTICATION_TIMEOUT_PROP_KEY, authenticationTimeOut);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn identity_type;\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"External component\";\n\t}\n\n\t@Override\n\tpublic ExtProcessor getProcessor(String key) {\n\t\treturn processors.get(key);\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\n\t\t// Warning size() for ConcurrentHashMap is very slow\n\t\t// unless we have a huge number of domains this should not be a problem\n\t\t// though.\n\t\tlist.add(getName(), \"Number of external domains\", connections.size(), Level.FINE);\n\n\t\tint size = 0;\n\n\t\tfor (CopyOnWriteArrayList<ComponentConnection> conns : connections.values()) {\n\t\t\tsize += conns.size();\n\t\t}\n\t\tlist.add(getName(), \"Number of external component connections\", size, Level.FINER);\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv) {\n\t\tList<Element> results = new LinkedList<Element>();\n\n\t\tfor (ExtProcessor proc : processors.values()) {\n\t\t\tList<Element> proc_res = proc.getStreamFeatures(serv, this);\n\n\t\t\tif (proc_res != null) {\n\t\t\t\tresults.addAll(proc_res);\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t@Override\n\tpublic StreamOpenHandler getStreamOpenHandler(String xmlns) {\n\t\treturn streamOpenHandlers.get(xmlns);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(ComponentRepository.COMP_REPO_BIND, repo);\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(ComponentIOService serv) {\n\t\tQueue<Packet> packets = serv.getReceivedPackets();\n\t\tPacket        p       = null;\n\t\tQueue<Packet> results = new ArrayDeque<Packet>(2);\n\n\t\twhile ((p = packets.poll()) != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing socket data: {0}, from socket: {1}\", new Object[] { p, serv });\n\t\t\t}\n\n\t\t\tboolean processed = false;\n\n\t\t\tfor (ExtProcessor proc : processors.values()) {\n\t\t\t\tprocessed |= proc.process(p, serv, this, results);\n\t\t\t\twritePacketsToSocket(serv, results);\n\t\t\t}\n\t\t\tif (!processed) {\n\n\t\t\t\t// This might be a bit slow, need to be tested.\n\t\t\t\t// Possibly a local variable in XMPPIOService might be needed\n\t\t\t\t// to improve performance\n\t\t\t\tif (serv.isAuthenticated()) {\n\t\t\t\t\tPacket result = p;\n\n\t\t\t\t\tif (p.isRouted()) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresult = p.unpackRouted();\n\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\"Packet stringprep addressing problem, dropping packet: {0}\", p);\n\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (p.isRouted())\n\t\t\t\t\tresult.getElement().setXMLNS(\"jabber:client\");\n\t\t\t\t\tif (result.getStanzaFrom() != null) {\n\t\t\t\t\t\tserv.addRecentJID(result.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t\taddOutPacket(result);\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPacket error = Authorization.NOT_AUTHORIZED.getResponseMessage(p,\n\t\t\t\t\t\t\t\t\"Connection not yet authorized to send this packet.\", true);\n\n\t\t\t\t\t\twritePacketToSocket(serv, error);\n\t\t\t\t\t} catch (PacketErrorTypeException ex) {\n\n\t\t\t\t\t\t// Already error packet, just ignore to prevent infinite loop\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Received an error packet from unauthorized connection: {0}\", p);\n\t\t\t\t\t}\n\t\t\t\t\tif (closeOnSequenceError) {\n\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\t// readd packet - this may be good as we would retry to send packet \n\t\t// which delivery failed due to IO error\n\t\taddPacket(packet);\n\t\treturn true;\n\t}\n\t\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\n\t\t// TODO: handle this somehow\n\t}\n\n\t@Override\n\tpublic void serviceStarted(ComponentIOService serv) {\n\t\tsuper.serviceStarted(serv);\n\t\taddTimerTask(new AuthenticationTimerTask(serv), authenticationTimeOut, TimeUnit.SECONDS);\n\n\t\tString xmlns = ((CompRepoItem) serv.getSessionData().get(REPO_ITEM_KEY)).getXMLNS();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Connection started: \" + serv.getRemoteAddress() + \", xmlns: \" + xmlns +\n\t\t\t\t\t\", type: \" + serv.connectionType().toString() + \", id=\" + serv.getUniqueId());\n\t\t}\n\n\t\tStreamOpenHandler handler = streamOpenHandlers.get(xmlns);\n\t\tString            result  = null;\n\n\t\tif (handler == null) {\n\n\t\t\t// Well, that's a but, we should not be here...\n\t\t\tlog.fine(\"XMLNS not set, accepting a new connection with xmlns auto-detection.\");\n\t\t} else {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"cid: {0}, sending: {1}, sessionData: {2}\",\n\t\t\t\t\t\t\t\t new Object[] { serv.getSessionData().get( \"cid\" ), result, serv.getSessionData() } );\n\t\t\t}\n\t\t\tresult = handler.serviceStarted(serv);\n\t\t}\n\t\tif (result != null) {\n\t\t\tserv.xmppStreamOpen(result);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(ComponentIOService service) {\n\t\tboolean result = super.serviceStopped(service);\n\n\t\tif (result) {\n\t\t\tMap<String, Object> sessionData = service.getSessionData();\n\t\t\tString              hostname = (String) sessionData.get(ComponentIOService\n\t\t\t\t\t.HOSTNAME_KEY);\n\n\t\t\tif ((hostname != null) &&!hostname.isEmpty()) {\n\t\t\t\tList<ComponentConnection> conns = service.getRefObject();\n\n\t\t\t\tif (conns != null) {\n\t\t\t\t\tfor (ComponentConnection conn : conns) {\n\t\t\t\t\t\tboolean moreConnections = removeComponentConnection(conn.getDomain(), conn);\n\n\t\t\t\t\t\tif (!moreConnections) {\n\t\t\t\t\t\t\tremoveRoutings(conn.getDomain());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Nothing to do, let's log this however.\n\t\t\t\t\tlog.finer(\n\t\t\t\t\t\t\t\"Closing XMPPIOService has not yet set ComponentConnection as RefObject: \" +\n\t\t\t\t\t\t\thostname + \", id: \" + service.getUniqueId());\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Stopped service which hasn't sent initial stream open yet\n\t\t\t\tlog.finer(\"Stopped service which hasn't sent initial stream open yet\" + service\n\t\t\t\t\t\t.getUniqueId());\n\t\t\t}\n\n\t\t\tConnectionType type = service.connectionType();\n\n\t\t\tif (type == ConnectionType.connect) {\n\t\t\t\taddWaitingTask(sessionData);\n\n\t\t\t\t// reconnectService(sessionData, connectionDelay);\n\t\t\t}    // end of if (type == ConnectionType.connect)\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic void setProperties(Map<String, Object> properties) throws ConfigurationException {\n\t\tif (properties.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\t\tidentity_type = (String) properties.get(IDENTITY_TYPE_KEY);\n\t\tsuper.setProperties(properties);\n\n\t\tString repo_class = (String) properties.get(EXTCOMP_REPO_CLASS_PROP_KEY);\n\n\t\ttry {\n\t\t\tComponentRepository<CompRepoItem> repo_tmp =\n\t\t\t\t\t(ComponentRepository<CompRepoItem>) Class.forName(repo_class).newInstance();\n\n\t\t\trepo_tmp.setProperties(properties);\n\t\t\tComponentRepository<CompRepoItem> old_repo = repo;\n\t\t\trepo = repo_tmp;\n\t\t\tif (old_repo != null) {\n\t\t\t\trepo.destroy();\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not create items repository instance for class: \" +\n\t\t\t\t\trepo_class, e);\n\t\t}\n\n\t\t// Activate all connections for which parameters are defined in the\n\t\t// repository\n\t\tfor (CompRepoItem repoItem : repo) {\n\t\t\tlog.log(Level.CONFIG, \"Loaded repoItem: {0}\", repoItem.toString());\n\t\t\tif (repoItem.getPort() > 0) {\n\t\t\t\tString[] remote_host   = PORT_IFC_PROP_VAL;\n\t\t\t\tString   remote_domain = repoItem.getRemoteHost();\n\n\t\t\t\tif (repoItem.getRemoteHost() != null) {\n\t\t\t\t\tremote_host = repoItem.getRemoteHost().split(\";\");\n\n\t\t\t\t\t// The first item on the list is always the remote domain name, if\n\t\t\t\t\t// there are\n\t\t\t\t\t// more entries, the rest is just addresses to connect to for this\n\t\t\t\t\t// domain\n\t\t\t\t\tremote_domain = remote_host[0];\n\t\t\t\t\tif (remote_host.length > 1) {\n\n\t\t\t\t\t\t// Remove the first entry as this is domain name, whereas the rest\n\t\t\t\t\t\t// is the\n\t\t\t\t\t\t// address to connect to.\n\t\t\t\t\t\tString[] remote_host_copy = new String[remote_host.length - 1];\n\n\t\t\t\t\t\tSystem.arraycopy(remote_host, 1, remote_host_copy, 0, remote_host_copy\n\t\t\t\t\t\t\t\t.length);\n\t\t\t\t\t\tremote_host = remote_host_copy;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (String r_host : remote_host) {\n\t\t\t\t\tMap<String, Object> port_props = new LinkedHashMap<String, Object>();\n\n\t\t\t\t\tport_props.put(PORT_KEY, repoItem.getPort());\n\t\t\t\t\tif (repoItem.getDomain() != null) {\n\t\t\t\t\t\tport_props.put(PORT_LOCAL_HOST_PROP_KEY, repoItem.getDomain());\n\t\t\t\t\t}\n\t\t\t\t\tport_props.put(PORT_REMOTE_HOST_PROP_KEY, remote_domain);\n\t\t\t\t\tport_props.put(PORT_TYPE_PROP_KEY, repoItem.getConnectionType());\n\t\t\t\t\tport_props.put(PORT_SOCKET_PROP_KEY, SocketType.plain);\n\t\t\t\t\tport_props.put(PORT_IFC_PROP_KEY, new String[] { r_host });\n\t\t\t\t\tport_props.put(MAX_RECONNECTS_PROP_KEY, (int) (120 * MINUTE));\n\t\t\t\t\tport_props.put(REPO_ITEM_KEY, repoItem);\n\t\t\t\t\tlog.config(\"Starting connection: \" + port_props);\n\t\t\t\t\taddWaitingTask(port_props);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\thostnamesToBind = (String[]) properties.get(EXTCOMP_BIND_HOSTNAMES_PROP_KEY);\n\t\tif ((hostnamesToBind.length == 1) && hostnamesToBind[0].isEmpty()) {\n\t\t\thostnamesToBind = null;\n\t\t}\n\t\tlog.config(\"Hostnames to bind: \" + Arrays.toString(hostnamesToBind));\n\t\tprocessors = new LinkedHashMap<String, ExtProcessor>();\n\n\t\tExtProcessor proc = new HandshakeProcessor();\n\n\t\tprocessors.put(proc.getId(), proc);\n\t\tproc = new StreamFeaturesProcessor();\n\t\tprocessors.put(proc.getId(), proc);\n\t\tproc = new StartTLSProcessor();\n\t\tprocessors.put(proc.getId(), proc);\n\t\tproc = new SASLProcessor();\n\t\tprocessors.put(proc.getId(), proc);\n\t\tproc = new BindProcessor();\n\t\tprocessors.put(proc.getId(), proc);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(ComponentIOService service) {}\n\n\t@Override\n\tpublic void unbindHostname(String hostname, ComponentIOService serv) {\n\t\tCopyOnWriteArrayList<ComponentConnection> conns = connections.get(hostname);\n\n\t\tif (conns != null) {\n\t\t\tComponentConnection conn = null;\n\n\t\t\tfor (ComponentConnection componentConnection : conns) {\n\t\t\t\tif (componentConnection.getService() == serv) {\n\t\t\t\t\tconn = componentConnection;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (conn != null) {\n\t\t\t\tboolean moreConnections = removeComponentConnection(conn.getDomain(), conn);\n\n\t\t\t\tif (!moreConnections) {\n\t\t\t\t\tremoveRoutings(conn.getDomain());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean writePacketToSocket(ComponentIOService ios, Packet p) {\n\n\t\t// String xmlns = (String)ios.getSessionData().get(\"xmlns\");\n\t\t// if (xmlns != null) {\n\t\t// p.getElement().setXMLNS(xmlns);\n\t\t// }\n\t\tp.getElement().removeAttribute(\"xmlns\");\n\n\t\treturn super.writePacketToSocket(ios, p);\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(ComponentIOService serv) {}\n\n\t@Override\n\tpublic String xmppStreamOpened(ComponentIOService serv, Map<String, String> attribs) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Stream opened: \" + serv.getRemoteAddress() + \", xmlns: \" + attribs.get(\n\t\t\t\t\t\"xmlns\") + \", type: \" + serv.connectionType().toString() + \", uniqueId=\" + serv\n\t\t\t\t\t.getUniqueId() + \", to=\" + attribs.get(\"to\"));\n\t\t}\n\n\t\tString            s_xmlns = attribs.get(\"xmlns\");\n\t\tString            result  = null;\n\t\tStreamOpenHandler handler = streamOpenHandlers.get(s_xmlns);\n\n\t\tif ((handler == null) || (s_xmlns == null)) {\n\t\t\tlog.finest(\"unknownXMLNSHandler is processing request\");\n\t\t\tresult = unknownXMLNSHandler.streamOpened(serv, attribs, this);\n\t\t} else {\n\t\t\tlog.finest(handler.getClass().getName() + \" is processing request\");\n\t\t\tresult = handler.streamOpened(serv, attribs, this);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Sending back: \" + result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 1000 * 24 * HOUR;\n\t}\n\n\t@Override\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def * 10;\n\t}\n\n\t@Override\n\tprotected ComponentIOService getXMPPIOService(Packet p) {\n\t\tif (p.getStanzaTo() == null) {\n\n\t\t\t// This is a bad packet actually\n\t\t\treturn null;\n\t\t}\n\n\t\tComponentIOService                        result   = null;\n\t\tString                                    hostname = p.getStanzaTo().getDomain();\n\t\tCopyOnWriteArrayList<ComponentConnection> conns    = connections.get(hostname);\n\n\t\t// If there is no connections list for this domain and routings are set to *\n\t\t// we use the first available list.\n\t\tfor (CopyOnWriteArrayList<ComponentConnection> c : connections.values()) {\n\n\t\t\t// Is there a better way to take the first available element?\n\t\t\tif ((c.size() > 0) && \".*\".equals(c.get(0).getService().getRoutings())) {\n\t\t\t\tconns = c;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (conns != null) {\n\n\t\t\t// First we check whether the receiver has sent to us a packet through one\n\t\t\t// of connections as this would be wise to send response on the same connection\n\t\t\tfor (ComponentConnection componentConnection : conns) {\n\t\t\t\tComponentIOService serv = componentConnection.getService();\n\n\t\t\t\tif ((serv != null) && serv.isConnected() && serv.isRecentJID(p.getStanzaTo())) {\n\t\t\t\t\tresult = serv;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now, load balancer selects the best connection to send the packet\n\t\t\tif ((result == null) && (conns.size() > 1)) {\n\t\t\t\tCompRepoItem cmp_repo_item = getCompRepoItem(hostname);\n\n\t\t\t\tif (cmp_repo_item == null) {\n\t\t\t\t\tcmp_repo_item = repo.getItem(p.getStanzaFrom().getDomain());\n\t\t\t\t}\n\n\t\t\t\tLoadBalancerIfc lb = cmp_repo_item.getLoadBalancer();\n\n\t\t\t\tresult = lb.selectConnection(p, conns);\n\t\t\t}\n\n\t\t\t// The above algorithm did not work for some reason. Now trying\n\t\t\t// traditional way to send a packet to the first available and working\n\t\t\t// connection\n\t\t\tif (result == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"LB could not select connection, or there is only one connection, trying traditional way\");\n\t\t\t\t}\n\t\t\t\tfor (ComponentConnection componentConnection : conns) {\n\t\t\t\t\tComponentIOService serv = componentConnection.getService();\n\n\t\t\t\t\tif (serv != null) {\n\t\t\t\t\t\tif (serv.isConnected()) {\n\t\t\t\t\t\t\tresult = serv;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.info(\"Service is not connected for connection for hostname: \" +\n\t\t\t\t\t\t\t\t\thostname);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.info(\"Service is null for connection for hostname: \" + hostname);\n\t\t\t\t\t}\n\t\t\t\t\tif (result != null) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.info(\"No ext connection for hostname: \" + hostname);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Selected connection: \" + result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tprotected ComponentIOService getXMPPIOServiceInstance() {\n\t\treturn new ComponentIOService();\n\t}\n\n\t@Override\n\tprotected boolean isHighThroughput() {\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate synchronized void addComponentConnection(String hostname,\n\t\t\tComponentIOService s) {\n\t\tComponentConnection       conn      = new ComponentConnection(hostname, s);\n\t\tList<ComponentConnection> refObject = s.getRefObject();\n\n\t\tif (refObject == null) {\n\t\t\trefObject = new CopyOnWriteArrayList<ComponentConnection>();\n\t\t}\n\n\t\t// keep all connections sorted, fix for #983\n\t\tsynchronized (refObject) {\n\t\t\trefObject.add(conn);\n\n\t\t\t// workaround to sort CopyOnWriteArrayList\n\t\t\tComponentConnection[] arr_list = refObject.toArray(\n\t\t\t\t\tnew ComponentConnection[refObject.size()]);\n\n\t\t\tArrays.sort(arr_list);\n\t\t\trefObject = new CopyOnWriteArrayList<ComponentConnection>(arr_list);\n\t\t}\n\t\ts.setRefObject(refObject);\n\n\t\tCopyOnWriteArrayList<ComponentConnection> conns = connections.get(hostname);\n\n\t\tif (conns == null) {\n\t\t\tconns = new CopyOnWriteArrayList<ComponentConnection>();\n\t\t}\n\n\t\t// Not very optimal, however this does not happen (should not) very often\n\t\t// and the data collections is optimized for fast object retrieval\n\t\t// by index (round robin balance for example)\n\t\t// keep all connections sorted, fix for #983\n\t\tboolean result;\n\n\t\tsynchronized (conns) {\n\t\t\tresult = conns.add(conn);\n\n\t\t\t// workaround to sort CopyOnWriteArrayList\n\t\t\tComponentConnection[] arr_list = conns.toArray(\n\t\t\t\t\tnew ComponentConnection[conns.size()]);\n\n\t\t\tArrays.sort(arr_list);\n\t\t\tconns = new CopyOnWriteArrayList<ComponentConnection>(arr_list);\n\t\t}\n\t\tconnections.put(hostname, conns);\n\t\tif (result) {\n\t\t\tlog.finer(\"A new component connection added for: \" + hostname);\n\t\t} else {\n\t\t\tlog.fine(\"A new component connection NOT added for: \" + hostname);\n\t\t}\n\t}\n\n\tprivate synchronized boolean removeComponentConnection(String hostname,\n\t\t\tComponentConnection conn) {\n\t\tboolean                                   result = false;\n\t\tCopyOnWriteArrayList<ComponentConnection> conns  = connections.get(hostname);\n\n\t\tif (conns != null) {\n\n\t\t\t// This is slow, however this does not happen (should not) very often\n\t\t\t// and the data collections is optimized for fast object retrieval\n\t\t\t// by index (round robin balance for example)\n\t\t\tboolean removed = conns.remove(conn);\n\n\t\t\tif (removed) {\n\t\t\t\tlog.finer(\"A component connection removed for: \" + hostname);\n\t\t\t} else {\n\t\t\t\tlog.fine(\"A component connection NOT removed for: \" + hostname);\n\t\t\t}\n\t\t\tfor (ComponentConnection compCon : conns) {\n\t\t\t\tComponentIOService serv = compCon.getService();\n\n\t\t\t\tif ((serv != null) && serv.isConnected()) {\n\n\t\t\t\t\t// There is still an active connection for this host\n\t\t\t\t\tresult = true;\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Null or disconnected service for ComponentConnection for host: \" +\n\t\t\t\t\t\t\thostname);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.warning(\"That should not happen, ComponentConnection is not null but \" +\n\t\t\t\t\t\"the collection is: \" + hostname);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate void removeRoutings(String hostname) {\n\t\tString[] routings = new String[] { hostname, \".*@\" + hostname, \".*\\\\.\" + hostname };\n\n\t\tupdateRoutings(routings, false);\n\n\t\t// removeRouting(serv.getRemoteHost());\n\t\t// String addr = (String)sessionData.get(PORT_REMOTE_HOST_PROP_KEY);\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.fine(\"Disonnected from: \" + hostname);\n\t\t}\n\t\tupdateServiceDiscoveryItem(hostname, null, \"XEP-0114 disconnected\", false);\n\t\tremoveComponentDomain(hostname);\n\t}\n\n\tprivate void updateRoutings(String[] routings, boolean add) {\n\t\tif (add) {\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\taddRegexRouting(route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.warning(\"Can not add regex routing '\" + route + \"' : \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\tremoveRegexRouting(route);\n\t\t\t\t\tlog.fine(\"Removed routings: \" + route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.warning(\"Can not remove regex routing '\" + route + \"' : \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlog.finest(\"All regex routings: \" + getRegexRoutings().toString());\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class AuthenticationTimerTask\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\tprivate ComponentIOService serv = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate AuthenticationTimerTask(ComponentIOService serv) {\n\t\t\tthis.serv = serv;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tif (!serv.isAuthenticated()) {\n\t\t\t\tserv.stop();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/ComponentProtocolHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Oct 7, 2009 5:54:56 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ComponentProtocolHandler {\n\n\t/** Field description */\n\tpublic static final String REPO_ITEM_KEY = \"repo-item\";\n\n//public static final String AUTHENTICATED_KEY = \"authenticated\";\n\n\t/** Field description */\n\tpublic static final String EXTCOMP_BIND_HOSTNAMES_PROP_KEY = \"bind-ext-hostnames\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\tvoid authenticated(ComponentIOService serv);\n\n\tvoid authenticationFailed(ComponentIOService serv, Packet packet);\n\n\tvoid bindHostname(String hostname, ComponentIOService serv);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tCompRepoItem getCompRepoItem(String hostname);\n\n\tExtProcessor getProcessor(String string);\n\n\tList<Element> getStreamFeatures(ComponentIOService serv);\n\n\tStreamOpenHandler getStreamOpenHandler(String xmlns);\n\n\t//~--- methods --------------------------------------------------------------\n\n\tString newPacketId(String prefix);\n\n\tvoid unbindHostname(String hostname, ComponentIOService serv);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/ExtProcessor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Oct 1, 2009 8:40:36 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ExtProcessor {\n\tString getId();\n\n\tList<Element> getStreamFeatures(ComponentIOService serv, ComponentProtocolHandler handler);\n\n\t//~--- methods --------------------------------------------------------------\n\n\tboolean process(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results);\n\n\tvoid startProcessing(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/StreamOpenHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Oct 2, 2009 12:15:43 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface StreamOpenHandler {\n\n\t/** Field description */\n\tpublic static final String XMLNS_KEY = \"xmlns\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tString[] getXMLNSs();\n\n\t//~--- methods --------------------------------------------------------------\n\n\tString serviceStarted(ComponentIOService s);\n\n\tString streamOpened(ComponentIOService s, Map<String, String> attribs,\n\t\t\tComponentProtocolHandler handler);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/BindProcessor.java",
    "content": "/*\n * BindProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.ext.ComponentProtocolHandler.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.logging.Logger;\nimport java.util.Queue;\n\n/**\n * Created: Nov 2, 2009 2:37:18 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BindProcessor\n\t\t\t\timplements ExtProcessor {\n\tprivate static final String EL_NAME                 = \"bind\";\n\tprivate static final String[] IQ_BIND_HOSTNAME_PATH = { \"iq\", \"bind\", \"hostname\" };\n\tprivate static final String[] IQ_UNBIND_PATH        = { \"iq\", \"unbind\" };\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log       = Logger.getLogger(BindProcessor.class.getName());\n\tprivate static final String XMLNS     = \"urn:xmpp:component:0\";\n\tprivate static final String ID        = EL_NAME;\n\tprivate static final Element FEATURES = new Element(EL_NAME, new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { XMLNS });\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv,\n\t\t\t\t\tComponentProtocolHandler handler) {\n\t\treturn Arrays.asList(FEATURES);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean process(Packet p, ComponentIOService serv,\n\t\t\t\t\t\t\t\t\t\t\t\t ComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tif (p.isXMLNSStaticStr(Iq.IQ_BIND_PATH, XMLNS)) {\n\t\t\tif ((p.getType() == StanzaType.set) && serv.isAuthenticated()) {\n\t\t\t\tString hostname = p.getElemCDataStaticStr(IQ_BIND_HOSTNAME_PATH);\n\n\t\t\t\thandler.bindHostname(hostname, serv);\n\t\t\t\tresults.offer(Packet.packetInstance(okResult(p.getElement()), null, null));\n\t\t\t} else {\n\t\t\t\tlog.fine(\"Ok result received: \" + p.toString());\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\tif (p.isXMLNSStaticStr(IQ_UNBIND_PATH, XMLNS)) {\n\t\t\tif ((p.getType() == StanzaType.set) && serv.isAuthenticated()) {\n\t\t\t\tString hostname = p.getElemCDataStaticStr(IQ_BIND_HOSTNAME_PATH);\n\n\t\t\t\thandler.unbindHostname(hostname, serv);\n\t\t\t\tresults.offer(Packet.packetInstance(okResult(p.getElement()), null, null));\n\t\t\t} else {\n\t\t\t\tlog.fine(\"Ok result received: \" + p.toString());\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void startProcessing(Packet p, ComponentIOService serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tString[] hostnames =\n\t\t\t(String[]) serv.getSessionData().get(EXTCOMP_BIND_HOSTNAMES_PROP_KEY);\n\n\t\tif (hostnames != null) {\n\t\t\tfor (String host : hostnames) {\n\t\t\t\tif (!host.isEmpty()) {\n\t\t\t\t\tPacket bind_p = Packet.packetInstance(newBindElement(host, handler), null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull);\n\n\t\t\t\t\tlog.info(\"Generating hostname bind packet: \" + bind_p.toString());\n\t\t\t\t\tresults.offer(bind_p);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Empty hostname set for bind...\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Element newBindElement(String host, ComponentProtocolHandler handler) {\n\t\tElement result = new Element(\"iq\", new String[] { \"type\", \"id\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"set\",\n\t\t\t\t\t\thandler.newPacketId(\"bind\") });\n\t\tElement bind = new Element(EL_NAME, new Element[] { new Element(\"hostname\", host) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"xmlns\" }, new String[] { XMLNS });\n\n\t\tresult.addChild(bind);\n\n\t\treturn result;\n\t}\n\n\tprivate Element okResult(Element elem) {\n\t\tElement result = elem.clone();\n\n\t\tresult.setAttribute(\"type\", \"result\");\n\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/ComponentAcceptStreamOpenHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.ext.CompRepoItem;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\nimport tigase.server.ext.StreamOpenHandler;\n\nimport static tigase.server.ext.ComponentProtocolHandler.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 7, 2009 5:51:47 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentAcceptStreamOpenHandler implements StreamOpenHandler {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log =\n\t\tLogger.getLogger(ComponentAcceptStreamOpenHandler.class.getName());\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"jabber:component:accept\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] xmlnss = new String[] { XMLNS };\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getXMLNSs() {\n\t\treturn xmlnss;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String serviceStarted(ComponentIOService serv) {\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect :\n\t\t\t\tCompRepoItem repoItem = (CompRepoItem) serv.getSessionData().get(REPO_ITEM_KEY);\n\t\t\t\tString r_host = (String) serv.getSessionData().get(\"remote-host\");\n\n\t\t\t\t// Send init xmpp stream here\n\t\t\t\tserv.getSessionData().put(ComponentIOService.HOSTNAME_KEY, r_host);\n\n\t\t\t\t// This should be done only, after authentication is completed\n\t\t\t\t// addComponentConnection(hostname, serv);\n\t\t\t\tString data = \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" to='\"\n\t\t\t\t\t+ repoItem.getDomain() + \"'\" + \">\";\n\n\t\t\t\treturn data;\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more/some data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String streamOpened(ComponentIOService serv, Map<String, String> attribs,\n\t\t\tComponentProtocolHandler handler) {\n\t\tserv.getSessionData().put(XMLNS_KEY, XMLNS);\n\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect : {\n\t\t\t\tString id = attribs.get(\"id\");\n\n\t\t\t\tif (id == null) {\n\t\t\t\t\tserv.stop();\n\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tserv.getSessionData().put(ComponentIOService.SESSION_ID_KEY, id);\n\n\t\t\t\tExtProcessor proc = handler.getProcessor(\"handshake\");\n\n\t\t\t\tif (proc != null) {\n\t\t\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\t\t\t\tproc.startProcessing(null, serv, handler, results);\n\n\t\t\t\t\tif (results != null) {\n\t\t\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\t\t\tfor (Packet p : results) {\n\t\t\t\t\t\t\tsb.append(p.getElement().toString());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn sb.toString();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Required processor is not available: 'handshake'\");\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tcase accept : {\n\t\t\t\tString hostname = attribs.get(\"to\");\n\t\t\t\tCompRepoItem repoItem = handler.getCompRepoItem(hostname);\n\n\t\t\t\tif (repoItem != null) {\n\t\t\t\t\tserv.getSessionData().put(REPO_ITEM_KEY, repoItem);\n\t\t\t\t\tserv.getSessionData().put(ComponentIOService.HOSTNAME_KEY, hostname);\n\t\t\t\t\tlog.finest(\"CompRepoItem for \" + hostname + \" set: \" + repoItem.toString());\n\n\t\t\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\t\t\tserv.getSessionData().put(ComponentIOService.SESSION_ID_KEY, id);\n\t\t\t\t\tlog.finest(\"ID generated and set: \" + id);\n\n\t\t\t\t\t// This should be done only, after authentication is completed\n\t\t\t\t\t// addComponentConnection(hostname, serv);\n\t\t\t\t\treturn \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" + hostname\n\t\t\t\t\t\t\t\t+ \"'\" + \" id='\" + id + \"'\" + \">\";\n\t\t\t\t} else {\n\t\t\t\t\treturn \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" + hostname\n\t\t\t\t\t\t\t\t+ \"'>\" + \"<stream:error>\"\n\t\t\t\t\t\t\t\t\t+ \"<host-unknown xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\"\n\t\t\t\t\t\t\t\t\t\t+ \"</stream:error></stream:stream>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/ComponentConnectStreamOpenHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n\n* along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.StreamOpenHandler;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 7, 2009 5:50:34 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentConnectStreamOpenHandler implements StreamOpenHandler {\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"jabber:component:connect\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] xmlnss = new String[] { XMLNS };\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getXMLNSs() {\n\t\treturn xmlnss;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String serviceStarted(ComponentIOService s) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic String streamOpened(ComponentIOService serv, Map<String, String> attribs,\n\t\t\tComponentProtocolHandler handler) {\n\n\t\t// Not sure if this is really used. For sure it is not well documented\n\t\t// and perhaps it is not worth implementing, unless someone requests it\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/HandshakeProcessor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.ext.CompRepoItem;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\n\nimport tigase.util.Algorithms;\n\nimport tigase.xml.Element;\n\nimport static tigase.server.ext.ComponentProtocolHandler.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.security.NoSuchAlgorithmException;\n\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 21, 2009 1:58:56 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class HandshakeProcessor implements ExtProcessor {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(HandshakeProcessor.class.getName());\n\tprivate static final String EL_NAME = \"handshake\";\n\tprivate static final String ID = EL_NAME;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler) {\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean process(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results) {\n\t\tboolean result = false;\n\n\t\tif (p.getElemName() == EL_NAME) {\n\t\t\tresult = true;\n\n\t\t\tswitch (serv.connectionType()) {\n\t\t\t\tcase connect : {\n\t\t\t\t\tString data = p.getElemCData();\n\n\t\t\t\t\tif (data == null) {\n\n\t\t\t\t\t\t// According to XEP-0114 the authentication was successful\n\t\t\t\t\t\thandler.authenticated(serv);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.warning(\"Incorrect packet received: \" + p);\n\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase accept : {\n\t\t\t\t\tString digest = p.getElemCData();\n\t\t\t\t\tCompRepoItem comp =\n\t\t\t\t\t\t(CompRepoItem) serv.getSessionData().get(ComponentProtocolHandler.REPO_ITEM_KEY);\n\t\t\t\t\tString id = (String) serv.getSessionData().get(ComponentIOService.SESSION_ID_KEY);\n\t\t\t\t\tString secret = comp.getAuthPasswd();\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString loc_digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Calculating digest: id=\" + id + \", secret=\" + secret + \", digest=\"\n\t\t\t\t\t\t\t\t\t+ loc_digest);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Password digest matches, authentication OK\n\t\t\t\t\t\tif ((digest != null) && digest.equals(loc_digest)) {\n\t\t\t\t\t\t\thandler.authenticated(serv);\n\n\t\t\t\t\t\t\tPacket resp = Packet.packetInstance(new Element(\"handshake\"), null, null);\n\n\t\t\t\t\t\t\tresults.offer(resp);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.info(\"Handshaking passwords don't match, disconnecting...\");\n\t\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"Handshaking error.\", e);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault :\n\n\t\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\t\tbreak;\n\t\t\t}    // end of switch (service.connectionType())\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void startProcessing(Packet p, ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tString secret = ((CompRepoItem) serv.getSessionData().get(REPO_ITEM_KEY)).getAuthPasswd();\n\n\t\ttry {\n\t\t\tString id = (String) serv.getSessionData().get(ComponentIOService.SESSION_ID_KEY);\n\t\t\tString digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\t\t\tPacket result = Packet.packetInstance(new Element(EL_NAME, digest), null, null);\n\n\t\t\tresults.offer(result);\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not generate digest for pass phrase.\", e);\n\t\t\tserv.stop();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/JabberClientStreamOpenHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ext.CompRepoItem;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.StreamOpenHandler;\n\nimport tigase.xml.Element;\n\nimport static tigase.server.ext.ComponentProtocolHandler.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 7, 2009 3:17:09 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberClientStreamOpenHandler implements StreamOpenHandler {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log =\n\t\tLogger.getLogger(JabberClientStreamOpenHandler.class.getName());\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"jabber:client\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] xmlnss = new String[] { XMLNS };\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String[] getXMLNSs() {\n\t\treturn xmlnss;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String serviceStarted(ComponentIOService serv) {\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect :\n\t\t\t\tCompRepoItem repoItem = (CompRepoItem) serv.getSessionData().get(REPO_ITEM_KEY);\n\n\t\t\t\tString r_host = (String) serv.getSessionData().get(\"remote-host\");\n\t\t\t\t// Send init xmpp stream here\n\t\t\t\tserv.getSessionData().put(ComponentIOService.HOSTNAME_KEY, r_host);\n\n\t\t\t\t// This should be done only, after authentication is completed\n\t\t\t\t// addComponentConnection(hostname, serv);\n\t\t\t\tString data = \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" version ='1.0'\"\n\t\t\t\t\t+ \" xml:lang='en'\" + \" from='\" + repoItem.getDomain() + \"'\" + \" to ='\"\n\t\t\t\t\t+ r_host + \"'\" + \">\";\n\n\t\t\t\treturn data;\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more/some data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String streamOpened(ComponentIOService serv, Map<String, String> attribs,\n\t\t\tComponentProtocolHandler handler) {\n\t\tserv.getSessionData().put(XMLNS_KEY, XMLNS);\n\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect : {\n\t\t\t\tString id = attribs.get(\"id\");\n\n\t\t\t\tif (id != null) {\n\t\t\t\t\tserv.getSessionData().put(ComponentIOService.SESSION_ID_KEY, id);\n\t\t\t\t}\n\n\t\t\t\t// Do nothing, stream features should come first\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tcase accept : {\n\t\t\t\tString from_hostname = attribs.get(\"from\");\n\t\t\t\tString to_hostname = attribs.get(\"to\");\n\t\t\t\tCompRepoItem repoItem = handler.getCompRepoItem(from_hostname);\n\n\t\t\t\tserv.getSessionData().put(REPO_ITEM_KEY, repoItem);\n\t\t\t\tserv.getSessionData().put(ComponentIOService.HOSTNAME_KEY, from_hostname);\n\n\t\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\t\tserv.getSessionData().put(ComponentIOService.SESSION_ID_KEY, id);\n\n\t\t\t\t// This should be done only, after authentication is completed\n\t\t\t\t// addComponentConnection(hostname, serv);\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\tsb.append(\"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" version ='1.0'\"\n\t\t\t\t\t\t\t+ \" xml:lang='en'\" + \" from='\" + to_hostname + \"'\" + \" to='\" + from_hostname\n\t\t\t\t\t\t\t\t+ \"'\" + \" id='\" + id + \"'\" + \"><stream:features>\");\n\n\t\t\t\tList<Element> features = handler.getStreamFeatures(serv);\n\n\t\t\t\tfor (Element element : features) {\n\t\t\t\t\tsb.append(element.toString());\n\t\t\t\t}\n\n\t\t\t\tsb.append(\"</stream:features>\");\n\n\t\t\t\treturn sb.toString();\n\t\t\t}\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/SASLProcessor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.ext.CompRepoItem;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\n\nimport tigase.util.Base64;\n\nimport tigase.xml.Element;\n\nimport static tigase.server.ext.ComponentProtocolHandler.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 31, 2009 11:06:57 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SASLProcessor implements ExtProcessor {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(SASLProcessor.class.getName());\n\tprivate static final String ID = \"sasl\";\n\tprivate static final String XMLNS = \"urn:ietf:params:xml:ns:xmpp-sasl\";\n\tprivate static final Element FEATURES = new Element(\"mechanisms\",\n\t\tnew Element[] { new Element(\"mechanism\", \"PLAIN\") }, new String[] { \"xmlns\" },\n\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-sasl\" });\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler) {\n\t\tif (serv.getSessionData().get(ID) != null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn Arrays.asList(FEATURES);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean process(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results) {\n\t\tif (p.isElement(\"auth\", XMLNS)) {\n\t\t\tString cdata = p.getElemCData();\n\t\t\tString[] credentials = decodeMessage(cdata);\n\n\t\t\tlog.fine(\"External credentials: \" + Arrays.toString(credentials));\n\n\t\t\tCompRepoItem repo_item = handler.getCompRepoItem(credentials[1]);\n\t\t\tboolean auth_ok = false;\n\n\t\t\tif (repo_item != null) {\n\t\t\t\tString local_password = repo_item.getAuthPasswd();\n\n\t\t\t\tif (local_password.equals(credentials[2])) {\n\t\t\t\t\tauth_ok = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (auth_ok) {\n\t\t\t\tElement success = new Element(\"success\", new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { XMLNS });\n\n\t\t\t\tresults.offer(Packet.packetInstance(success, null, null));\n\t\t\t\thandler.authenticated(serv);\n\t\t\t} else {\n\t\t\t\tElement failure = new Element(\"failure\",\n\t\t\t\t\tnew Element[] { new Element(\"not-authorized\") }, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { XMLNS });\n\n\t\t\t\thandler.authenticationFailed(serv, Packet.packetInstance(failure, null, null));\n\t\t\t}\n\n\t\t\tserv.getSessionData().put(ID, ID);\n\n\t\t\treturn true;\n\t\t}\n\n\t\tif (p.isElement(\"success\", XMLNS)) {\n\t\t\thandler.authenticated(serv);\n\t\t\tserv.getSessionData().put(ID, ID);\n\n\t\t\treturn true;\n\t\t}\n\n\t\tif (p.isElement(\"abort\", XMLNS)) {\n\t\t\tserv.stop();\n\n\t\t\treturn true;\n\t\t}\n\n\t\tif (p.isElement(\"failure\", XMLNS)) {\n\t\t\tserv.stop();\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void startProcessing(Packet p, ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tCompRepoItem comp_item = (CompRepoItem) serv.getSessionData().get(REPO_ITEM_KEY);\n\t\tString domain = comp_item.getDomain();\n\t\tString secret = comp_item.getAuthPasswd();\n\t\tString challenge = encodeMessage(null, domain, secret);\n\n//  <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'\n//       mechanism='PLAIN'>AGp1bGlldAByMG0zMG15cjBtMzA=</auth>\n\t\tElement auth = new Element(\"auth\", challenge, new String[] { \"xmlns\", \"mechanism\" },\n\t\t\tnew String[] { XMLNS,\n\t\t\t\t\"PLAIN\" });\n\n\t\tresults.offer(Packet.packetInstance(auth, null, null));\n\t}\n\n\tprivate String[] decodeMessage(String input) {\n\n\t\t// Container for authoriz, user_id and password\n\t\tString[] result = new String[3];\n\t\tbyte[] challenge = Base64.decode(input);\n\t\tint auth_idx = 0;\n\n\t\twhile ((challenge[auth_idx] != 0) && (auth_idx < challenge.length)) {\n\t\t\t++auth_idx;\n\t\t}\n\n\t\tString authoriz = new String(challenge, 0, auth_idx);\n\t\tint user_idx = ++auth_idx;\n\n\t\twhile ((challenge[user_idx] != 0) && (user_idx < challenge.length)) {\n\t\t\t++user_idx;\n\t\t}\n\n\t\tString user_id = new String(challenge, auth_idx, user_idx - auth_idx);\n\n\t\t++user_idx;\n\n\t\tString passwd = new String(challenge, user_idx, challenge.length - user_idx);\n\n\t\tresult[0] = ((authoriz.length() > 0) ? authoriz : null);\n\t\tresult[1] = ((user_id.length() > 0) ? user_id : null);\n\t\tresult[2] = ((passwd.length() > 0) ? passwd : null);\n\n\t\treturn result;\n\t}\n\n\tprivate String encodeMessage(String authoriz, String user_id, String password) {\n\t\tint authoriz_size = ((authoriz != null) ? authoriz.getBytes().length : 0);\n\t\tint user_id_size = ((user_id != null) ? user_id.getBytes().length : 0);\n\t\tint password_size = ((password != null) ? password.getBytes().length : 0);\n\n\t\t// 2 NUL U+0000 characters\n\t\tint size = 2;\n\n\t\tsize += authoriz_size + user_id_size + password_size;\n\n\t\tbyte[] result = new byte[size];\n\n\t\tif ((authoriz != null) && (authoriz_size > 0)) {\n\t\t\tSystem.arraycopy(authoriz.getBytes(), 0, result, 0, authoriz_size);\n\t\t}\n\n\t\tresult[authoriz_size] = 0;\n\n\t\tif ((user_id != null) && (user_id_size > 0)) {\n\t\t\tSystem.arraycopy(user_id.getBytes(), 0, result, authoriz_size + 1, user_id_size);\n\t\t}\n\n\t\tresult[authoriz_size + 1 + user_id_size] = 0;\n\n\t\tif ((password != null) && (password_size > 0)) {\n\t\t\tSystem.arraycopy(password.getBytes(), 0, result, authoriz_size + 1 + user_id_size + 1,\n\t\t\t\t\tpassword_size);\n\t\t}\n\n\t\treturn Base64.encode(result);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/StartTLSProcessor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\nimport tigase.server.ext.StreamOpenHandler;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 31, 2009 4:54:39 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StartTLSProcessor implements ExtProcessor {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(StartTLSProcessor.class.getName());\n\tprivate static final String EL_NAME = \"starttls\";\n\tprivate static final String ID = EL_NAME;\n\tprivate static final Element FEATURES = new Element(EL_NAME,\n\t\tnew Element[] { new Element(\"required\") }, new String[] { \"xmlns\" },\n\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-tls\" });\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler) {\n\t\tif (serv.getSessionData().get(ID) != null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn Arrays.asList(FEATURES);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean process(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results) {\n\t\tif (p.getElemName() == EL_NAME) {\n\t\t\tserv.getSessionData().put(ID, ID);\n\n\t\t\tString data = \"<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\";\n\n\t\t\tinitTLS(serv, data, false);\n\t\t\tlog.fine(\"Started server side TLS.\");\n\n\t\t\treturn true;\n\t\t}\n\n\t\tif (p.getElemName() == \"proceed\") {\n\t\t\tserv.getSessionData().put(ID, ID);\n\t\t\tinitTLS(serv, null, true);\n\t\t\tlog.fine(\"Started client side TLS.\");\n\n\t\t\tStreamOpenHandler soh = handler.getStreamOpenHandler(\"jabber:client\");\n\t\t\tString data = soh.serviceStarted(serv);\n\n\t\t\tserv.xmppStreamOpen(data);\n\t\t\tlog.fine(\"New stream opened: \" + data);\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void startProcessing(Packet p, ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tresults.offer(Packet.packetInstance(new Element(EL_NAME, new String[] { \"xmlns\" },\n\t\t\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-tls\" }), null, null));\n\t}\n\n\tprivate void initTLS(ComponentIOService serv, String data, boolean client) {\n\t\ttry {\n\t\t\tserv.writeRawData(data);\n\t\t\tThread.sleep(10);\n\n\t\t\twhile (serv.waitingToSend()) {\n\t\t\t\tserv.writeRawData(null);\n\t\t\t\tThread.sleep(10);\n\t\t\t}\n\n\t\t\tserv.startTLS(client, false, false);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"TLS mode start failed: \" + e.getMessage());\n\t\t\tserv.forceStop();\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/StreamFeaturesProcessor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.ExtProcessor;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 31, 2009 3:51:09 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StreamFeaturesProcessor implements ExtProcessor {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(StreamFeaturesProcessor.class.getName());\n\tprivate static final String EL_NAME = \"stream:features\";\n\tprivate static final String ID = EL_NAME;\n\tprivate static final String STARTTLS = \"starttls\";\n\tprivate static final String SASL = \"sasl\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler) {\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean process(Packet p, ComponentIOService serv, ComponentProtocolHandler handler,\n\t\t\tQueue<Packet> results) {\n\t\tif (p.isElement(\"features\", \"http://etherx.jabber.org/streams\")) {\n\t\t\tlog.fine(\"Received stream features: \" + p.toString());\n\n\t\t\tElement elem = p.getElement();\n\n\t\t\tif (elem.getChild(STARTTLS) != null) {\n\t\t\t\tExtProcessor proc = handler.getProcessor(STARTTLS);\n\n\t\t\t\tproc.startProcessing(null, serv, handler, results);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (elem.getChild(\"mechanisms\") != null) {\n\t\t\t\tExtProcessor proc = handler.getProcessor(SASL);\n\n\t\t\t\tproc.startProcessing(null, serv, handler, results);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void startProcessing(Packet p, ComponentIOService serv,\n\t\t\tComponentProtocolHandler handler, Queue<Packet> results) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/handlers/UnknownXMLNSStreamOpenHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ext.handlers;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.ext.ComponentProtocolHandler;\nimport tigase.server.ext.StreamOpenHandler;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 2, 2009 5:18:44 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UnknownXMLNSStreamOpenHandler implements StreamOpenHandler {\n\n\t@Override\n\tpublic String[] getXMLNSs() {\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String serviceStarted(ComponentIOService s) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic String streamOpened(ComponentIOService serv, Map<String, String> attribs,\n\t\t\tComponentProtocolHandler handler) {\n\t\tString xmlns = attribs.get(\"xmlns\");\n\t\tStringBuilder sb =\n\t\t\tnew StringBuilder(\"<stream:stream xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t+ \" version='1.0'\" + \" xml:lang='en'\");\n\n\t\tif (xmlns != null) {\n\t\t\tsb.append(\" xmlns='\").append(xmlns).append(\"'\");\n\t\t}\n\n\t\tif (attribs.get(\"to\") != null) {\n\t\t\tsb.append(\" from='\").append(attribs.get(\"to\")).append(\"'\");\n\t\t}\n\n\t\tif (attribs.get(\"from\") != null) {\n\t\t\tsb.append(\" to='\").append(attribs.get(\"from\")).append(\"'\");\n\t\t}\n\n\t\tif (attribs.get(\"id\") != null) {\n\t\t\tsb.append(\" id='\").append(attribs.get(\"id\")).append(\"'\");\n\t\t}\n\n\t\tsb.append('>');\n\t\tsb.append(\"<stream:error>\"\n\t\t\t\t+ \"<invalid-namespace xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\"\n\t\t\t\t\t+ \"</stream:error>\" + \"</stream:stream>\");\n\n\t\treturn sb.toString();\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/lb/LoadBalancerIfc.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\npackage tigase.server.ext.lb;\n\nimport java.util.List;\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\n\n/**\n * @author Artur Hefczyc\n * Created Jul 9, 2011\n */\npublic interface LoadBalancerIfc {\n\n\t/**\n\t * @param p\n\t * @param conns\n\t * \n\t */\n\tComponentIOService selectConnection(Packet p, List<ComponentConnection> conns);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/lb/ReceiverBareJidLB.java",
    "content": "/*\n * ReceiverBareJidLB.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.ext.lb;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\n\n/**\n * @author Artur Hefczyc Created Jul 9, 2011\n */\npublic class ReceiverBareJidLB\n\t\t\t\timplements LoadBalancerIfc {\n\t@Override\n\tpublic ComponentIOService selectConnection(Packet p, List<ComponentConnection> conns) {\n\t\tComponentIOService  result = null;\n\t\tint                 idx = Math.abs(p.getStanzaTo().getBareJID().hashCode() % conns\n\t\t\t\t.size());\n\t\tComponentConnection conn   = conns.get(idx);\n\n\t\tif ((conn.getService() != null) && conn.getService().isConnected()) {\n\t\t\tresult = conn.getService();\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/lb/ReceiverFullJidLB.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\npackage tigase.server.ext.lb;\n\nimport java.util.List;\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\n\n/**\n * @author Artur Hefczyc\n * Created Jul 9, 2011\n */\npublic class ReceiverFullJidLB implements LoadBalancerIfc {\n\n\t@Override\n\tpublic ComponentIOService selectConnection(Packet p, List<ComponentConnection> conns) {\n\t\tComponentIOService result = null;\n\t\tint idx = Math.abs(p.getStanzaTo().hashCode() % conns.size());\n\t\tComponentConnection conn = conns.get(idx);\n\t\tif (conn.getService() != null && conn.getService().isConnected()) {\n\t\t\tresult = conn.getService();\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/lb/SenderBareJidLB.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\npackage tigase.server.ext.lb;\n\nimport java.util.List;\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\n\n/**\n * @author Artur Hefczyc\n * Created Jul 9, 2011\n */\npublic class SenderBareJidLB implements LoadBalancerIfc {\n\n\t@Override\n\tpublic ComponentIOService selectConnection(Packet p, List<ComponentConnection> conns) {\n\t\tComponentIOService result = null;\n\t\tint idx = Math.abs(p.getStanzaFrom().getBareJID().hashCode() % conns.size());\n\t\tComponentConnection conn = conns.get(idx);\n\t\tif (conn.getService() != null && conn.getService().isConnected()) {\n\t\t\tresult = conn.getService();\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ext/lb/SenderFullJidLB.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n *\n */\npackage tigase.server.ext.lb;\n\nimport java.util.List;\n\nimport tigase.server.Packet;\nimport tigase.server.ext.ComponentConnection;\nimport tigase.server.ext.ComponentIOService;\n\n/**\n * @author Artur Hefczyc\n * Created Jul 9, 2011\n */\npublic class SenderFullJidLB implements LoadBalancerIfc {\n\n\t@Override\n\tpublic ComponentIOService selectConnection(Packet p, List<ComponentConnection> conns) {\n\t\tComponentIOService result = null;\n\t\tint idx = Math.abs(p.getStanzaFrom().hashCode() % conns.size());\n\t\tComponentConnection conn = conns.get(idx);\n\t\tif (conn.getService() != null && conn.getService().isConnected()) {\n\t\t\tresult = conn.getService();\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/filters/PacketCounter.java",
    "content": "/*\n * PacketCounter.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.filters;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.PacketFilterIfc;\nimport tigase.server.QueueType;\n\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map.Entry;\n\n/**\n * Created: Jun 8, 2009 1:47:31 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PacketCounter\n\t\t\t\timplements PacketFilterIfc {\n\tprivate long                               clusterCounter = 0;\n\tprivate long[]                             iqCounters     = new long[1];\n\tprivate int                                lastNodeNo     = -1;\n\tprivate Logger                             log = Logger.getLogger(this.getClass()\n\t\t\t.getName());\n\tprivate long                               msgCounter     = 0;\n\tprivate String                             name           = null;\n\tprivate long                               otherCounter   = 0;\n\tprivate long                               presCounter    = 0;\n\tprivate QueueType                          qType          = null;\n\tprivate ConcurrentHashMap<String, Integer> iqCounterIdx = new ConcurrentHashMap<String,\n\t\t\tInteger>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Packet filter(Packet packet) {\n\t\tif (packet.getElemName() == \"message\") {\n\t\t\t++msgCounter;\n\n\t\t\treturn packet;\n\t\t}\n\t\tif (packet.getElemName() == \"presence\") {\n\t\t\t++presCounter;\n\n\t\t\treturn packet;\n\t\t}\n\t\tif (packet.getElemName() == \"cluster\") {\n\t\t\t++clusterCounter;\n\n\t\t\treturn packet;\n\t\t}\n\t\t++otherCounter;\n\t\tif (packet.getElemName() == \"iq\") {\n\t\t\tString xmlns = ((Iq) packet).getIQXMLNS();\n\n\t\t\tincIQCounter((xmlns != null)\n\t\t\t\t\t? xmlns\n\t\t\t\t\t: ((Iq) packet).getIQChildName());\n\t\t}\n\n\t\treturn packet;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(String name, QueueType qType) {\n\t\tthis.name  = name;\n\t\tthis.qType = qType;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tlist.add(name, qType.name() + \" processed messages\", msgCounter, Level.FINER);\n\t\tlist.add(name, qType.name() + \" processed presences\", presCounter, Level.FINER);\n\t\tlist.add(name, qType.name() + \" processed cluster\", clusterCounter, Level.FINER);\n\t\tlist.add(name, qType.name() + \" processed other\", otherCounter, Level.FINER);\n\t\tlist.add(name, qType.name() + \" processed IQ no XMLNS\", iqCounters[0], Level.FINER);\n\n\t\tlong iqs = iqCounters[0];\n\n\t\tfor (Entry<String, Integer> iqCounter : iqCounterIdx.entrySet()) {\n\t\t\tlist.add(name, qType.name() + \" processed IQ \" + iqCounter.getKey(),\n\t\t\t\t\tiqCounters[iqCounter.getValue()], Level.FINER);\n\t\t\tiqs += iqCounters[iqCounter.getValue()];\n\t\t}\n\t\tlist.add(name, qType.name() + \" processed total IQ\", iqs, Level.FINER);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate synchronized void incIQCounter(String xmlns) {\n\t\tif (xmlns == null) {\n\t\t\t++iqCounters[0];\n\t\t} else {\n\t\t\tInteger idx = iqCounterIdx.get(xmlns);\n\n\t\t\tif (idx == null) {\n\t\t\t\tiqCounters = Arrays.copyOf(iqCounters, iqCounters.length + 1);\n\t\t\t\tidx        = iqCounters.length - 1;\n\t\t\t\tiqCounterIdx.put(xmlns, idx);\n\t\t\t}\n\t\t\t++iqCounters[idx];\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/04/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/monitor/MonitorComponent.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.monitor;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.Map;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\n\nimport tigase.conf.ConfigurationException;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jun 17, 2010 10:14:23 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated Use {@link  tigase.monitor.MonitorComponent} instead.\n */\n@Deprecated\npublic class MonitorComponent extends AbstractMessageReceiver {\n\tprivate static final Logger log = Logger.getLogger(MonitorComponent.class.getName());\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"generic\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Monitor\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/monitor/MonitorPluginIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.monitor;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Jun 17, 2010 11:59:13 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface MonitorPluginIfc {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void check10Secs(Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void check1Day(Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void check1Hour(Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void check1Min(Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String commandsHelp();\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void destroy();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getState();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param command\n\t *\n\t * \n\t */\n\tpublic boolean isMonitorCommand(String command);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param command\n\t *\n\t * \n\t */\n\tpublic String runCommand(String[] command);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tvoid getStatistics(StatisticsList list);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/monitor/MonitorRuntime.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.monitor;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.sys.CPULoadListener;\nimport tigase.sys.MemoryChangeListener;\nimport tigase.sys.OnlineJidsReporter;\nimport tigase.sys.ShutdownHook;\nimport tigase.sys.TigaseRuntime;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.ThreadInfo;\nimport java.lang.management.ThreadMXBean;\nimport java.util.LinkedHashSet;\nimport java.util.LinkedList;\nimport java.util.logging.Logger;\n\n/**\n * Created: Feb 19, 2009 12:31:14 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MonitorRuntime extends TigaseRuntime {\n\n  /**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n\t\t\t\t\tLogger.getLogger(MonitorRuntime.class.getName());\n\n\tprivate static MonitorRuntime runtime = null;\n\tprivate final LinkedHashSet<ShutdownHook> shutdownHooks =\n\t\t\t\t\tnew LinkedHashSet<ShutdownHook>();\n\tprivate final LinkedList<OnlineJidsReporter> onlineJidsReporters =\n\t\t\t\t\tnew LinkedList<OnlineJidsReporter>();\n\n\tprivate MonitorRuntime() {\n\t\tsuper();\n\t\tRuntime.getRuntime().addShutdownHook(new MainShutdownThread());\n\t}\n\t\n\tpublic static MonitorRuntime getMonitorRuntime() {\n\t\tif (runtime == null) {\n\t\t\truntime = new MonitorRuntime();\n\t\t}\n\t\treturn runtime;\n\t}\n\n\t@Override\n\tpublic synchronized void addShutdownHook(ShutdownHook hook) {\n\t\tshutdownHooks.add(hook);\n\t}\n\n\t@Override\n\tpublic synchronized void addMemoryChangeListener(MemoryChangeListener memListener) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic synchronized void addCPULoadListener(CPULoadListener cpuListener) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic synchronized void addOnlineJidsReporter(OnlineJidsReporter onlineReporter) {\n\t\tonlineJidsReporters.add(onlineReporter);\n\t}\n\n\t@Override\n\tpublic boolean hasCompleteJidsInfo() {\n\t\tif (onlineJidsReporters.size() == 1) {\n\t\t\treturn onlineJidsReporters.getFirst().hasCompleteJidsInfo();\n\t\t} else {\n\t\t\tfor (OnlineJidsReporter onlineJidsReporter : onlineJidsReporters) {\n\t\t\t\tif (!onlineJidsReporter.hasCompleteJidsInfo()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isJidOnline(JID jid) {\n\t\tif (onlineJidsReporters.size() == 1) {\n\t\t\treturn onlineJidsReporters.getFirst().containsJid(jid.getBareJID());\n\t\t} else {\n\t\t\tfor (OnlineJidsReporter onlineJidsReporter : onlineJidsReporters) {\n\t\t\t\tif (onlineJidsReporter.containsJid(jid.getBareJID())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isJidOnlineLocally(BareJID jid) {\n\t\tif (onlineJidsReporters.size() == 1) {\n\t\t\treturn onlineJidsReporters.getFirst().containsJidLocally(jid);\n\t\t} else {\n\t\t\tfor (OnlineJidsReporter onlineJidsReporter : onlineJidsReporters) {\n\t\t\t\tif (onlineJidsReporter.containsJidLocally(jid)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t@Override\n\tpublic boolean isJidOnlineLocally(JID jid) {\n\t\tif (onlineJidsReporters.size() == 1) {\n\t\t\treturn onlineJidsReporters.getFirst().containsJidLocally(jid);\n\t\t} else {\n\t\t\tfor (OnlineJidsReporter onlineJidsReporter : onlineJidsReporters) {\n\t\t\t\tif (onlineJidsReporter.containsJidLocally(jid)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\t\n\t\n\t@Override\n\tpublic JID[] getConnectionIdsForJid(JID jid) {\n\t\tif (onlineJidsReporters.size() == 1) {\n\t\t\treturn onlineJidsReporters.getFirst().getConnectionIdsForJid(jid.getBareJID());\n\t\t} else {\n\t\t\tfor (OnlineJidsReporter onlineJidsReporter : onlineJidsReporters) {\n\t\t\t\tJID[] connIds = onlineJidsReporter.getConnectionIdsForJid(jid.getBareJID());\n\t\t\t\tif (connIds != null) {\n\t\t\t\t\treturn connIds;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate class ShutdownHandlerThread extends Thread {\n\n\t\tprivate ShutdownHook hook = null;\n\t\tprivate String result = null;\n\n\t\tpublic ShutdownHandlerThread(ThreadGroup group, ShutdownHook hook) {\n\t\t\tsuper(group, hook.getName());\n\t\t\tthis.hook = hook;\n\t\t\tsetDaemon(true);\n\t\t}\n\n\t\t@Override\n\t\tpublic void run () {\n\t\t\tresult = hook.shutdown();\n\t\t}\n\n\t\tpublic String getResultMessage() {\n\t\t\treturn result;\n\t\t}\n\n\t}\n\t\n\tprivate class MainShutdownThread extends Thread {\n\n\t\tpublic MainShutdownThread() {\n\t\t\tsuper();\n\t\t\tsetName(\"MainShutdownThread\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tSystem.out.println(\"ShutdownThread started...\");\n\t\t\tlog.warning(\"ShutdownThread started...\");\n\t\t\tLinkedList<ShutdownHandlerThread> thlist = \n\t\t\t\t\t\t\tnew LinkedList<ShutdownHandlerThread>();\n\t\t\tThreadGroup threads =\n\t\t\t\t\t\t\tnew ThreadGroup(Thread.currentThread().getThreadGroup(),\n\t\t\t\t\t\t\t\"Tigase Shutdown\");\n\t\t\tfor (ShutdownHook shutdownHook : shutdownHooks) {\n\t\t\t\tShutdownHandlerThread thr = \n\t\t\t\t\t\t\t\tnew ShutdownHandlerThread(threads, shutdownHook);\n\t\t\t\tthr.start();\n\t\t\t\tthlist.add(thr);\n\t\t\t}\n\t\t\t// We allow for max 10 secs for the shutdown code to run...\n\t\t\tlong shutdownStart = System.currentTimeMillis();\n\t\t\twhile (threads.activeCount() > 0 &&\n\t\t\t\t\t\t\t(System.currentTimeMillis() - shutdownStart) < 10000) {\n\t\t\t\ttry {\n\t\t\t\t\tsleep(100);\n\t\t\t\t} catch (Exception e) {\t}\n\t\t\t}\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tfor (ShutdownHandlerThread shutdownHandlerThread : thlist) {\n\t\t\t\tif (shutdownHandlerThread.getResultMessage() != null) {\n\t\t\t\t\tsb.append(shutdownHandlerThread.getResultMessage());\n\t\t\t\t}\n\t\t\t}\n\t\t\tThreadMXBean thBean = ManagementFactory.getThreadMXBean();\n\t\t\tsb.append(\"\\nTotal number of threads: \" + thBean.getThreadCount()).append('\\n');\n\t\t\tlong[] tids = thBean.findDeadlockedThreads();\n\t\t\tif (tids != null && tids.length > 0) {\n\t\t\t\tsb.append(\"Locked threads:\\n\");\n\t\t\t\tThreadInfo[] lockedThreads = thBean.getThreadInfo(tids);\n\t\t\t\tfor (ThreadInfo threadInfo : lockedThreads) {\n\t\t\t\tsb.append(\"Locked thread \" + threadInfo.getThreadName() + \" on \" +\n\t\t\t\t\t\t\t\tthreadInfo.getLockInfo().toString()).append('\\n');\n\t\t\t\t\tStackTraceElement[] ste = threadInfo.getStackTrace();\n\t\t\t\t\tfor (StackTraceElement stackTraceElement : ste) {\n\t\t\t\t\t\tsb.append(stackTraceElement.toString()).append('\\n');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsb.append(\"No locked threads.\\n\");\n\t\t\t}\n\t\t\tif (sb.length() > 0) {\n\t\t\t\tSystem.out.println(sb.toString());\n\t\t\t\tlog.warning(sb.toString());\n\t\t\t}\n\t\t\tSystem.out.println(\"ShutdownThread finished...\");\n\t\t\tlog.warning(\"ShutdownThread finished...\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/package-info.java",
    "content": "/**\n * The main package with top level API for server side components.\n */\npackage tigase.server;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/script/AbstractScriptCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.script;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport tigase.stats.StatisticHolderImpl;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jan 2, 2009 2:32:17 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class AbstractScriptCommand extends StatisticHolderImpl implements CommandIfc {\n\n\t/** Field description */\n\tpublic static final Map<String, String> lineCommentStart = new LinkedHashMap<String, String>(20);\n\n\t//~--- static initializers --------------------------------------------------\n\n\tstatic {\n\t\tlineCommentStart.put(\"groovy\", \"//\");\n\t\tlineCommentStart.put(\"scala\", \"//\");\n\t\tlineCommentStart.put(\"python\", \"#\");\n\t\tlineCommentStart.put(\"py\", \"#\");\n\t\tlineCommentStart.put(\"js\", \"//\");\n\t\tlineCommentStart.put(\"ruby\", \"#\");\n\t\tlineCommentStart.put(\"rb\", \"#\");\n\t\tlineCommentStart.put(\"perl\", \"#\");\n\t\tlineCommentStart.put(\"pl\", \"#\");\n\t\tlineCommentStart.put(\"awk\", \"//\");\n\t\tlineCommentStart.put(\"lisp\", \";\");\n\t\tlineCommentStart.put(\"el\", \";\");\n\t\tlineCommentStart.put(\"cl\", \";\");\n\t\tlineCommentStart.put(\"gc1\", \";\");\n\t\tlineCommentStart.put(\"gc3\", \";\");\n\t\tlineCommentStart.put(\"java\", \"//\");\n\t}\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String commandId = null;\n\tprivate String description = null;\n\tprivate String group = null;\n\tprivate boolean adminOnly = true;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getCommandId() {\n\t\treturn this.commandId;\n\t}\n\n\t@Override\n\tpublic String getDescription() {\n\t\treturn this.description;\n\t}\n\n\t@Override\n\tpublic String getGroup() {\n\t\treturn this.group;\n\t}\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(String id, String description, String group) {\n\t\tthis.commandId = id;\n\t\tthis.description = description;\n\t\tthis.group = group;\n\n\t\tsetStatisticsPrefix(\"adhoc-command/\" + id);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isAdminOnly() {\n\t\treturn adminOnly;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setAdminOnly(boolean adminOnly) {\n\t\tthis.adminOnly = adminOnly;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected boolean isEmpty(String val) {\n\t\treturn (val == null) || val.isEmpty();\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/script/AddScriptCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.script;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.script.Bindings;\nimport javax.script.ScriptEngineFactory;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\nimport tigase.server.BasicComponent;\nimport tigase.server.CmdAcl;\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jan 2, 2009 2:29:48 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AddScriptCommand extends AbstractScriptCommand {\n\tprivate static final Logger log = Logger.getLogger(AddScriptCommand.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cmdId\n\t * @param cmdDescr\n\t * @param cmdGroup\n\t * @param script\n\t * @param lang\n\t * @param ext\n\t * @param binds\n\t *\n\t * \n\t *\n\t * @throws ScriptException\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic Script addAdminScript(String cmdId, String cmdDescr, String cmdGroup, String script, String lang,\n\t\t\tString ext, Bindings binds)\n\t\t\tthrows ScriptException {\n\t\tScript as = new Script();\n\n\t\tas.init(cmdId, cmdDescr, cmdGroup, script, lang, ext, binds);\n\n\t\tMap<String, CommandIfc> adminCommands = (Map<String, CommandIfc>) binds.get(ADMN_CMDS);\n\n\t\tadminCommands.put(as.getCommandId(), as);\n\n\t\tMap<String, EnumSet<CmdAcl>> commandsACL = (Map<String,\n\t\t\tEnumSet<CmdAcl>>) binds.get(COMMANDS_ACL);\n\t\tEnumSet<CmdAcl> acl = commandsACL.get(as.getCommandId());\n\n\t\tif (acl != null) {\n\t\t\tfor (CmdAcl cmdAcl : acl) {\n\t\t\t\tif (cmdAcl != CmdAcl.ADMIN) {\n\t\t\t\t\tas.setAdminOnly(false);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn as;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Bindings getBindings() {\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic void runCommand(Iq packet, Bindings binds, Queue<Packet> results) {\n\t\tString language = Command.getFieldValue(packet, LANGUAGE);\n\t\tString commandId = Command.getFieldValue(packet, COMMAND_ID);\n\t\tString description = Command.getFieldValue(packet, DESCRIPT);\n\t\tString group = Command.getFieldValue(packet, GROUP);\n\t\tString[] scriptText = Command.getFieldValues(packet, SCRIPT_TEXT);\n\t\tboolean saveToDisk = Command.getCheckBoxFieldValue(packet, SAVE_TO_DISK);\n\n\t\tif (isEmpty(language) || isEmpty(commandId) || isEmpty(description) || (scriptText == null)) {\n\t\t\tresults.offer(prepareScriptCommand(packet, binds));\n\t\t} else {\n\t\t\tStringBuilder sb = new StringBuilder(1024);\n\n\t\t\tfor (String string : scriptText) {\n\t\t\t\tif (string != null) {\n\t\t\t\t\tsb.append(string).append(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tString originalGroup = group;\n\t\t\t\tif (group != null && group.contains(\"${componentName}\")) {\n\t\t\t\t\tBasicComponent component = (BasicComponent) binds.get(\"component\");\n\t\t\t\t\tif (component != null) {\n\t\t\t\t\t\tgroup = group.replace(\"${componentName}\", component.getDiscoDescription());\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\n\t\t\t\tScript s = addAdminScript(commandId, description, group, sb.toString(), language, null, binds);\n\t\t\t\tPacket result = packet.commandResult(Command.DataType.result);\n\n\t\t\t\tCommand.addTextField(result, \"Note\", \"Script loaded successfuly.\");\n\t\t\t\tresults.offer(result);\n\n\t\t\t\tif (saveToDisk) {\n\t\t\t\t\tsaveCommandToDisk(commandId, description, originalGroup, sb, s.getFileExtension(), binds);\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't initialize script: \", e);\n\n\t\t\t\tPacket result = packet.commandResult(Command.DataType.result);\n\n\t\t\t\tCommand.addTextField(result, \"Note\", \"Script initialization error.\");\n\n\t\t\t\tStackTraceElement[] ste = e.getStackTrace();\n\t\t\t\tString[] error = new String[ste.length + 2];\n\n\t\t\t\terror[0] = e.getMessage();\n\t\t\t\terror[1] = e.toString();\n\n\t\t\t\tfor (int i = 0; i < ste.length; i++) {\n\t\t\t\t\terror[i + 2] = ste[i].toString();\n\t\t\t\t}\n\n\t\t\t\tCommand.addTextField(result, \"Error message\", e.getMessage());\n\t\t\t\tCommand.addFieldMultiValue(result, \"Debug info\", Arrays.asList(error));\n\t\t\t\tresults.offer(result);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Packet prepareScriptCommand(Iq packet, Bindings binds) {\n\t\tPacket result = packet.commandResult(Command.DataType.form);\n\n\t\tCommand.addFieldValue(result, DESCRIPT, \"Short description\");\n\t\tCommand.addFieldValue(result, COMMAND_ID, \"new-command\");\n\t\tCommand.addFieldValue(result, GROUP, \"group\");\n\n\t\tScriptEngineManager scriptEngineManager = (ScriptEngineManager) binds.get(SCRI_MANA);\n\t\tList<ScriptEngineFactory> scriptFactories = scriptEngineManager.getEngineFactories();\n\n\t\tif (scriptFactories != null) {\n\t\t\tString[] langs = new String[scriptFactories.size()];\n\t\t\tint idx = 0;\n\t\t\tString def = null;\n\n\t\t\tfor (ScriptEngineFactory scriptEngineFactory : scriptFactories) {\n\t\t\t\tlangs[idx++] = scriptEngineFactory.getLanguageName();\n\n\t\t\t\tif (scriptEngineFactory.getLanguageName().equals(\"groovy\")) {\n\t\t\t\t\tdef = \"groovy\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (def == null) {\n\t\t\t\tdef = langs[0];\n\t\t\t}\n\n\t\t\tCommand.addFieldValue(result, LANGUAGE, def, LANGUAGE, langs, langs);\n\t\t}\n\n\t\tCommand.addFieldMultiValue(result, SCRIPT_TEXT, Collections.nCopies(1, \"\"));\n\t\tCommand.addCheckBoxField(result, SAVE_TO_DISK, true);\n\n\t\treturn result;\n\t}\n\n\tprivate void saveCommandToDisk(String commandId, String description, String group, StringBuilder sb,\n\t\t\tString fileExtension, Bindings binds)\n\t\t\tthrows IOException {\n\t\tFile fileName = new File((String) binds.get(SCRIPT_COMP_DIR), commandId + \".\" + fileExtension);\n\n\t\tFile parentDirectory = fileName.getParentFile();\n\n\t\tif ( ( parentDirectory != null ) && !parentDirectory.exists() ){\n\t\t\tlog.log( Level.CONFIG, \"Admin scripts directory is missing: {0}, creating...\",\n\t\t\t\t\t\t\t parentDirectory );\n\t\t\ttry {\n\t\t\t\tparentDirectory.mkdirs();\n\t\t\t} catch ( Exception e ) {\n\t\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t\t \"Can't create scripts directory , read-only filesystem: \" + parentDirectory, e );\n\t\t\t}\n\t\t}\n\n\t\tlog.log(Level.INFO, \"Saving command: {0} to disk file: {1}\", new Object[] { commandId,\n\t\t\t\tfileName.toString() });\n\n\t\tFileWriter fw = new FileWriter(fileName, false);\n\t\tString comment = lineCommentStart.get(fileExtension);\n\n\t\tif (comment == null) {\n\t\t\tcomment = \"//\";\n\t\t}\n\n\t\tfw.write(comment + \" \" + SCRIPT_DESCRIPTION + \" \" + description + '\\n');\n\t\tfw.write(comment + \" \" + SCRIPT_ID + \" \" + commandId + '\\n');\n\t\tfw.write(comment + \" \" + SCRIPT_COMPONENT + \" \" + binds.get(COMPONENT_NAME) + '\\n');\n\t\tif (group != null) {\n\t\t\tfw.write(comment + \" \" + SCRIPT_GROUP + \" \" + group + '\\n');\n\t\t}\n\t\tfw.write(sb.toString());\n\t\tfw.close();\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/script/CommandIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.script;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\nimport javax.script.Bindings;\nimport tigase.stats.StatisticHolder;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Jan 2, 2009 1:20:16 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface CommandIfc extends StatisticHolder {\n\n\t/** Field description */\n\tpublic static final String VHOST_MANAGER = \"vhostMan\";\n\n\t/** Field description */\n\tpublic static final String ADMINS_SET = \"adminsSet\";\n\n\t/** Field description */\n\tpublic static final String COMMANDS_ACL = \"cmdsAcl\";\n\n\t/** Field description */\n\tpublic static final String ADMN_CMDS = \"adminCommands\";\n\n\t/** Field description */\n\tpublic static final String USER_REPO = \"userRepository\";\n\n\t/** Field description */\n\tpublic static final String AUTH_REPO = \"authRepository\";\n\n\t/** Field description */\n\tpublic static final String USER_SESS = \"userSessions\";\n\n\t/** Field description */\n\tpublic static final String USER_CONN = \"userConnections\";\n\n\t/** Field description */\n\tpublic static final String ADMN_DISC = \"adminDisco\";\n\n\t/** Field description */\n\tpublic static final String SCRI_MANA = \"scriptManager\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_BASE_DIR = \"scriptBaseDir\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_COMP_DIR = \"scriptCompDir\";\n\n\t/** Field description */\n\tpublic static final String COMPONENT_NAME = \"componentName\";\n\t\n\t/** Field description */\n\tpublic static final String COMPONENT = \"component\";\n\n\tpublic static final String CONNECTED_NODES = \"connectedNodes\";\n\tpublic static final String CONNECTED_NODES_WITH_LOCAL = \"connectedNodesWithLocal\";\n\t\n\t/** Field description */\n\tpublic static final String SERVICES_MAP = \"servicesMap\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_DESCRIPTION = \"AS:Description:\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_ID = \"AS:CommandId:\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_COMPONENT = \"AS:Component:\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_CLASS = \"AS:ComponentClass:\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_GROUP = \"AS:Group:\";\n\t\n\t/** Field description */\n\tpublic static final String LANGUAGE = \"Language\";\n\n\t/** Field description */\n\tpublic static final String COMMAND_ID = \"Command Id\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_TEXT = \"Script text\";\n\n\t/** Field description */\n\tpublic static final String SCRIPT_RESULT = \"Script result\";\n\n\t/** Field description */\n\tpublic static final String DESCRIPT = \"Description\";\n\n\t/** Field description */\n\tpublic static final String GROUP = \"Group\";\n\t\n\t/** Field description */\n\tpublic static final String SAVE_TO_DISK = \"Save to disk\";\n\n\t/** Field description */\n\tpublic static final String REMOVE_FROM_DISK = \"Remove from disk\";\n\n\t/** Field description */\n\tpublic static final String PACKET = \"packet\";\n\n\t/** Field description */\n\tpublic static final String ADD_SCRIPT_CMD = \"add-script\";\n\n\t/** Field description */\n\tpublic static final String DEL_SCRIPT_CMD = \"del-script\";\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Bindings getBindings();\n\n\tString getCommandId();\n\n\tString getDescription();\n\t\n\tString getGroup();\n\n\t//~--- methods --------------------------------------------------------------\n\n\tvoid init(String id, String description, String group);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tboolean isAdminOnly();\n\n\t//~--- methods --------------------------------------------------------------\n\n\tvoid runCommand(Iq packet, Bindings binds, Queue<Packet> results);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tvoid setAdminOnly(boolean adminOnly);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/script/RemoveScriptCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.script;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.disco.ServiceEntity;\n\nimport java.io.File;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\n\n/**\n * Created: Jan 2, 2009 2:30:41 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class RemoveScriptCommand extends AbstractScriptCommand {\n\n\tprivate static final Logger log = Logger.getLogger(RemoveScriptCommand.class.getName());\n\n\t@Override\n\t@SuppressWarnings({\"unchecked\"})\n\tpublic void runCommand(Iq packet, Bindings binds, Queue<Packet> results) {\n\t\tString commandId = Command.getFieldValue(packet, COMMAND_ID);\n\t\tif (isEmpty(commandId)) {\n\t\t\tresults.offer(prepareScriptCommand(packet, binds));\n\t\t} else {\n\t\t\tboolean removeFromDisk = Command.getCheckBoxFieldValue(packet, REMOVE_FROM_DISK);\n\n\t\t\tMap<String, CommandIfc> adminCommands =\n\t\t\t\t\t\t\t(Map<String, CommandIfc>) binds.get(ADMN_CMDS);\n\t\t\tScript command = (Script)adminCommands.remove(commandId);\n\t\t\tServiceEntity serviceEntity = (ServiceEntity) binds.get(ADMN_DISC);\n\t\t\tServiceEntity item =\n\t\t\t\t\t\t\tserviceEntity.findNode(\"http://jabber.org/protocol/admin#\" +\n\t\t\t\t\t\t\tcommandId);\n\t\t\tserviceEntity.removeItems(item);\n\n\t\t\tif (removeFromDisk) {\n\t\t\t\tdeleteCommandFromDisk(command.getCommandId(), command.getFileExtension(),binds);\n\t\t\t}\n\n\t\t\tPacket result = packet.commandResult(Command.DataType.result);\n\t\t\tCommand.addTextField(result, \"Note\",\n\t\t\t\t\t\t\t\"Script removed correctly\");\n\t\t\tresults.offer(result);\n\t\t}\n\t}\n\n\t@SuppressWarnings({\"unchecked\"})\n\tprivate Packet prepareScriptCommand(Iq packet, Bindings binds) {\n\t\tPacket result = null;\n\t\tMap<String, CommandIfc> adminCommands =\n\t\t\t\t\t\t(Map<String, CommandIfc>) binds.get(ADMN_CMDS);\n\t\tif (adminCommands.size() > 2) {\n\t\t\tresult = packet.commandResult(Command.DataType.form);\n\t\t\tSet<String> ids = new LinkedHashSet<String>(adminCommands.keySet());\n\t\t\tids.remove(ADD_SCRIPT_CMD);\n\t\t\tids.remove(DEL_SCRIPT_CMD);\n\t\t\tString[] commandIds = ids.toArray(new String[ids.size()]);\n\t\t\tCommand.addFieldValue(result, COMMAND_ID, commandIds[0], \"Command Id\",\n\t\t\t\t\t\t\tcommandIds, commandIds);\n\t\t\tCommand.addCheckBoxField(result, REMOVE_FROM_DISK, true);\n\t\t} else {\n\t\t\tresult = packet.commandResult(Command.DataType.result);\n\t\t\tCommand.addTextField(result, \"Note\",\n\t\t\t\t\t\t\t\"There is no command script to remove\");\n\t\t}\n\t\treturn result;\n\t}\n\n\n\tprivate void deleteCommandFromDisk(String commandId, String fileExtension,Bindings binds) {\n\t\tFile fileName = new File((String) binds.get(SCRIPT_COMP_DIR), commandId + \".\" + fileExtension);\n\n\t\tif (fileName.exists()) {\n\t\t\tlog.log(Level.CONFIG, \"Deleting file: {0}\", fileName);\n\t\t\tfileName.delete();\n\t\t}\n\t}\n\n\t@Override\n\tpublic Bindings getBindings() {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/script/Script.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.script;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.StringWriter;\n\nimport java.util.Arrays;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.script.Bindings;\nimport javax.script.Compilable;\nimport javax.script.CompiledScript;\nimport javax.script.ScriptContext;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jan 2, 2009 1:21:55 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Script extends AbstractScriptCommand {\n\tprivate static final Logger log = Logger.getLogger(Script.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CompiledScript compiledScript = null;\n\tprivate String ext = null;\n\tprivate String language = null;\n\tprivate String script = null;\n\tprivate ScriptEngine scriptEngine = null;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Bindings getBindings() {\n\t\treturn scriptEngine.createBindings();\n\t}\n\n\tpublic String getFileExtension() {\n\t\treturn ext;\n\t}\n\n\tpublic String getLanguageName() {\n\t\treturn language;\n\t}\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t * @param description\n\t * @param group\n\t * @param script\n\t * @param lang\n\t * @param ext\n\t * @param binds\n\t *\n\t * @throws ScriptException\n\t */\n\tpublic void init(String id, String description, String group, String script, String lang, String ext,\n\t\t\tBindings binds)\n\t\t\tthrows ScriptException {\n\t\tsuper.init(id, description, group);\n\t\tthis.script = script;\n\t\tthis.language = lang;\n\t\tthis.ext = ext;\n\n\t\tScriptEngineManager scriptEngineManager = (ScriptEngineManager) binds.get(SCRI_MANA);\n\n\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t \"Trying to load admin command: {0}, description: {1}, language: {2}, ext: {3}\",\n\t\t\t\t\t\t new Object[] { id, description, this.language, this.ext } );\n\n\t\tif (language != null) {\n\t\t\tscriptEngine = scriptEngineManager.getEngineByName(language);\n\t\t}\n\n\t\tif (ext != null) {\n\t\t\tscriptEngine = scriptEngineManager.getEngineByExtension(ext);\n\t\t}\n\n\t\tif ( !Packet.FULL_DEBUG && (scriptEngine instanceof Compilable)) {\n\t\t\tcompiledScript = ((Compilable) scriptEngine).compile(script);\n\t\t}\n\n\t\tif (this.language == null && scriptEngine != null) {\n\t\t\tthis.language = scriptEngine.getFactory().getLanguageName();\n\t\t}\n\n\t\tif (this.ext == null && scriptEngine != null) {\n\t\t\tthis.ext = scriptEngine.getFactory().getExtensions().get(0);\n\t\t}\n\n\t\tlog.log(Level.FINE, \"Initialized script command, id: {0}, lang: {1}, ext: {2}\",\n\t\t\t\tnew Object[] { id, this.language, this.ext });\n\n\t}\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic void runCommand(Iq packet, Bindings binds, Queue<Packet> results) {\n\t\tScriptContext context = null;\n\t\tStringWriter writer = null;\n\n\t\ttry {\n\t\t\tlong start = System.currentTimeMillis();\n\t\t\t// Bindings localBinds = scriptEngine.createBindings();\n\t\t\tbinds.put(PACKET, packet);\n\n\t\t\t// Workaround for Python which doesn't return values and can overwrite\n\t\t\t// values only if type is correct\n\t\t\tObject res = \"\";\n\n\t\t\tbinds.put(\"result\", res);\n\t\t\tcontext = scriptEngine.getContext();\n\t\t\tcontext.setBindings(binds, ScriptContext.ENGINE_SCOPE);\n\t\t\twriter = new StringWriter();\n\t\t\tcontext.setErrorWriter(writer);\n\n\t\t\tif (compiledScript != null) {\n\t\t\t\tres = compiledScript.eval(context);\n\t\t\t} else {\n\t\t\t\tres = scriptEngine.eval(script, context);\n\t\t\t}\n\n\t\t\tif (res == null) {\n\n\t\t\t\t// Yes, Python doesn't return results normally\n\t\t\t\t// (or I don't know how to do it)\n\t\t\t\t// Python can either return a Packet as 'packet' or string as 'result'\n\t\t\t\tres = binds.get(\"result\");\n\n\t\t\t\tif (res.toString().isEmpty()) {\n\t\t\t\t\tres = binds.get(PACKET);\n\n\t\t\t\t\tif (res == packet) {\n\n\t\t\t\t\t\t// Ups, apparently the script returned no results, to avoid infinite loop\n\t\t\t\t\t\t// we have to handle this somehow...\n\t\t\t\t\t\tres = \"Script finished with no errors but returned no results.\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (res instanceof Packet) {\n\t\t\t\tresults.offer((Packet) res);\n\t\t\t} else {\n\t\t\t\tif (res instanceof Queue) {\n\t\t\t\t\tresults.addAll((Queue<Packet>) res);\n\t\t\t\t} else {\n\t\t\t\t\tPacket result = packet.commandResult(Command.DataType.result);\n\n\t\t\t\t\t// Command.addTextField(result, \"Note\", \"Script execution result\");\n\t\t\t\t\tString[] text = null;\n\n\t\t\t\t\tif (res != null) {\n\t\t\t\t\t\ttext = res.toString().split(\"\\n\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext = new String[] { \"Script returned no results.\" };\n\t\t\t\t\t}\n\n\t\t\t\t\tCommand.addFieldMultiValue(result, SCRIPT_RESULT, Arrays.asList(text));\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlong end = System.currentTimeMillis();\n\t\t\tstatisticExecutedIn(end-start);\n\t\t} catch (Exception e) {\n\t\t\tPacket result = packet.commandResult(Command.DataType.result);\n\n\t\t\tCommand.addTextField(result, \"Note\", \"Script execution error.\");\n\n\t\t\tStackTraceElement[] ste = e.getStackTrace();\n\t\t\tString[] error =\n\t\t\t\tnew String[ste.length + 2 + ((writer != null) ? writer.toString().split(\"\\n\").length : 0)];\n\n\t\t\terror[0] = e.getMessage();\n\t\t\terror[1] = e.toString();\n\n\t\t\tfor (int i = 0; i < ste.length; i++) {\n\t\t\t\terror[i + 2] = ste[i].toString();\n\t\t\t}\n\n\t\t\tif (writer != null) {\n\t\t\t\tString[] errorMsgs = writer.toString().split(\"\\n\");\n\n\t\t\t\tfor (int i = 0; i < errorMsgs.length; i++) {\n\t\t\t\t\terror[i + 2 + ste.length] = errorMsgs[i];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (e.getMessage() != null) {\n\t\t\t\tCommand.addTextField(result, \"Error message\", e.getMessage());\n\t\t\t}\n\n\t\t\tCommand.addFieldMultiValue(result, \"Debug info\", Arrays.asList(error));\n\t\t\tresults.offer(result);\n\t\t}\n\t}\t\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/AbstractReceiverTask.java",
    "content": "/*\n * AbstractReceiverTask.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\nimport tigase.stats.StatRecord;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\nimport static tigase.server.sreceiver.TaskCommons.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.regex.Pattern;\nimport java.util.TreeMap;\n\n/**\n * Describe class AbstractReceiverTask here.\n *\n *\n * Created: Fri May 11 08:34:04 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class AbstractReceiverTask\n\t\t\t\timplements ReceiverTaskIfc {\n\tprivate static Logger log =\n\t\tLogger.getLogger(\"tigase.server.sreceiver.AbstractReceiverTask\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JID[] admins = {};\n\n//private String name = null;\n//protected String local_domain = null;\n\tprivate String description                   = null;\n\tprivate JID jid                              = null;\n\tprivate JID owner                            = null;\n\tprivate long packets_received                = 0;\n\tprivate long packets_sent                    = 0;\n\tprivate Map<String, PropertyItem> props      = null;\n\tprivate StanzaReceiverIfc srecv              = null;\n\tprivate SubscrRestrictions subsc_restr       = SUBSCR_RESTRICTIONS_PROP_VAL;\n\tprivate boolean send_to_online_only          = ONLINE_ONLY_PROP_VAL;\n\tprivate SenderRestrictions send_restr        = ALLOWED_SENDERS_PROP_VAL;\n\tprivate SenderAddress replace_sender_address = REPLACE_SENDER_PROP_VAL;\n\tprivate MessageType message_type             = MESSAGE_TYPE_PROP_VAL;\n\tprivate Pattern subscr_restr_regex           =\n\t\tPattern.compile(SUBSCR_RESTR_REGEX_PROP_VAL);\n\tprivate Map<JID, RosterItem> roster          = new HashMap<JID, RosterItem>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Describe <code>addNewSubscribers</code> method here.\n\t *\n\t * @param results\n\t * @param new_subscr a <code>String[]</code> value\n\t */\n\tpublic void addNewSubscribers(Queue<Packet> results, JID... new_subscr) {\n\t\tfor (JID buddy : new_subscr) {\n\t\t\tPacket presence = null;\n\n\t\t\tif (isAllowedToSubscribe(buddy)) {\n\t\t\t\tif (getRosterItem(buddy) == null) {\n\t\t\t\t\taddToRoster(buddy);\n\t\t\t\t}    // end of if (getRosterItem(buddy) == null)\n\t\t\t\tlog.info(getJID() + \": \" + \"Adding buddy to roster: \" + buddy);\n\t\t\t\tpresence = getPresence(jid, buddy, StanzaType.subscribe, jid.getLocalpart(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t null);\n\t\t\t} else {\n\t\t\t\tlog.info(getJID() + \": \" + \"Not allowed to subscribe, rejecting: \" + buddy);\n\t\t\t\tpresence = getPresence(jid, buddy, StanzaType.unsubscribed);\n\t\t\t}    // end of else\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(getJID() + \": \" + \"Sending back: \" + presence.toString());\n\t\t\t}\n\t\t\tresults.offer(presence);\n\t\t}      // end of for (String buddy: new_subscr)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t */\n\tpublic void addToRoster(RosterItem ri) {\n\t\troster.put(ri.getJid(), ri);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic RosterItem addToRoster(JID jid) {\n\t\tRosterItem ri = new RosterItem(jid.copyWithoutResource());\n\n\t\tif (jid.copyWithoutResource().equals(owner)) {\n\t\t\tri.setOwner(true);\n\t\t}    // end of if (id.equals(owner))\n\t\tif (subsc_restr != SubscrRestrictions.MODERATED) {\n\t\t\tri.setModerationAccepted(true);\n\t\t}    // end of if (subsc_restr != SubscrRestrictions.MODERATED)\n\t\taddToRoster(ri);\n\n\t\treturn ri;\n\t}\n\n\t@Override\n\tpublic void destroy(Queue<Packet> results) {\n\t\tfor (RosterItem ri : roster.values()) {\n\t\t\tPacket presence = getPresence(jid, ri.getJid(), StanzaType.unsubscribe);\n\n\t\t\tresults.offer(presence);\n\t\t\tpresence = getPresence(jid, ri.getJid(), StanzaType.unsubscribed);\n\t\t\tresults.offer(presence);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, PropertyItem> getDefaultParams() {\n\t\tMap<String, PropertyItem> defs = new TreeMap<String, PropertyItem>();\n\n\t\tdefs.put(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTRICTIONS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTRICTIONS_PROP_VAL));\n\t\tdefs.put(MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(MESSAGE_TYPE_PROP_KEY, MESSAGE_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMESSAGE_TYPE_PROP_VAL));\n\t\tdefs.put(ALLOWED_SENDERS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(ALLOWED_SENDERS_PROP_KEY, ALLOWED_SENDERS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tALLOWED_SENDERS_PROP_VAL));\n\t\tdefs.put(SUBSCR_RESTR_REGEX_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(SUBSCR_RESTR_REGEX_PROP_KEY, SUBSCR_RESTR_REGEX_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTR_REGEX_PROP_VAL));\n\t\tdefs.put(ONLINE_ONLY_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(ONLINE_ONLY_PROP_KEY, ONLINE_ONLY_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tONLINE_ONLY_PROP_VAL));\n\t\tdefs.put(REPLACE_SENDER_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(REPLACE_SENDER_PROP_KEY, REPLACE_SENDER_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tREPLACE_SENDER_PROP_VAL));\n\t\tdefs.put(ALLOWED_SENDERS_LIST_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(ALLOWED_SENDERS_LIST_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tALLOWED_SENDERS_LIST_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tALLOWED_SENDERS_LIST_PROP_VAL));\n\t\tdefs.put(DESCRIPTION_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DESCRIPTION_PROP_KEY, DESCRIPTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tDESCRIPTION_PROP_VAL));\n\t\tdefs.put(TASK_ADMINS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(TASK_ADMINS_PROP_KEY, TASK_ADMINS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTASK_ADMINS_PROP_VAL));\n\t\tdefs.put(TASK_OWNER_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(TASK_OWNER_PROP_KEY, TASK_OWNER_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTASK_OWNER_PROP_VAL));\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDescription() {\n\t\treturn description;\n\t}\n\n\t@Override\n\tpublic ReceiverTaskIfc getInstance() {\n\t\ttry {\n\t\t\treturn getClass().newInstance();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can't instantiate receiver task: \" + getClass().getName(),\n\t\t\t\t\t\t\te);\n\n\t\t\treturn null;\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic JID getJID() {\n\t\treturn jid;\n\t}\n\n\t@Override\n\tpublic Map<String, PropertyItem> getParams() {\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic Map<JID, RosterItem> getRoster() {\n\t\treturn roster;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic RosterItem getRosterItem(JID jid) {\n\t\treturn roster.get(jid.copyWithoutResource());\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {}\n\n\t@Override\n\tpublic List<StatRecord> getStats() {\n\t\tList<StatRecord> stats = new LinkedList<StatRecord>();\n\n\t\tstats.add(new StatRecord(getJID().toString(), \"Roster size\", roster.size(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Level.INFO));\n\t\tstats.add(new StatRecord(getJID().toString(), \"Packets received\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t packets_received, Level.INFO));\n\t\tstats.add(new StatRecord(getJID().toString(), \"Packets sent\", packets_sent,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Level.INFO));\n\n\t\tint moderation_needed = 0;\n\n\t\tfor (RosterItem ri : roster.values()) {\n\t\t\tmoderation_needed += (ri.isModerationAccepted()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 1);\n\t\t}    // end of for (RosterItem ri: roster)\n\t\tstats.add(new StatRecord(getJID().toString(), \"Awaiting moderation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t moderation_needed, Level.INFO));\n\n\t\treturn stats;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(final Queue<Packet> results) {\n\t\tfor (RosterItem ri : roster.values()) {\n\t\t\tPacket presence = null;\n\n\t\t\tif (ri.isSubscribed()) {\n\t\t\t\tpresence = getPresence(jid, ri.getJid(), StanzaType.available, null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t getDescription());\n\t\t\t} else {\n\t\t\t\tpresence = getPresence(jid, ri.getJid(), StanzaType.subscribe,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t jid.getLocalpart(), null);\n\t\t\t}    // end of if (ri.isSubscribed()) else\n\t\t\tresults.offer(presence);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isAdmin(JID jid) {\n\t\tRosterItem ri = getRosterItem(jid);\n\n\t\treturn (ri != null) && (ri.isAdmin() || ri.isOwner());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param buddy\n\t *\n\t * \n\t */\n\tpublic boolean isAllowedToPost(JID buddy) {\n\t\tboolean result = false;\n\t\tRosterItem ri  = getRosterItem(buddy);\n\n\t\tswitch (send_restr) {\n\t\tcase SUBSCRIBED :\n\t\t\tresult = (ri != null) && ri.isSubscribed() && ri.isModerationAccepted();\n\n\t\t\tbreak;\n\n\t\tcase OWNER :\n\t\t\tresult = (ri != null) && ri.isOwner();\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tresult = true;\n\n\t\t\tbreak;\n\t\t}    // end of switch (send_restr)\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param buddy\n\t *\n\t * \n\t */\n\tpublic boolean isAllowedToSubscribe(JID buddy) {\n\t\tboolean result = false;\n\n\t\tswitch (subsc_restr) {\n\t\tcase LOCAL :\n\t\t\tString buddy_domain = buddy.getDomain();\n\n\t\t\tif (buddy_domain.equals(jid.getDomain())) {\n\t\t\t\tresult = true;\n\t\t\t}    // end of if (buddy_domain.equals(local_domain))\n\n\t\t\tbreak;\n\n\t\tcase REGEX :\n\t\t\tresult = subscr_restr_regex.matcher(buddy.toString()).matches();\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tresult = true;\n\n\t\t\tbreak;\n\t\t}      // end of switch (subsc_restr)\n\n\t\treturn result;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(final Packet packet, final Queue<Packet> results) {\n\t\t++packets_received;\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(getJID() + \": \" + \"Processing packet: \" + packet.toString());\n\t\t}\n\t\tif (packet.getType() == StanzaType.error) {\n\t\t\tlog.fine(\"Ignoring error stanza: \" + packet.toString());\n\n\t\t\treturn;\n\t\t}\n\t\tif (packet.getElemName().equals(\"presence\")) {\n\t\t\tprocessPresence(packet, results);\n\t\t}    // end of if (packet.getElemName().equals(\"presence))\n\t\tif (packet.getElemName().equals(\"message\")) {\n\t\t\tif (isAllowedToPost(packet.getStanzaFrom())) {\n\t\t\t\tprocessMessage(packet, results);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\t\"You are not allowed to post a message.\", true));\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.warning(\"Packet processing exception: \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of if (packet.getElemName().equals(\"message\"))\n\t\tpackets_sent += results.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t * \n\t */\n\tpublic RosterItem removeFromRoster(JID jid) {\n\t\treturn roster.remove(jid.copyWithoutResource());\n\t}\n\n\t@Override\n\tpublic void removeSubscribers(Queue<Packet> results, JID... subscr) {\n\t\tfor (JID buddy : subscr) {\n\t\t\tRosterItem ri = removeFromRoster(buddy);\n\n\t\t\tif (ri != null) {\n\t\t\t\tlog.info(getJID() + \": \" + \"Removing buddy from roster: \" + buddy);\n\t\t\t\tresults.offer(getPresence(jid, buddy, StanzaType.unsubscribed));\n\t\t\t}    // end of if (getRosterItem(buddy) == null)\n\t\t}      // end of for (String buddy: new_subscr)\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setJID(JID jid) {\n\t\tthis.jid = jid;\n\t\tlog.fine(\"JID set to: \" + this.jid);\n\n\t}\n\n\t@Override\n\tpublic void setParams(final Map<String, Object> map) {\n\t\tif (props == null) {\n\t\t\tprops = new TreeMap<String, PropertyItem>();\n\t\t}    // end of if (props == null)\n\t\tif (map.get(DESCRIPTION_PROP_KEY) != null) {\n\t\t\tdescription = (String) map.get(DESCRIPTION_PROP_KEY);\n\t\t\tprops.put(DESCRIPTION_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(DESCRIPTION_PROP_KEY, DESCRIPTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t description));\n\t\t}    // end of if (map.get(DESCRIPTION_PROP_KEY) != null)\n\t\tif (map.get(SUBSCR_RESTR_REGEX_PROP_KEY) != null) {\n\t\t\tsubscr_restr_regex = Pattern.compile((String) map.get(SUBSCR_RESTR_REGEX_PROP_KEY));\n\t\t\tprops.put(SUBSCR_RESTR_REGEX_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(SUBSCR_RESTR_REGEX_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t SUBSCR_RESTR_REGEX_DISPL_NAME, subscr_restr_regex));\n\t\t}    // end of if (map.get(SUBSCR_RESTR_REGEX_PROP_KEY) != null)\n\n\t\tString tmp = (String) map.get(SUBSCR_RESTRICTIONS_PROP_KEY);\n\n\t\tif (tmp != null) {\n\t\t\tsubsc_restr = SubscrRestrictions.valueOf(tmp);\n\t\t\tprops.put(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t SUBSCR_RESTRICTIONS_DISPL_NAME, subsc_restr));\n\t\t}    // end of if (tmp != null)\n\t\ttmp = (String) map.get(ALLOWED_SENDERS_PROP_KEY);\n\t\tif (tmp != null) {\n\t\t\tsend_restr = SenderRestrictions.valueOf(tmp);\n\t\t\tprops.put(ALLOWED_SENDERS_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(ALLOWED_SENDERS_PROP_KEY, ALLOWED_SENDERS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t send_restr));\n\t\t}    // end of if (tmp != null)\n\t\ttmp = (String) map.get(MESSAGE_TYPE_PROP_KEY);\n\t\tif (tmp != null) {\n\t\t\tmessage_type = MessageType.valueOf(tmp);\n\t\t\tprops.put(MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(MESSAGE_TYPE_PROP_KEY, MESSAGE_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t message_type));\n\t\t}    // end of if (tmp != null)\n\t\tif (map.get(ONLINE_ONLY_PROP_KEY) != null) {\n\t\t\tsend_to_online_only = parseBool(map.get(ONLINE_ONLY_PROP_KEY));\n\t\t\tprops.put(ONLINE_ONLY_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(ONLINE_ONLY_PROP_KEY, ONLINE_ONLY_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t send_to_online_only));\n\t\t}    // end of if (map.get(ONLINE_ONLY_PROP_KEY) != null)\n\t\ttmp = (String) map.get(REPLACE_SENDER_PROP_KEY);\n\t\tif (tmp != null) {\n\t\t\treplace_sender_address = SenderAddress.valueOf(tmp);\n\t\t\tprops.put(REPLACE_SENDER_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(REPLACE_SENDER_PROP_KEY, REPLACE_SENDER_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t replace_sender_address));\n\t\t}    // end of if (map.get(REPLACE_SENDER_PROP_KEY) != null)\n\t\ttmp = (String) map.get(TASK_OWNER_PROP_KEY);\n\t\tif ((tmp != null) && (tmp.length() > 0)) {\n\t\t\ttry {\n\t\t\t\towner = JID.jidInstance(tmp).copyWithoutResource();\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tlog.warning(\"Incorrect owner JID, stringprep processing failed: \" + tmp);\n\t\t\t}\n\n\t\t\tRosterItem ri = getRosterItem(owner);\n\n\t\t\tif (ri == null) {\n\t\t\t\tri = addToRoster(owner);\n\t\t\t}    // end of if (ri == null)\n\t\t\tsetRosterItemOwner(ri, true);\n\t\t\tsetRosterItemAdmin(ri, true);\n\t\t\tsetRosterItemModerationAccepted(ri, true);\n\t\t\tprops.put(TASK_OWNER_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(TASK_OWNER_PROP_KEY, TASK_OWNER_DISPL_NAME, owner));\n\t\t}\n\t\tif (props.get(TASK_OWNER_PROP_KEY) == null) {\n\t\t\tprops.put(TASK_OWNER_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(TASK_OWNER_PROP_KEY, TASK_OWNER_DISPL_NAME, \"\"));\n\t\t}\n\t\ttmp = (String) map.get(TASK_ADMINS_PROP_KEY);\n\t\tif ((tmp != null) && (tmp.length() > 0)) {\n\t\t\tString[] admins_stra = tmp.split(\",\");\n\n\t\t\tadmins = new JID[admins_stra.length];\n\n\t\t\tint idx = 0;\n\n\t\t\tfor (String admin : admins_stra) {\n\t\t\t\ttry {\n\t\t\t\t\tJID adm = JID.jidInstance(admin).copyWithoutResource();\n\n\t\t\t\t\tadmins[idx++] = adm;\n\n\t\t\t\t\tRosterItem ri = getRosterItem(adm);\n\n\t\t\t\t\tif (ri == null) {\n\t\t\t\t\t\tri = addToRoster(adm);\n\t\t\t\t\t}    // end of if (ri == null)\n\t\t\t\t\tsetRosterItemAdmin(ri, true);\n\t\t\t\t\tsetRosterItemModerationAccepted(ri, true);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.warning(\"Incorrect admin JID, stringprep processing failed: \" + admin);\n\t\t\t\t}\n\t\t\t}        // end of for (String tmp_b: tmp_arr)\n\t\t\tprops.put(TASK_ADMINS_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(TASK_ADMINS_PROP_KEY, TASK_ADMINS_DISPL_NAME, tmp));\n\t\t}\n\t\tif (props.get(TASK_ADMINS_PROP_KEY) == null) {\n\t\t\tprops.put(TASK_ADMINS_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(TASK_ADMINS_PROP_KEY, TASK_ADMINS_DISPL_NAME, \"\"));\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param admin\n\t */\n\tpublic void setRosterItemAdmin(RosterItem ri, boolean admin) {\n\t\tri.setAdmin(admin);\n\t}\n\n\t@Override\n\tpublic void setRosterItemModerationAccepted(RosterItem ri, boolean accepted) {\n\t\tri.setModerationAccepted(accepted);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param online\n\t */\n\tpublic void setRosterItemOnline(RosterItem ri, boolean online) {\n\t\tri.setOnline(online);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param owner\n\t */\n\tpublic void setRosterItemOwner(RosterItem ri, boolean owner) {\n\t\tri.setOwner(owner);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param subscribed\n\t */\n\tpublic void setRosterItemSubscribed(RosterItem ri, boolean subscribed) {\n\t\tlog.fine(getJID() + \": \" + \"Updating subscription for \" + ri.getJid() + \" to \" +\n\t\t\t\t\t\t subscribed);\n\t\tri.setSubscribed(subscribed);\n\t}\n\n\t// Implementation of tigase.server.sreceiver.ReceiverTaskIfc\n\n\t@Override\n\tpublic void setStanzaReceiver(StanzaReceiverIfc srecv) {\n\t\tthis.srecv = srecv;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t */\n\tprotected boolean addOutPacket(Packet packet) {\n\t\treturn srecv.addOutPacket(packet);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param results\n\t */\n\tprotected void processMessage(Packet packet, Queue<Packet> results) {\n\t\tfor (RosterItem ri : roster.values()) {\n\t\t\tif (ri.isSubscribed() && ri.isModerationAccepted() &&\n\t\t\t\t\t(!send_to_online_only || ri.isOnline()) &&\n\t\t\t\t\t(!packet.getStanzaFrom().copyWithoutResource().equals(ri.getJid()))) {\n\t\t\t\tElement message = packet.getElement().clone();\n\t\t\t\tElement body    = message.getChild(\"body\");\n\n\t\t\t\tif (body == null) {\n\t\t\t\t\treturn;\n\t\t\t\t}    // end of if (body == null)\n\n\t\t\t\tJID from = null;\n\n\t\t\t\tmessage.setAttribute(\"to\", ri.getJid().toString());\n\t\t\t\tmessage.setAttribute(\"type\", message_type.toString().toLowerCase());\n\t\t\t\tswitch (replace_sender_address) {\n\t\t\t\tcase REPLACE : {\n\t\t\t\t\tString old_from = message.getAttributeStaticStr(Packet.FROM_ATT);\n\n\t\t\t\t\tfrom = jid;\n\n\t\t\t\t\tString cdata = body.getCData();\n\n\t\t\t\t\tbody.setCData(old_from + \" sends:\\n\\n\" + cdata);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase REMOVE :\n\t\t\t\t\tfrom = jid;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase REPLACE_SRECV : {\n\t\t\t\t\tString old_from = message.getAttributeStaticStr(Packet.FROM_ATT);\n\n\t\t\t\t\tfrom = JID.jidInstanceNS(srecv.getName(), jid.getDomain(), jid.getLocalpart());\n\n\t\t\t\t\tString cdata = body.getCData();\n\n\t\t\t\t\tbody.setCData(old_from + \" sends for installation at \" +\n\t\t\t\t\t\t\t\t\t\t\t\tsrecv.getDefHostName() + \":\\n\\n\" + cdata);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmessage.setAttribute(\"from\", from.toString());\n\t\t\t\tresults.offer(Packet.packetInstance(message, from, ri.getJid()));\n\t\t\t}    // end of if (ri.isSubscribed() && ri.isModerationAccepted())\n\t\t}      // end of for (RosterItem ri: roster.values())\n\t}\n\n\tprivate void processPresence(Packet packet, Queue<Packet> results) {\n\t\tStanzaType presence_type = StanzaType.available;\n\n\t\tif (packet.getType() != null) {\n\t\t\tpresence_type = packet.getType();\n\t\t}\n\n\t\tRosterItem ri = getRosterItem(packet.getStanzaFrom());\n\n\t\tswitch (presence_type) {\n\t\tcase available :\n\t\tcase probe :\n\t\t\tif (ri != null) {\n\t\t\t\tsetRosterItemOnline(ri, true);\n\t\t\t\tresults.offer(getPresence(jid, packet.getStanzaFrom(), StanzaType.available,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull, getDescription()));\n\t\t\t}    // end of if (ri != null)\n\n\t\t\tbreak;\n\n\t\tcase unavailable :\n\t\t\tif (ri != null) {\n\t\t\t\tsetRosterItemOnline(ri, false);\n\t\t\t}    // end of if (ri != null)\n\n\t\t\tbreak;\n\n\t\tcase subscribe :\n\t\t\taddNewSubscribers(results, packet.getStanzaFrom());\n\t\t\tresults.offer(getPresence(jid, packet.getStanzaFrom(), StanzaType.subscribed));\n\n\t\t\tbreak;\n\n\t\tcase subscribed :\n\t\t\tif (ri != null) {\n\t\t\t\tsetRosterItemSubscribed(ri, true);\n\t\t\t\tresults.offer(getPresence(jid, packet.getStanzaFrom(), StanzaType.available,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull, getDescription()));\n\t\t\t\tif (!ri.isModerationAccepted()) {\n\t\t\t\t\tresults.offer(getMessage(jid, packet.getStanzaFrom(), StanzaType.headline,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"You are now subscribed to \" + getJID() + \".\\n\\n\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Your subscription, however awaits moderation.\\n\\n\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Once your subscription is approved next message\\n\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"will be sent confirming your membership.\"));\n\t\t\t\t}\n\t\t\t}    // end of if (ri != null)\n\n\t\t\tbreak;\n\n\t\tcase unsubscribe :\n\t\tcase unsubscribed :\n\t\t\tremoveSubscribers(results, packet.getStanzaFrom());\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tbreak;\n\t\t}      // end of switch (packet.getType())\n\t}\n}    // AbstractReceiverTask\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/DefaultValues.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\n/**\n * Describe interface DefaultValues here.\n *\n *\n * Created: Fri May 18 14:27:26 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface DefaultValues {\n\n\t\tString[] strValues();\n\n} // DefaultValues\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/NewTaskCommand.java",
    "content": "/*\n * NewTaskCommand.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.BareJID;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\nimport static tigase.server.sreceiver.TaskCommons.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Describe class NewTaskCommand here.\n *\n *\n * Created: Thu May 17 22:19:28 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NewTaskCommand\n\t\t\t\timplements TaskCommandIfc {\n\tprivate static Logger log = Logger.getLogger(\"tigase.server.sreceiver.NewTaskCommand\");\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processCommand(Packet packet, Packet result, StanzaReceiver receiv) {\n\t\tString task_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\n\t\tif ((task_name == null) ||!checkTaskName(task_name, result, receiv) || (Command\n\t\t\t\t.getAction(packet) == Command.Action.prev)) {\n\t\t\tCommand.addFieldValue(result, STEP, \"step1\", \"hidden\");\n\t\t\tnewTask_Step1(result, receiv);\n\n\t\t\treturn;\n\t\t}    // end of if (!checkTaskName(receiv, task_name))\n\n\t\tString   task_type = Command.getFieldValue(packet, TASK_TYPE_FIELD);\n\t\tTaskType tt        = receiv.getTaskTypes().get(task_type);\n\n\t\tif (tt == null) {\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"I am sorry there is a problem with instantiating task of this type: \" +\n\t\t\t\t\ttask_type, \"fixed\");\n\n\t\t\treturn;\n\t\t}\n\t\tif (tt.getMaxInstancesNo() <= tt.getInstancesNo()) {\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"I am sorry, maximum number of tasks instances for this type has been\" +\n\t\t\t\t\t\" exceeded: \" + task_type, \"fixed\");\n\n\t\t\treturn;\n\t\t}\n\t\tif (!receiv.isAllowedCreate(packet.getStanzaFrom(), task_type)) {\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"I am sorry, you are not allowed to create task of this type: \" + task_type,\n\t\t\t\t\t\"fixed\");\n\n\t\t\treturn;\n\t\t}\n\t\tCommand.addFieldValue(result, TASK_NAME_FIELD, task_name, \"hidden\");\n\t\tCommand.addFieldValue(result, TASK_TYPE_FIELD, task_type, \"hidden\");\n\n\t\tString step = Command.getFieldValue(packet, STEP);\n\n\t\tif ((step == null) || step.equals(\"step1\")) {\n\t\t\tCommand.addFieldValue(result, STEP, \"step2\", \"hidden\");\n\t\t\tnewTask_Step2(packet, result, receiv);\n\n\t\t\treturn;\n\t\t}    // end of if (step == null || step.equals(\"step1\"))\n\t\ttry {\n\t\t\tnewTask_Step3(packet, result, receiv);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(NewTaskCommand.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getDescription() {\n\t\treturn \"Add new task...\";\n\t}\n\n\t@Override\n\tpublic String getNodeName() {\n\t\treturn \"new-task\";\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate boolean checkTaskName(String task_name, Packet result, StanzaReceiver receiv) {\n\t\tString msg = BareJID.parseJID(task_name)[0];\n\n\t\tif (msg != null) {\n\t\t\tCommand.addFieldValue(result, \"Info\", \"Note!! \" + msg +\n\t\t\t\t\t\", please provide valid task name.\", \"fixed\");\n\n\t\t\treturn false;\n\t\t}    // end of if (msg != null)\n\n\t\tReceiverTaskIfc task = receiv.getTaskInstances().get(task_name);\n\n\t\tif (task != null) {\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"Note!! Task with provided name already exists.\", \"fixed\");\n\t\t\tCommand.addFieldValue(result, \"Info\", \"Please provide different task name.\",\n\t\t\t\t\t\"fixed\");\n\n\t\t\treturn false;\n\t\t}    // end of if (task != null)\n\n\t\treturn true;\n\t}\n\n\tprivate void newTask_Step1(Packet result, StanzaReceiver receiv) {\n\t\tCommand.addFieldValue(result, \"Info\", \"Press:\", \"fixed\");\n\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\"'Next' to set all parameters for the new task.\", \"fixed\");\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addAction(result, Command.Action.next);\n\t\tCommand.addFieldValue(result, TASK_NAME_FIELD, \"\", \"text-single\", TASK_NAME_FIELD);\n\n\t\tString[] task_types = receiv.getTaskTypes().keySet().toArray(new String[0]);\n\n\t\tCommand.addFieldValue(result, TASK_TYPE_FIELD, task_types[0], TASK_TYPE_FIELD,\n\t\t\t\ttask_types, task_types);\n\t}\n\n\tprivate void newTask_Step2(Packet packet, Packet result, StanzaReceiver receiv) {\n\t\tString          task_type = Command.getFieldValue(packet, TASK_TYPE_FIELD);\n\t\tReceiverTaskIfc task_t    = receiv.getTaskTypes().get(task_type).getTaskType();\n\t\tint             start     = 0;\n\t\tint             line_len  = 60;\n\n\t\tdo {\n\t\t\tint end = ((start + line_len < task_t.getHelp().length())\n\t\t\t\t\t? start + line_len\n\t\t\t\t\t: task_t.getHelp().length());\n\n\t\t\twhile ((end < task_t.getHelp().length()) && (task_t.getHelp().charAt(end) != ' ')) {\n\t\t\t\t++end;\n\t\t\t}\n\t\t\tCommand.addFieldValue(result, \"task\" + start, task_t.getHelp().substring(start,\n\t\t\t\t\tend), \"fixed\");\n\t\t\tstart = end;\n\t\t} while (start < task_t.getHelp().length());\n\t\tCommand.addFieldValue(result, \"Info2\",\n\t\t\t\t\"1. 'Finish' to create component with this parameters.\", \"fixed\");\n\t\tCommand.addFieldValue(result, \"Info3\",\n\t\t\t\t\"2. 'Previous' to go back and select different component.\", \"fixed\");\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addAction(result, Command.Action.complete);\n\t\tCommand.addAction(result, Command.Action.prev);\n\n\t\tMap<String, PropertyItem> default_props = task_t.getDefaultParams();\n\t\tPropertyItem              pi            = default_props.get(TASK_OWNER_PROP_KEY);\n\n\t\tif (pi != null) {\n\t\t\tpi.setValue(packet.getStanzaFrom().getBareJID().toString());\n\t\t}\n\t\tpropertyItems2Command(default_props, result);\n\t}\n\n\tprivate void newTask_Step3(Packet packet, Packet result, StanzaReceiver receiv)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tString                    task_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\t\tString                    task_type = Command.getFieldValue(packet, TASK_TYPE_FIELD);\n\t\tMap<String, PropertyItem> default_props = receiv.getTaskTypes().get(task_type)\n\t\t\t\t.getTaskType().getDefaultParams();\n\t\tMap<String, Object> new_params = new LinkedHashMap<String, Object>();\n\n\t\tfor (String key : default_props.keySet()) {\n\t\t\tif (default_props.get(key).isMultiValue()) {\n\t\t\t\tString[] values = Command.getFieldValues(packet, XMLUtils.escape(key));\n\n\t\t\t\tnew_params.put(key, values);\n\t\t\t} else {\n\t\t\t\tString value = Command.getFieldValue(packet, XMLUtils.escape(key));\n\n\t\t\t\tif (value == null) {\n\t\t\t\t\tvalue = \"\";\n\t\t\t\t}    // end of if (value == null)\n\t\t\t\tvalue = XMLUtils.unescape(value);\n\t\t\t\tnew_params.put(key, value);\n\t\t\t}\n\t\t}        // end of for (String key: default_props.keySet())\n\t\treceiv.addTaskInstance(task_type, task_name, new_params);\n\t\tCommand.addFieldValue(result, \"Info\", \"Created task: \" + task_name, \"fixed\");\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/NewsDistributor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\n/**\n * Simple news distributor task.\n *\n * Created: Fri May 11 08:53:16 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NewsDistributor extends RepoRosterTask {\n\n\tprivate static final String TASK_TYPE = \"News Distribution\";\n\tprivate static final String TASK_HELP =\n\t\t\"The task acts as a newsletter over Jabber/XMPP protocol.\"\n\t\t+ \" Users can subscribe to the news just by adding task JID\"\n\t\t+ \" to their roster, unsubscribing is equally simple - remove\"\n\t\t+ \" JID from roster to stop receiving news.\";\n\n\tpublic String getType() {\n\t\treturn TASK_TYPE;\n\t}\n\n\tpublic String getHelp() {\n\t\treturn TASK_HELP;\n\t}\n\n} // NewsDistributor\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/PropertyConstants.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\n/**\n * Describe class PropertyConstants here.\n *\n *\n * Created: Fri May 18 12:52:02 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class PropertyConstants {\n\n\tpublic enum SubscrRestrictions implements DefaultValues {\n\t\tPUBLIC,\tLOCAL, REGEX, MODERATED;\n\t\tpublic String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\t\t\tfor (Enum val: values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t} // end of for (Enum en_v: en_val.values())\n\t\t\treturn possible_values;\n\t\t}\n\t};\n\n\tpublic enum MessageType implements DefaultValues {\n\t\tCHAT, HEADLINE, NORMAL;\n\t\tpublic String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\t\t\tfor (Enum val: values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t} // end of for (Enum en_v: en_val.values())\n\t\t\treturn possible_values;\n\t\t}\n\t};\n\n\tpublic enum SenderRestrictions implements DefaultValues {\n\t\tALL, SUBSCRIBED, OWNER, LIST;\n\t\tpublic String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\t\t\tfor (Enum val: values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t} // end of for (Enum en_v: en_val.values())\n\t\t\treturn possible_values;\n\t\t}\n\t};\n\n\tpublic enum SenderAddress implements DefaultValues {\n\t\tREPLACE, LEAVE, REMOVE, REPLACE_SRECV;\n\t\tpublic String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\t\t\tfor (Enum val: values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t} // end of for (Enum en_v: en_val.values())\n\t\t\treturn possible_values;\n\t\t}\n\t};\n\n\t/**\n\t * Constant <code>SUBSCR_LIST_PROP_KEY</code> is a property key for task\n\t * instance configuration parameters. With this property you can provide\n\t * task with initial list of subscribers. These users however must accept\n\t * subscription first before any message is delivered to them. So you\n\t * can't force ppl to receive any messages using this setting.\n\t */\n\tpublic static final String SUBSCR_LIST_PROP_KEY =\n\t\t\"subscription-list-key\";\n\t/**\n\t * Constant <code>SUBSCR_LIST_PROP_KEY</code> is a property value for a key\n\t * <strong>SUBSCR_LIST_PROP_KEY</strong>. Please refer to key description\n\t * for more details. Default value is an empty String array.\n\t */\n\tpublic static final String[] SUBSCR_LIST_PROP_VAL = {};\n\t/**\n\t * Constant <code>SUBSCR_RESTRICTIONS_PROP_KEY</code> is a property key for task\n\t * instance configuration parameters. With this property you can decide who\n\t * can subscribe to the task. Default value is <strong>PUBLIC</strong> so anybody\n\t * can subscribe.\n\t */\n\tpublic static final String SUBSCR_RESTRICTIONS_PROP_KEY =\n\t\t\"subscription-restr\";\n\tpublic static final String SUBSCR_RESTRICTIONS_DISPL_NAME =\n\t\t\"Subscription restrictions\";\n\tpublic static final SubscrRestrictions SUBSCR_RESTRICTIONS_PROP_VAL =\n\t\tSubscrRestrictions.PUBLIC;\n\tpublic static final String ALLOWED_SENDERS_PROP_KEY = \"allowed-senders\";\n\tpublic static final String ALLOWED_SENDERS_DISPL_NAME = \"Allowed senders\";\n\tpublic static final SenderRestrictions ALLOWED_SENDERS_PROP_VAL =\n\t\tSenderRestrictions.SUBSCRIBED;\n\tpublic static final String MESSAGE_TYPE_PROP_KEY = \"message-type\";\n\tpublic static final String MESSAGE_TYPE_DISPL_NAME = \"Message type\";\n\tpublic static final MessageType MESSAGE_TYPE_PROP_VAL = MessageType.CHAT;\n\tpublic static final String SUBSCR_RESTR_REGEX_PROP_KEY =\n\t\t\"subscription-restr-regex\";\n\tpublic static final String SUBSCR_RESTR_REGEX_DISPL_NAME =\n\t\t\"Subscription restrictions regex\";\n\tpublic static final String SUBSCR_RESTR_REGEX_PROP_VAL = \".*\";\n\tpublic static final String ONLINE_ONLY_PROP_KEY = \"online-users-only\";\n\tpublic static final String ONLINE_ONLY_DISPL_NAME =\n\t\t\"Send to online users only\";\n\tpublic static final Boolean  ONLINE_ONLY_PROP_VAL = false;\n\tpublic static final String REPLACE_SENDER_PROP_KEY = \"replace-sender\";\n\tpublic static final String REPLACE_SENDER_DISPL_NAME =\n\t\t\"Replace sender address\";\n\tpublic static final SenderAddress REPLACE_SENDER_PROP_VAL =\n\t\tSenderAddress.REPLACE;\n\tpublic static final String ALLOWED_SENDERS_LIST_PROP_KEY =\n\t\t\"allowed-senders-list\";\n\tpublic static final String ALLOWED_SENDERS_LIST_DISPL_NAME =\n\t\t\"List of users allowed to post\";\n\tpublic static final String ALLOWED_SENDERS_LIST_PROP_VAL = \"\";\n\t/**\n\t * Constant <code>DESCRIPTION_PROP_KEY</code> is a description for task instance.\n\t * Let's say the user want's to create new <em>Interest group</em> for\n\t * cyclists. This property allows to set some more detailed information about\n\t * the group like: <em>This is group of ppl interested in mountain cycling\n\t * near Cambridge.</em>\n\t */\n\tpublic static final String DESCRIPTION_PROP_KEY = \"description\";\n\tpublic static final String DESCRIPTION_DISPL_NAME =\n\t\t\"Description\";\n\tpublic static final String DESCRIPTION_PROP_VAL = \"News distribution task\";\n\tpublic static final String TASK_OWNER_PROP_KEY = \"task-owner\";\n\tpublic static final String TASK_OWNER_DISPL_NAME = \"Owner\";\n\tpublic static final String TASK_OWNER_PROP_VAL = \"admin@localhost\";\n\n\tpublic static final String TASK_ADMINS_PROP_KEY = \"task-admins\";\n\tpublic static final String TASK_ADMINS_DISPL_NAME = \"Administrators\";\n\tpublic static final String TASK_ADMINS_PROP_VAL = \"\";\n\n\tpublic static final String USER_REPOSITORY_PROP_KEY = \"user-repository\";\n\n\n\n} // PropertyConstants\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/PropertyItem.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\nimport java.util.Arrays;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\n\n/**\n * Describe class PropertyItem here.\n *\n *\n * Created: Fri May 18 12:14:03 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PropertyItem {\n\n\tprivate String name = null;\n\tprivate String display_name = null;\n\tprivate Object value = null;\n\tprivate String[] possible_values = null;\n\tprivate String description = null;\n\tprivate boolean multiValue = false;\n\n\t/**\n\t * Creates a new <code>PropertyItem</code> instance.\n\t *\n\t */\n\tpublic PropertyItem(String name, String display_name, Object def_value,\n\t\tString[] possible_values, String description) {\n\t\tthis.name = name;\n\t\tthis.display_name = display_name;\n\t\tthis.value = def_value;\n\t\tthis.description = description;\n\t\tif (possible_values != null) {\n\t\t\tthis.possible_values =\n\t\t\t\tArrays.copyOf(possible_values, possible_values.length);\n\t\t} else {\n\t\t\tif (value != null) {\n\t\t\t\tguessPossibleValues();\n\t\t\t} // end of if (possible_values == null && value != null)\n\t\t}\n\t}\n\n\tpublic PropertyItem(String name, String display_name, String[] def_values,\n\t\tString[] possible_values, String description) {\n\t\tthis.multiValue = true;\n\t\tthis.name = name;\n\t\tthis.display_name = display_name;\n\t\tthis.value = def_values;\n\t\tthis.description = description;\n\t\tif (possible_values != null) {\n\t\t\tthis.possible_values =\n\t\t\t\tArrays.copyOf(possible_values, possible_values.length);\n\t\t} else {\n\t\t\tif (value != null) {\n\t\t\t\tguessPossibleValues();\n\t\t\t} // end of if (possible_values == null && value != null)\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new <code>PropertyItem</code> instance.\n\t *\n\t */\n\tpublic PropertyItem(String name, Object def_value) {\n\t\tthis.name = name;\n\t\tthis.value = def_value;\n\t\tif (value != null) {\n\t\t\tguessPossibleValues();\n\t\t} // end of if (possible_values == null && value != null)\n\t}\n\n\t/**\n\t * Creates a new <code>PropertyItem</code> instance.\n\t *\n\t */\n\tpublic PropertyItem(String name, String display_name, Object def_value) {\n\t\tthis.name = name;\n\t\tthis.display_name = display_name;\n\t\tthis.value = def_value;\n\t\tif (value != null) {\n\t\t\tguessPossibleValues();\n\t\t} // end of if (possible_values == null && value != null)\n\t}\n\n\tpublic boolean isMultiValue() {\n\t\treturn multiValue;\n\t}\n\n\tprivate void guessPossibleValues() {\n\t\tif (value instanceof DefaultValues) {\n\t\t\tDefaultValues en_val = (DefaultValues)value;\n\t\t\tpossible_values = en_val.strValues();\n\t\t} // end of if (value instanceof Enum)\n\t\tif (value instanceof Boolean) {\n\t\t\tpossible_values = new String[] {\"true\", \"false\"};\n\t\t} // end of if (value instanceof Boolean)\n\t}\n\n\t/**\n\t * Gets the value of name\n\t *\n\t * @return the value of name\n\t */\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\t/**\n\t * Sets the value of name\n\t *\n\t * @param argName Value to assign to this.name\n\t */\n\tpublic void setName(final String argName) {\n\t\tthis.name = argName;\n\t}\n\n\t/**\n\t * Gets the value of display_name\n\t *\n\t * @return the value of display_name\n\t */\n\tpublic String getDisplay_name() {\n\t\treturn (this.display_name != null ? this.display_name : this.name);\n\t}\n\n\t/**\n\t * Sets the value of display_name\n\t *\n\t * @param argDisplay_name Value to assign to this.display_name\n\t */\n\tpublic void setDisplay_name(final String argDisplay_name) {\n\t\tthis.display_name = argDisplay_name;\n\t}\n\n\t/**\n\t * Gets the value of the property\n\t *\n\t * @return the value of value\n\t */\n\tpublic Object getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * Sets the value of the property\n\t *\n\t * @param argValue Value to assign to this.value\n\t */\n\tpublic void setValue(final Object argValue) {\n\t\tthis.value = argValue;\n\t}\n\n\t/**\n\t * Gets the value of possible_values\n\t *\n\t * @return the value of possible_values\n\t */\n\tpublic String[] getPossible_values() {\n\t\treturn (this.possible_values != null ?\n\t\t\tArrays.copyOf(this.possible_values, this.possible_values.length)\n\t\t\t: null);\n\t}\n\n\t/**\n\t * Sets the value of possible_values\n\t *\n\t * @param argPossible_values Value to assign to this.possible_values\n\t */\n\tpublic void setPossible_values(final String[] argPossible_values) {\n\t\tthis.possible_values = (argPossible_values != null ?\n\t\t\tArrays.copyOf(argPossible_values, argPossible_values.length)\n\t\t\t: null);\n\t}\n\n\t/**\n\t * Gets the value of description\n\t *\n\t * @return the value of description\n\t */\n\tpublic String getDescription() {\n\t\treturn this.description;\n\t}\n\n\t/**\n\t * Sets the value of description\n\t *\n\t * @param argDescription Value to assign to this.description\n\t */\n\tpublic void setDescription(final String argDescription) {\n\t\tthis.description = argDescription;\n\t}\n\n\tpublic String toString() {\n\t\treturn value != null ? value.toString() : \"\";\n\t}\n\n} // PropertyItem\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/PubSubTestsTask.java",
    "content": "/*\n * PubSubTestsTask.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.sys.TigaseRuntime;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Date;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Created: Jan 22, 2009 11:02:59 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PubSubTestsTask\n\t\t\t\textends RepoRosterTask {\n\tprivate static final String[] IQ_PUBSUB_CONFIGURE_PATH = { \"iq\", \"pubsub\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"configure\" };\n\tprivate static final String[] IQ_PUBSUB_PATH               = { \"iq\", \"pubsub\" };\n\tprivate static final String[] IQ_PUBSUB_SUBSCRIPTIONS_PATH = { \"iq\", \"pubsub\",\n\t\t\t\t\t\"subscriptions\" };\n\tprivate static final String TASK_HELP =\n\t\t\"This is a PubSub component testing task.\" +\n\t\t\" Only for testing and only to be run by an admnistrator.\";\n\tprivate static final String TASK_TYPE = \"PubSub tests\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long delay   = 2000;\n\tprivate Element conf =\n\t\tnew Element(\n\t\t\t\t\"x\",\n\t\t\t\tnew Element[] {\n\t\t\t\t\tnew Element(\n\t\t\t\t\t\t\t\"field\",\n\t\t\t\t\t\t\tnew Element[] {\n\t\t\t\t\t\t\t\tnew Element(\n\t\t\t\t\t\t\t\t\t\t\"value\",\n\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/pubsub#node_config\") }, new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\"var\",\n\t\t\t\t\t\t\t\t\t\t\t\"type\" }, new String[] { \"FORM_TYPE\", \"hidden\" }),\n\t\t\t\t\tnew Element(\"field\", new Element[] { new Element(\"value\", \"0\") },\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"pubsub#notify_sub_aff_state\" }) }, new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\"xmlns\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\" }, new String[] { \"jabber:x:data\", \"submit\" });\n\tprivate String[] last_nodes   = null;\n\tprivate long packetsGenerated = 0;\n\tprivate boolean stop          = false;\n\n\t//~--- enums ----------------------------------------------------------------\n\n\tprivate enum command {\n\t\thelp(\" - Displays help info.\"), newnodes(\" N - Create N nodes in the pubsub.\"),\n\t\tnewsubscr(\" node-name N - create N subscriptions for a given node name.\"),\n\t\tnewnodessubscr(\" N M -  create N nodes with M subscriptions each.\"),\n\t\tsetdelay(\" N - set the delay between sending node creation packet.\"),\n\t\tstop(\" - Stops the current packets generation.\");\n\n\t\tprivate String helpText = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate command(String helpText) {\n\t\t\tthis.helpText = helpText;\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * \n\t\t */\n\t\tpublic String getHelp() {\n\t\t\treturn helpText;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, PropertyItem> getDefaultParams() {\n\t\tMap<String, PropertyItem> defs = super.getDefaultParams();\n\n\t\tdefs.put(DESCRIPTION_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DESCRIPTION_PROP_KEY, DESCRIPTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"PubSub Testing Task\"));\n\t\tdefs.put(MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(MESSAGE_TYPE_PROP_KEY, MESSAGE_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMessageType.NORMAL));\n\t\tdefs.put(ONLINE_ONLY_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(ONLINE_ONLY_PROP_KEY, ONLINE_ONLY_DISPL_NAME, false));\n\t\tdefs.put(REPLACE_SENDER_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(REPLACE_SENDER_PROP_KEY, REPLACE_SENDER_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSenderAddress.LEAVE));\n\t\tdefs.put(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTRICTIONS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSubscrRestrictions.MODERATED));\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getHelp() {\n\t\treturn TASK_HELP;\n\t}\n\n\t@Override\n\tpublic String getType() {\n\t\treturn TASK_TYPE;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected boolean addOutPacket(Packet packet) {\n\t\t++packetsGenerated;\n\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\t@Override\n\tprotected void processMessage(Packet packet, Queue<Packet> results) {\n\t\tif (isPostCommand(packet)) {\n\t\t\trunCommand(packet, results);\n\t\t}\n\t}\n\n\tprivate void addSubscriptionsForNode(JID from, JID to, String node, int subscr) {\n\t\tint j      = 0;\n\t\tElement el = createPubSubEl(from, to, \"ids-\" + (++j), node, \"subscriptions\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/pubsub#owner\");\n\n\t\tfor (int i = 0; i < subscr; i++) {\n\t\t\tElement subs = new Element(\"subscription\", new String[] { \"jid\", \"subscription\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"frank-\" + i + \"@\" + getJID().getDomain(),\n\t\t\t\t\t\t\t\"subscribed\" });\n\n\t\t\tel.findChildStaticStr(IQ_PUBSUB_SUBSCRIPTIONS_PATH).addChild(subs);\n\t\t\tif (i % 100 == 0) {\n\t\t\t\taddOutPacket(Packet.packetInstance(el, from, to));\n\t\t\t\tel = createPubSubEl(from, to, \"ids-\" + (++j), node, \"subscriptions\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/pubsub#owner\");\n\t\t\t}\n\t\t}\n\t\taddOutPacket(Packet.packetInstance(el, from, to));\n\t}\n\n\tprivate void addSubscriptionsForNodes(JID from, JID to, String[] nodes, int subscr) {\n\t\tfor (String node : nodes) {\n\t\t\taddSubscriptionsForNode(from, to, node, subscr);\n\t\t}\n\t}\n\n\tprivate String commandsHelp() {\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tfor (command comm : command.values()) {\n\t\t\tsb.append(\"//\" + comm.name() + comm.getHelp() + \"\\n\");\n\t\t}\n\n\t\treturn \"Available commands are:\\n\" + sb.toString();\n\t}\n\n\tprivate String[] createNodes(JID from, JID to, int... nums) {\n\t\tString[] nodes = new String[nums[0]];\n\n\t\tfor (int i = 0; i < nums[0]; i++) {\n\t\t\tif (stop) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tString node = \"node-\" + i;\n\n\t\t\tnodes[i] = node;\n\n\t\t\tElement el = createPubSubEl(from, to, \"id-\" + i, node, \"create\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/pubsub\");\n\n\t\t\tel.findChildStaticStr(IQ_PUBSUB_PATH).addChild(new Element(\"configure\"));\n\t\t\tel.findChildStaticStr(IQ_PUBSUB_CONFIGURE_PATH).addChild(conf);\n\t\t\taddOutPacket(Packet.packetInstance(el, from, to));\n\t\t\tif ((nums.length > 1) && (nums[1] > 0)) {\n\t\t\t\taddSubscriptionsForNode(from, to, node, nums[1]);\n\t\t\t}\n\t\t\twhile (memoryLow()) {\n\t\t\t\ttry {\n\t\t\t\t\tSystem.gc();\n\t\t\t\t\tThread.sleep(delay);\n\t\t\t\t} catch (Exception e) {}\n\t\t\t}\n\t\t}\n\t\tstop = false;\n\n//  if (nums.length > 1 && nums[1] > 0) {\n//    addSubscriptionsForNodes(from, nodes, nums[1]);\n//  }\n\t\treturn nodes;\n\t}\n\n\tprivate Element createPubSubEl(JID from, JID to, String id, String node,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t String pubsub_call, String xmlns) {\n\t\tElement elem = new Element(\"iq\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element(\"pubsub\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element(pubsub_call, new String[] { \"node\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { node }) }, new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"xmlns\" }, new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t xmlns }) }, new String[] { \"type\",\n\t\t\t\t\t\t\"from\", \"to\", \"id\" }, new String[] { \"set\", from.toString(), to.toString(),\n\t\t\t\t\t\tid });\n\n\t\treturn elem;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isPostCommand(Packet packet) {\n\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body != null) {\n\t\t\tfor (command comm : command.values()) {\n\t\t\t\tif (body.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate boolean memoryLow() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getHeapMemUsage() > 80f;\n\t}\n\n\t;\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate int[] parseNumbers(String[] args, int pos, int num) {\n\n\t\t// The first arg is command name, after that command parameters come\n\t\tint[] res = new int[num];\n\n\t\tfor (int i = 0; i < res.length; i++) {\n\t\t\ttry {\n\t\t\t\tres[i] = Integer.parseInt(args[i + pos]);\n\t\t\t} catch (Exception e) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprivate void runCommand(final Packet packet, Queue<Packet> results) {\n\t\tString body               = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\t\tfinal String[] body_split = body.split(\"\\\\s\");\n\t\tcommand comm              = command.valueOf(body_split[0].substring(2));\n\t\tfinal int[] pars;\n\t\tfinal JID to = JID.jidInstanceNS(\"pubsub.\" + getJID().getDomain());\n\n\t\tswitch (comm) {\n\t\tcase help :\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, commandsHelp(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Commands description\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\tbreak;\n\n\t\tcase setdelay :\n\t\t\tpars = parseNumbers(body_split, 1, 1);\n\t\t\tif (pars != null) {\n\t\t\t\tdelay = pars[0];\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase newnodes :\n\t\t\tpars = parseNumbers(body_split, 1, 1);\n\t\t\tif (pars != null) {\n\t\t\t\taddOutPacket(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tStanzaType.chat, \"Task accepted, processing...\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket.getStanzaId()));\n\t\t\t\trunInThread(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tlast_nodes = createNodes(packet.getStanzaFrom(), to, pars);\n\t\t\t\t\t}\n\t\t\t\t}, packet);\n\t\t\t} else {\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Incorrect command parameters.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase newsubscr :\n\t\t\tif (last_nodes != null) {\n\t\t\t\tpars = parseNumbers(body_split, 2, 1);\n\t\t\t\tif (pars != null) {\n\t\t\t\t\taddOutPacket(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tStanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Task accepted, processing...\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket.getStanzaId()));\n\t\t\t\t\trunInThread(new Runnable() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\taddSubscriptionsForNode(packet.getStanzaFrom(), to, body_split[1], pars[0]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, packet);\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Incorrect command parameters.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"There are no pubsub nodes created yet.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase newnodessubscr :\n\t\t\tpars = parseNumbers(body_split, 1, 2);\n\t\t\tif (pars != null) {\n\t\t\t\taddOutPacket(\n\t\t\t\t\t\tMessage.getMessage(\n\t\t\t\t\t\t\tpacket.getStanzaTo(), packet.getStanzaFrom(), StanzaType.chat,\n\t\t\t\t\t\t\t\"\" + new Date() + \" Task accepted, processing...\", \"PubSub testing task\",\n\t\t\t\t\t\t\tnull, packet.getStanzaId()));\n\t\t\t\trunInThread(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tlast_nodes = createNodes(packet.getStanzaFrom(), to, pars);\n\t\t\t\t\t}\n\t\t\t\t}, packet);\n\t\t\t} else {\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Incorrect command parameters.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"PubSub testing task\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase stop :\n\t\t\tstop = true;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate void runInThread(final Runnable job, final Packet packet) {\n\t\tThread thr = new Thread() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tlong gen_start = System.currentTimeMillis();\n\n\t\t\t\tjob.run();\n\n\t\t\t\tlong gen_end   = System.currentTimeMillis();\n\t\t\t\tlong gen_time  = gen_end - gen_start;\n\t\t\t\tlong gen_hours = gen_time / 3600000;\n\t\t\t\tlong gen_mins  = (gen_time - (gen_hours * 3600000)) / 60000;\n\t\t\t\tlong gen_secs  = (gen_time - ((gen_hours * 3600000) + (gen_mins * 60000))) / 1000;\n\n\t\t\t\taddOutPacket(\n\t\t\t\t\t\tMessage.getMessage(\n\t\t\t\t\t\t\tpacket.getStanzaTo(), packet.getStanzaFrom(), StanzaType.chat,\n\t\t\t\t\t\t\t\"\" + new Date() + \" Generation of the test data completed.\\n\" +\n\t\t\t\t\t\t\t\"Generated in: \" + gen_hours + \"h, \" + gen_mins + \"m, \" + gen_secs +\n\t\t\t\t\t\t\t\"sec\" + \", packets generated: \" + packetsGenerated, \"PubSub testing task\",\n\t\t\t\t\t\t\t\tnull, packet.getStanzaId()));\n\t\t\t}\n\t\t};\n\n\t\tthr.setName(\"pubsub-test-job\");\n\t\tthr.start();\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/ReceiverTaskIfc.java",
    "content": "/*\n * ReceiverTaskIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\nimport tigase.stats.StatRecord;\n\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * This is <code>StanzaReceiver</code> task which can receive XMPP packets\n * to do something with them. It may produce new XMPP packets in exchange\n * to send them back or to other users.\n * <p>\n * Created: Wed May  9 13:52:57 2007\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ReceiverTaskIfc {\n\t/**\n\t * <code>destroy</code> method is called when the task is being permanently\n\t * deleted. The method should take care of sending notification to all\n\t * subscribed users that the task is being deleted and should also clear\n\t * databases from all task data.\n\t *\n\t * @param results a <code>Queue</code> value with all packets needed to send\n\t * upon task deletion.\n\t */\n\tvoid destroy(Queue<Packet> results);\n\n\t/**\n\t * <code>init</code> method initializes task. It allows also for a task to\n\t * send initial stanzas to user like <code>available</code>\n\t * <strong>presence</strong> or any other stanza which does make sense to\n\t * send at startup time.\n\t *\n\t * @param results a {@code Queue<Packet>} is a collection of\n\t * result packets to send out.\n\t */\n\tvoid init(Queue<Packet> results);\n\n\t/**\n\t * <code>processPacket</code> method takes a packet addressed to this task\n\t * as a parameter and does something with the packet. If as a result of\n\t * input packet processing it generates some other packets to send they\n\t * should be included in the <code>results</code> queue.\n\t *\n\t * @param packet a <code>Packet</code> input packet for processing.\n\t * @param results a {@code Queue<Packet>} is a collection of\n\t * result packets to send out.\n\t */\n\tvoid processPacket(Packet packet, Queue<Packet> results);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results is a {@code Queue<Packet>}\n\t * @param subscr is a <code>JID</code>\n\t */\n\tvoid removeSubscribers(Queue<Packet> results, JID... subscr);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * <code>getDefaultParams</code> method return task instance default configuration\n\t * parameters. The map should contains all possible parameters accepted by\n\t * the task in <code>setParams</code> method. Values may be empty but may\n\t * not be <code>null</code>. All of parameters should be converted to\n\t * <code>String</code> type to make it possible to display them in ad-hoc\n\t * command x-form. Parameters then should be converted back to whatever format\n\t * is needed when passed back in <code>setParams</code> method.\n\t * For more detailed information about configuration parameters please refer\n\t * to <code>setParams</code> method.\n\t *\n\t * @return a <code>Map</code> value with task instance configuration parameters.\n\t * @see #setParams(Map)\n\t */\n\tMap<String, PropertyItem> getDefaultParams();\n\n\t/**\n\t * <code>getDescription</code> method returns a description for task instance.\n\t * Let's say the user want's to create new <em>Interest group</em> for\n\t * cyclists. This property allows to set some more detailed information about\n\t * the group like: <em>This is group of ppl interested in mountain cycling\n\t * near Cambridge.</em>\n\t *\n\t * The description is set via properties using <code>DESCRIPTION_PROP_KEY</code>.\n\t *\n\t * @return a <code>String</code> value of task instance description;\n\t */\n\tString getDescription();\n\n\t/**\n\t * <code>getHelp</code> method returns task help information. This\n\t * general information about tasks abilties so when the user selects\n\t * task for creation he might know what the task is about. This is more\n\t * like class description rather then instance description.\n\t *\n\t * @return a <code>String</code> value of task class help information.\n\t */\n\tString getHelp();\n\n\t/**\n\t * <code>getInstance</code> method returns new task instance of this type.\n\t * This is something like <code>Class.newInstance()</code> but as this method\n\t * is called on the already created instance there is no danger of the number\n\t * of exceptions which could be normally thrown.\n\t *\n\t * @return a <code>ReceiverTaskIfc</code> new task instance of this type.\n\t */\n\tReceiverTaskIfc getInstance();\n\n\t/**\n\t * <code>getJID</code> method returns task instance\n\t * <strong>Jabber ID</strong>. Refer to corresponding <code>set</code>\n\t * method for more details.\n\t *\n\t * @return a <code>String</code> value of task instance JID,\n\t * @see #setJID\n\t */\n\tJID getJID();\n\n\t/**\n\t * <code>getParams</code> method return task instance configuration parameters.\n\t * For more detailed information about configuration parameters please refer\n\t * to corresponding <code>set</code> method.\n\t *\n\t * @return a <code>Map</code> value with task instance configuration parameters.\n\t * @see #setParams(Map)\n\t */\n\tMap<String, PropertyItem> getParams();\n\n\t/**\n\t * <code>getRoster</code> returns <code>roster</code> that is a collection with\n\t * all users subscribed to this task.\n\t *\n\t * @return a <code>Map</code> value with all user subscribed to this task.\n\t */\n\tMap<JID, RosterItem> getRoster();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param list is a <code>StatisticsList</code>\n\t */\n\tvoid getStatistics(StatisticsList list);\n\n\t/**\n\t * <code>getStats</code> method retorns list of statistics records. Have a look\n\t * at <code>StatRecord</code> description for more details.\n\t * @return a <code>List</code> of statistics records.\n\t * @see StatRecord\n\t */\n\tList<StatRecord> getStats();\n\n\t/**\n\t * <code>getType</code> method returns the task type name. This\n\t * name is displayed on the list of all tasks available for creation.\n\t * This is not a nick name of created task this is something more like\n\t * \"<em>Drupal forums connector</em>\" or \"<em>Interest group</em>\".\n\t * Like a Java class name is unique in JVM the task name must be\n\t * also inique for <code>StanzaReceiver.</code> Look at\n\t * <strong>task nick name</strong> for more details.\n\t *\n\t * @return a <code>String</code> value of the task name.\n\t */\n\tString getType();\n\n\t/**\n\t * <code>isAdmin</code> method checks whether user given as parameter is one\n\t * of defined admins. If user is the task owner it is also considered to be\n\t * task administrator.\n\t *\n\t * @param jid a <code>String</code> value of user JID.\n\t * @return a <code>boolean</code> value true if given user is either task admin\n\t * or task owner.\n\t */\n\tboolean isAdmin(JID jid);\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * <code>setJID</code> method sets tasks <strong>Jabber ID</strong>, unique\n\t * ID which is used to identify the task. Example of the resulting\n\t * Jabber ID for domain <code>tigase.org</code> and\n\t * <code>StanzaReceiver</code> component name <code>srec</code> would be:\n\t * <code>devs@srec.tigase.org</code>.\n\t * There can be many tasks of the same type (having the same\n\t * <strong>TaskType</strong>) but they have to have distinct JIDs.\n\t * Examples of possible JIDs names are: \"<em>admin-forum@srec.tigase.org</em>\",\n\t * \"<em>cycling-interest-group@srec.tigase.org</em>\".\n\t *\n\t * @param jid a <code>String</code> value of the nick name.\n\t */\n\tvoid setJID(JID jid);\n\n\t/**\n\t * <code>setParams</code> method sets <code>Map</code> with configuration\n\t * parameters. Some parameters are predefined and common for most of task\n\t * types but some tasks may require/accept extra parameters to work properly.\n\t *\n\t * @param params a <code>Map</code> value with configuration parameters.\n\t */\n\tvoid setParams(Map<String, Object> params);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri is a <code>RosterItem</code>\n\t * @param accepted is a <code>boolean</code>\n\t */\n\tvoid setRosterItemModerationAccepted(RosterItem ri, boolean accepted);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param srecv is a <code>StanzaReceiverIfc</code>\n\t */\n\tvoid setStanzaReceiver(StanzaReceiverIfc srecv);\n}    // ReceiverTaskIfc\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/RepoRosterTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xmpp.JID;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\nimport static tigase.server.sreceiver.TaskCommons.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class RepoRosterTask here.\n *\n *\n * Created: Sat May 12 23:41:52 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class RepoRosterTask extends AbstractReceiverTask {\n\tprivate static Logger log = Logger.getLogger(\"tigase.server.sreceiver.RepoRosterTask\");\n\tprivate static final String roster_node = \"/roster\";\n\tprivate static final String subscribed_key = \"subscribed\";\n\tprivate static final String owner_key = \"owner\";\n\tprivate static final String admin_key = \"admin\";\n\tprivate static final String moderation_accepted_key = \"moderation-accepted\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate boolean loaded = false;\n\tprivate UserRepository repository = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic RosterItem addToRoster(JID jid) {\n\t\tRosterItem ri = super.addToRoster(jid);\n\n\t\tsaveToRepository(ri);\n\n\t\treturn ri;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void destroy(Queue<Packet> results) {\n\t\tsuper.destroy(results);\n\n\t\ttry {\n\t\t\trepository.removeUser(getJID().getBareJID());\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem removing task data from repository\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws TigaseDBException\n\t */\n\tpublic void loadRoster() throws TigaseDBException {\n\t\tString[] roster = repository.getSubnodes(getJID().getBareJID(), roster_node);\n\n\t\tif (roster != null) {\n\t\t\tfor (String jid : roster) {\n\t\t\t\ttry {\n\t\t\t\t\tJID rjid = JID.jidInstance(jid);\n\n\t\t\t\t\tlog.fine(getJID() + \": \" + \" loadin from repository: \" + rjid);\n\t\t\t\t\taddToRoster(loadFromRepository(rjid));\n\t\t\t\t}    // end of for (String jid: roster)\n\t\t\t\t\t\tcatch (TigaseStringprepException ex) {\n\t\t\t\t\tLogger.getLogger(RepoRosterTask.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t\t}\n\t\t\t}      // end of for (String jid: roster)\n\t\t}        // end of if (roster != null)\n\t}\n\n\t@Override\n\tpublic RosterItem removeFromRoster(JID jid) {\n\t\tRosterItem ri = super.removeFromRoster(jid);\n\n\t\tif (ri != null) {\n\t\t\tremoveFromRepository(ri);\n\t\t}\n\n\t\treturn ri;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param map\n\t */\n\tpublic void setParams(final Map<String, Object> map) {\n\t\tif (map.get(USER_REPOSITORY_PROP_KEY) != null) {\n\t\t\trepository = (UserRepository) map.get(USER_REPOSITORY_PROP_KEY);\n\t\t}\n\n\t\tif ((repository != null) &&!loaded) {\n\t\t\ttry {\n\t\t\t\ttry {\n\t\t\t\t\trepository.addUser(getJID().getBareJID());\n\t\t\t\t} catch (UserExistsException e) {    /* Ignore, this is correct and expected */\n\t\t\t\t}\n\n\t\t\t\tloaded = true;\n\t\t\t\tloadRoster();\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem loading roster from repository\", e);\n\t\t\t}                                      // end of try-catch\n\t\t}                                        // end of if (repository != null && !loaded)\n\n\t\tsuper.setParams(map);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param admin\n\t */\n\tpublic void setRosterItemAdmin(RosterItem ri, boolean admin) {\n\t\tsuper.setRosterItemAdmin(ri, admin);\n\t\tsaveToRepository(ri);\n\t}\n\n\t@Override\n\tpublic void setRosterItemModerationAccepted(RosterItem ri, boolean accepted) {\n\t\tsuper.setRosterItemModerationAccepted(ri, accepted);\n\t\tsaveToRepository(ri);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param ri\n\t * @param owner\n\t */\n\tpublic void setRosterItemOwner(RosterItem ri, boolean owner) {\n\t\tsuper.setRosterItemOwner(ri, owner);\n\t\tsaveToRepository(ri);\n\t}\n\n\t@Override\n\tpublic void setRosterItemSubscribed(RosterItem ri, boolean subscribed) {\n\t\tsuper.setRosterItemSubscribed(ri, subscribed);\n\t\tlog.fine(getJID() + \": \" + \"Updating subscription for \" + ri.getJid() + \" to \"\n\t\t\t\t+ subscribed);\n\t\tsaveToRepository(ri);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate RosterItem loadFromRepository(JID jid) {\n\t\tlog.info(getJID() + \": Loading roster item for: \" + jid);\n\n\t\tString repo_node = roster_node + \"/\" + jid;\n\t\tRosterItem ri = new RosterItem(jid);\n\n\t\ttry {\n\t\t\tString tmp = repository.getData(getJID().getBareJID(), repo_node, subscribed_key);\n\n\t\t\tlog.info(getJID() + \": \" + jid + \": subscribed = \" + tmp);\n\t\t\tri.setSubscribed(parseBool(tmp));\n\t\t\ttmp = repository.getData(getJID().getBareJID(), repo_node, owner_key);\n\t\t\tri.setOwner(parseBool(tmp));\n\t\t\ttmp = repository.getData(getJID().getBareJID(), repo_node, admin_key);\n\t\t\tri.setAdmin(parseBool(tmp));\n\t\t\ttmp = repository.getData(getJID().getBareJID(), repo_node, moderation_accepted_key);\n\t\t\tri.setModerationAccepted(parseBool(tmp));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem loading roster data for: \" + jid, e);\n\t\t}    // end of try-catch\n\n\t\treturn ri;\n\t}\n\n\tprivate void removeFromRepository(RosterItem ri) {\n\t\tString repo_node = roster_node + \"/\" + ri.getJid();\n\n\t\ttry {\n\t\t\trepository.removeSubnode(getJID().getBareJID(), repo_node);\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem removing from roster data for: \" + ri.getJid(), e);\n\t\t}    // end of try-catch\n\t}\n\n\tprivate void saveToRepository(RosterItem ri) {\n\t\tlog.info(getJID() + \": Saving roster item for: \" + ri.getJid());\n\n//  Thread.dumpStack();\n\t\tString repo_node = roster_node + \"/\" + ri.getJid();\n\n\t\ttry {\n\t\t\tString tmp = Boolean.valueOf(ri.isSubscribed()).toString();\n\n\t\t\tlog.info(getJID() + \": \" + ri.getJid() + \": subscribed = \" + tmp);\n\t\t\trepository.setData(getJID().getBareJID(), repo_node, subscribed_key, tmp);\n\t\t\trepository.setData(getJID().getBareJID(), repo_node, owner_key,\n\t\t\t\t\tBoolean.valueOf(ri.isOwner()).toString());\n\t\t\trepository.setData(getJID().getBareJID(), repo_node, admin_key,\n\t\t\t\t\tBoolean.valueOf(ri.isAdmin()).toString());\n\t\t\trepository.setData(getJID().getBareJID(), repo_node, moderation_accepted_key,\n\t\t\t\t\tBoolean.valueOf(ri.isModerationAccepted()).toString());\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE,\n\t\t\t\t\t\"Problem saving roster data for: \" + \"JID = \" + getJID() + \", node = \" + repo_node\n\t\t\t\t\t\t+ \", RosterItem = \" + ri.getJid(), e);\n\t\t}    // end of try-catch\n\t}\n}    // RepoRosterTask\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/RosterItem.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\nimport tigase.xmpp.JID;\n\n/**\n * Describe class RosterItem here.\n *\n *\n * Created: Fri May 11 22:46:58 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class RosterItem {\n\n\tprivate JID jid = null;\n\tprivate boolean online = false;\n\tprivate boolean subscribed = false;\n\tprivate boolean moderation_accepted = false;\n\tprivate boolean owner = false;\n\tprivate boolean admin = false;\n\n\t/**\n\t * Creates a new <code>RosterItem</code> instance.\n\t *\n\t */\n\tpublic RosterItem(JID jid) {\n\t\tthis.jid = jid;\n\t}\n\n\t/**\n\t * Gets the value of jid\n\t *\n\t * @return the value of jid\n\t */\n\tpublic JID getJid() {\n\t\treturn this.jid;\n\t}\n\n\t/**\n\t * Gets the value of online\n\t *\n\t * @return the value of online\n\t */\n\tpublic boolean isOnline() {\n\t\treturn this.online;\n\t}\n\n\t/**\n\t * Sets the value of online\n\t *\n\t * @param argOnline Value to assign to this.online\n\t */\n\tpublic void setOnline(final boolean argOnline) {\n\t\tthis.online = argOnline;\n\t}\n\n\t/**\n\t * Gets the value of subscribed\n\t *\n\t * @return the value of subscribed\n\t */\n\tpublic boolean isSubscribed() {\n\t\treturn this.subscribed;\n\t}\n\n\t/**\n\t * Sets the value of subscribed\n\t *\n\t * @param argSubscribed Value to assign to this.subscribed\n\t */\n\tpublic void setSubscribed(final boolean argSubscribed) {\n\t\tthis.subscribed = argSubscribed;\n\t}\n\n\t/**\n\t * Gets the value of owner\n\t *\n\t * @return the value of owner\n\t */\n\tpublic boolean isOwner() {\n\t\treturn this.owner;\n\t}\n\n\t/**\n\t * Sets the value of owner\n\t *\n\t * @param argOwner Value to assign to this.owner\n\t */\n\tpublic void setOwner(final boolean argOwner) {\n\t\tthis.owner = argOwner;\n\t}\n\n\t/**\n\t * Gets the value of admin\n\t *\n\t * @return the value of admin\n\t */\n\tpublic boolean isAdmin() {\n\t\treturn this.admin;\n\t}\n\n\t/**\n\t * Sets the value of admin\n\t *\n\t * @param argAdmin Value to assign to this.admin\n\t */\n\tpublic void setAdmin(final boolean argAdmin) {\n\t\tthis.admin = argAdmin;\n\t}\n\n\t/**\n\t * Gets the value of moderation_accepted\n\t *\n\t * @return the value of moderation_accepted\n\t */\n\tpublic boolean isModerationAccepted() {\n\t\treturn this.moderation_accepted;\n\t}\n\n\t/**\n\t * Sets the value of moderation_accepted\n\t *\n\t * @param argModeration_accepted Value to assign to this.moderation_accepted\n\t */\n\tpublic void setModerationAccepted(final boolean argModeration_accepted) {\n\t\tthis.moderation_accepted = argModeration_accepted;\n\t}\n\n} // RosterItem\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/ShortNewsPublisher.java",
    "content": "/*\n * ShortNewsPublisher.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * This subscription tasks allows you to publish short news on your site.\n * In fact this task behaves exactly as <code>NewsDistributor</code> tasks\n * but it also writes all messages content to a table in database.\n * Web application can then read content from this table and publish it\n * on the Web site.\n *\n * Format of the table is as follows (schema definition in MySQL script):\n * <pre>\n * create table short_news (\n *   -- Automatic record ID\n *   snid            bigint unsigned NOT NULL auto_increment,\n *   -- Automaticly generated timestamp and automaticly updated on change\n *   publishing_time timestamp,\n *   -- Optional news type: 'shorts', 'minis', 'techs', 'funs'....\n *   news_type        varchar(10),\n *   -- Author JID\n *   author          varchar(128) NOT NULL,\n *   -- Short subject - this is short news, right?\n *   subject         varchar(128) NOT NULL,\n *   -- Short news message - this is short news, right?\n *   body            varchar(1024) NOT NULL,\n *   primary key(snid),\n *   key publishing_date (publishing_date),\n *   key author (author)\n * ) default character set utf8;\n * </pre>\n *\n * Created: Sat May 26 10:25:42 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ShortNewsPublisher\n\t\t\t\textends RepoRosterTask {\n\tprivate static final String DB_CONNECTION_DISPL_NAME = \"Database connection string\";\n\tprivate static final String DB_CONNECTION_PROP_KEY   = \"db-connection-string\";\n\tprivate static final String DB_CONNECTION_PROP_VAL   =\n\t\t\"jdbc:mysql://localhost/tigase?user=root&password=mypass\";\n\tprivate static final String DB_TABLE_DISPL_NAME  = \"Database table name\";\n\tprivate static final String DB_TABLE_PROP_KEY    = \"db-table\";\n\tprivate static final String DB_TABLE_PROP_VAL    = \"short_news\";\n\tprivate static final String NEWS_TYPE_DISPL_NAME = \"News type\";\n\tprivate static final String NEWS_TYPE_PROP_KEY   = \"news-type\";\n\tprivate static final String NEWS_TYPE_PROP_VAL   = \"minis\";\n\tprivate static final String TASK_HELP            =\n\t\t\"This tasks writes all messages to special table in database\" +\n\t\t\" called 'short_news' and notifies all subscribed users about\" +\n\t\t\" new post. Table in database keeps following information about\" +\n\t\t\" post: publishing_time, author, subject, body. This subscription\" +\n\t\t\" task is ideal for publish short news on your Web site.\" +\n\t\t\" Users can subscribe to the news just by adding task JID\" +\n\t\t\" to their roster, unsubscribing is equally simple - remove\" +\n\t\t\" JID from roster to stop receiving news. By default subscription\" +\n\t\t\" to this task is moderated.\"\n\t;\n\tprivate static final String TASK_TYPE = \"Short news publisher\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.server.ssender.JDBCTask\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * <code>conn</code> variable keeps connection to database.\n\t */\n\tprivate Connection conn = null;\n\n\t/**\n\t * <code>conn_valid_st</code> is a prepared statement keeping query used\n\t * to validate connection to database:\n\t * <pre>select 1</pre>\n\t */\n\tprivate PreparedStatement conn_valid_st = null;\n\n\t/**\n\t * <code>connectionValidateInterval</code> is kind of constant keeping minimum\n\t * interval for validating connection to database.\n\t */\n\tprivate long connectionValidateInterval = 1000 * 60;\n\n\t/**\n\t * <code>db_conn</code> field stores database connection string.\n\t */\n\tprivate String db_conn = null;\n\n\t/**\n\t * <code>delete_post</code> is a prepared statement for deleting post\n\t * from database.\n\t */\n\tprivate PreparedStatement delete_post = null;\n\n\t/**\n\t * <code>insert_post</code> is a prepared statement for inserting new\n\t * post to database.\n\t */\n\tprivate PreparedStatement insert_post = null;\n\n\t/**\n\t * <code>lastConnectionValidated</code> variable keeps time where the\n\t * connection was validated for the last time.\n\t */\n\tprivate long lastConnectionValidated = 0;\n\n\t/**\n\t * <code>newsType</code> is a type of news saved to database.\n\t */\n\tprivate String newsType = \"minis\";\n\n\t/**\n\t * <code>tableName</code> keeps a table name where are stanza packets waiting\n\t * for sending. Default is <code>xmpp_stanza</code>\n\t */\n\tprivate String tableName = \"short_news\";\n\n\t/**\n\t * <code>update_post</code> is a prepared statement for updating existing\n\t * post in database.\n\t */\n\tprivate PreparedStatement update_post = null;\n\t;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate enum command { help, delete, update; }\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param results\n\t */\n\tpublic void destroy(Queue<Packet> results) {\n\t\tsuper.destroy(results);\n\t\ttry {\n\t\t\tconn_valid_st.close();\n\t\t\tinsert_post.close();\n\t\t\tconn.close();\n\t\t} catch (Exception e) {\n\n\t\t\t// Ignore.\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Map<String, PropertyItem> getDefaultParams() {\n\t\tMap<String, PropertyItem> defs = super.getDefaultParams();\n\n\t\tdefs.put(MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(MESSAGE_TYPE_PROP_KEY, MESSAGE_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMessageType.NORMAL));\n\t\tdefs.put(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTRICTIONS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSubscrRestrictions.MODERATED));\n\t\tdefs.put(DESCRIPTION_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DESCRIPTION_PROP_KEY, DESCRIPTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Short news for the Web site...\"));\n\t\tdefs.put(DB_CONNECTION_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DB_CONNECTION_PROP_KEY, DB_CONNECTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tDB_CONNECTION_PROP_VAL));\n\t\tdefs.put(DB_TABLE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DB_TABLE_PROP_KEY, DB_TABLE_DISPL_NAME, DB_TABLE_PROP_VAL));\n\t\tdefs.put(NEWS_TYPE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(NEWS_TYPE_PROP_KEY, NEWS_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNEWS_TYPE_PROP_VAL));\n\n\t\treturn defs;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getHelp() {\n\t\treturn TASK_HELP;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getType() {\n\t\treturn TASK_TYPE;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param map\n\t */\n\tpublic void setParams(final Map<String, Object> map) {\n\t\tsuper.setParams(map);\n\n\t\tMap<String, PropertyItem> props = getParams();\n\n\t\tif (map.get(DB_TABLE_PROP_KEY) != null) {\n\t\t\ttableName = (String) map.get(DB_TABLE_PROP_KEY);\n\t\t\tprops.put(DB_TABLE_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(DB_TABLE_PROP_KEY, DB_TABLE_DISPL_NAME, tableName));\n\t\t}\n\t\tif (map.get(NEWS_TYPE_PROP_KEY) != null) {\n\t\t\tnewsType = (String) map.get(NEWS_TYPE_PROP_KEY);\n\t\t\tprops.put(NEWS_TYPE_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(NEWS_TYPE_PROP_KEY, NEWS_TYPE_DISPL_NAME, newsType));\n\t\t}\n\t\tif (map.get(DB_CONNECTION_PROP_KEY) != null) {\n\t\t\tdb_conn = (String) map.get(DB_CONNECTION_PROP_KEY);\n\t\t\tprops.put(DB_CONNECTION_PROP_KEY,\n\t\t\t\t\t\t\t\tnew PropertyItem(DB_CONNECTION_PROP_KEY, DB_CONNECTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t db_conn));\n\t\t\ttry {\n\t\t\t\tinitRepo();\n\t\t\t} catch (SQLException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem initializing database connection.\", e);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void processMessage(Packet packet, Queue<Packet> results) {\n\t\tif (isPostCommand(packet)) {\n\t\t\trunCommand(packet, results);\n\t\t} else {\n\t\t\tsuper.processMessage(packet, results);\n\t\t\taddPost(packet, results);\n\t\t}\n\t}\n\n\tprivate void addPost(Packet packet, Queue<Packet> results) {\n\t\ttry {\n\t\t\tcheckConnection();\n\n\t\t\tString author  = packet.getStanzaFrom().getBareJID().toString();\n\t\t\tString subject = packet.getElemCDataStaticStr(Message.MESSAGE_SUBJECT_PATH);\n\t\t\tString body    = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\t\tif (body != null) {\n\t\t\t\tif ((subject == null) || (subject.length() == 0)) {\n\t\t\t\t\tint dotIdx = body.indexOf('.');\n\n\t\t\t\t\tif (dotIdx > 0) {\n\t\t\t\t\t\tsubject = body.substring(0, dotIdx);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsubject = \"--\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinsert_post.setString(1, author);\n\t\t\t\tinsert_post.setString(2, XMLUtils.unescape(subject));\n\t\t\t\tinsert_post.setString(3, XMLUtils.unescape(body));\n\t\t\t\tinsert_post.executeUpdate();\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Your post has been successfuly submitted.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Short news submitions result.\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t\t} else {\n\n\t\t\t\t// if body is null it might be an empty message used for\n\t\t\t\t// announcing other side that the user has just started typing\n\t\t\t\t// message, such messages we just ignore\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Missing body, post has NOT been submitted.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Short news submitions result.\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem inserting new post: \" + packet.toString(), e);\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"There was a problem with post submitting: \" + e,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Short news submitions result.\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t}\n\t}\n\n\t/**\n\t * <code>checkConnection</code> method checks whether connection to database\n\t * is still valid, if not it simply reconnect and reinitializes database\n\t * backend.\n\t *\n\t * @return a <code>boolean</code> value\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate boolean checkConnection() throws SQLException {\n\t\ttry {\n\t\t\tlong tmp = System.currentTimeMillis();\n\n\t\t\tif ((tmp - lastConnectionValidated) >= connectionValidateInterval) {\n\t\t\t\tconn_valid_st.executeQuery();\n\t\t\t\tlastConnectionValidated = tmp;\n\t\t\t}    // end of if ()\n\t\t} catch (Exception e) {\n\t\t\tinitRepo();\n\t\t}      // end of try-catch\n\n\t\treturn true;\n\t}\n\n\tprivate String commandsHelp() {\n\t\treturn \"Available commands are:\\n\" + \"//help - display this help info\\n\" +\n\t\t\t\t\t \"//update N - update post number N, posts content to update\\n\" +\n\t\t\t\t\t \"             starts from the next line\\n\" +\n\t\t\t\t\t \"//delete N - remove post number N\";\n\t}\n\n\tprivate void deletePost(long snid) throws SQLException {\n\t\tcheckConnection();\n\t\tdelete_post.setLong(1, snid);\n\t\tdelete_post.executeUpdate();\n\t}\n\n\t/**\n\t * <code>initRepo</code> method initializes database backend - connects to\n\t * database, creates prepared statements and sets basic variables.\n\t *\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate void initRepo() throws SQLException {\n\t\tconn = DriverManager.getConnection(db_conn);\n\t\tconn.setAutoCommit(true);\n\n\t\tString query = \"select 1;\";\n\n\t\tconn_valid_st = conn.prepareStatement(query);\n\t\tif ((newsType == null) || (newsType.length() == 0)) {\n\t\t\tquery = \"insert into \" + tableName + \" (news_type, author, subject, body) \" +\n\t\t\t\t\t\t\t\" values (null, ?, ?, ?)\";\n\t\t} else {\n\t\t\tquery = \"insert into \" + tableName + \" (news_type, author, subject, body) \" +\n\t\t\t\t\t\t\t\" values ('\" + newsType + \"', ?, ?, ?)\";\n\t\t}\n\t\tinsert_post = conn.prepareStatement(query);\n\t\tquery       = \"delete from \" + tableName + \" where snid = ?\";\n\t\tdelete_post = conn.prepareStatement(query);\n\t\tquery       = \"update \" + tableName + \" set subject = ?, body = ?\" +\n\t\t\t\t\t\t\t\t\t\" where snid = ? \";\n\t\tupdate_post = conn.prepareStatement(query);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isPostCommand(Packet packet) {\n\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body != null) {\n\t\t\tfor (command comm : command.values()) {\n\t\t\t\tif (body.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void runCommand(Packet packet, Queue<Packet> results) {\n\t\tString body         = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\t\tString[] body_split = body.split(\" |\\n|\\r\");\n\n\t\ttry {\n\t\t\tcommand comm = command.valueOf(body_split[0].substring(2));\n\n\t\t\tswitch (comm) {\n\t\t\tcase help :\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, commandsHelp(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Commands description\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\t\tbreak;\n\n\t\t\tcase update :\n\t\t\t\tupdatePost(packet, Long.parseLong(body_split[1]));\n\t\t\t\tresults.offer(\n\t\t\t\t\t\tMessage.getMessage(\n\t\t\t\t\t\t\tpacket.getStanzaTo(), packet.getStanzaFrom(), StanzaType.normal,\n\t\t\t\t\t\t\t\"Post \" + body_split[1] + \" successfuly updated.\",\n\t\t\t\t\t\t\t\"Command execution result\", null, packet.getStanzaId()));\n\n\t\t\t\tbreak;\n\n\t\t\tcase delete :\n\t\t\t\tdeletePost(Long.parseLong(body_split[1]));\n\t\t\t\tresults.offer(\n\t\t\t\t\t\tMessage.getMessage(\n\t\t\t\t\t\t\tpacket.getStanzaTo(), packet.getStanzaFrom(), StanzaType.normal,\n\t\t\t\t\t\t\t\"Post \" + body_split[1] + \" successfuly deleted.\",\n\t\t\t\t\t\t\t\"Command execution result\", null, packet.getStanzaId()));\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tString error_text = \"Hm, something wrong with command executing...: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\tbody_split[0] + \", \" + body_split[1] + \", \" + e;\n\n\t\t\tlog.log(Level.WARNING, error_text, e);\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal, error_text,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Problem with command execution\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t}\n\t}\n\n\tprivate void updatePost(Packet packet, long snid) throws SQLException {\n\t\tcheckConnection();\n\n\t\tString subject = packet.getElemCDataStaticStr(Message.MESSAGE_SUBJECT_PATH);\n\t\tString body    = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif ((body != null) && (subject != null)) {\n\t\t\tint idx = body.indexOf('\\n');\n\n\t\t\tif ((idx > 0) && (idx < body.length() - 1) && (body.charAt(idx + 1) == '\\r')) {\n\t\t\t\t++idx;\n\t\t\t}\n\t\t\tupdate_post.setString(1, XMLUtils.unescape(subject));\n\t\t\tupdate_post.setString(2, XMLUtils.unescape(body.substring(idx)));\n\t\t\tupdate_post.setLong(3, snid);\n\t\t\tupdate_post.executeUpdate();\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/19\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/StanzaReceiver.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserRepository;\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.sreceiver.PropertyConstants.MessageType;\nimport tigase.server.sreceiver.PropertyConstants.SenderAddress;\nimport tigase.server.sreceiver.PropertyConstants.SenderRestrictions;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport tigase.conf.Configurable;\nimport tigase.conf.ConfigurationException;\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\nimport tigase.disco.XMPPService;\nimport tigase.stats.StatisticsList;\nimport tigase.util.ClassUtil;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * This is a sibling to <code>StanzaSender</code> class and offers just an\n * opposite functionality. It can receive XMPP packets to do something with\n * them. And what to do it depends on the destination address. Destination\n * address points to certain receiver task and this is up to task to decide what\n * to do with the stanza. Task address is just a usual Jabber ID:\n * <strong>task-short-name@srec.tigase.org</strong>.\n * <p>\n * Like public chat rooms in <strong>MUC</strong> tasks can be preconfigured in\n * the <code>StanzaReceiver</code> configuration or can be created on demand\n * using <code>ad-hoc</code> commands and <code>service-discovery</code>. User\n * can subscribe to some tasks and can add them to the roster just like a normal\n * contacts. This allows to use the functionality from all existing clients\n * without implementing any special protocols or extensions.\n * </p>\n * <p>\n * Possible tasks are:\n * </p>\n * <ul>\n * <li><strong>Interests groups</strong> - simple stanza (message) distribution\n * to a group of interested ppl. To receive this information user has to\n * subscribe to the task first. It is a bit like a <strong>MUC</strong> without\n * a chat room or like a mailing list.</li>\n * <li><strong>Persistent storage</strong> - which is like an archive of some\n * information for group of ppl.</li>\n * <li><strong>Web page publishing</strong> - this might be useful for web sites\n * with kind of <em>Short, instant news board</em> where selected users can send\n * information and they are published instantly. (Through the database for\n * example.)</li>\n * <li><strong>Forums integration</strong> - this might be useful for kind of\n * forums where you can post messages from Web site as well as from your Jabber\n * client.</li>\n * </ul>\n * <br>\n * <strong>Task creation parameters:</strong><br>\n * <ul>\n * <li><strong>Task short name</strong> - the nick name of the task which is\n * used to create Jabber ID for the task.</li>\n * <li><strong>Task description</strong> - description of the task what is the\n * purpose of the task.</li>\n * <li><strong>Task type</strong> - the server, through <code>ad-hoc</code>\n * commands should present available tasks types which can be created. User can\n * select a task to create. There may be some restrictions on tasks creation\n * like certain types can be created only by server administrator or some tasks\n * types can be created only once on single server and so on.</li>\n * <li><strong>Subscription list</strong> - server admin should be able to add\n * list of users who might be interested in subscription to the task. After task\n * is created <code>subscribe</code> presence is sent to these users and they\n * can accept the subscription or not.</li>\n * <li><strong>Subscription restrictions</strong> - who may subscribe to the\n * task like: <em>public task</em> - anybody can subscribe,\n * <em>local users only</em> - users from the local server (domain) only can\n * subscribe, <em>by regex</em> - regular expression matching JIDs,\n * <em>moderated subscription</em> - anybody may request subscription but the\n * creator of the task must approve the subscription.</li>\n * <li><strong>On line only</strong> - the task may distribute packets to online\n * users only.</li>\n * <li><strong>Replace sender address</strong> - whether sender address should\n * be replaced with task address. This might be useful depending where the\n * responses should go. If the list is kind on announces board like new version\n * release then maybe replies should go to the sender. If this is more like\n * topic discussion group then the reply should go to all subscribers.</li>\n * <li><strong>Message type</strong> - whether messages should be distributed as\n * a <code>chat</code>, <code>headline</code> or <code>normal</code>.</li>\n * <li><strong>Who can post</strong> - who can send a message for processing,\n * possible options are: <code>all</code>, <code>subscribed</code>,\n * <code>owner</code>, <code>list</code></li>\n * </ul>\n * There can be also some per task specific settings...\n * <br>\n * Created: Wed May 9 08:27:22 2007\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StanzaReceiver extends AbstractMessageReceiver implements Configurable,\n\t\tXMPPService, StanzaReceiverIfc {\n\tprivate static String[] ADMINS_PROP_VAL = { \"admin@localhost\", \"admin@hostname\" };\n\tprivate static final int CREATION_MAX_NO_PROP_VAL = 1;\n\n\t// private static final String LOCAL_DOMAINS_PROP_KEY = \"local-domains\";\n\t// private static String[] LOCAL_DOMAINS_PROP_VAL = {\"localhost\"};\n\n\t/** Field description */\n\tpublic static final String MY_DOMAIN_NAME_PROP_KEY = \"domain-name\";\n\n\t/** Field description */\n\tpublic static final String MY_DOMAIN_NAME_PROP_VAL = \"srecv.localhost\";\n\n\t// public static final String SIMPLE_JID_PROP_KEY = \"simple-jid\";\n\t// public static final String SIMPLE_JID_PROP_VAL = \"srecv@localhost\";\n\tprivate static final String SREC_REPO_CLASS_PROP_KEY = \"srec-repo-class\";\n\tprivate static final String SREC_REPO_URL_PROP_KEY = \"srec-repo-url\";\n\tprivate static final String TASKS_LIST_PROP_KEY = \"tasks-list\";\n\tprivate static final String[] TASKS_LIST_PROP_VAL = {};\n\tprivate static final String TASK_ACTIVE_PROP_KEY = \"active\";\n\tprivate static final String TASK_TYPES_PROP_NODE = \"task-types/\";\n\tprivate static final String TASK_TYPE_PROP_KEY = \"task-type\";\n\tprivate static final String TASK_TYPE_PROP_VAL = \"News Distribution\";\n\tprivate static final String TESTER_TASK_NAME = \"tester_1\";\n\tprivate static final String TESTER_TASK_TYPE = \"Tester Task\";\n\tprivate static final Logger log = Logger\n\t\t\t.getLogger(\"tigase.server.sreceiver.StanzaReceiver\");\n\tprivate static final String[] TASK_TYPES_PROP_VAL = { TASK_TYPE_PROP_VAL };\n\tprivate static final String TASK_TYPES_PROP_KEY = TASK_TYPES_PROP_NODE + \"list\";\n\tprivate static final boolean TASK_ACTIVE_PROP_VAL = true;\n\tprivate static final TaskCreationPolicy CREATION_POLICY_PROP_VAL =\n\t\t\tTaskCreationPolicy.ADMIN;\n\tprivate static final String CREATION_POLICY_PROP_KEY = TASK_TYPES_PROP_NODE\n\t\t\t+ \"default-policy\";\n\tprivate static final String CREATION_MAX_NO_PROP_KEY = TASK_TYPES_PROP_NODE\n\t\t\t+ \"default-max-number\";\n\tprivate static final String params_node = \"/params\";\n\tprivate static final String task_type_key = \"task-type\";\n\tprivate static final String tasks_node = \"/tasks\";\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\tprivate String[] admins = { \"admin@localhost\" };\n\n\t// private String simpleJid = null;\n\tprivate UserRepository repository = null;\n\n\t// /**\n\t// * Variable <code>defaultPolicy</code> specifies default task creation\n\t// policy.\n\t// * In other words who can create task. This is default setting for task\n\t// types\n\t// * not specified separately in configuration file.\n\t// */\n\t// private TaskCreationPolicy defaultPolicy = CREATION_POLICY_PROP_VAL;\n\tprivate ServiceEntity serviceEntity = null;\n\n\t/**\n\t * This maps keeps all available task types which can be instantiated by the\n\t * user.\n\t */\n\tprivate Map<String, TaskType> task_types = new ConcurrentHashMap<String, TaskType>();\n\n\t/**\n\t * This map keeps all active tasks instances as pairs: (JabberID, task)\n\t */\n\tprivate Map<String, ReceiverTaskIfc> task_instances =\n\t\t\tnew ConcurrentHashMap<String, ReceiverTaskIfc>();\n\n\t// private Set<String> local_domains = new HashSet<String>();\n\tprivate String my_hostname = MY_DOMAIN_NAME_PROP_VAL;\n\n\t/**\n\t * Variable <code>defaultMaxTasksNo</code> specifies default max number of\n\t * tasks for a task type. This is default setting for task types not specified\n\t * separately in configuration file.\n\t */\n\tprivate int defaultMaxTasksNo = CREATION_MAX_NO_PROP_VAL;\n\tprivate Map<String, TaskCommandIfc> commands =\n\t\t\tnew ConcurrentHashMap<String, TaskCommandIfc>();\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t * \n\t */\n\tpublic StanzaReceiver() {\n\t\ttry {\n\t\t\tSet<Class<ReceiverTaskIfc>> ctasks =\n\t\t\t\t\tClassUtil.getClassesImplementing(ReceiverTaskIfc.class);\n\n\t\t\tfor (Class<ReceiverTaskIfc> ctask : ctasks) {\n\t\t\t\tReceiverTaskIfc itask = ctask.newInstance();\n\n\t\t\t\ttask_types.put(itask.getType(), new TaskType(itask));\n\t\t\t} // end of for (Class<ReceiverTaskIfc> ctask: ctasks)\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not load ReceiverTaskIfc implementations\", e);\n\t\t} // end of try-catch\n\n\t\tTaskCommandIfc new_task = new NewTaskCommand();\n\n\t\tcommands.put(new_task.getNodeName(), new_task);\n\t\tnew_task = new TaskInstanceCommand();\n\t\tcommands.put(new_task.getNodeName(), new_task);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutPacket(Packet packet) {\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(final Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\t\tList<String> conf_tasks = new LinkedList<String>();\n\n\t\tconf_tasks.addAll(Arrays.asList(TASKS_LIST_PROP_VAL));\n\n\t\tif (params.get(GEN_CONF + \"ssend-forum-task\") != null) {\n\t\t\tString[] forum_ids =\n\t\t\t\t\t((String) params.get(GEN_CONF + \"ssend-forum-task\")).split(\",\");\n\n\t\t\tfor (String id : forum_ids) {\n\t\t\t\tString task_name = \"forum-\" + id;\n\n\t\t\t\tconf_tasks.add(task_name);\n\t\t\t\tdefs.put(task_name + \"/\" + TASK_ACTIVE_PROP_KEY, true);\n\t\t\t\tdefs.put(task_name + \"/\" + TASK_TYPE_PROP_KEY, TASK_TYPE_PROP_VAL);\n\n\t\t\t\tMap<String, PropertyItem> default_props =\n\t\t\t\t\t\ttask_types.get(TASK_TYPE_PROP_VAL).getTaskType().getDefaultParams();\n\n\t\t\t\tfor (Map.Entry<String, PropertyItem> entry : default_props.entrySet()) {\n\t\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(), entry.getValue().toString());\n\n\t\t\t\t\tif (entry.getKey().equals(ALLOWED_SENDERS_PROP_KEY)) {\n\t\t\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(),\n\t\t\t\t\t\t\t\tSenderRestrictions.OWNER.toString());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entry.getKey().equals(MESSAGE_TYPE_PROP_KEY)) {\n\t\t\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(),\n\t\t\t\t\t\t\t\tMessageType.NORMAL.toString());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entry.getKey().equals(REPLACE_SENDER_PROP_KEY)) {\n\t\t\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(),\n\t\t\t\t\t\t\t\tSenderAddress.REMOVE.toString());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entry.getKey().equals(TASK_OWNER_PROP_KEY)) {\n\t\t\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(), \"drupal-forum-\" + id + \"@\"\n\t\t\t\t\t\t\t\t+ my_hostname);\n\t\t\t\t\t}\n\t\t\t\t} // end of for ()\n\t\t\t}\n\t\t}\n\n\t\tfor (String task_name : TASKS_LIST_PROP_VAL) {\n\t\t\tdefs.put(task_name + \"/\" + TASK_ACTIVE_PROP_KEY, TASK_ACTIVE_PROP_VAL);\n\t\t\tdefs.put(task_name + \"/\" + TASK_TYPE_PROP_KEY, TASK_TYPE_PROP_VAL);\n\n\t\t\tMap<String, PropertyItem> default_props =\n\t\t\t\t\ttask_types.get(TASK_TYPE_PROP_VAL).getTaskType().getDefaultParams();\n\n\t\t\tfor (Map.Entry<String, PropertyItem> entry : default_props.entrySet()) {\n\t\t\t\tdefs.put(task_name + \"/props/\" + entry.getKey(), entry.getValue().toString());\n\t\t\t} // end of for ()\n\t\t} // end of for (String task_name: TASKS_LIST_PROP_VAL)\n\n\t\tif ((Boolean) params.get(GEN_TEST)) {\n\t\t\tlog.config(\"Activating tester task....\");\n\t\t\tconf_tasks.add(TESTER_TASK_NAME);\n\t\t\tdefs.put(TESTER_TASK_NAME + \"/\" + TASK_ACTIVE_PROP_KEY, true);\n\t\t\tdefs.put(TESTER_TASK_NAME + \"/\" + TASK_TYPE_PROP_KEY, TESTER_TASK_TYPE);\n\t\t\tdefs.put(TESTER_TASK_NAME + \"/props/\" + ALLOWED_SENDERS_PROP_KEY,\n\t\t\t\t\tSenderRestrictions.ALL.toString());\n\t\t\tdefs.put(TESTER_TASK_NAME + \"/props/\" + MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\tMessageType.NORMAL.toString());\n\t\t}\n\n\t\tdefs.put(TASKS_LIST_PROP_KEY, conf_tasks.toArray(new String[0]));\n\n\t\tString srec_repo_uri = null;\n\n\t\tif (params.get(GEN_SREC_DB_URI) != null) {\n\t\t\tsrec_repo_uri = (String) params.get(GEN_SREC_DB_URI);\n\t\t} else {\n\t\t\tif (params.get(RepositoryFactory.GEN_USER_DB_URI) != null) {\n\t\t\t\tsrec_repo_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t\t} // end of if (params.get(GEN_USER_DB_URI) != null)\n\t\t} // end of else\n\n\t\tdefs.put(SREC_REPO_URL_PROP_KEY, srec_repo_uri);\n\n\t\tif (params.get(GEN_SREC_ADMINS) != null) {\n\t\t\tADMINS_PROP_VAL = ((String) params.get(GEN_SREC_ADMINS)).split(\",\");\n\t\t} else {\n\t\t\tif (params.get(GEN_ADMINS) != null) {\n\t\t\t\tADMINS_PROP_VAL = ((String) params.get(GEN_ADMINS)).split(\",\");\n\t\t\t} else {\n\t\t\t\tADMINS_PROP_VAL = new String[1];\n\t\t\t\tADMINS_PROP_VAL[0] = \"admin@\" + getDefHostName();\n\t\t\t}\n\t\t} // end of if (params.get(GEN_SREC_ADMINS) != null) else\n\n\t\tdefs.put(ADMINS_PROP_KEY, ADMINS_PROP_VAL);\n\n\t\tString[] local_domains = DNSResolverFactory.getInstance().getDefaultHosts();\n\n\t\tif (params.get(GEN_VIRT_HOSTS) != null) {\n\t\t\tlocal_domains = ((String) params.get(GEN_VIRT_HOSTS)).split(\",\");\n\t\t}\n\n\t\t// defs.put(LOCAL_DOMAINS_PROP_KEY, LOCAL_DOMAINS_PROP_VAL);\n\t\tdefs.put(MY_DOMAIN_NAME_PROP_KEY, \"srecv.\" + local_domains[0]);\n\n\t\t// defs.put(SIMPLE_JID_PROP_KEY, \"srecv@\" + local_domains[0]);\n\t\tdefs.put(TASK_TYPES_PROP_KEY, TASK_TYPES_PROP_VAL);\n\t\tdefs.put(CREATION_POLICY_PROP_KEY, CREATION_POLICY_PROP_VAL.toString());\n\t\tdefs.put(CREATION_MAX_NO_PROP_KEY, CREATION_MAX_NO_PROP_VAL);\n\t\tdefs.put(TASK_TYPE_PROP_VAL + \"/\" + CREATION_POLICY_PROP_KEY,\n\t\t\t\tTaskCreationPolicy.ALL.toString());\n\t\tdefs.put(TASK_TYPE_PROP_VAL + \"/\" + CREATION_MAX_NO_PROP_KEY, 100);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tif ((jid != null) && jid.toString().startsWith(getName() + \".\")) {\n\t\t\treturn serviceEntity.getDiscoInfo(node);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\t\tif (jid.toString().startsWith(getName() + \".\")) {\n\t\t\treturn serviceEntity.getDiscoItems(node, null);\n\t\t} else {\n\t\t\tif (node == null) {\n\t\t\t\treturn Arrays.asList(serviceEntity.getDiscoItem(null, getName() + \".\" + jid));\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\n\t\tfor (ReceiverTaskIfc task : task_instances.values()) {\n\t\t\ttask.getStatistics(list);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t * \n\t * \n\t * @param jidOrName\n\t * \n\t * \n\t */\n\tpublic ReceiverTaskIfc getTask(String jidOrName) {\n\t\tif (jidOrName == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tReceiverTaskIfc task = task_instances.get(jidOrName.toLowerCase());\n\n\t\tif (task == null) {\n\t\t\ttask = task_instances.get(jidOrName + \"@\" + my_hostname);\n\t\t}\n\n\t\treturn task;\n\t}\n\n\t@Override\n\tpublic boolean isAdmin(JID jid) {\n\t\tlog.log(Level.INFO, \"Looking for JID: {0} in admins array: {1}\", new Object[] {\n\t\t\t\tjid.getBareJID().toString(), Arrays.toString(admins) });\n\t\treturn Arrays.binarySearch(admins, jid.getBareJID().toString()) >= 0;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(final Packet packet) {\n\t\tif (packet.isCommand()) {\n\t\t\tIq iqc = (Iq) packet;\n\t\t\tCommand.Action action = Command.getAction(iqc);\n\n\t\t\tif (action == Command.Action.cancel) {\n\t\t\t\tPacket result = iqc.commandResult(null);\n\n\t\t\t\taddOutPacket(result);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Packet result = packet.commandResult(\"result\");\n\t\t\t// TaskCommandIfc command = commands.get(\"*\");\n\t\t\t// if (command != null) {\n\t\t\t// command.processCommand(packet, result, this);\n\t\t\t// } // end of if (command != null)\n\t\t\t// addOutPacket(result);\n\t\t\t// return;\n\t\t\tPacket result = iqc.commandResult(Command.DataType.result);\n\t\t\tString str_command = iqc.getStrCommand();\n\n\t\t\tif (str_command != null) {\n\t\t\t\tString[] arr_command = str_command.split(\"/\");\n\n\t\t\t\tif (arr_command.length > 1) {\n\t\t\t\t\tTaskCommandIfc command = commands.get(arr_command[1]);\n\n\t\t\t\t\tif (command != null) {\n\t\t\t\t\t\tlog.fine(\"Processing task command: \" + arr_command[1]);\n\t\t\t\t\t\tcommand.processCommand(packet, result, this);\n\t\t\t\t\t} // end of if (command != null)\n\t\t\t\t} // end of if (arr_command.length > 1)\n\t\t\t} // end of if (str_command != null)\n\n\t\t\taddOutPacket(result);\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet.toString());\n\t\t}\n\n\t\tif (packet.getElemName().equals(\"iq\")) {\n\t\t\tprocessIQPacket(packet);\n\n\t\t\treturn;\n\t\t} // end of if (packet.getElemName().equals(\"iq\"))\n\n\t\tReceiverTaskIfc task = getTask(packet.getStanzaTo().toString());\n\n\t\tif (task == null) {\n\t\t\ttask = getTask(packet.getStanzaTo().getLocalpart());\n\t\t}\n\n\t\tif (task == null) {\n\t\t\tString resource = packet.getStanzaTo().getResource();\n\n\t\t\tif (resource != null) {\n\t\t\t\ttask = getTask(resource);\n\t\t\t}\n\t\t}\n\n\t\tif (task != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Found a task for packet: \" + task.getJID());\n\t\t\t}\n\n\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\t\ttask.processPacket(packet, results);\n\t\t\taddOutPackets(results);\n\t\t} // end of if (task != null)\n\t}\n\n\t// ~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(final Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.size() == 1) {\n\t\t\t// If props.size() == 1, it means this is a single property update \n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\t\tmy_hostname = (String) props.get(MY_DOMAIN_NAME_PROP_KEY);\n\n\t\t// simpleJid = (String)props.get(SIMPLE_JID_PROP_KEY);\n\t\tserviceEntity = new ServiceEntity(getName(), null, \"Stanza Receiver\");\n\t\tserviceEntity.addIdentities(new ServiceIdentity(\"component\", \"generic\",\n\t\t\t\t\"Stanza Receiver\"));\n\t\tserviceEntity.addFeatures(DEF_FEATURES);\n\n\t\tServiceEntity com =\n\t\t\t\tnew ServiceEntity(my_hostname, \"commands\", \"Tasks management commands\");\n\n\t\tcom.addFeatures(DEF_FEATURES);\n\t\tcom.addIdentities(new ServiceIdentity(\"automation\", \"command-list\",\n\t\t\t\t\"Tasks management commands\"));\n\t\tserviceEntity.addItems(com);\n\n\t\tfor (TaskCommandIfc comm : commands.values()) {\n\t\t\tServiceEntity item =\n\t\t\t\t\tnew ServiceEntity(my_hostname, comm.getNodeName(), comm.getDescription());\n\n\t\t\titem.addFeatures(CMD_FEATURES);\n\t\t\titem.addIdentities(new ServiceIdentity(\"automation\", \"command-node\", comm\n\t\t\t\t\t.getDescription()));\n\t\t\tcom.addItems(item);\n\t\t} // end of for (TaskCommandIfc comm: commands.values())\n\n\t\tadmins = (String[]) props.get(ADMINS_PROP_KEY);\n\t\tArrays.sort(admins);\n\n\t\t// addRouting(my_hostname);\n\t\ttry {\n\t\t\tString cls_name = (String) props.get(SREC_REPO_CLASS_PROP_KEY);\n\t\t\tString res_uri = (String) props.get(SREC_REPO_URL_PROP_KEY);\n\n\t\t\t// if (!res_uri.contains(\"autoCreateUser=true\")) {\n\t\t\t// res_uri += \"&autoCreateUser=true\";\n\t\t\t// } // end of if (!res_uri.contains(\"autoCreateUser=true\"))\n\t\t\trepository = RepositoryFactory.getUserRepository(cls_name, res_uri, null);\n\n\t\t\ttry {\n\t\t\t\trepository.addUser(getComponentId().getBareJID());\n\t\t\t} catch (UserExistsException e) { /* Ignore, this is correct and expected */\n\t\t\t}\n\n\t\t\tloadTasksFromRepository();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can't initialize repository: \", e);\n\t\t} // end of try-catch\n\n\t\tString[] tasks_list = (String[]) props.get(TASKS_LIST_PROP_KEY);\n\n\t\tif ((tasks_list != null) && (tasks_list.length > 0)) {\n\t\t\tfor (String task_name : tasks_list) {\n\t\t\t\tString task_type = (String) props.get(task_name + \"/\" + TASK_TYPE_PROP_KEY);\n\t\t\t\tMap<String, Object> task_params = new LinkedHashMap<String, Object>();\n\t\t\t\tString prep = task_name + \"/props/\";\n\n\t\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\t\tif (entry.getKey().startsWith(prep)) {\n\t\t\t\t\t\ttask_params.put(entry.getKey().substring(prep.length()), entry.getValue());\n\t\t\t\t\t} // end of if (entry.getKey().startsWith())\n\t\t\t\t} // end of for (Map.Entry entry: props.entrySet())\n\n\t\t\t\ttry {\n\t\t\t\t\taddTaskInstance(createTask(task_type,\n\t\t\t\t\t\t\tJID.jidInstance(task_name + \"@\" + my_hostname), task_params));\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tLogger.getLogger(StanzaReceiver.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t\t}\n\t\t\t} // end of for (String task_name: tasks_list)\n\t\t}\n\n\t\t// defaultPolicy =\n\t\t// TaskCreationPolicy.valueOf((String)props.get(CREATION_POLICY_PROP_KEY));\n\t\tdefaultMaxTasksNo = (Integer) props.get(CREATION_MAX_NO_PROP_KEY);\n\n\t\tString[] task_types_arr = (String[]) props.get(TASK_TYPES_PROP_KEY);\n\n\t\tfor (String task_t : task_types_arr) {\n\t\t\tTaskType tt = task_types.get(task_t);\n\n\t\t\tif (tt != null) {\n\t\t\t\tString policy_str = (String) props.get(task_t + \"/\" + CREATION_POLICY_PROP_KEY);\n\t\t\t\tTaskCreationPolicy policy = TaskCreationPolicy.valueOf(policy_str);\n\n\t\t\t\ttt.setCreationPolicy(policy);\n\n\t\t\t\tint max_inst = (Integer) props.get(task_t + \"/\" + CREATION_MAX_NO_PROP_KEY);\n\n\t\t\t\ttt.setMaxInstancesNo(max_inst);\n\t\t\t}\n\t\t}\n\n\t\t// local_domains =\n\t\t// new\n\t\t// HashSet<String>(Arrays.asList((String[])props.get(LOCAL_DOMAINS_PROP_KEY)));\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\tprotected void addTaskInstance(String task_type, String task_name,\n\t\t\tMap<String, Object> task_params) throws TigaseStringprepException {\n\t\taddTaskInstance(createTask(task_type, JID.jidInstance(task_name + \"@\" + my_hostname),\n\t\t\t\ttask_params));\n\t}\n\n\t/**\n\t * Describe <code>addTaskInstance</code> method here.\n\t * \n\t * @param task\n\t *          a <code>ReceiverTaskIfc</code> value\n\t */\n\tprotected void addTaskInstance(ReceiverTaskIfc task) {\n\t\tif (getTask(task.getJID().toString()) == null) {\n\t\t\taddTaskToInstances(task);\n\n\t\t\ttry {\n\t\t\t\tsaveTaskToRepository(task);\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem with saving task to repository: \" + task.getJID(),\n\t\t\t\t\t\te);\n\t\t\t} // end of try-catch\n\t\t} else {\n\n\t\t\t// Exception exep = new Exception(\"Attempt to add another task with jid: \"\n\t\t\t// +\n\t\t\t// task.getJID() + \", ignoring.\");\n\t\t\t// exep.fillInStackTrace();\n\t\t\tlog.log(Level.INFO, \"Attempt to add another task with jid: \" + task.getJID()\n\t\t\t\t\t+ \", ignoring.\");\n\t\t} // end of else\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\tprotected Map<String, ReceiverTaskIfc> getTaskInstances() {\n\t\treturn task_instances;\n\t}\n\n\tprotected Map<String, TaskType> getTaskTypes() {\n\t\treturn task_types;\n\t}\n\n\t// public String getSimpleJid() {\n\t// return simpleJid;\n\t// }\n\tprotected boolean isAllowedCreate(JID jid, String task_type) {\n\t\tTaskType tt = task_types.get(task_type);\n\n\t\tswitch (tt.getCreationPolicy()) {\n\t\t\tcase ADMIN:\n\t\t\t\treturn isAdmin(jid);\n\n\t\t\tcase LOCAL:\n\t\t\t\treturn isLocalDomain(jid.getDomain());\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\tprotected void removeTaskInstance(ReceiverTaskIfc task) {\n\t\tServiceEntity item =\n\t\t\t\tnew ServiceEntity(task.getJID().toString(), task.getJID().getLocalpart(),\n\t\t\t\t\t\ttask.getDescription());\n\n\t\tserviceEntity.removeItems(item);\n\t\ttask_instances.remove(task.getJID().toString());\n\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\ttask.destroy(results);\n\t\taddOutPackets(results);\n\t\ttask_types.get(task.getType()).instanceRemoved();\n\n\t\ttry {\n\t\t\tString repo_node = tasks_node + \"/\" + task.getJID();\n\n\t\t\trepository.removeSubnode(getComponentId().getBareJID(), repo_node);\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Problem removing task from repository: \" + task.getJID(), e);\n\t\t} // end of try-catch\n\t}\n\n\tprotected void removeTaskSubscribers(ReceiverTaskIfc task, JID... subscr) {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\ttask.removeSubscribers(results, subscr);\n\t\taddOutPackets(results);\n\t}\n\n\tprotected void saveTaskToRepository(ReceiverTaskIfc task) throws TigaseDBException {\n\t\tString repo_node = tasks_node + \"/\" + task.getJID();\n\n\t\trepository.setData(getComponentId().getBareJID(), repo_node, task_type_key,\n\t\t\t\ttask.getType());\n\n\t\tMap<String, PropertyItem> task_params = task.getParams();\n\n\t\trepo_node += params_node;\n\n\t\tfor (Map.Entry<String, PropertyItem> entry : task_params.entrySet()) {\n\t\t\tif (!entry.getKey().equals(USER_REPOSITORY_PROP_KEY)) {\n\t\t\t\tif (entry.getValue().getValue().getClass().isArray()) {\n\t\t\t\t\trepository.setDataList(getComponentId().getBareJID(), repo_node,\n\t\t\t\t\t\t\tentry.getKey(), (String[]) entry.getValue().getValue());\n\t\t\t\t\tlog.info(\"Saving task data list: \" + entry.getKey() + \", value: \"\n\t\t\t\t\t\t\t+ Arrays.toString((String[]) entry.getValue().getValue()));\n\t\t\t\t} else {\n\t\t\t\t\trepository.setData(getComponentId().getBareJID(), repo_node, entry.getKey(),\n\t\t\t\t\t\t\tentry.getValue().toString());\n\t\t\t\t\tlog.info(\"Saving task data: \" + entry.getKey() + \", value: \"\n\t\t\t\t\t\t\t+ entry.getValue().toString());\n\t\t\t\t}\n\t\t\t} // end of if (!entry.getKey().equals(USER_REPOSITORY_PROP_KEY))\n\t\t}\n\t}\n\n\tprivate void addTaskToInstances(ReceiverTaskIfc task) {\n\t\ttask_instances.put(task.getJID().toString(), task);\n\n\t\tServiceEntity item =\n\t\t\t\tnew ServiceEntity(task.getJID().toString(), task.getJID().getLocalpart(),\n\t\t\t\t\t\ttask.getDescription());\n\n\t\titem.addIdentities(new ServiceIdentity(\"component\", \"generic\", task.getJID()\n\t\t\t\t.toString()));\n\t\titem.addFeatures(CMD_FEATURES);\n\t\tserviceEntity.addItems(item);\n\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\ttask.init(results);\n\t\taddOutPackets(results);\n\t\ttask_types.get(task.getType()).instanceAdded();\n\t}\n\n\tprivate ReceiverTaskIfc createTask(String task_type, JID task_jid,\n\t\t\tMap<String, Object> task_params) {\n\n\t\t// ReceiverTaskIfc ttask = task_types.get(task_type);\n\t\tReceiverTaskIfc ntask = task_types.get(task_type).getTaskInstance();\n\n\t\tntask.setStanzaReceiver(this);\n\t\tntask.setJID(task_jid);\n\t\ttask_params.put(USER_REPOSITORY_PROP_KEY, repository);\n\t\tntask.setParams(task_params);\n\n\t\treturn ntask;\n\t}\n\n\tprivate void loadTasksFromRepository() throws TigaseDBException {\n\t\tString[] tasks_jids =\n\t\t\t\trepository.getSubnodes(getComponentId().getBareJID(), tasks_node);\n\n\t\tif (tasks_jids != null) {\n\t\t\tfor (String task_jid : tasks_jids) {\n\t\t\t\tStringBuilder repo_node = new StringBuilder(tasks_node + \"/\" + task_jid);\n\t\t\t\tString task_type =\n\t\t\t\t\t\trepository.getData(getComponentId().getBareJID(), repo_node.toString(),\n\t\t\t\t\t\t\t\ttask_type_key);\n\n\t\t\t\trepo_node.append(params_node);\n\n\t\t\t\tString[] keys =\n\t\t\t\t\t\trepository.getKeys(getComponentId().getBareJID(), repo_node.toString());\n\t\t\t\tMap<String, Object> task_params = new LinkedHashMap<String, Object>();\n\n\t\t\t\tif (keys != null) {\n\t\t\t\t\tfor (String key : keys) {\n\t\t\t\t\t\tString[] vals =\n\t\t\t\t\t\t\t\trepository.getDataList(getComponentId().getBareJID(),\n\t\t\t\t\t\t\t\t\t\trepo_node.toString(), key);\n\n\t\t\t\t\t\tif (vals.length == 1) {\n\t\t\t\t\t\t\ttask_params.put(key, vals[0]);\n\t\t\t\t\t\t\tlog.info(\"Loaded data: \" + key + \", value: \" + vals[0]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttask_params.put(key, vals);\n\t\t\t\t\t\t\tlog.info(\"Loaded data list: \" + key + \", value: \" + Arrays.toString(vals));\n\t\t\t\t\t\t}\n\t\t\t\t\t} // end of for (String key: keys)\n\t\t\t\t} // end of if (keys != null)\n\n\t\t\t\ttry {\n\t\t\t\t\taddTaskToInstances(createTask(task_type, JID.jidInstance(task_jid), task_params));\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't create task: \" + task_jid, e);\n\t\t\t\t}\n\t\t\t} // end of for (String task_jid: tasks_jids)\n\t\t} // end of if (tasks_jids != null)\n\t}\n\n\t/**\n\t * Describe <code>processIQPacket</code> method here.\n\t * \n\t * @param packet\n\t *          a <code>Packet</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\tprivate boolean processIQPacket(Packet packet) {\n\t\tboolean processed = false;\n\t\tElement iq = packet.getElement();\n\t\tElement query = iq.getChild(\"query\", INFO_XMLNS);\n\t\tElement query_rep = null;\n\n\t\tif ((query != null) && (packet.getType() == StanzaType.get)) {\n\t\t\tquery_rep = serviceEntity.getDiscoInfo(packet.getStanzaTo().getLocalpart());\n\t\t\tprocessed = true;\n\t\t} // end of if (query != null && packet.getType() == StanzaType.get)\n\n\t\tquery = iq.getChild(\"query\", ITEMS_XMLNS);\n\n\t\tif ((query != null) && (packet.getType() == StanzaType.get)) {\n\t\t\tquery_rep = query.clone();\n\n\t\t\tList<Element> items =\n\t\t\t\t\tserviceEntity.getDiscoItems(packet.getStanzaTo().getLocalpart(), packet\n\t\t\t\t\t\t\t.getStanzaTo().toString());\n\n\t\t\tif ((items != null) && (items.size() > 0)) {\n\t\t\t\tquery_rep.addChildren(items);\n\t\t\t} // end of if (items != null && items.size() > 0)\n\n\t\t\tprocessed = true;\n\t\t} // end of if (query != null && packet.getType() == StanzaType.get)\n\n\t\tif (query_rep != null) {\n\t\t\taddOutPacket(packet.okResult(query_rep, 0));\n\t\t} // end of if (query_rep != null)\n\n\t\treturn processed;\n\t}\n} // StanzaReceiver\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/StanzaReceiverIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.BareJID;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Dec 6, 2008 8:03:35 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface StanzaReceiverIfc {\n\tboolean addOutPacket(Packet packet);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tBareJID getDefHostName();\n\n\tString getName();\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TaskCommandIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\nimport tigase.server.Packet;\n\n/**\n * Describe class TaskCommandIfc here.\n *\n *\n * Created: Wed May 16 18:29:18 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface TaskCommandIfc {\n\n\tpublic static final String TASK_NAME_FIELD = \"Task name\";\n\tpublic static final String TASK_TYPE_FIELD = \"Task type\";\n\tpublic static final String STEP = \"step\";\n\n\t/**\n\t * Describe <code>getNodeName</code> method here.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tString getNodeName();\n\n\t/**\n\t * Describe <code>getDescription</code> method here.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tString getDescription();\n\n\t/**\n\t * Describe <code>processCommand</code> method here.\n\t *\n\t * @param packet a <code>Packet</code> value\n\t * @param result a <code>Packet</code> value\n\t * @param reciv a <code>StanzaReceiver</code> value\n\t */\n\tvoid processCommand(Packet packet, Packet result, StanzaReceiver reciv);\n\n} // TaskCommandIfc\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TaskCommons.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\nimport java.util.Map;\nimport tigase.server.Command;\nimport tigase.xml.XMLUtils;\nimport tigase.xml.Element;\nimport tigase.server.Packet;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\n\n/**\n * Describe class TaskCommons here.\n *\n *\n * Created: Mon May 21 08:31:25 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class TaskCommons {\n\n\tpublic static void propertyItems2Command(Map<String, PropertyItem> props,\n\t\tPacket result) {\n\t\tfor (Map.Entry<String, PropertyItem> entry: props.entrySet()) {\n\t\t\tif (!entry.getKey().equals(USER_REPOSITORY_PROP_KEY)) {\n\t\t\t\tPropertyItem item = entry.getValue();\n\t\t\t\tif (item.isMultiValue()) {\n\t\t\t\t\tif (item.getPossible_values() != null) {\n\t\t\t\t\t\tCommand.addFieldValue(result,\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getName()),\n\t\t\t\t\t\t\t\t\t\t(String[])item.getValue(),\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getDisplay_name()),\n\t\t\t\t\t\t\t\t\t\titem.getPossible_values(), item.getPossible_values());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCommand.addFieldValue(result,\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getName()),\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.toString()),\n\t\t\t\t\t\t\t\t\t\t\"text-single\", XMLUtils.escape(item.getDisplay_name()));\n\t\t\t\t\t} // end of if (item.getPossible_values() != null) else\n\t\t\t\t} else {\n\t\t\t\t\tif (item.getPossible_values() != null) {\n\t\t\t\t\t\tCommand.addFieldValue(result,\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getName()),\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.toString()),\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getDisplay_name()),\n\t\t\t\t\t\t\t\t\t\titem.getPossible_values(), item.getPossible_values());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCommand.addFieldValue(result,\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.getName()),\n\t\t\t\t\t\t\t\t\t\tXMLUtils.escape(item.toString()),\n\t\t\t\t\t\t\t\t\t\t\"text-single\", XMLUtils.escape(item.getDisplay_name()));\n\t\t\t\t\t} // end of if (item.getPossible_values() != null) else\n\t\t\t\t}\n\t\t\t} // end of if (!entry.getKey().equals(USER_REPOSITORY_PROP_KEY))\n\t\t} // end of for (Map.Entry entry: prop.entrySet())\n\t}\n\n\tpublic static Packet getPresence(JID from, JID to, StanzaType type,\n\t\tString nick, String status) {\n\t\tElement presence = new Element(\"presence\",\n\t\t\tnew String[] {\"to\", \"from\", \"type\"},\n\t\t\tnew String[] {to.toString(), from.toString(), type.toString()});\n\t\tif (nick != null) {\n\t\t\t//<x xmlns=\"vcard-temp:x:update\"><nickname>tus</nickname></x>\n\t\t\t//<nick xmlns=\"http://jabber.org/protocol/nick\">tus</nick>\n\t\t\tpresence.addChild(new Element(\"nick\", nick,\n\t\t\t\t\tnew String[] {\"xmlns\"},\n\t\t\t\t\tnew String[] {\"http://jabber.org/protocol/nick\"}));\n\t\t}\n\t\tif (status != null) {\n\t\t\tpresence.addChild(new Element(\"status\", status));\n\t\t}\n\t\treturn Packet.packetInstance(presence, from, to);\n\t}\n\n\tpublic static Packet getPresence(JID from, JID to, StanzaType type) {\n\t\treturn getPresence(to, from, type, null, null);\n\t}\n\n\tpublic static Packet getMessage(JID from, JID to, StanzaType type,\n\t\tString body) {\n\t\tElement message = new Element(\"message\",\n\t\t\tnew Element[] {\n\t\t\t\tnew Element(\"subject\", \"Automatic system message\"),\n\t\t\t\tnew Element(\"body\", body)},\n\t\t\tnew String[] {\"to\", \"from\", \"type\"},\n\t\t\tnew String[] {to.toString(), from.toString(), type.toString()});\n\t\treturn Packet.packetInstance(message, from, to);\n\t}\n\n\tpublic static boolean parseBool(final Object val) {\n\t\treturn val != null &&\n\t\t\t(val.toString().equalsIgnoreCase(\"yes\")\n\t\t\t\t|| val.toString().equalsIgnoreCase(\"true\")\n\t\t\t\t|| val.toString().equalsIgnoreCase(\"on\"));\n\t}\n\n} // TaskCommons\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TaskCreationPolicy.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\n/**\n * Describe enum TaskCreationPolicy here.\n *\n *\n * Created: Mon May 28 08:53:40 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum TaskCreationPolicy {\n\n\t ALL, LOCAL, ADMIN; \n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TaskInstanceCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.stats.StatRecord;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.TaskCommons.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class TaskInstanceCommand here.\n *\n *\n * Created: Fri May 18 22:45:40 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TaskInstanceCommand implements TaskCommandIfc {\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum ACTION {\n\t\tTASK_CONFIGURATION, USER_MANAGEMENT,\n\t\tREMOVE_TASK;\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * \n\t\t */\n\t\tpublic static String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\n\t\t\tfor (Enum val : values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t}    // end of for (Enum en_v: en_val.values())\n\n\t\t\treturn possible_values;\n\t\t}\n\t}\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum ROSTER_ACTION {\n\t\tUPDATE_DATA,\n\t\tREMOVE_USER;\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * \n\t\t */\n\t\tpublic static String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\n\t\t\tfor (Enum val : values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t}    // end of for (Enum en_v: en_val.values())\n\n\t\t\treturn possible_values;\n\t\t}\n\t}\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum USER_ACTION {\n\t\tAPROVE_PENDING_MODERATIONS, REJECT_PENDING_MODERATIONS,\n\t\tSELECT_USER;\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * \n\t\t */\n\t\tpublic static String[] strValues() {\n\t\t\tString[] possible_values = new String[values().length];\n\t\t\tint i = 0;\n\n\t\t\tfor (Enum val : values()) {\n\t\t\t\tpossible_values[i++] = val.toString();\n\t\t\t}    // end of for (Enum en_v: en_val.values())\n\n\t\t\treturn possible_values;\n\t\t}\n\t}\n\n\t//~--- static fields --------------------------------------------------------\n\n\tprivate static Logger log = Logger.getLogger(\"tigase.server.sreceiver.TaskInstanceCommand\");\n\tprotected static final String ACTION_FIELD = \"action-field\";\n\tprotected static final String USER_ACTION_FIELD = \"user-action-field\";\n\tprotected static final String CONFIRM = \"confirm-field\";\n\tprotected static final String PENDING_MODERATIONS_FIELD = \"Pending moderations\";\n\tprotected static final String SUBSCRIBERS_FIELD = \"Subscribers\";\n\tprotected static final String ROSTER_ACTION_FIELD = \"roster-action-field\";\n\t;\n\t;\n\t;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getDescription() {\n\t\treturn \"Manage task exiting instance\";\n\t}\n\n\t@Override\n\tpublic String getNodeName() {\n\t\treturn \"*\";\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processCommand(Packet packet, Packet result, StanzaReceiver receiv) {\n\t\tString task_name = packet.getStanzaTo().toString();\n\t\tReceiverTaskIfc task = receiv.getTaskInstances().get(task_name);\n\n\t\tif (task == null) {\n\t\t\ttask_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\n\t\t\tif (task_name != null) {\n\t\t\t\ttask = receiv.getTask(task_name);\n\t\t\t}    // end of if (task_name != null)\n\t\t}      // end of if (task == null)\n\n\t\tif (task != null) {\n\t\t\ttask_name = task.getJID().toString();\n\n\t\t\tif ( !(receiv.isAdmin(packet.getStanzaFrom()) || task.isAdmin(packet.getStanzaFrom()))) {\n\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\"You are not administrator of: \" + task_name + \" task.\", \"fixed\");\n\t\t\t\tCommand.addFieldValue(result, \"Info\", \"You can not execute task commands.\", \"fixed\");\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tCommand.addFieldValue(result, TASK_NAME_FIELD, task_name, \"hidden\");\n\n\t\t\tString action_str = Command.getFieldValue(packet, ACTION_FIELD);\n\n\t\t\tif (action_str == null) {\n\t\t\t\ttaskMainScreen(result, task);\n\n\t\t\t\treturn;\n\t\t\t}    // end of if (step == null)\n\n\t\t\tCommand.addFieldValue(result, ACTION_FIELD, action_str, \"hidden\");\n\n\t\t\tACTION action = ACTION.valueOf(action_str);\n\n\t\t\tswitch (action) {\n\t\t\t\tcase TASK_CONFIGURATION :\n\t\t\t\t\teditConfiguration(packet, result, receiv);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase USER_MANAGEMENT :\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmanageUsers(packet, result, receiv);\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tLogger.getLogger(TaskInstanceCommand.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase REMOVE_TASK :\n\t\t\t\t\tremoveTask(packet, result, receiv);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t}    // end of switch (action)\n\t\t} else {\n\t\t\tCommand.setStatus(result, Command.Status.executing);\n\t\t\tCommand.addAction(result, Command.Action.next);\n\t\t\tCommand.addFieldValue(result, TASK_NAME_FIELD, \"\", \"text-single\",\n\t\t\t\t\t\"Enter task JID or Name\");\n\t\t}    // end of if (task != null) else\n\t}\n\n\tprivate void editConfiguration(Packet packet, Packet result, StanzaReceiver receiv) {\n\t\tString confirm = Command.getFieldValue(packet, CONFIRM);\n\t\tString task_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\t\tReceiverTaskIfc task = receiv.getTaskInstances().get(task_name);\n\n\t\tif (confirm == null) {\n\t\t\tCommand.addFieldValue(result, CONFIRM, \"true\", \"hidden\");\n\t\t\tCommand.setStatus(result, Command.Status.executing);\n\t\t\tCommand.addAction(result, Command.Action.complete);\n\t\t\tpropertyItems2Command(task.getParams(), result);\n\t\t} else {\n\t\t\tCommand.addFieldValue(result, \"Info\", \"Changed parameters for \" + task_name + \":\",\n\t\t\t\t\t\"fixed\");\n\n\t\t\tMap<String, PropertyItem> old_params = task.getParams();\n\t\t\tMap<String, Object> new_params = new LinkedHashMap<String, Object>();\n\n\t\t\tfor (Map.Entry<String, PropertyItem> entry : old_params.entrySet()) {\n\t\t\t\tif (entry.getValue().isMultiValue()) {\n\t\t\t\t\tString[] values = Command.getFieldValues(packet, XMLUtils.escape(entry.getKey()));\n\n\t\t\t\t\tnew_params.put(entry.getKey(), values);\n\t\t\t\t} else {\n\t\t\t\t\tString value = Command.getFieldValue(packet, XMLUtils.escape(entry.getKey()));\n\n\t\t\t\t\tif (value == null) {\n\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t}    // end of if (value == null)\n\n\t\t\t\t\tvalue = XMLUtils.unescape(value);\n\n\t\t\t\t\tif ( !value.equals(entry.getValue().toString())) {\n\t\t\t\t\t\tnew_params.put(entry.getKey(), value);\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\t\tentry.getValue().getDisplay_name() + \": \" + value, \"fixed\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String key: default_props.keySet())\n\n\t\t\ttry {\n\t\t\t\ttask.setParams(new_params);\n\t\t\t\treceiv.saveTaskToRepository(task);\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem with saving task to repository: \" + task.getJID(), e);\n\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\"Problem saving task to repository, look in log file for details.\", \"fixed\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void manageUsers(Packet packet, Packet result, StanzaReceiver receiv)\n\t\t\tthrows TigaseStringprepException {\n\t\tString task_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\t\tReceiverTaskIfc task = receiv.getTaskInstances().get(task_name);\n\t\tString user_action = Command.getFieldValue(packet, USER_ACTION_FIELD);\n\n\t\tif (user_action == null) {\n\t\t\tCommand.setStatus(result, Command.Status.executing);\n\t\t\tCommand.addAction(result, Command.Action.complete);\n\t\t\tCommand.addAction(result, Command.Action.next);\n\t\t\tCommand.addFieldValue(result, \"Info\", \"Select action and user:\", \"fixed\");\n\n\t\t\tString[] actions = USER_ACTION.strValues();\n\t\t\tList<String> moderated = new LinkedList<String>();\n\n\t\t\tfor (RosterItem ri : task.getRoster().values()) {\n\t\t\t\tif ( !ri.isModerationAccepted()) {\n\t\t\t\t\tmoderated.add(ri.getJid().toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (moderated.size() > 0) {\n\t\t\t\tCommand.addFieldValue(result, USER_ACTION_FIELD, actions[0], \"Select action\", actions,\n\t\t\t\t\t\tactions);\n\n\t\t\t\tString[] moder = moderated.toArray(new String[0]);\n\n\t\t\t\tCommand.addFieldValue(result, PENDING_MODERATIONS_FIELD, moder[0],\n\t\t\t\t\t\tPENDING_MODERATIONS_FIELD, moder, moder, \"list-multi\");\n\t\t\t} else {\n\t\t\t\tCommand.addFieldValue(result, USER_ACTION_FIELD, actions[2], \"Select action\", actions,\n\t\t\t\t\t\tactions);\n\t\t\t\tCommand.addFieldValue(result, \"Info\", \"No pending moderations.\", \"fixed\");\n\t\t\t}\n\n\t\t\tString[] all_subscr = new String[task.getRoster().values().size()];\n\t\t\tint idx = 0;\n\n\t\t\tfor (RosterItem ri : task.getRoster().values()) {\n\t\t\t\tall_subscr[idx++] = ri.getJid().toString();\n\t\t\t}\n\n\t\t\tCommand.addFieldValue(result, SUBSCRIBERS_FIELD, all_subscr[0], SUBSCRIBERS_FIELD,\n\t\t\t\t\tall_subscr, all_subscr);\n\t\t} else {\n\t\t\tCommand.addFieldValue(result, USER_ACTION_FIELD, user_action, \"hidden\");\n\n\t\t\tString[] jids = Command.getFieldValues(packet, PENDING_MODERATIONS_FIELD);\n\n\t\t\tswitch (USER_ACTION.valueOf(user_action)) {\n\t\t\t\tcase APROVE_PENDING_MODERATIONS :\n\t\t\t\t\tif (jids != null) {\n\t\t\t\t\t\tMap<JID, RosterItem> roster = task.getRoster();\n\n\t\t\t\t\t\tfor (String jid : jids) {\n\t\t\t\t\t\t\tRosterItem ri = roster.get(JID.jidInstanceNS(jid));\n\n\t\t\t\t\t\t\tif (ri != null) {\n\t\t\t\t\t\t\t\ttask.setRosterItemModerationAccepted(ri, true);\n\t\t\t\t\t\t\t\treceiv.addOutPacket(getMessage(ri.getJid(), task.getJID(),\n\t\t\t\t\t\t\t\t\t\tStanzaType.headline, \"Your subscription has been approved.\"));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlog.warning(\"Missing jid: \" + jid + \" in task: \" + task_name + \" roster.\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\", \"Subscriptions have been approved.\",\n\t\t\t\t\t\t\t\t\"fixed\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\", \"No subscriptions to approve.\", \"fixed\");\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase REJECT_PENDING_MODERATIONS :\n\t\t\t\t\tif (jids != null) {\n\t\t\t\t\t\tJID[] jjids = new JID[jids.length];\n\t\t\t\t\t\tint idx = 0;\n\n\t\t\t\t\t\tfor (String jid : jids) {\n\t\t\t\t\t\t\tjjids[idx] = JID.jidInstanceNS(jid);\n\t\t\t\t\t\t\treceiv.addOutPacket(getMessage(task.getJID(), jjids[idx++], StanzaType.headline,\n\t\t\t\t\t\t\t\t\t\"Your subscription has been rejected.\"));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treceiv.removeTaskSubscribers(task, jjids);\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\", \"Subscriptions have been rejected.\",\n\t\t\t\t\t\t\t\t\"fixed\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\", \"No subscriptions to reject.\", \"fixed\");\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SELECT_USER :\n\t\t\t\t\tJID jid = JID.jidInstance(Command.getFieldValue(packet, SUBSCRIBERS_FIELD));\n\t\t\t\t\tRosterItem ri = task.getRoster().get(jid);\n\n\t\t\t\t\tif (ri != null) {\n\t\t\t\t\t\tString roster_action = Command.getFieldValue(packet, ROSTER_ACTION_FIELD);\n\n\t\t\t\t\t\tif (roster_action == null) {\n\t\t\t\t\t\t\tCommand.setStatus(result, Command.Status.executing);\n\t\t\t\t\t\t\tCommand.addAction(result, Command.Action.complete);\n\t\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\", \"Update subscription data for: \" + jid,\n\t\t\t\t\t\t\t\t\t\"fixed\");\n\t\t\t\t\t\t\tCommand.addFieldValue(result, SUBSCRIBERS_FIELD, jid.toString(), \"hidden\");\n\n\t\t\t\t\t\t\tString[] actions = ROSTER_ACTION.strValues();\n\n\t\t\t\t\t\t\tCommand.addFieldValue(result, ROSTER_ACTION_FIELD, actions[0], \"Select action\",\n\t\t\t\t\t\t\t\t\tactions, actions);\n\n\t\t\t\t\t\t\tString[] bool_arr = new String[] { \"true\", \"false\" };\n\n\t\t\t\t\t\t\tCommand.addFieldValue(result, \"subscribed-ri\",\n\t\t\t\t\t\t\t\t\tBoolean.valueOf(ri.isSubscribed()).toString(), \"Subscribed\", bool_arr,\n\t\t\t\t\t\t\t\t\t\tbool_arr);\n\t\t\t\t\t\t\tCommand.addFieldValue(result, \"moderation-ri\",\n\t\t\t\t\t\t\t\t\tBoolean.valueOf(ri.isModerationAccepted()).toString(),\n\t\t\t\t\t\t\t\t\t\t\"Moderation approved\", bool_arr, bool_arr);\n\t\t\t\t\t\t\tCommand.addFieldValue(result, \"owner-ri\",\n\t\t\t\t\t\t\t\t\tBoolean.valueOf(ri.isOwner()).toString(), \"Owner\", bool_arr, bool_arr);\n\t\t\t\t\t\t\tCommand.addFieldValue(result, \"admin-ri\",\n\t\t\t\t\t\t\t\t\tBoolean.valueOf(ri.isAdmin()).toString(), \"Admin\", bool_arr, bool_arr);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tCommand.addFieldValue(result, ROSTER_ACTION_FIELD, roster_action, \"hidden\");\n\n\t\t\t\t\t\t\tswitch (ROSTER_ACTION.valueOf(roster_action)) {\n\t\t\t\t\t\t\t\tcase UPDATE_DATA :\n\t\t\t\t\t\t\t\t\tri.setSubscribed(parseBool(Command.getFieldValue(packet, \"subscribed-ri\")));\n\t\t\t\t\t\t\t\t\tri.setModerationAccepted(parseBool(Command.getFieldValue(packet,\n\t\t\t\t\t\t\t\t\t\t\t\"moderation-ri\")));\n\t\t\t\t\t\t\t\t\tri.setOwner(parseBool(Command.getFieldValue(packet, \"owner-ri\")));\n\t\t\t\t\t\t\t\t\tri.setAdmin(parseBool(Command.getFieldValue(packet, \"admin-ri\")));\n\t\t\t\t\t\t\t\t\ttask.setRosterItemModerationAccepted(ri, ri.isModerationAccepted());\n\t\t\t\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\t\t\t\t\t\"Subscription data for user \" + jid + \" have been updated.\", \"fixed\");\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase REMOVE_USER :\n\t\t\t\t\t\t\t\t\treceiv.removeTaskSubscribers(task, jid);\n\t\t\t\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\t\t\t\t\t\"Subscription for user \" + jid + \" has been removed.\", \"fixed\");\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault :\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\t\t\t\"There was a problem accesing user subscription data.\", \"fixed\");\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void removeTask(Packet packet, Packet result, StanzaReceiver receiv) {\n\t\tString confirm = Command.getFieldValue(packet, CONFIRM);\n\t\tString task_name = Command.getFieldValue(packet, TASK_NAME_FIELD);\n\n\t\tif (confirm == null) {\n\t\t\tCommand.addFieldValue(result, CONFIRM, \"true\", \"hidden\");\n\t\t\tCommand.setStatus(result, Command.Status.executing);\n\t\t\tCommand.addAction(result, Command.Action.complete);\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"Are you sure you want to remove task: \" + task_name + \" and all it's data?\",\n\t\t\t\t\t\t\"fixed\");\n\t\t\tCommand.addFieldValue(result, \"Info\",\n\t\t\t\t\t\"Note! There is no undo for task deletion function\", \"fixed\");\n\n\t\t\treturn;\n\t\t}    // end of if (confirm == null)\n\n\t\treceiv.removeTaskInstance(receiv.getTask(task_name));\n\t\tCommand.addFieldValue(result, \"Info\", \"Task \" + task_name + \" has been removed.\", \"fixed\");\n\t}\n\n\tprivate void taskMainScreen(Packet result, ReceiverTaskIfc task) {\n\t\tCommand.setStatus(result, Command.Status.executing);\n\t\tCommand.addAction(result, Command.Action.next);\n\n\t\tList<StatRecord> stats = task.getStats();\n\n\t\tif (stats != null) {\n\t\t\tfor (StatRecord rec : stats) {\n\t\t\t\tCommand.addFieldValue(result, \"Info\", rec.getDescription() + \": \" + rec.getValue(),\n\t\t\t\t\t\t\"fixed\");\n\t\t\t}    // end of for (StatRecord rec: stats)\n\t\t}      // end of if (stats != null)\n\n\t\tString[] actions = ACTION.strValues();\n\n\t\tCommand.addFieldValue(result, ACTION_FIELD, actions[0], \"Select action\", actions, actions);\n\t}\n}    // TaskInstanceCommand\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TaskType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.sreceiver;\n\n/**\n * Describe class TaskType here.\n *\n *\n * Created: Mon May 28 08:52:07 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TaskType {\n\n\tprivate ReceiverTaskIfc task = null;\n\tprivate int max_instances = 1;\n\tprivate TaskCreationPolicy creation_policy = TaskCreationPolicy.ADMIN;\n\tprivate int curr_instances = 0;\n\n\t/**\n\t * Creates a new <code>TaskType</code> instance.\n\t *\n\t *\n\t * @param task\n\t */\n\tpublic TaskType(ReceiverTaskIfc task) {\n\t\tthis.task = task;\n\t}\n\n\tpublic ReceiverTaskIfc getTaskType() {\n\t\treturn task;\n\t}\n\n\tpublic ReceiverTaskIfc getTaskInstance() {\n\t\treturn task.getInstance();\n\t}\n\n\tpublic void instanceAdded() {\n\t\t++curr_instances;\n\t}\n\n\tpublic void instanceRemoved() {\n\t\t--curr_instances;\n\t}\n\n\tpublic int getInstancesNo() {\n\t\treturn curr_instances;\n\t}\n\n\tpublic int getMaxInstancesNo() {\n\t\treturn max_instances;\n\t}\n\n\tpublic void setMaxInstancesNo(int max_instances) {\n\t\tthis.max_instances = max_instances;\n\t}\n\n\tpublic TaskCreationPolicy getCreationPolicy() {\n\t\treturn creation_policy;\n\t}\n\n\tpublic void setCreationPolicy(TaskCreationPolicy policy) {\n\t\tthis.creation_policy = policy;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/TesterTask.java",
    "content": "/*\n * TesterTask.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n/**\n * Describe class TesterTask here.\n *\n *\n * Created: Mon Sep 17 18:07:12 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TesterTask\n\t\t\t\textends AbstractReceiverTask {\n\tprivate static final String TASK_HELP =\n\t\t\"This task pretends to be a user.\" +\n\t\t\" Allows you to [un]subscribe to its roster, send a message\" +\n\t\t\" and perform some other actions. Roster of this task is stored\" +\n\t\t\" in memory only and is cleared on server restart.\" +\n\t\t\" Full list of supported actions will be sent to you as a response\" +\n\t\t\" to //help message.\" +\n\t\t\" The purpose of this task is testing of the Tigase server and\" +\n\t\t\" the task should not be normally loaded on to live system.\";\n\tprivate static final String TASK_TYPE = \"Tester Task\";\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprivate enum command { help, genn; }\n\n\t;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getHelp() {\n\t\treturn TASK_HELP;\n\t}\n\n\t@Override\n\tpublic String getType() {\n\t\treturn TASK_TYPE;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param results\n\t */\n\tprotected void processMessage(Packet packet, Queue<Packet> results) {\n\t\tif (isPostCommand(packet)) {\n\t\t\trunCommand(packet, results);\n\t\t} else {\n\t\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"This is response to your message: [\" + body +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"]\", \"Response\", null, packet.getStanzaId()));\n\t\t}\n\t}\n\n\tprivate String commandsHelp() {\n\t\treturn \"Available commands are:\\n\" + \"//help - display this help info\\n\" +\n\t\t\t\t\t \"//genn N - generates N messages to random, non-existen users on \" +\n\t\t\t\t\t \"the server and responds with a simple reply masse: 'Completed N.'\\n\" +\n\t\t\t\t\t \" For now you can only subsribe to and unsubscribe from task roster\" +\n\t\t\t\t\t \" and send a message to task as it was a user. The task will always\" +\n\t\t\t\t\t \" respond to your messages with following text:\\n\" +\n\t\t\t\t\t \" This is response to your message: [your message included here]\";\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isPostCommand(Packet packet) {\n\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body != null) {\n\t\t\tfor (command comm : command.values()) {\n\t\t\t\tif (body.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void runCommand(Packet packet, Queue<Packet> results) {\n\t\tString body         = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\t\tString[] body_split = body.split(\" |\\n|\\r\");\n\t\tcommand comm        = command.valueOf(body_split[0].substring(2));\n\n\t\tswitch (comm) {\n\t\tcase help :\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, commandsHelp(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Commands description\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\tbreak;\n\n\t\tcase genn :\n\t\t\ttry {\n\t\t\t\tint number    = Integer.parseInt(body_split[1]);\n\t\t\t\tString domain = packet.getStanzaFrom().getDomain();\n\n\t\t\t\tfor (int i = 0; i < number; i++) {\n\t\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t JID.jidInstance(\"nonename_\" + i + \"@\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t domain), StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Traffic generattion: \" + number,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Internal load test\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t\t\t}\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal, \"Completed \" + number,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Response\", null, packet.getStanzaId()));\n\t\t\t} catch (Exception e) {\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Incorrect command parameter: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ((body_split.length > 1)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? body_split[1]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null) + \", expecting Integer.\", \"Response\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull, packet.getStanzaId()));\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/AbstractMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.util.Date;\nimport java.util.LinkedHashSet;\nimport java.util.Queue;\nimport java.util.Set;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.xml.XMLUtils;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Created: Dec 10, 2008 8:37:28 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class AbstractMonitor implements ResourceMonitorIfc {\n\n\tprotected Set<Object> warningsSent = new LinkedHashSet<Object>();\n\tprivate JID jid = null;\n\tprivate SystemMonitorTask smTask = null;\n\tprotected float treshold = 0.8F;\n\n\t@Override\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask) {\n\t\tthis.jid = jid;\n\t\tthis.treshold = treshold;\n\t\tthis.smTask = smTask;\n\t\tresetWarnings();\n\t}\n\n\tpublic void resetWarnings() {\n\t\twarningsSent = new LinkedHashSet<Object>();\n\t}\n\n\tpublic void prepareWarning(String text, Queue<Packet> results,\n\t\t\t\t\tObject warning) {\n\t\tif (!warningsSent.contains(warning)) {\n\t\t\tPacket result = Message.getMessage(jid, null, StanzaType.normal,\n\t\t\t\t\t\t\tXMLUtils.escape(\"Warning! High resource usage alert from: \" +\n\t\t\t\t\t\t\tgetClass().getSimpleName() + \"\\n\" +\n\t\t\t\t\t\t\tnew Date() + \" - \" + text),\n\t\t\t\t\t\t\t\"System Monitor Alert\", null, null);\n\t\t\tresults.add(result);\n\t\t\twarningsSent.add(warning);\n\t\t}\n\t}\n\n\tpublic void prepareCalmDown(String text, Queue<Packet> results,\n\t\t\t\t\tObject warning) {\n\t\tif (warningsSent.contains(warning)) {\n\t\t\tPacket result = Message.getMessage(jid, null, StanzaType.normal,\n\t\t\t\t\t\t\tXMLUtils.escape(\"Calm down! Resource usage notification from: \" +\n\t\t\t\t\t\t\tgetClass().getSimpleName() + \"\\n\" +\n\t\t\t\t\t\t\tnew Date() + \" - \" + text),\n\t\t\t\t\t\t\t\"System Monitor Alert\", null, null);\n\t\t\tresults.add(result);\n\t\t\twarningsSent.remove(warning);\n\t\t}\n\t}\n\n\tpublic void sendWarningOut(String text, Object warning) {\n\t\tif (warning == null || !warningsSent.contains(warning)) {\n\t\t\tPacket result = Message.getMessage(jid, null, StanzaType.normal,\n\t\t\t\t\t\t\tXMLUtils.escape(\"Warning! High resource usage alert from: \" +\n\t\t\t\t\t\t\tgetClass().getSimpleName() + \"\\n\" +\n\t\t\t\t\t\t\tnew Date() + \" - \" + text),\n\t\t\t\t\t\t\t\"System Monitor Alert\", null, null);\n\t\t\tsmTask.sendPacketOut(result);\n\t\t\tif (warning != null) {\n\t\t\t\twarningsSent.add(warning);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int setValueInArr(float[] arr, int idx, float val) {\n\t\tarr[idx] = val;\n\t\t++idx; idx %= arr.length;\n\t\treturn idx;\n\t}\n\n\tpublic int setValueInArr(double[] arr, int idx, double val) {\n\t\tarr[idx] = val;\n\t\t++idx; idx %= arr.length;\n\t\treturn idx;\n\t}\n\n\t@Override\n\tpublic void check10Secs(Queue<Packet> results) {\n\t}\n\t\n\t@Override\n\tpublic void check1Day(Queue<Packet> results) {\n\t}\n\n\t@Override\n\tpublic void check1Hour(Queue<Packet> results) {\n\t}\n\n\t@Override\n\tpublic void check1Min(Queue<Packet> results) {\n\t}\n\n\t@Override\n\tpublic String commandsHelp() {\n\t\treturn \"\";\n\t}\n\n\t@Override\n\tpublic String runCommand(String[] command) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isMonitorCommand(String command) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/CPUMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.OperatingSystemMXBean;\nimport java.lang.management.ThreadInfo;\nimport java.lang.management.ThreadMXBean;\nimport java.text.NumberFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.sys.TigaseRuntime;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 10, 2008 12:27:15 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CPUMonitor extends AbstractMonitor {\n\n  /**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n\t\t\t\t\tLogger.getLogger(CPUMonitor.class.getName());\n\n\tprivate int historySize = 100;\n\tprivate long prevUptime = TigaseRuntime.getTigaseRuntime().getUptime();;\n\tprivate long prevCputime = TigaseRuntime.getTigaseRuntime().getProcessCPUTime();\n\n//\tprivate long lastCpuUsage = 0;\n//\tprivate long lastCpuChecked = 0;\n\tprivate float[] cpuUsage = new float[historySize];\n\tprivate int cpuUsageIdx = 0;\n\tprivate double[] loadAverage = new double[historySize];\n\tprivate int loadAverageIdx = 0;\n\tprivate ThreadMXBean thBean = null;\n\tprivate OperatingSystemMXBean osBean = null;\n\tprivate NumberFormat format = NumberFormat.getNumberInstance();\n\tprivate Map<Long, ThreadData> threads =\n\t\t\t\t\tnew ConcurrentHashMap<Long, ThreadData>();\n\tprivate int deadLockedThreadsNo = 0;\n\n\tprivate String checkForDeadLock() {\n\t\tlong[] tids = thBean.findDeadlockedThreads();\n\t\tif (tids != null && tids.length > 0) {\n\t\t\tdeadLockedThreadsNo = tids.length;\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tsb.append(\"Locked threads \" + tids.length + \":\\n\");\n\t\t\tSet<Long> tidSet = new LinkedHashSet<Long>();\n\t\t\tfor (long tid : tids) {\n\t\t\t\ttidSet.add(tid);\n\t\t\t}\n\t\t\tThreadGroup rootGroup = Thread.currentThread().getThreadGroup();\n\t\t\twhile (rootGroup.getParent() != null)\n\t\t\t\trootGroup = rootGroup.getParent();\n\t\t\tint allThreadsCount = thBean.getThreadCount();\n\t\t\tThread[] allThreads = new Thread[allThreadsCount];\n\t\t\trootGroup.enumerate(allThreads, true);\n\t\t\tfor (Thread thread : allThreads) {\n\t\t\t\tif (tidSet.contains(thread.getId())) {\n\t\t\t\t\tThreadInfo threadInfo = thBean.getThreadInfo(thread.getId());\n\t\t\t\t\tsb.append(\"Locked thread [\" + thread.getId() + \"] \" +\n\t\t\t\t\t\t\t\t\tthreadInfo.getThreadName() + \" on \" +\n\t\t\t\t\t\t\t\t\tthreadInfo.getLockInfo().toString() +\n\t\t\t\t\t\t\t\t\t\", locked synchronizers: \" +\n\t\t\t\t\t\t\t\t\tArrays.toString(threadInfo.getLockedSynchronizers()) +\n\t\t\t\t\t\t\t\t\t\", locked monitors: \" +\n\t\t\t\t\t\t\t\t\tArrays.toString(threadInfo.getLockedMonitors()) +\n\t\t\t\t\t\t\t\t\t\" by [\" + threadInfo.getLockOwnerId() + \"] \" +\n\t\t\t\t\t\t\t\t\tthreadInfo.getLockOwnerName()).append('\\n');\n\t\t\t\t\tStackTraceElement[] ste = thread.getStackTrace();\n\t\t\t\t\tfor (StackTraceElement stackTraceElement : ste) {\n\t\t\t\t\t\tsb.append(\"  \" + stackTraceElement.toString()).append('\\n');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn sb.toString();\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate enum command {\n\t\tmaxthread(\" - Returns information about the most active thread.\"),\n\t\tmth(\" - Short version of the command above.\"),\n\t\tallthreads(\" [ex] - display all threads information, with 'ex' parameters it prints extended information.\");\n\n\t\tprivate String helpText = null;\n\n\t\tprivate command(String helpText) {\n\t\t\tthis.helpText = helpText;\n\t\t}\n\n\t\tpublic String getHelp() {\n\t\t\treturn helpText;\n\t\t}\n\n\t};\n\n\tprivate String getStackTrace(Map<Thread,StackTraceElement[]> map, long id) {\n\t\tfor (Map.Entry<Thread, StackTraceElement[]> entry : map.entrySet()) {\n\t\t\tif (entry.getKey().getId() == id) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\t\tfor (StackTraceElement stelem : entry.getValue()) {\n\t\t\t\t\tsb.append(stelem.toString() + \"\\n\");\n\t\t\t\t}\n\t\t\t\treturn sb.toString();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate String getThreadInfo(long thid, boolean stack) {\n\t\tThreadInfo ti = thBean.getThreadInfo(thid);\n\t\tif (ti != null) {\n\t\t\tMap<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();\n\t\t\tStringBuilder sb =\n\t\t\t\t\t\t\tnew StringBuilder(\"Thread: \" + ti.getThreadName() +\n\t\t\t\t\t\t\t\", ID: \" + ti.getThreadId());\n\t\t\tThreadData td = threads.get(thid);\n\t\t\tif (td != null) {\n\t\t\t\tsb.append(\", CPU usage: \" + format.format(td.cpuUse) + \"%\\n\");\n\t\t\t}\n\t\t\tif (stack) {\n\t\t\t\tsb.append(ti.toString());\n\t\t\t\tsb.append(getStackTrace(map, thid));\n\t\t\t}\n\t\t\treturn sb.toString();\n\t\t} else {\n\t\t\treturn \"ThreadInfo is null...\";\n\t\t}\n\t}\n\n\t@Override\n\tpublic String runCommand(String[] com) {\n\t\tcommand comm = command.valueOf(com[0].substring(2));\n\t\tswitch (comm) {\n\t\t\tcase mth:\n\t\t\tcase maxthread:\n\t\t\t\tif (com.length > 1) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlong thid = Long.parseLong(com[1]);\n\t\t\t\t\t\treturn getThreadInfo(thid, true);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\treturn \"Incorrect Thread ID\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tList<ThreadData> sorted = sortThreadCPUUse();\n        if (sorted.size() > 0) {\n\t\t\t\t\treturn getThreadInfo(sorted.get(0).id, true);\n\t\t\t\t} else {\n\t\t\t\t\treturn \"No max threads info yet.\";\n\t\t\t\t}\n\t\t\tcase allthreads:\n\t\t\t\tboolean extend = false;\n\t\t\t\tif (com.length > 1 && com[1].equals(\"ex\")) {\n\t\t\t\t\textend = true;\n\t\t\t\t}\n\t\t\t\tStringBuilder sb = new StringBuilder(\"All threads information:\\n\");\n\t\t\t\tfor (long thid : thBean.getAllThreadIds()) {\n\t\t\t\t\tsb.append(getThreadInfo(thid, extend));\n\t\t\t\t}\n\t\t\t\treturn sb.toString();\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate List<ThreadData> sortThreadCPUUse() {\n\t\tArrayList<ThreadData> list =\n\t\t\t\t\t\tnew ArrayList<ThreadData>(threads.values());\n\t\tCollections.sort(list, new Comparator<ThreadData>() {\n\n\t\t\t@Override\n\t\t\tpublic int compare(ThreadData o1, ThreadData o2) {\n\t\t\t\tif (o1.cpuUse < o2.cpuUse) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (o1.cpuUse > o2.cpuUse) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t});\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic String commandsHelp() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (command comm : command.values()) {\n\t\t\tsb.append(\"//\" + comm.name() + comm.getHelp() + \"\\n\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic boolean isMonitorCommand(String com) {\n\t\tif (com != null) {\n\t\t\tfor (command comm: command.values()) {\n\t\t\t\tif (com.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask) {\n\t\tsuper.init(jid, treshold, smTask);\n\t\tthBean = ManagementFactory.getThreadMXBean();\n\t\tosBean = ManagementFactory.getOperatingSystemMXBean();\n\t\tformat.setMaximumFractionDigits(1);\n//\t\tif (format instanceof DecimalFormat) {\n//\t\t\tDecimalFormat decf = (DecimalFormat)format;\n//\t\t\tdecf.applyPattern(decf.toPattern()+\"%\");\n//\t\t}\n\t\tif (thBean.isCurrentThreadCpuTimeSupported()) {\n\t\t\tthBean.setThreadCpuTimeEnabled(true);\n\t\t} else {\n\t\t\tlog.warning(\"Current thread CPU Time is NOT supported.\");\n\t\t}\n\t\tif (thBean.isThreadContentionMonitoringSupported()) {\n\t\t\tthBean.setThreadContentionMonitoringEnabled(true);\n\t\t} else {\n\t\t\tlog.warning(\"Thread contention monitoring is NOT supported.\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void check10Secs(Queue<Packet> results) {\n\t\tlong currUptime = TigaseRuntime.getTigaseRuntime().getUptime();\n\t\tlong currCputime = TigaseRuntime.getTigaseRuntime().getProcessCPUTime();\n\t\tfloat cpuUse = calcCPUUse(prevUptime, currUptime, prevCputime, currCputime,\n\t\t\t\t\t\tTigaseRuntime.getTigaseRuntime().getCPUsNumber());\n\t\tprevUptime = currUptime;\n\t\tprevCputime = currCputime;\n\t\tcpuUsageIdx = setValueInArr(cpuUsage, cpuUsageIdx, cpuUse);\n\t\tloadAverageIdx = setValueInArr(loadAverage, loadAverageIdx,\n\t\t\t\t\t\tosBean.getSystemLoadAverage());\n\t\tfloat thresh = treshold * 100;\n\t\tif ((cpuUse > thresh) && (recentCpu(6) > thresh)) {\n\t\t\tprepareWarning(\"High CPU usage, current: \" + format.format(cpuUse) +\n\t\t\t\t\t\t\t\"%, last minute: \" +\n\t\t\t\t\t\t\tformat.format(recentCpu(6)) + \"%\", results, this);\n\t\t} else {\n\t\t\tif (cpuUse < (thresh * 0.75)) {\n\t\t\t\tprepareCalmDown(\"CPU usage is now low again, current: \" +\n\t\t\t\t\t\t\t\tformat.format(cpuUse) + \"%, last minute: \" +\n\t\t\t\t\t\t\t\tformat.format(recentCpu(6)) + \"%\", results, this);\n\t\t\t}\n\t\t}\n\t\tString result = checkForDeadLock();\n\t\tif (result != null) {\n\t\t\tSystem.out.println(\"Dead-locked threads:\\n\" + result);\n\t\t\tprepareWarning(\"Dead-locked threads:\\n\" + result, results, this);\n\t\t}\n\t\tupdateThreadCPUUse();\n\t}\n\n\tprivate double recentCpu(int histCheck) {\n\t\tdouble recentCpu = 0;\n\t\tint start = cpuUsageIdx - histCheck;\n\t\tif (start < 0) {\n\t\t\tstart = cpuUsage.length - start;\n\t\t}\n\t\tfor (int i = 0; i < histCheck; i++) {\n\t\t\tint idx = (start + i) % cpuUsage.length;\n\t\t\trecentCpu += cpuUsage[idx];\n\t\t}\n\t\treturn recentCpu / histCheck;\n\t}\n\n\t@Override\n\tpublic String getState() {\n\t\tint idx = cpuUsageIdx-1;\n\t\tif (idx < 0) {\n\t\t\tidx = cpuUsage.length-1;\n\t\t}\n\t\tNumberFormat formd = NumberFormat.getNumberInstance();\n\t\tformd.setMaximumFractionDigits(4);\n\t\treturn \"Current CPU usage is: \" + format.format(cpuUsage[idx]) +\n\t\t\t\t\t\t\"%, Last minute CPU usage is: \" + format.format(recentCpu(6)) +\n\t\t\t\t\t\t\"%, Load average is: \" + formd.format(loadAverage[idx]) + \"\\n\";\n\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to destroy\n\t}\n\n\tprivate static final String CPU_MON = \"cpu-mon\";\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n\t\tlist.add(CPU_MON, \"Deadlocked threads no\", deadLockedThreadsNo, Level.INFO);\n\t\tList<ThreadData> sorted = sortThreadCPUUse();\n\t\tif (sorted.size() > 0) {\n\t\t\tThreadData td = sorted.get(0);\n\t\t\tlist.add(CPU_MON, \"1st max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.INFO);\n\t\t}\n\t\tif (sorted.size() > 1) {\n\t\t\tThreadData td = sorted.get(1);\n\t\t\tlist.add(CPU_MON, \"2nd max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.FINE);\n\t\t}\n\t\tif (sorted.size() > 2) {\n\t\t\tThreadData td = sorted.get(2);\n\t\t\tlist.add(CPU_MON, \"3rd max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.FINE);\n\t\t}\n\t\tif (sorted.size() > 3) {\n\t\t\tThreadData td = sorted.get(3);\n\t\t\tlist.add(CPU_MON, \"4th max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.FINER);\n\t\t}\n\t\tif (sorted.size() > 4) {\n\t\t\tThreadData td = sorted.get(4);\n\t\t\tlist.add(CPU_MON, \"5th max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.FINER);\n\t\t}\n\t\tif (sorted.size() > 5) {\n\t\t\tThreadData td = sorted.get(5);\n\t\t\tlist.add(CPU_MON, \"6th max CPU thread\",\n\t\t\t\t\t\t\ttd.name + \": \" + format.format(td.cpuUse) + \"%\", Level.FINEST);\n\t\t}\n\t}\n\n\tpublic float calcCPUUse(long prevUptime, long currUptime, long prevCputime,\n\t\t\t\t\tlong currCputime, int cpus) {\n\t\tlong elapsedTime = currUptime - prevUptime;\n\t\tlong elapsedCpu = currCputime - prevCputime;\n\t\treturn Math.min(99.99F, elapsedCpu / (elapsedTime * 10000F * cpus));\n\t}\n\n\tprivate void updateThreadCPUUse() {\n\t\tlong currUptime = TigaseRuntime.getTigaseRuntime().getUptime();\n    long[] allIds = thBean.getAllThreadIds();\n\t\tfor (long l : allIds) {\n\t\t\tThreadData td = threads.get(l);\n\t\t\tif (td == null) {\n\t\t\t\tThreadInfo ti = thBean.getThreadInfo(l);\n\t\t\t\tif (ti != null) {\n\t\t\t\t\ttd = new ThreadData();\n\t\t\t\t\ttd.id = l;\n\t\t\t\t\ttd.name = ti.getThreadName();\n\t\t\t\t\ttd.prevCputime = thBean.getThreadCpuTime(l);\n\t\t\t\t\ttd.prevUptime = currUptime;\n\t\t\t\t\tthreads.put(l, td);\n\t\t\t\t} else {\n\t\t\t\t\tlog.finer(\"ThreadInfo null for thread: \" + l);\n\t\t\t\t}\n\t\t\t} else {\n        long currCputime = thBean.getThreadCpuTime(l);\n\t\t\t\tif ((currCputime) > 0) {\n\t\t\t\t\ttd.cpuUse = calcCPUUse(td.prevUptime, currUptime, td.prevCputime,\n\t\t\t\t\t\t\t\t\tcurrCputime, 1);\n//\t\t\t\t\tSystem.out.println(td.name + \" - td.prevUptime: \" + td.prevUptime +\n//\t\t\t\t\t\t\t\t\t\", currUptime: \" + currUptime +\n//\t\t\t\t\t\t\t\t\t\", td.prevCputime: \" + td.prevCputime +\n//\t\t\t\t\t\t\t\t\t\", currCputime: \" + currCputime +\n//\t\t\t\t\t\t\t\t\t\", td.cpuUse: \" + td.cpuUse);\n\t\t\t\t}\n\t\t\t\ttd.prevCputime = currCputime;\n\t\t\t\ttd.prevUptime = currUptime;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate class ThreadData {\n\t\tlong id = 0;\n\t\tString name = \"\";\n\t\tfloat cpuUse = 0F;\n\t\tlong prevUptime = 0;\n\t\tlong prevCputime = 0;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/DiskMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileReader;\nimport java.text.DecimalFormat;\nimport java.text.NumberFormat;\nimport java.util.ArrayList;\nimport java.util.Formatter;\nimport java.util.Queue;\nimport java.util.logging.Logger;\nimport java.util.logging.Level;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.util.OSUtils;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 10, 2008 8:14:53 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DiskMonitor extends AbstractMonitor {\n\n  private static final Logger log =\n    Logger.getLogger(\"tigase.server.sreceiver.sysmon.DiskMonitor\");\n\n\tprivate File[] roots = null;\n\n\t@Override\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask) {\n\t\tsuper.init(jid, treshold, smTask);\n\t\troots = File.listRoots();\n\t\tfindAllRoots();\n\t}\n\n\tprivate void findAllRoots() {\n\t\tswitch (OSUtils.getOSType()) {\n\t\t\tcase windows:\n\t\t\t\tFile[] winRoots = File.listRoots();\n\t\t\t\troots = winRoots;\n\t\t\t\tbreak;\n\t\t\tcase linux:\n\t\t\t\tFile[] linRoots = getLinuxRoots();\n\t\t\t\troots = linRoots;\n\t\t\t\tbreak;\n\t\t\tcase sunos:\n\t\t\tcase solaris:\n\t\t\t\tFile[] solRoots = getSolarisRoots();\n\t\t\t\troots = solRoots;\n\t\t\t\tbreak;\n\t\t\tcase mac:\n\t\t\t\tFile[] macRoots = getMacRoots();\n\t\t\t\troots = macRoots;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tFile[] otherRoots = File.listRoots();\n\t\t\t\tif (otherRoots.length == 1) {\n\t\t\t\t\tFile[] mtabRoots = getLinuxRoots();\n\t\t\t\t\tif (mtabRoots != null && mtabRoots.length > 1) {\n\t\t\t\t\t\totherRoots = mtabRoots;\n\t\t\t\t\t}\n\t\t\t\t\troots = otherRoots;\n\t\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void check1Min(Queue<Packet> results) {\n\t\tfor (File file : roots) {\n\t\t\tNumberFormat format = NumberFormat.getIntegerInstance();\n\t\t\tif (format instanceof DecimalFormat) {\n\t\t\t\tDecimalFormat decf = (DecimalFormat) format;\n\t\t\t\tdecf.applyPattern(decf.toPattern() + \" KB\");\n\t\t\t}\n\t\t\tNumberFormat formp = NumberFormat.getPercentInstance();\n\t\t\tformp.setMaximumFractionDigits(2);\n\t\t\tdouble percent = new Long(file.getUsableSpace()).doubleValue() /\n\t\t\t\t\t\t\tnew Long(file.getTotalSpace()).doubleValue();\n\t\t\tif (file.getUsableSpace() < file.getTotalSpace() * (1 - treshold)) {\n\t\t\t\tprepareWarning(\"Available space on volume: \" + file.toString() +\n\t\t\t\t\t\t\t\t\" is low: \" + format.format(file.getUsableSpace() / 1024) +\n\t\t\t\t\t\t\t\t\" of \" + format.format(file.getTotalSpace() / 1024) +\n\t\t\t\t\t\t\t\t\" - \" + formp.format(percent),\n\t\t\t\t\t\t\t\tresults, file.toString());\n\t\t\t} else {\n\t\t\t\tprepareCalmDown(\"Available space on volume: \" + file.toString() +\n\t\t\t\t\t\t\t\t\" is OK now: \" + format.format(file.getUsableSpace() / 1024) +\n\t\t\t\t\t\t\t\t\" of \" + format.format(file.getTotalSpace() / 1024) +\n\t\t\t\t\t\t\t\t\" - \" + formp.format(percent),\n\t\t\t\t\t\t\t\tresults, file.toString());\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void check1Hour(Queue<Packet> results) {\n\t\tfindAllRoots();\n\t}\n\n\t@Override\n\tpublic String getState() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tFormatter formatter = new Formatter(sb);\n\t\tString format_s = \"%1$20s%2$12s%3$12s%4$12s%5$12s\\n\";\n\t\tformatter.format(format_s, \"Filesystem\", \"Size\", \"Used\", \"Avail\", \"Free%\");\n\t\tString format_n = \"%1$20s%2$,12dM%3$,12dM%4$,12dM%5$12.2f%%\\n\";\n\t\tlong MEGA = 1024*1024;\n\t\tfor (File file : roots) {\n\t\t\tdouble percent = new Long(file.getUsableSpace()).doubleValue() /\n\t\t\t\t\t\t\tnew Long(file.getTotalSpace()).doubleValue();\n\t\t\tformatter.format(format_n, file.toString(),\n\t\t\t\t\t\t\t(file.getTotalSpace() / MEGA),\n\t\t\t\t\t\t\t(file.getTotalSpace() - file.getUsableSpace()) / MEGA,\n\t\t\t\t\t\t\t(file.getUsableSpace() / MEGA), percent * 100);\n\t\t}\n\t\treturn formatter.toString();\n\t}\n\n\tprivate File[] getLinuxRoots() {\n\t\ttry {\n\t\t\tString mtab = \"/etc/mtab\";\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n    \t\t\tlog.finest(\"Reading mtab: \" + mtab);\n            }\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(mtab));\n\t\t\tString line = null;\n\t\t\tArrayList<File> results = new ArrayList<File>();\n\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n    \t\t\t\tlog.finest(\"Analyzing line: \" + line);\n                }\n\t\t\t\tif (line.contains(\"proc\") || line.contains(\"devfs\") ||\n\t\t\t\t\t\t\t\tline.contains(\"tmpfs\") || line.contains(\"sysfs\") ||\n\t\t\t\t\t\t\t\tline.contains(\"devpts\") || line.contains(\"securityfs\")) {\n    \t\t\t\tif (log.isLoggable(Level.FINEST)) {\n        \t\t\t\tlog.finest(\"Found virtual fs line, omitting...\");\n                    }\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n    \t\t\t\tlog.finest(\"Splitting line...\");\n                }\n\t\t\t\tString[] parts = line.split(\"\\\\s\");\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n    \t\t\t\tlog.finest(\"Found file system: \" + parts[1]);\n                }\n\t\t\t\tresults.add(new File(parts[1]));\n\t\t\t}\n\t\t\treturn results.toArray(new File[results.size()]);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"Can not read filesystems from /etc/mtab file\" + e);\n\t\t\treturn File.listRoots();\n\t\t}\n\n\t}\n\n\tprivate File[] getMacRoots() {\n\t\tFile volumes = new File(\"/Volumes\");\n\t\treturn volumes.listFiles(new FileFilter() {\n\t\t\t@Override\n\t\t\tpublic boolean accept(File path) {\n\t\t\t\treturn path.isDirectory();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate File[] getSolarisRoots() { return File.listRoots();\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to destroy....\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/LogMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.LogRecord;\nimport java.util.logging.Logger;\nimport java.util.logging.MemoryHandler;\nimport tigase.conf.ConfiguratorOld;\nimport tigase.stats.StatisticsList;\nimport tigase.util.LogFormatter;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 12, 2008 8:31:38 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class LogMonitor extends AbstractMonitor {\n\n\tprivate MonitorHandler monitorHandler = null;\n\tprivate MemoryHandlerFlush memoryHandler = null;\n\tprivate Map<String, String> monitorLevels =\n\t\t\t\t\tnew LinkedHashMap<String, String>();\n\tprivate int loggerSize = 50;\n\tprivate Level levelTreshold = Level.WARNING;\n\tprivate int maxLogBuffer = 1000*1000;\n\tprivate long lastWarningSent = 0;\n\tprivate long logWarings = 0;\n\n\tprivate enum command {\n\t\tsetlevel(\" [package=level] - Sets logging level for specified package.\"),\n\t\tloggersize(\" [N] - Sets memory logger size to specified value.\"),\n\t\tleveltreshold(\" [level] - Sets level treshold to specified level.\"),\n\t\tlogdump(\" - retrieves all logs collected in the memory buffer and clears that buffer.\");\n\n\t\tprivate String helpText = null;\n\n\t\tprivate command(String helpText) {\n\t\t\tthis.helpText = helpText;\n\t\t}\n\n\t\tpublic String getHelp() {\n\t\t\treturn helpText;\n\t\t}\n\n\t};\n\n\t@Override\n\tpublic String commandsHelp() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (command comm : command.values()) {\n\t\t\tsb.append(\"//\" + comm.name() + comm.getHelp() + \"\\n\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic String runCommand(String[] com) {\n\t\tcommand comm = command.valueOf(com[0].substring(2));\n\t\tswitch (comm) {\n\t\t\tcase setlevel:\n\t\t\t\tif (com.length > 1) {\n\t\t\t\t\tString[] keyval = com[1].split(\"=\");\n\t\t\t\t\tif (keyval.length > 1) {\n\t\t\t\t\t\tString key = (keyval[0].endsWith(\".level\") ? keyval[0].substring(\n\t\t\t\t\t\t\t\t\t\t0, keyval[0].length() - 6) : keyval[0]);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tLevel level = Level.parse(keyval[1]);\n\t\t\t\t\t\t\tLogger.getLogger(key).setLevel(level);\n\t\t\t\t\t\t\tmonitorLevels.put(key + \".level\", level.getName());\n\t\t\t\t\t\t\treturn \"Level set successfuly: \" + key + \"=\" + level.getName();\n\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\treturn \"Incorrect level name, use: ALL, FINEST, FINER, FINE, \" +\n\t\t\t\t\t\t\t\t\t\t\t\"INFO, WARNING, SEVERE, OFF\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn \"Incorrect level setting, use: package=level\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn \"Current logging levels are:\\n\" + getCurrentLevels();\n\t\t\t\t}\n\t\t\tcase loggersize:\n\t\t\t\tif (com.length > 1) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tint newLoggerSize = Integer.parseInt(com[1]);\n\t\t\t\t\t\tloggerSize = newLoggerSize;\n\t\t\t\t\t\tregisterHandler();\n\t\t\t\t\t\treturn \"New logger size successfuly set to: \" + loggerSize;\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\treturn \"Incorrect logger size: \" + com[1];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn \"Current memory logger size is: \" + loggerSize;\n\t\t\t\t}\n\t\t\tcase leveltreshold:\n\t\t\t\tif (com.length > 1) {\n\t\t\t\t\treturn \"Setting logging treshold level is not supported yet.\";\n\t\t\t\t} else {\n\t\t\t\t\treturn \"Current logging treshold level is: \" + levelTreshold;\n\t\t\t\t}\n\t\t\tcase logdump:\n\t\t\t\treturn \"Memory logging buffer content:\\n\" +\n\t\t\t\t\t\t\t\tmemoryHandler.pushToString();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isMonitorCommand(String com) {\n\t\tif (com != null) {\n\t\t\tfor (command comm: command.values()) {\n\t\t\t\tif (com.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate void removeHandler() {\n\t\tif (memoryHandler != null) {\n\t\t\tLogger.getLogger(\"\").removeHandler(memoryHandler);\n\t\t}\n\t}\n\n\tprivate void registerHandler() {\n\t\tremoveHandler();\n\t\tif (monitorHandler == null) {\n\t\t\tmonitorHandler = new MonitorHandler();\n\t\t\tmonitorHandler.setLevel(Level.ALL);\n\t\t}\n\t\tmemoryHandler =\n\t\t\t\t\t\tnew MemoryHandlerFlush(monitorHandler, loggerSize, levelTreshold);\n\t\tmemoryHandler.setLevel(Level.ALL);\n\t\tLogger.getLogger(\"\").addHandler(memoryHandler);\n\t}\n\n\t@Override\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask) {\n\t\tsuper.init(jid, treshold, smTask);\n\t\tregisterHandler();\n\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\tremoveHandler();\n\t}\n\n\tprivate String getCurrentLevels() {\n\t\tString[] configLines = ConfiguratorOld.logManagerConfiguration.split(\"\\n\");\n\t\tMap<String, String> results = new LinkedHashMap<String, String>();\n\t\tfor (String string : configLines) {\n\t\t\tif (string.contains(\".level\") && !string.contains(\"FileHandler\") &&\n\t\t\t\t\t\t\t!string.contains(\"ConsoleHandler\")) {\n\t\t\t\tString[] keyval = string.split(\"=\");\n\t\t\t\tresults.put(keyval[0], keyval[1]);\n\t\t\t}\n\t\t}\n\t\tresults.putAll(monitorLevels);\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (Map.Entry<String, String> entry : results.entrySet()) {\n\t\t\tsb.append(entry.getKey() + \"=\" + entry.getValue() + \"\\n\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic String getState() {\n\t\tStringBuilder sb = new StringBuilder(\"Logging levels:\\n\");\n\t\tsb.append(getCurrentLevels());\n\t\tsb.append(\"Monitor parameters:\\n\");\n\t\tsb.append(\"loggerSize=\" + loggerSize + \"\\n\");\n\t\tsb.append(\"levelTreshold=\" + levelTreshold + \"\\n\");\n\t\treturn sb.toString();\n\t}\n\n\tprivate class MonitorHandler extends Handler {\n\n\t\tprivate LinkedList<String> logs = new LinkedList<String>();\n\t\tprivate LogFormatter formatter = new LogFormatter();\n\n\t\t@Override\n\t\tpublic synchronized void publish(LogRecord record) {\n\t\t\tString logEntry =\n\t\t\t\t\t\t\tformatter.format(record).replace('<', '[').replace('>', ']');\n\t\t\tlogs.add(logEntry);\n\t\t}\n\n\t\tpublic synchronized String logsToString() {\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tString logEntry = null;\n\t\t\twhile (((logEntry = logs.pollLast()) != null) &&\n\t\t\t\t\t\t\t(sb.length() < maxLogBuffer)) {\n\t\t\t\tsb.insert(0, logEntry);\n\t\t\t}\n\t\t\tlogs.clear();\n\t\t\tString result = sb.length() <= maxLogBuffer ? sb.toString()\n\t\t\t\t\t\t\t: sb.substring(sb.length() - maxLogBuffer);\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic synchronized void flush() {\n\t\t\t++logWarings;\n\t\t\tif (System.currentTimeMillis() - lastWarningSent > 5*MINUTE) {\n\t\t\t\tString logBuff = logsToString();\n\t\t\t\t// We don't want to flood the system with this in case of\n\t\t\t\t// some frequent error....\n\t\t\t\tsendWarningOut(logBuff, null);\n\t\t\t\tlastWarningSent = System.currentTimeMillis();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void close() throws SecurityException { }\n\t\t\n\t}\n\n\tprivate class MemoryHandlerFlush extends MemoryHandler {\n\n\t\tMonitorHandler monHandle = null;\n\n\t\tpublic MemoryHandlerFlush(MonitorHandler target, int size, Level pushLevel) {\n\t\t\tsuper(target, size, pushLevel);\n\t\t\tmonHandle = target;\n\t\t}\n\n\t\tpublic String pushToString() {\n\t\t\tsuper.push();\n\t\t\treturn monHandle.logsToString();\n\t\t}\n\n\t\t@Override\n\t\tpublic void push() {\n\t\t\tsuper.push();\n\t\t\tflush();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n\t\tlist.add(\"log-mon\", \"Log warings\", logWarings, Level.FINE);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/MemMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.MemoryMXBean;\nimport java.lang.management.MemoryNotificationInfo;\nimport java.lang.management.MemoryPoolMXBean;\nimport java.lang.management.MemoryUsage;\nimport java.text.DecimalFormat;\nimport java.text.NumberFormat;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.Random;\nimport java.util.logging.Logger;\nimport javax.management.Notification;\nimport javax.management.NotificationEmitter;\nimport javax.management.NotificationListener;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 10, 2008 1:23:17 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MemMonitor extends AbstractMonitor\n\t\t\t\timplements NotificationListener {\n\n\tprivate static Logger log =\n\t\t\t\t\tLogger.getLogger(\"tigase.server.sreceiver.sysmon.MemMonitor\");\n\n\tprivate MemoryMXBean memoryMXBean = null;\n\n\t@Override\n\tpublic void destroy() {\n\t\tmemoryMXBean = ManagementFactory.getMemoryMXBean();\n\t\tNotificationEmitter emitter = (NotificationEmitter)memoryMXBean;\n\t\tList<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();\n\t\tfor (MemoryPoolMXBean memoryPoolMXBean : memPools) {\n\t\t\ttry {\n\t\t\t\temitter.removeNotificationListener(this, null, memoryPoolMXBean);\n\t\t\t} catch (Exception e) {\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask) {\n\t\tsuper.init(jid, treshold, smTask);\n\t\tmemoryMXBean = ManagementFactory.getMemoryMXBean();\n\t\tNotificationEmitter emitter = (NotificationEmitter)memoryMXBean;\n\t\tList<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();\n\t\tfor (MemoryPoolMXBean memoryPoolMXBean : memPools) {\n\t\t\ttry {\n\t\t\t\temitter.removeNotificationListener(this, null, memoryPoolMXBean);\n\t\t\t} catch (Exception e) {\t}\n\t\t\tMemoryUsage memUsage = memoryPoolMXBean.getUsage();\n\t\t\tif (memUsage != null) {\n\t\t\t\tif (memoryPoolMXBean.isUsageThresholdSupported()) {\n\t\t\t\t\temitter.addNotificationListener(this, null, memoryPoolMXBean);\n\t\t\t\t\tlong memUsageTreshold =\n\t\t\t\t\t\t\t\t\tnew Double(new Long(memUsage.getMax()).doubleValue() *\n\t\t\t\t\t\t\t\t\ttreshold).longValue();\n\t\t\t\t\tmemoryPoolMXBean.setUsageThreshold(memUsageTreshold);\n\t\t\t\t\tlog.config(\"Setting treshold: \" + memUsageTreshold +\n\t\t\t\t\t\t\t\t\t\" for memory pool: \" + memoryPoolMXBean.getName() +\n\t\t\t\t\t\t\t\t\t\", type: \" + memoryPoolMXBean.getType().toString() +\n\t\t\t\t\t\t\t\t\t\", memMax: \" + memUsage.getMax() +\n\t\t\t\t\t\t\t\t\t\", memUsed: \" + memUsage.getUsed() +\n\t\t\t\t\t\t\t\t\t\", config treeshold: \" + treshold);\n\t\t\t\t\tif (memUsage.getUsed() > memUsageTreshold) {\n\t\t\t\t\t\tNotification not = new Notification(\n\t\t\t\t\t\t\t\t\t\tMemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,\n\t\t\t\t\t\t\t\t\t\tthis, 1);\n\t\t\t\t\t\thandleNotification(not, memoryPoolMXBean);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlog.config(\"Memory pool name: \" + memoryPoolMXBean.getName() +\n\t\t\t\t\t\t\t\t\t\", type: \" + memoryPoolMXBean.getType().toString() +\n\t\t\t\t\t\t\t\t\t\" usage threshold is not supported.\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.config(\"Memory pool name: \" + memoryPoolMXBean.getName() +\n\t\t\t\t\t\t\t\t\", type: \" + memoryPoolMXBean.getType().toString() +\n\t\t\t\t\t\t\t\t\" is invalid.\");\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleNotification(Notification note, Object handback) {\n\t\tif (note.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {\n\t\t\tlog.info(\"Usage threshold exceeded, sending notification.\");\n\t\t\tNumberFormat format = NumberFormat.getIntegerInstance();\n\t\t\tif (format instanceof DecimalFormat) {\n\t\t\t\tDecimalFormat decf = (DecimalFormat) format;\n\t\t\t\tdecf.applyPattern(decf.toPattern() + \" KB\");\n\t\t\t}\n\t\t\tMemoryPoolMXBean memoryPoolMXBean = (MemoryPoolMXBean) handback;\n\t\t\tString message = \"Threshold \" +\n\t\t\t\t\t\t\tformat.format(memoryPoolMXBean.getUsageThreshold() / 1024) +\n\t\t\t\t\t\t\t\" for memory pool: \" + memoryPoolMXBean.getName() +\n\t\t\t\t\t\t\t\", type: \" + memoryPoolMXBean.getType().toString() +\n\t\t\t\t\t\t\t\" exceeded.\";\n\t\t\tsendWarningOut(message, handback);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getState() {\n\t\tNumberFormat format = NumberFormat.getIntegerInstance();\n\t\tif (format instanceof DecimalFormat) {\n\t\t\tDecimalFormat decf = (DecimalFormat) format;\n\t\t\tdecf.applyPattern(decf.toPattern() + \" KB\");\n\t\t}\n\t\tNumberFormat formp = NumberFormat.getPercentInstance();\n\t\tformp.setMaximumFractionDigits(2);\n\t\tStringBuilder sb = new StringBuilder();\n\t\tList<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();\n\t\tfor (MemoryPoolMXBean memoryPoolMXBean : memPools) {\n\t\t\tMemoryUsage memUsage = memoryPoolMXBean.getUsage();\n\t\t\tif (memUsage != null) {\n\t\t\t\tsb.append(\"Memory pool: \" + memoryPoolMXBean.getName() +\n\t\t\t\t\t\t\t\t\", type: \" + memoryPoolMXBean.getType().toString() +\n\t\t\t\t\t\t\t\t\", usage: \" + format.format(memUsage.getUsed()/1024) +\n\t\t\t\t\t\t\t\t\" of \" + format.format(memUsage.getMax()/1024) +\n\t\t\t\t\t\t\t\t\" - \" +\n\t\t\t\t\t\t\t\tformp.format(new Long(memUsage.getUsed()).doubleValue()/\n\t\t\t\t\t\t\t\tnew Long(memUsage.getMax()).doubleValue()));\n\t\t\t\tif (memoryPoolMXBean.isUsageThresholdSupported()) {\n\t\t\t\t\tsb.append(\", treshold: \" +\n\t\t\t\t\t\t\t\t\tformat.format(memoryPoolMXBean.getUsageThreshold() / 1024));\n\t\t\t\t}\n\t\t\t\tsb.append(\"\\n\");\n\t\t\t}\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n\t}\n\n\tprivate static int GC_INTERVAL = 40;\n\tprivate int gc_cnt = new Random(System.currentTimeMillis()).nextInt(GC_INTERVAL);\n\t@Override\n\tpublic void check1Min(Queue<Packet> results) {\n\t\tif (++gc_cnt >= GC_INTERVAL) {\n\t\t\tRuntime.getRuntime().gc();\n\t\t\tgc_cnt = 0;\n\t\t}\n\t}\n\n\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/N270Monitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\n\n/**\n * Created: Jun 20, 2009 3:42:32 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class N270Monitor extends AbstractMonitor {\n\n  /**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n\t\t\t\t\tLogger.getLogger(N270Monitor.class.getName());\n\n\tprivate static final String TEMP_FILE =\n\t\t\t\t\t\"/proc/acpi/thermal_zone/TZ01/temperature\";\n\tprivate static final String THROTT_DIR = \"/proc/acpi/processor/CPU\";\n\tprivate static final String THROTT_FILE =\t\"/throttling\";\n\tprivate static final String FREQ_FILE = \"/proc/cpuinfo\";\n\tprivate int cpu_temp = 0;\n\tprivate int[] cpu_thrott_st = new int[Runtime.getRuntime().availableProcessors()];\n\tprivate int[] cpu_thrott_pr = new int[Runtime.getRuntime().availableProcessors()];\n\tprivate float[] cpu_freq = new float[Runtime.getRuntime().availableProcessors()];\n\n\t@Override\n\tpublic void destroy() {\n\t  // Nothing to destroy\n\t}\n\n\t@Override\n\tpublic void check10Secs(Queue<Packet> results) {\n\t\tcheckCPUTemperature();\n\t\tcheckCPUFrequency();\n\t\tcheckCPUThrottling();\n\t}\n\n\tprivate void checkCPUFrequency() {\n\t\ttry {\n\t\t\tint cpu = 0;\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(FREQ_FILE));\n\t\t\tString line = null;\n\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\tif (line.startsWith(\"cpu MHz\")) {\n\t\t\t\t\tint idx = line.indexOf(':');\n\t\t\t\t\tcpu_freq[cpu++] = Float.parseFloat(line.substring(idx+1).trim());\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuffr.close();\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Can't read file: \" + FREQ_FILE, ex);\n\t\t}\n\t}\n\n\tprivate void checkCPUTemperature() {\n\t\ttry {\n\t\t\tBufferedReader buffr = new BufferedReader(new FileReader(TEMP_FILE));\n\t\t\tString line = buffr.readLine();\n\t\t\tif (line != null) {\n\t\t\t\tcpu_temp = Integer.parseInt(line.substring(\"temperature:\".length(),\n\t\t\t\t\t\t\t\tline.length()-1).trim());\n\t\t\t} else {\n\t\t\t\tlog.warning(\"Empty file: \" + TEMP_FILE);\n\t\t\t}\n\t\t\tbuffr.close();\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.WARNING, \"Can't read file: \" + TEMP_FILE, ex);\n\t\t}\n\t}\n\n\tprivate void checkCPUThrottling() {\n\t\tfor (int i = 0; i < cpu_thrott_st.length; i++) {\n\t\t\ttry {\n\t\t\t\tBufferedReader buffr = \n\t\t\t\t\t\t\t\tnew BufferedReader(new FileReader(THROTT_DIR + i + THROTT_FILE));\n\t\t\t\tString line = null;\n\t\t\t\twhile ((line = buffr.readLine()) != null) {\n          String line_trimmed = line.trim();\n\t\t\t\t\tif (line_trimmed.startsWith(\"*\")) {\n\t\t\t\t\t\tint idx = line_trimmed.indexOf(':');\n\t\t\t\t\t\tcpu_thrott_st[i] = Integer.parseInt(line_trimmed.substring(2, idx));\n\t\t\t\t\t\tString line_pr = line_trimmed.substring(idx+1, \n\t\t\t\t\t\t\t\t\t\tline_trimmed.length()-1).trim();\n\t\t\t\t\t\tcpu_thrott_pr[i] = Integer.parseInt(line_pr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbuffr.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't read file: \" +\n\t\t\t\t\t\t\t\tTHROTT_DIR + i + THROTT_FILE, ex);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getState() {\n\t\tStringBuilder sb = new StringBuilder(\"CPU temperature: \" + cpu_temp + \" C\\n\");\n\t\tfor (int i = 0; i < cpu_thrott_st.length; i++) {\n\t\t\tsb.append(\"CPU \" + i + \": FREQ: \" + cpu_freq[i] +\n\t\t\t\t\t\t\t\" MHz, Throtting: T\" + cpu_thrott_st[i] +\n\t\t\t\t\t\t\t\" - \" + cpu_thrott_pr[i] + \"%\\n\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\tprivate final static String N270_MON = \"cpu-mon\";\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n    super.getStatistics(list);\n\t\tlist.add(N270_MON, \"CPU temp\", this.cpu_temp, Level.INFO);\n\t\tif (list.checkLevel(Level.FINE)) {\n\t\t\tStringBuilder cpu_freq_str = new StringBuilder();\n\t\t\tStringBuilder cpu_thr_str = new StringBuilder();\n\t\t\tfor (int i = 0; i < cpu_thrott_st.length; i++) {\n\t\t\t\tif (cpu_freq_str.length() > 0) {\n\t\t\t\t\tcpu_freq_str.append(\", \");\n\t\t\t\t}\n\t\t\t\tcpu_freq_str.append(\"CPU\").append(i).append(\": \");\n\t\t\t\tcpu_freq_str.append(cpu_freq[i]).append(\" MHz\");\n\t\t\t\tif (cpu_thr_str.length() > 0) {\n\t\t\t\t\tcpu_thr_str.append(\", \");\n\t\t\t\t}\n\t\t\t\tcpu_thr_str.append(\"CPU\").append(i).append(\": T\");\n\t\t\t\tcpu_thr_str.append(cpu_thrott_st[i]).append(\" - \");\n\t\t\t\tcpu_thr_str.append(cpu_thrott_pr[i]).append(\"%\");\n\t\t\t}\n\t\t\tlist.add(N270_MON, \"CPU freq\", cpu_freq_str.toString(), Level.FINE);\n\t\t\tlist.add(N270_MON, \"CPU throt\", cpu_thr_str.toString(), Level.FINE);\n\t\t}\n\t}\n\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/ResourceMonitorIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.sreceiver.sysmon;\n\nimport java.util.Queue;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Dec 10, 2008 12:12:27 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ResourceMonitorIfc {\n\n\tpublic static final long SECOND = 1000;\n\tpublic static final long MINUTE = 60*SECOND;\n\tpublic static final long INTERVAL_10SECS = 10 * SECOND;\n\tpublic static final long INTERVAL_1MIN = MINUTE;\n\tpublic static final long INTERVAL_1HOUR = 60 * MINUTE;\n\tpublic static final long INTERVAL_1DAY = 24 * INTERVAL_1HOUR;\n\n\tpublic void init(JID jid, float treshold, SystemMonitorTask smTask);\n\n\tpublic void destroy();\n\n\tpublic void check10Secs(Queue<Packet> results);\n\n\tpublic void check1Day(Queue<Packet> results);\n\n\tpublic void check1Hour(Queue<Packet> results);\n\n\tpublic void check1Min(Queue<Packet> results);\n\n\tpublic String getState();\n\n\tpublic String commandsHelp();\n\n\tpublic String runCommand(String[] command);\n\n\tpublic boolean isMonitorCommand(String command);\n\n\tvoid getStatistics(StatisticsList list);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/sreceiver/sysmon/SystemMonitorTask.java",
    "content": "/*\n * SystemMonitorTask.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.sreceiver.sysmon;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.sreceiver.PropertyItem;\nimport tigase.server.sreceiver.RepoRosterTask;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.util.ClassUtil;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport static tigase.server.sreceiver.PropertyConstants.*;\nimport static tigase.server.sreceiver.sysmon.ResourceMonitorIfc.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.LinkedHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\n/**\n * Created: Dec 6, 2008 8:12:41 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SystemMonitorTask\n\t\t\t\textends RepoRosterTask {\n\tprivate static Logger log =\n\t\tLogger.getLogger(\"tigase.server.sreceiver.sysmon.SystemMonitorTask\");\n\tprivate static final String MONITORS_CLASSES_PROP_KEY = \"Monitor implementations\";\n\tprivate static final String TASK_HELP                 =\n\t\t\"This is a system monitor task.\" +\n\t\t\" It monitors system resources usage and sends notifications\" +\n\t\t\" to subscribed users. It allos responds to your messages with\" +\n\t\t\" a simple reply message. This is to ensure the monitor works.\";\n\tprivate static final String TASK_TYPE                  = \"System Monitor\";\n\tprivate static final String WARNING_THRESHOLD_PROP_KEY = \"Warning threshold\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// private long interval = 10*SECOND;\n\tprivate String[] all_monitors                 = null;\n\tprivate String[] selected_monitors            = null;\n\tprivate Map<JID, ResourceMonitorIfc> monitors = new LinkedHashMap<JID,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tResourceMonitorIfc>();\n\tprivate Timer tasks             = null;\n\tprivate float warning_threshold = 0.8f;\n\t;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic SystemMonitorTask() {\n\t\ttry {\n\t\t\tSet<ResourceMonitorIfc> mons =\n\t\t\t\tClassUtil.getImplementations(ResourceMonitorIfc.class);\n\n\t\t\tall_monitors = new String[mons.size()];\n\n\t\t\tint idx = 0;\n\n\t\t\tfor (ResourceMonitorIfc monitor : mons) {\n\t\t\t\tall_monitors[idx++] = monitor.getClass().getName();\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"Can't load resource monitors implementations\", ex);\n\t\t\tall_monitors    = new String[2];\n\t\t\tall_monitors[0] = \"tigase.server.sreceiver.sysmon.CPUMonitor\";\n\t\t\tall_monitors[1] = \"tigase.server.sreceiver.sysmon.MemMonitor\";\n\t\t}\n\t}\n\n\t//~--- enums ----------------------------------------------------------------\n\n\tprivate enum command {\n\t\thelp(\" - Displays help info.\"),\n\t\tstate(\" - Displays current state from all monitors.\"),\n\t\tthreshold(\" [0.NN] - sets/displays current threshold value.\");\n\n\t\tprivate String helpText = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate command(String helpText) {\n\t\t\tthis.helpText = helpText;\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * \n\t\t */\n\t\tpublic String getHelp() {\n\t\t\treturn helpText;\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void destroy(Queue<Packet> results) {\n\t\ttasks.cancel();\n\t\ttasks = null;\n\t\tsuper.destroy(results);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, PropertyItem> getDefaultParams() {\n\t\tMap<String, PropertyItem> defs = super.getDefaultParams();\n\n\t\tdefs.put(DESCRIPTION_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(DESCRIPTION_PROP_KEY, DESCRIPTION_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"System Monitor Task\"));\n\t\tdefs.put(MESSAGE_TYPE_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(MESSAGE_TYPE_PROP_KEY, MESSAGE_TYPE_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMessageType.NORMAL));\n\t\tdefs.put(ONLINE_ONLY_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(ONLINE_ONLY_PROP_KEY, ONLINE_ONLY_DISPL_NAME, false));\n\t\tdefs.put(REPLACE_SENDER_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(REPLACE_SENDER_PROP_KEY, REPLACE_SENDER_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSenderAddress.REPLACE_SRECV));\n\t\tdefs.put(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBSCR_RESTRICTIONS_DISPL_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSubscrRestrictions.MODERATED));\n\t\tdefs.put(MONITORS_CLASSES_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(MONITORS_CLASSES_PROP_KEY, MONITORS_CLASSES_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tall_monitors, all_monitors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"List of system monitors available for use\"));\n\t\tdefs.put(WARNING_THRESHOLD_PROP_KEY,\n\t\t\t\t\t\t new PropertyItem(WARNING_THRESHOLD_PROP_KEY, WARNING_THRESHOLD_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twarning_threshold));\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getHelp() {\n\t\treturn TASK_HELP;\n\t}\n\n\t@Override\n\tpublic Map<String, PropertyItem> getParams() {\n\t\tMap<String, PropertyItem> props = super.getParams();\n\n\t\tprops.put(MONITORS_CLASSES_PROP_KEY,\n\t\t\t\t\t\t\tnew PropertyItem(MONITORS_CLASSES_PROP_KEY, MONITORS_CLASSES_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t selected_monitors, all_monitors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"List of system monitors available for use\"));\n\t\tprops.put(WARNING_THRESHOLD_PROP_KEY,\n\t\t\t\t\t\t\tnew PropertyItem(WARNING_THRESHOLD_PROP_KEY, WARNING_THRESHOLD_PROP_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t warning_threshold));\n\n//  log.fine(\"selected_monitors: \" + Arrays.toString(selected_monitors) +\n//            \", all_monitors: \" + Arrays.toString(all_monitors));\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tmonitor.getStatistics(list);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getType() {\n\t\treturn TASK_TYPE;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(Queue<Packet> results) {\n\t\tsuper.init(results);\n\t\ttasks = new Timer(\"SystemMonitorTask\", true);\n\t\ttasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmonitor10Secs();\n\t\t\t}\n\t\t}, INTERVAL_10SECS, INTERVAL_10SECS);\n\t\ttasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmonitor1Min();\n\t\t\t}\n\t\t}, INTERVAL_1MIN, INTERVAL_1MIN);\n\t\ttasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmonitor1Hour();\n\t\t\t}\n\t\t}, INTERVAL_1HOUR, INTERVAL_1HOUR);\n\t\ttasks.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmonitor1Day();\n\t\t\t}\n\t\t}, INTERVAL_1DAY, INTERVAL_1DAY);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setParams(Map<String, Object> map) {\n\t\tsuper.setParams(map);\n\n\t\tString threshold = (String) map.get(WARNING_THRESHOLD_PROP_KEY);\n\n\t\tif (threshold != null) {\n\n\t\t\t// In fact it can be null if this is just a configuration change\n\t\t\t// in this case only changed properties are passed to the task\n\t\t\ttry {\n\t\t\t\tfloat tresh = Float.parseFloat(threshold);\n\n\t\t\t\twarning_threshold = tresh;\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.warning(\"Incorrect warning threshold, using default\" + threshold);\n\t\t\t}\n\t\t}\n\n\t\tString[] mons = null;\n\n\t\ttry {\n\t\t\tmons = (String[]) map.get(MONITORS_CLASSES_PROP_KEY);\n\t\t} catch (Exception e) {\n\t\t\tlog.warning(\"Incorrect monitors list: \" + map.get(MONITORS_CLASSES_PROP_KEY));\n\t\t\tmons = all_monitors;\n\t\t}\n\t\tif (mons != null) {\n\t\t\tselected_monitors = mons;\n\t\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\t\tmonitor.destroy();\n\t\t\t}\n\t\t\tmonitors.clear();\n\t\t\tfor (String string : mons) {\n\t\t\t\ttry {\n\t\t\t\t\tResourceMonitorIfc resMon =\n\t\t\t\t\t\t(ResourceMonitorIfc) Class.forName(string).newInstance();\n\t\t\t\t\tJID monJid = JID.jidInstance(getJID() + \"/\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t resMon.getClass().getSimpleName());\n\n\t\t\t\t\tresMon.init(monJid, warning_threshold, this);\n\t\t\t\t\tmonitors.put(monJid, resMon);\n\t\t\t\t\tlog.config(\"Loaded resource monitor: \" + monJid);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Can't instantiate resource monitor: \" + string, ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void processMessage(Packet packet, Queue<Packet> results) {\n\t\tif (isPostCommand(packet)) {\n\t\t\trunCommand(packet, results);\n\t\t} else {\n\t\t\tResourceMonitorIfc monitor = monitorForCommand(packet);\n\n\t\t\tif (monitor != null) {\n\t\t\t\trunMonitorCommand(monitor, packet, results);\n\t\t\t} else {\n\t\t\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"This is response to your message: [\" + body +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"]\", \"Response\", null, packet.getStanzaId()));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param input\n\t */\n\tprotected void sendPacketOut(Packet input) {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tif ((input.getElemName() == \"message\") || (input.getStanzaTo() == null)) {\n\t\t\tsuper.processMessage(input, results);\n\t\t} else {\n\t\t\tresults.add(input);\n\t\t}\n\t\tfor (Packet packet : results) {\n\t\t\taddOutPacket(packet);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param input\n\t */\n\tprotected void sendPacketsOut(Queue<Packet> input) {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tfor (Packet packet : input) {\n\t\t\tif ((packet.getElemName() == \"message\") || (packet.getStanzaTo() == null)) {\n\t\t\t\tsuper.processMessage(packet, results);\n\t\t\t} else {\n\t\t\t\tresults.add(packet);\n\t\t\t}\n\t\t}\n\t\tfor (Packet packet : results) {\n\t\t\taddOutPacket(packet);\n\t\t}\n\t}\n\n\tprivate String commandsHelp() {\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tfor (command comm : command.values()) {\n\t\t\tsb.append(\"//\" + comm.name() + comm.getHelp() + \"\\n\");\n\t\t}\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tsb.append(monitor.commandsHelp());\n\t\t}\n\n\t\treturn \"Available commands are:\\n\" + sb.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isPostCommand(Packet packet) {\n\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body != null) {\n\t\t\tfor (command comm : command.values()) {\n\t\t\t\tif (body.startsWith(\"//\" + comm.toString())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void monitor10Secs() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tmonitor.check10Secs(results);\n\t\t}\n\t\tsendPacketsOut(results);\n\t}\n\n\tprivate void monitor1Day() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tmonitor.check1Day(results);\n\t\t}\n\t\tsendPacketsOut(results);\n\t}\n\n\tprivate void monitor1Hour() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tmonitor.check1Hour(results);\n\t\t}\n\t\tsendPacketsOut(results);\n\t}\n\n\tprivate void monitor1Min() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\tmonitor.check1Min(results);\n\t\t}\n\t\tsendPacketsOut(results);\n\t}\n\n\tprivate ResourceMonitorIfc monitorForCommand(Packet packet) {\n\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\tif (body != null) {\n\t\t\tfor (ResourceMonitorIfc monitor : monitors.values()) {\n\t\t\t\tif (monitor.isMonitorCommand(body)) {\n\t\t\t\t\treturn monitor;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate void runCommand(Packet packet, Queue<Packet> results) {\n\t\tString body         = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\t\tString[] body_split = body.split(\"\\\\s\");\n\t\tcommand comm        = command.valueOf(body_split[0].substring(2));\n\n\t\tswitch (comm) {\n\t\tcase help :\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, commandsHelp(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Commands description\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\n\t\t\tbreak;\n\n\t\tcase state :\n\t\t\tStringBuilder sb = new StringBuilder(\"\\n\");\n\n\t\t\tfor (ResourceMonitorIfc resmon : monitors.values()) {\n\t\t\t\tsb.append(resmon.getClass().getSimpleName() + \":\\n\");\n\t\t\t\tsb.append(resmon.getState() + \"\\n\");\n\t\t\t}\n\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, sb.toString(), \"Monitors State\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t null, packet.getStanzaId()));\n\n\t\t\tbreak;\n\n\t\tcase threshold :\n\t\t\tif (body_split.length > 1) {\n\t\t\t\tboolean correct = false;\n\n\t\t\t\ttry {\n\t\t\t\t\tfloat newthreshold = Float.parseFloat(body_split[1]);\n\n\t\t\t\t\tif ((newthreshold > 0) && (newthreshold < 1)) {\n\t\t\t\t\t\twarning_threshold = newthreshold;\n\t\t\t\t\t\tfor (Map.Entry<JID, ResourceMonitorIfc> resmon : monitors.entrySet()) {\n\t\t\t\t\t\t\tresmon.getValue().init(resmon.getKey(), warning_threshold, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcorrect = true;\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {}\n\t\t\t\tif (correct) {\n\t\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"New threshold set to: \" + warning_threshold +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"\\n\", \"Threshold command.\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t\t\t} else {\n\t\t\t\t\tresults\n\t\t\t\t\t\t.offer(Message\n\t\t\t\t\t\t\t.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(), StanzaType\n\t\t\t\t\t\t\t\t.chat, \"Incorrect threshold givenm using the old threshold: \" +\n\t\t\t\t\t\t\t\t\twarning_threshold + \"\\n\" +\n\t\t\t\t\t\t\t\t\t\"Correct threshold is a float point number 0 < N < 1.\", \"Threshold command.\", null, packet\n\t\t\t\t\t\t\t\t\t\t.getStanzaId()));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Current threshold value is: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t warning_threshold, \"Threshold command.\", null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaId()));\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate void runMonitorCommand(ResourceMonitorIfc monitor, Packet packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Queue<Packet> results) {\n\t\tString body         = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\t\tString[] body_split = body.split(\"\\\\s\");\n\t\tString result       = monitor.runCommand(body_split);\n\n\t\tif (result == null) {\n\t\t\tresult = \"Monitor \" + monitor.getClass().getSimpleName() +\n\t\t\t\t\t\t\t \" command was run but returned no results.\";\n\t\t}\n\t\tresults.offer(Message.getMessage(packet.getStanzaTo(), packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t StanzaType.chat, result,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t monitor.getClass().getSimpleName() + \" command.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t null, packet.getStanzaId()));\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/DrupalCommentsTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ssender;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n//import java.sql.Date;\nimport java.util.ArrayDeque;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * <code>DrupalCommentsTask</code> implements tasks for cyclic retrieving new\n * comments in the Drupal database.\n * Then it can sends this to one selected JID. Thus it should be used toghether\n * with StanzaReceiver task which can distribute this informatin to all interested\n * (subscribed) users.\n * <br>\n * You have to specify destination JID where comments have to be sent.\n * It is not very useful to\n * send post to just one person so to ditribute forum posts to biger number of\n * users this task should be paired with <code>StanzaReceiver</code> task which\n * can distribute it to all interested users.\n * Sample connection string:\n * <pre>jdbc:mysql://localhost/tigasedb?user=tigase&amp;password=pass&amp;id=nick@domain.com</pre>\n * <br>\n * Created: Fri Apr 20 12:10:55 2007\n * <br>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DrupalCommentsTask extends SenderTask {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log =\n\t\tLogger.getLogger(\"tigase.server.ssender.DrupalCommentsTask\");\n\tprivate static final long SECOND = 1000;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * <code>conn</code> variable keeps connection to database.\n\t */\n\tprivate Connection conn = null;\n\n\t/**\n\t * <code>conn_valid_st</code> is a prepared statement keeping query used\n\t * to validate connection to database:\n\t * <pre>select 1</pre>\n\t */\n\tprivate PreparedStatement conn_valid_st = null;\n\n\t/**\n\t * <code>db_conn</code> field stores database connection string.\n\t */\n\tprivate String db_conn = null;\n\n\t/**\n\t * <code>get_new_comments</code> is a prepared statement for retrieving all\n\t * new comments from drupal forum.\n\t */\n\tprivate PreparedStatement get_new_comments = null;\n\n\t/**\n\t * <code>get_new_topics</code> is a prepared statement for retrieving all\n\t * new topics for drupal forum.\n\t */\n\tprivate PreparedStatement get_new_topics = null;\n\n\t/**\n\t * <code>handler</code> is a reference to object processing stanza\n\t * read from database.\n\t */\n\tprivate StanzaHandler handler = null;\n\n\t/**\n\t * <code>jid</code> keeps destination address where all new posts from\n\t * the forum are sent.\n\t *\n\t */\n\tprivate JID jid = null;\n\n\t/**\n\t * <code>lastCheck</code> keeps time of last forum comments check so it\n\t * gets only new posts.\n\t *\n\t */\n\tprotected long lastCommentsCheck = -1;\n\n\t/**\n\t * <code>lastConnectionValidated</code> variable keeps time where the\n\t * connection was validated for the last time.\n\t */\n\tprivate long lastConnectionValidated = 0;\n\n\t/**\n\t * <code>lastCheck</code> keeps time of last forum topics check so it\n\t * gets only new posts.\n\t *\n\t */\n\tprotected long lastTopicsCheck = -1;\n\n\t/**\n\t * <code>connectionValidateInterval</code> is kind of constant keeping minimum\n\t * interval for validating connection to database.\n\t */\n\tprivate long connectionValidateInterval = SECOND * 60;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean cancel() {\n\t\tboolean result = super.cancel();\n\n\t\ttry {\n\t\t\tconn_valid_st.close();\n\t\t\tget_new_comments.close();\n\t\t\tconn.close();\n\t\t} catch (Exception e) {\n\n\t\t\t// Ignore.\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getInitString() {\n\t\treturn db_conn;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(StanzaHandler handler, String initString) throws IOException {\n\t\tthis.handler = handler;\n\t\tdb_conn = initString;\n\n\t\ttry {\n\t\t\tfindExtraParams(db_conn);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new IOException(\"Destination address problem, stringprep processing failed\", ex);\n\t\t}\n\n\t\tlastCommentsCheck = System.currentTimeMillis() / SECOND;\n\t\tlastTopicsCheck = System.currentTimeMillis() / SECOND;\n\n\t\ttry {\n\t\t\tinitRepo();\n\t\t} catch (SQLException e) {\n\t\t\tthrow new IOException(\"Problem initializing SenderTask.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void run() {\n\n//  log.info(\"Task \" + getName()\n//      + \", timestamp = \" + lastCommentsCheck\n\t\t// + \", getTime() = \" + lastCommentsCheck.getTime()\n//    + \", System.currentTimeMillis() = \" + System.currentTimeMillis());\n\t\tQueue<Packet> results = getNewPackets();\n\n\t\thandler.handleStanzas(results);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected Queue<Packet> getNewPackets() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tnewTopics(results);\n\t\tnewComments(results);\n\n\t\treturn results;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * <code>checkConnection</code> method checks whether connection to database\n\t * is still valid, if not it simply reconnect and reinitializes database\n\t * backend.\n\t *\n\t * @return a <code>boolean</code> value\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate boolean checkConnection() throws SQLException {\n\t\ttry {\n\t\t\tlong tmp = System.currentTimeMillis();\n\n\t\t\tif ((tmp - lastConnectionValidated) >= connectionValidateInterval) {\n\t\t\t\tconn_valid_st.executeQuery();\n\t\t\t\tlastConnectionValidated = tmp;\n\t\t\t}    // end of if ()\n\t\t} catch (Exception e) {\n\t\t\tinitRepo();\n\t\t}      // end of try-catch\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * <code>findTableName</code> method parses database connection string to find\n\t * table name where stanza packets are waiting for sending.\n\t *\n\t * @param db_str a <code>String</code> value\n\t */\n\tprivate void findExtraParams(String db_str) throws TigaseStringprepException {\n\t\tString[] params = db_str.split(\"&\");\n\n\t\tfor (String par : params) {\n\t\t\tif (par.startsWith(\"jid=\")) {\n\t\t\t\tjid = JID.jidInstance(par.substring(\"jid=\".length(), par.length()));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * <code>initRepo</code> method initializes database backend - connects to\n\t * database, creates prepared statements and sets basic variables.\n\t *\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate void initRepo() throws SQLException {\n\t\tconn = DriverManager.getConnection(db_conn);\n\t\tconn.setAutoCommit(true);\n\n\t\tString query = \"select 1;\";\n\n\t\tconn_valid_st = conn.prepareStatement(query);\n\t\tquery = \"select name, thread, subject, comment \" + \"from comments where\"\n\t\t\t\t+ \" (status = 0) and (timestamp > ?);\";\n\t\tget_new_comments = conn.prepareStatement(query);\n\t\tquery = \"select users.name as name, node_revisions.title as title,\"\n\t\t\t\t+ \" node_revisions.body as body\" + \" from forum, node_revisions, users where\"\n\t\t\t\t\t+ \" (status = 1) and (node_revisions.timestamp > ?)\"\n\t\t\t\t\t\t+ \" and users.uid = node_revisions.uid\" + \" and node_revisions.vid = forum.vid;\";\n\t\tget_new_topics = conn.prepareStatement(query);\n\t}\n\n\tprivate void newComments(Queue<Packet> results) {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tcheckConnection();\n\t\t\tlog.info(\"New comment check, timestamp = \" + lastCommentsCheck);\n\t\t\tget_new_comments.setLong(1, lastCommentsCheck);\n\t\t\tlastCommentsCheck = System.currentTimeMillis() / SECOND;\n\t\t\trs = get_new_comments.executeQuery();\n\n\t\t\twhile (rs.next()) {\n\t\t\t\tString name = rs.getString(\"name\");\n\t\t\t\tString thread = rs.getString(\"thread\");\n\t\t\t\tString subject = rs.getString(\"subject\");\n\t\t\t\tString comment = rs.getString(\"comment\");\n\t\t\t\tPacket msg = Message.getMessage(getName(), jid, StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t \"New comment by \" + name + \":\\n\\n\" + XMLUtils.escape(comment),\n\t\t\t\t\t\t\t\t\t\t\t XMLUtils.escape(subject), thread, null);\n\n\t\t\t\tlog.fine(\"Sending new comment: \" + msg.toString());\n\t\t\t\tresults.offer(msg);\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t// this.cancel();\n\t\t} finally {\n\t\t\trelease(rs);\n\t\t\trs = null;\n\t\t}\n\t}\n\n\tprivate void newTopics(Queue<Packet> results) {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tcheckConnection();\n\t\t\tget_new_topics.setLong(1, lastTopicsCheck);\n\t\t\tlastTopicsCheck = System.currentTimeMillis() / SECOND;\n\t\t\trs = get_new_topics.executeQuery();\n\n\t\t\twhile (rs.next()) {\n\t\t\t\tString name = rs.getString(\"name\");\n\t\t\t\tString title = rs.getString(\"title\");\n\t\t\t\tString body = rs.getString(\"body\");\n\t\t\t\tPacket msg = Message.getMessage(getName(), jid, StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t \"New post by \" + name + \":\\n\\n\" + XMLUtils.escape(body),\n\t\t\t\t\t\t\t\t\t\t\t XMLUtils.escape(title), null, null);\n\n\t\t\t\tlog.fine(\"Sending new topic: \" + msg.toString());\n\t\t\t\tresults.offer(msg);\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t// this.cancel();\n\t\t} finally {\n\t\t\trelease(rs);\n\t\t\trs = null;\n\t\t}\n\t}\n\n\t/**\n\t * <code>release</code> method releases some SQL query variables.\n\t *\n\t * @param rs a <code>ResultSet</code> value\n\t */\n\tprivate void release(ResultSet rs) {\n\t\tif (rs != null) {\n\t\t\ttry {\n\t\t\t\trs.close();\n\t\t\t} catch (SQLException sqlEx) {}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/DrupalForumTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.ssender;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n//import java.sql.Date;\nimport java.util.ArrayDeque;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * <code>DrupalForumTask</code> implements tasks for cyclic retrieving new\n * posts on selected <a href=\"http://drupal.org/\">Drupal</a> forum.\n * It detects both new forum topics and new comments for forum topics.\n * Then it can sends this to one selected JID. Thus it should be used toghether\n * with StanzaReceiver task which can distribute this informatin to all interested\n * (subscribed) users.\n * <br>\n * You have to specify forum ID for monitoring in connection string as well as\n * destination JID where forum posts have to be sent. It is not very useful to\n * send post to just one person so to ditribute forum posts to biger number of\n * users this task should be paired with <code>StanzaReceiver</code> task which\n * can distribute it to all interested users.\n * Sample connection string:\n * <pre>jdbc:mysql://localhost/tigasedb?user=tigase&amp;password=pass&amp;forum=3&amp;jid=nick@domain.com</pre>\n * <br>\n * Created: Fri Apr 20 12:10:55 2007\n * <br>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DrupalForumTask extends SenderTask {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.server.ssender.DrupalForumTask\");\n\tprivate static final long SECOND = 1000;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/**\n\t * <code>conn</code> variable keeps connection to database.\n\t */\n\tprivate Connection conn = null;\n\n\t/**\n\t * <code>conn_valid_st</code> is a prepared statement keeping query used\n\t * to validate connection to database:\n\t * <pre>select 1</pre>\n\t */\n\tprivate PreparedStatement conn_valid_st = null;\n\n\t/**\n\t * <code>connectionValidateInterval</code> is kind of constant keeping minimum\n\t * interval for validating connection to database.\n\t */\n\tprivate long connectionValidateInterval = 1000 * 60;\n\n\t/**\n\t * <code>db_conn</code> field stores database connection string.\n\t */\n\tprivate String db_conn = null;\n\n\t/**\n\t * <code>forumId</code> variable keeps drupal numerical forum ID which\n\t * has to be monitored for new posts.\n\t */\n\tprivate long forumId = -1;\n\n\t/**\n\t * <code>get_new_comments</code> is a prepared statement for retrieving all\n\t * new comments from drupal forum.\n\t */\n\tprivate PreparedStatement get_new_comments = null;\n\n\t/**\n\t * <code>get_new_topics</code> is a prepared statement for retrieving all\n\t * new topics for drupal forum.\n\t */\n\tprivate PreparedStatement get_new_topics = null;\n\n\t/**\n\t * <code>handler</code> is a reference to object processing stanza\n\t * read from database.\n\t */\n\tprivate StanzaHandler handler = null;\n\n\t/**\n\t * <code>jid</code> keeps destination address where all new posts from\n\t * the forum are sent.\n\t *\n\t */\n\tprivate JID jid = null;\n\n\t/**\n\t * <code>lastCheck</code> keeps time of last forum comments check so it\n\t * gets only new posts.\n\t *\n\t */\n\tprotected long lastCommentsCheck = -1;\n\n\t/**\n\t * <code>lastConnectionValidated</code> variable keeps time where the\n\t * connection was validated for the last time.\n\t */\n\tprivate long lastConnectionValidated = 0;\n\n\t/**\n\t * <code>lastCheck</code> keeps time of last forum topics check so it\n\t * gets only new posts.\n\t *\n\t */\n\tprotected long lastTopicsCheck = -1;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean cancel() {\n\t\tboolean result = super.cancel();\n\n\t\ttry {\n\t\t\tconn_valid_st.close();\n\t\t\tget_new_topics.close();\n\t\t\tget_new_comments.close();\n\t\t\tconn.close();\n\t\t} catch (Exception e) {\n\n\t\t\t// Ignore.\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getInitString() {\n\t\treturn db_conn;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(StanzaHandler handler, String initString) throws IOException {\n\t\tthis.handler = handler;\n\t\tdb_conn = initString;\n\n\t\ttry {\n\t\t\tfindExtraParams(db_conn);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new IOException(\"Destination address problem, stringprep processing failed\", ex);\n\t\t}\n\n\t\tlastTopicsCheck = System.currentTimeMillis() / SECOND;\n\t\tlastCommentsCheck = System.currentTimeMillis() / SECOND;\n\n\t\ttry {\n\t\t\tinitRepo();\n\t\t} catch (SQLException e) {\n\t\t\tthrow new IOException(\"Problem initializing SenderTask.\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void run() {\n\n//  log.info(\"Task \" + getName()\n//      + \", timestamp = \" + lastCommentsCheck\n// //      + \", getTime() = \" + lastCommentsCheck.getTime()\n//    + \", System.currentTimeMillis() = \" + System.currentTimeMillis());\n\t\tQueue<Packet> results = getNewPackets();\n\n\t\thandler.handleStanzas(results);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected Queue<Packet> getNewPackets() {\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\n\t\tnewTopics(results);\n\t\tnewComments(results);\n\n\t\treturn results;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * <code>checkConnection</code> method checks whether connection to database\n\t * is still valid, if not it simply reconnect and reinitializes database\n\t * backend.\n\t *\n\t * @return a <code>boolean</code> value\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate boolean checkConnection() throws SQLException {\n\t\ttry {\n\t\t\tlong tmp = System.currentTimeMillis();\n\n\t\t\tif ((tmp - lastConnectionValidated) >= connectionValidateInterval) {\n\t\t\t\tconn_valid_st.executeQuery();\n\t\t\t\tlastConnectionValidated = tmp;\n\t\t\t}    // end of if ()\n\t\t} catch (Exception e) {\n\t\t\tinitRepo();\n\t\t}      // end of try-catch\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * <code>findTableName</code> method parses database connection string to find\n\t * table name where stanza packets are waiting for sending.\n\t *\n\t * @param db_str a <code>String</code> value\n\t */\n\tprivate void findExtraParams(String db_str) throws TigaseStringprepException {\n\t\tString[] params = db_str.split(\"&\");\n\n\t\tfor (String par : params) {\n\t\t\tif (par.startsWith(\"jid=\")) {\n\t\t\t\tjid = JID.jidInstance(par.substring(\"jid=\".length(), par.length()));\n\t\t\t}\n\n\t\t\tif (par.startsWith(\"forum\")) {\n\t\t\t\ttry {\n\t\t\t\t\tforumId = Long.parseLong(par.substring(\"forum=\".length(), par.length()));\n\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\tforumId = -1;\n\t\t\t\t\tlog.warning(\"Forum ID number is incorrect: \"\n\t\t\t\t\t\t\t+ par.substring(\"forum=\".length(), par.length()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * <code>initRepo</code> method initializes database backend - connects to\n\t * database, creates prepared statements and sets basic variables.\n\t *\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate void initRepo() throws SQLException {\n\t\tconn = DriverManager.getConnection(db_conn);\n\t\tconn.setAutoCommit(true);\n\n\t\tString query = \"select 1;\";\n\n\t\tconn_valid_st = conn.prepareStatement(query);\n\t\tquery = \"select users.name as name, node_revisions.title as title,\"\n\t\t\t\t+ \" node_revisions.body as body\" + \" from forum, node_revisions, users where\"\n\t\t\t\t\t+ \" (status = 1) and (node_revisions.timestamp > ?)\"\n\t\t\t\t\t\t+ \" and forum.tid = ? and users.uid = node_revisions.uid\"\n\t\t\t\t\t\t\t+ \" and node_revisions.vid = forum.vid;\";\n\t\tget_new_topics = conn.prepareStatement(query);\n\t\tquery = \"select name, thread, subject, comment \" + \"from comments where\"\n\t\t\t\t+ \" (status = 0) and (timestamp > ?)\"\n\t\t\t\t\t+ \" and (nid in (select nid from forum where tid = ?));\";\n\t\tget_new_comments = conn.prepareStatement(query);\n\t}\n\n\tprivate void newComments(Queue<Packet> results) {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tcheckConnection();\n\t\t\tlog.info(\"New comment check, timestamp = \" + lastCommentsCheck);\n\t\t\tget_new_comments.setLong(1, lastCommentsCheck);\n\t\t\tlastCommentsCheck = System.currentTimeMillis() / SECOND;\n\t\t\tget_new_comments.setLong(2, forumId);\n\t\t\trs = get_new_comments.executeQuery();\n\n\t\t\twhile (rs.next()) {\n\t\t\t\tString name = rs.getString(\"name\");\n\t\t\t\tString thread = rs.getString(\"thread\");\n\t\t\t\tString subject = rs.getString(\"subject\");\n\t\t\t\tString comment = rs.getString(\"comment\");\n\t\t\t\tPacket msg = Message.getMessage(getName(), jid, StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t \"New comment by \" + name + \":\\n\\n\" + XMLUtils.escape(comment),\n\t\t\t\t\t\t\t\t\t\t\t XMLUtils.escape(subject), thread, null);\n\n\t\t\t\tlog.fine(\"Sending new comment: \" + msg.toString());\n\t\t\t\tresults.offer(msg);\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t// this.cancel();\n\t\t} finally {\n\t\t\trelease(rs);\n\t\t\trs = null;\n\t\t}\n\t}\n\n\tprivate void newTopics(Queue<Packet> results) {\n\t\tResultSet rs = null;\n\n\t\ttry {\n\t\t\tcheckConnection();\n\t\t\tget_new_topics.setLong(1, lastTopicsCheck);\n\t\t\tlastTopicsCheck = System.currentTimeMillis() / SECOND;\n\t\t\tget_new_topics.setLong(2, forumId);\n\t\t\trs = get_new_topics.executeQuery();\n\n\t\t\twhile (rs.next()) {\n\t\t\t\tString name = rs.getString(\"name\");\n\t\t\t\tString title = rs.getString(\"title\");\n\t\t\t\tString body = rs.getString(\"body\");\n\t\t\t\tPacket msg = Message.getMessage(getName(), jid, StanzaType.normal,\n\t\t\t\t\t\t\t\t\t\t\t \"New post by \" + name + \":\\n\\n\" + XMLUtils.escape(body),\n\t\t\t\t\t\t\t\t\t\t\t XMLUtils.escape(title), null, null);\n\n\t\t\t\tlog.fine(\"Sending new topic: \" + msg.toString());\n\t\t\t\tresults.offer(msg);\n\t\t\t}\n\t\t} catch (SQLException e) {\n\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t// this.cancel();\n\t\t} finally {\n\t\t\trelease(rs);\n\t\t\trs = null;\n\t\t}\n\t}\n\n\t/**\n\t * <code>release</code> method releases some SQL query variables.\n\t *\n\t * @param rs a <code>ResultSet</code> value\n\t */\n\tprivate void release(ResultSet rs) {\n\t\tif (rs != null) {\n\t\t\ttry {\n\t\t\t\trs.close();\n\t\t\t} catch (SQLException sqlEx) {}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/FileTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ssender;\n\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.FilenameFilter;\nimport java.io.IOException;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * <code>FileTask</code> implements tasks for cyclic retrieving stanzas from\n * a directory and sending them to the StanzaHandler object.\n * <br>\n * It looks for any new stanza to send. Any single file can contain only single\n * stanza to send and any entry in database table can also contain only single\n * stanza to send. File on hard disk and record in database is deleted after\n * it is read.\n * <br>\n * Any file in given directory is treated the same way - Tigase assumes it\n * contains valid XML data with XMPP stanza to send. You can however set in\n * configuration, using wildchars which files contain stanzas.\n * All stanzas must contain complete data including correct <em>\"from\"</em>\n * and <em>\"to\"</em> attributes.\n * <br>\n * By default it looks for <code>*.stanza</code> files in\n * <code>/var/spool/jabber/</code> folder but you can specify different\n * directory name in initialization string. Sample initialization strings:\n * <br>\n * <pre>/var/spool/jabber/*.stanza</pre>\n * <pre>/var/spool/jabber/*</pre>\n * <br>\n * The last is equal to:\n * <br>\n * <pre>/var/spool/jabber/</pre>\n * <br>\n * Note the last forward slash '/' is required in such case if the last element\n * of the path is a directory.\n * <br>\n * <strong>Please note! Tigase must have writing permissions for this directory,\n * otherwise it may not function properly.</strong>\n * <br>\n * Created: Fri Apr 20 12:10:55 2007\n * <br>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class FileTask extends SenderTask {\n\n\t/**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n    Logger.getLogger(\"tigase.server.ssender.FileTask\");\n\n\t/**\n\t * <code>handler</code> is a reference to object processing stanza\n\t * read from database.\n\t */\n\tprivate StanzaHandler handler = null;\n\t/**\n\t * <code>db_conn</code> field stores database connection string.\n\t */\n\tprivate String init_str = null;\n\t/**\n\t * Variable <code>file_mask</code> keeps wildchar mask of the files which\n\t * are suposed to store XMPP stanzas to send in given directory.\n\t */\n\tprivate String file_mask = null;\n\t/**\n\t * Variable <code>directory</code> keeps directory path where files\n\t * with XMPP stanzas are stored for sending.\n\t */\n\tprivate String directory = null;\n\n\t/**\n\t * <code>init</code> method is a task specific initialization rountine.\n\t *\n\t * @param handler a <code>StanzaHandler</code> value is a reference to object\n\t * which handles all stanza retrieved from data source. The handler is\n\t * responsible for delivering stanza to destination address.\n\t * @param initString a <code>String</code> value is an initialization string\n\t * for this task. For example database tasks would expect database connection\n\t * string here, filesystem task would expect directory here.\n\t * @exception IOException if an error occurs during task or data storage\n\t * initialization.\n\t */\n\tpublic void init(StanzaHandler handler, String initString) throws IOException {\n\t\tthis.handler = handler;\n\t\tinit_str = initString;\n\t\tif (init_str.endsWith(File.separator)) {\n\t\t\tfile_mask = \"\";\n\t\t\tdirectory = init_str;\n\t\t} else {\n\t\t\tint idx = init_str.lastIndexOf(File.separator);\n\t\t\tdirectory = init_str.substring(0, idx);\n\t\t\tfile_mask = init_str.substring(idx+1, init_str.length());\n\t\t}\n\t\tlog.config(\"file_mask='\" + file_mask + \"', directory='\" + directory + \"'\");\n\t}\n\n\t/**\n\t * <code>getInitString</code> method returns initialization string passed\n\t * to it in <code>init()</code> method.\n\t *\n\t * @return a <code>String</code> value of initialization string.\n\t */\n\tpublic String getInitString() {\n\t\treturn init_str;\n\t}\n\n\tprivate String readFile(File ffile) throws IOException {\n\t\tStringBuilder result = new StringBuilder();\n\t\tchar[] buff = new char[16*1024];\n\t\tFileReader fr = new FileReader(ffile);\n\t\tint res = fr.read(buff);\n\t\twhile (res > 0) {\n\t\t\tresult.append(buff, 0, res);\n\t\t\tres = fr.read(buff);\n\t\t}\n\t\tfr.close();\n\t\treturn result.toString();\n\t}\n\n\t/**\n\t * <code>run</code> method is where all task work is done.\n\t */\n\tpublic void run() {\n\t\ttry {\n\t\t\tFile fdir = new File(directory);\n\t\t\tString[] files = fdir.list(new MaskFilter(file_mask));\n\t\t\tif (files != null) {\n\t\t\t\tfor (String file: files) {\n    \t\t\t\tif (log.isLoggable(Level.FINEST)) {\n        \t\t\t\tlog.finest(\"Processing file: \" + file);\n                    }\n\t\t\t\t\tFile ffile = new File(fdir, file);\n\t\t\t\t\tString stanza = readFile(ffile);\n\t\t\t\t\thandler.handleStanza(stanza);\n\t\t\t\t\tffile.delete();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t//this.cancel();\n\t\t}\n\t}\n\n\tprivate static class MaskFilter implements FilenameFilter {\n\n\t\tprivate String mask = null;\n\n\t\tprivate MaskFilter(String mask) {\n\t\t\tif (mask.startsWith(\"*\")) {\n\t\t\t\tthis.mask = mask.substring(1);\n\t\t\t} else {\n\t\t\t\tthis.mask = mask;\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean accept(final File file, final String name) {\n\t\t\treturn name.endsWith(mask);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/JDBCTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ssender;\n\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * <code>JDBCTask</code> implements tasks for cyclic retrieving stanzas from\n * database and sending them to the StanzaHandler object.\n * <br>\n * Database table format:\n * <ul>\n * <li><b>id</b> - numerical unique record indetifier.</li>\n * <li><b>stanza</b> - text field containing valid XML data with XMPP stanza to\n * send.</li>\n * </ul>\n * Any record in this table is treated the same way - Tigase assmes it contains\n * valid XML data with XMPP stanza to send. No other data are allowed in this\n * table. All stanzas must be complete including correct <em>\"from\"</em>\n * and <em>\"to\"</em> attriutes.\n * <br>\n * By default it looks for stanzas in <code>xmpp_stanza</code> table but you can\n * specify different table name in connection string. Sample connection string:\n * <pre>jdbc:mysql://localhost/tigasedb?user=tigase&amp;password=pass&amp;table=xmpp_stanza</pre>\n * <br>\n * Created: Fri Apr 20 12:10:55 2007\n * <br>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JDBCTask extends SenderTask {\n\n\t/**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n    Logger.getLogger(\"tigase.server.ssender.JDBCTask\");\n\n\t/**\n\t * <code>handler</code> is a reference to object processing stanza\n\t * read from database.\n\t */\n\tprivate StanzaHandler handler = null;\n\t/**\n\t * <code>db_conn</code> field stores database connection string.\n\t */\n\tprivate String db_conn = null;\n\t/**\n\t * <code>conn</code> variable keeps connection to database.\n\t */\n\tprivate Connection conn = null;\n\t/**\n\t * <code>get_all_stanzas</code> is a prepared statement for retrieving all\n\t * stanzas from database:\n\t * <pre>select id, stanza from <tableName></pre>\n\t */\n\tprivate PreparedStatement get_all_stanzas = null;\n\t/**\n\t * <code>remove_stanza</code> is a prepared statement for query removing\n\t * processed stanzas from database:\n\t * <pre>delete from <tableName> where id = ?</pre>\n\t */\n\tprivate PreparedStatement remove_stanza = null;\n\t/**\n\t * <code>conn_valid_st</code> is a prepared statement keeping query used\n\t * to validate connection to database:\n\t * <pre>select 1</pre>\n\t */\n\tprivate PreparedStatement conn_valid_st = null;\n\n\t/**\n\t * <code>tableName</code> keeps a table name where are stanza packets waiting\n\t * for sending. Default is <code>xmpp_stanza</code>\n\t */\n\tprivate String tableName = \"xmpp_stanza\";\n\n\t/**\n\t * <code>lastConnectionValidated</code> variable keeps time where the\n\t * connection was validated for the last time.\n\t */\n\tprivate long lastConnectionValidated = 0;\n\t/**\n\t * <code>connectionValidateInterval</code> is kind of constant keeping minimum\n\t * interval for validating connection to database.\n\t */\n\tprivate long connectionValidateInterval = 1000*60;\n\n\t/**\n\t * <code>release</code> method releases some SQL query variables.\n\t *\n\t * @param rs a <code>ResultSet</code> value\n\t */\n\tprivate void release(ResultSet rs) {\n\t\tif (rs != null) {\n\t\t\ttry {\n\t\t\t\trs.close();\n\t\t\t} catch (SQLException sqlEx) { }\n\t\t}\n\t}\n\n\t/**\n\t * <code>checkConnection</code> method checks whether connection to database\n\t * is still valid, if not it simply reconnect and reinitializes database\n\t * backend.\n\t *\n\t * @return a <code>boolean</code> value\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate boolean checkConnection() throws SQLException {\n\t\ttry {\n\t\t\tlong tmp = System.currentTimeMillis();\n\t\t\tif ((tmp - lastConnectionValidated) >= connectionValidateInterval) {\n\t\t\t\tconn_valid_st.executeQuery();\n\t\t\t\tlastConnectionValidated = tmp;\n\t\t\t} // end of if ()\n\t\t} catch (Exception e) {\n\t\t\tinitRepo();\n\t\t} // end of try-catch\n\t\treturn true;\n\t}\n\n\t/**\n\t * <code>findTableName</code> method parses database connection string to find\n\t * table name where stanza packets are waiting for sending.\n\t *\n\t * @param db_str a <code>String</code> value\n\t */\n\tprivate void findTableName(String db_str) {\n\t\tString[] params = db_str.split(\"&\");\n\t\tfor (String par: params) {\n\t\t\tif (par.startsWith(\"table=\")) {\n\t\t\t\ttableName = par.substring(\"table=\".length(), par.length());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * <code>initRepo</code> method initializes database backend - connects to\n\t * database, creates prepared statements and sets basic variables.\n\t *\n\t * @exception SQLException if an error occurs\n\t */\n\tprivate void initRepo() throws SQLException {\n\t\tconn = DriverManager.getConnection(db_conn);\n\t\tconn.setAutoCommit(true);\n\n\t\tString query = \"select 1;\";\n\t\tconn_valid_st = conn.prepareStatement(query);\n\n\t\tquery = \"select id, stanza from \" + tableName;\n\t\tget_all_stanzas = conn.prepareStatement(query);\n\n\t\tquery = \"delete from \" + tableName + \" where id = ?\";\n\t\tremove_stanza = conn.prepareStatement(query);\n\t}\n\n\t/**\n\t * <code>init</code> method is a task specific initialization rountine.\n\t *\n\t * @param handler a <code>StanzaHandler</code> value is a reference to object\n\t * which handles all stanza retrieved from data source. The handler is\n\t * responsible for delivering stanza to destination address.\n\t * @param initString a <code>String</code> value is an initialization string\n\t * for this task. For example database tasks would expect database connection\n\t * string here, filesystem task would expect directory here.\n\t * @exception IOException if an error occurs during task or data storage\n\t * initialization.\n\t */\n\tpublic void init(StanzaHandler handler, String initString) throws IOException {\n\t\tthis.handler = handler;\n\t\tdb_conn = initString;\n\t\tfindTableName(db_conn);\n\n\t\ttry {\n\t\t\tinitRepo();\n\t\t} catch (SQLException e) {\n\t\t\tthrow new IOException(\"Problem initializing SenderTask.\", e);\n\t\t}\n\t}\n\n\t/**\n\t * <code>getInitString</code> method returns initialization string passed\n\t * to it in <code>init()</code> method.\n\t *\n\t * @return a <code>String</code> value of initialization string.\n\t */\n\tpublic String getInitString() {\n\t\treturn db_conn;\n\t}\n\n\tpublic boolean cancel() {\n\t\tboolean result = super.cancel();\n\t\ttry {\n\t\t\tconn_valid_st.close();\n\t\t\tget_all_stanzas.close();\n\t\t\tremove_stanza.close();\n\t\t\tconn.close();\n\t\t} catch (Exception e) {\n\t\t\t// Ignore.\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * <code>run</code> method is where all task work is done.\n\t */\n\tpublic void run() {\n\t\tResultSet rs = null;\n\t\ttry {\n\t\t\tcheckConnection();\n\t\t\trs = get_all_stanzas.executeQuery();\n\t\t\t// Place to store all data ids to remove them later\n\t\t\tSet<Long> ids_to_delete = new HashSet<Long>();\n\t\t\twhile (rs.next()) {\n\t\t\t\t// Collect all data ids to remove them later\n\t\t\t\t// it can be done simultanously as most JDBC drivers\n\t\t\t\t// don't support concurrent query execution\n\t\t\t\t// I would need to establish another connection to database\n\t\t\t\tids_to_delete.add(rs.getLong(\"id\"));\n\t\t\t\t// Handle stanza to the StanzaSender....\n\t\t\t\tString stanza = rs.getString(\"stanza\");\n\t\t\t\thandler.handleStanza(stanza);\n   \t\t\t\tif (log.isLoggable(Level.FINEST)) {\n    \t\t\t\tlog.finest(\"Sent stanza found in database: \" + stanza);\n                }\n\t\t\t}\n\t\t\t// Remove all processed stanzas\n\t\t\tfor (long id: ids_to_delete) {\n\t\t\t\tremove_stanza.setLong(1, id);\n\t\t\t\tremove_stanza.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\t// Let's ignore it for now.\n\t\t\tlog.log(Level.WARNING, \"Error retrieving stanzas from database: \", e);\n\t\t\t// It should probably do kind of auto-stop???\n\t\t\t// if so just uncomment below line:\n\t\t\t//this.cancel();\n\t\t} finally {\n\t\t\trelease(rs);\n\t\t\trs = null;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/SenderTask.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ssender;\n\nimport java.io.IOException;\nimport java.util.TimerTask;\nimport tigase.xmpp.JID;\n\n/**\n * Describe class SenderTask here.\n *\n *\n * Created: Fri Apr 20 12:05:38 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class SenderTask extends TimerTask {\n\n\tprivate JID name = null;\n\n\tpublic void setName(JID name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic JID getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * <code>init</code> method is a task specific initialization rountine.\n\t *\n\t * @param handler a <code>StanzaHandler</code> value is a reference to object\n\t * which handles all stanza retrieved from data source. The handler is\n\t * responsible for delivering stanza to destination address.\n\t * @param initString a <code>String</code> value is an initialization string\n\t * for this task. For example database tasks would expect database connection\n\t * string here, filesystem task would expect directory here.\n\t * @exception IOException if an error occurs during task or data storage\n\t * initialization.\n\t */\n\tpublic abstract void init(StanzaHandler handler, String initString)\n\t\tthrows IOException;\n\n\t/**\n\t * <code>getInitString</code> method returns initialization string passed\n\t * to it in <code>init()</code> method.\n\t *\n\t * @return a <code>String</code> value of initialization string.\n\t */\n\tpublic abstract String getInitString();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/StanzaHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ssender;\n\nimport java.util.Queue;\nimport tigase.server.Packet;\n\n/**\n * Describe interface StanzaHandler here.\n *\n *\n * Created: Fri Apr 20 11:54:10 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface StanzaHandler {\n\n\tvoid handleStanza(String stanza);\n\n\tvoid handleStanza(Packet stanza);\n\n\tvoid handleStanzas(Queue<Packet> results);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/ssender/StanzaSender.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.ssender;\n\nimport tigase.db.RepositoryFactory;\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.JID;\n\nimport tigase.conf.Configurable;\nimport tigase.conf.ConfigurationException;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Timer;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * <code>StanzaSender</code> class implements simple cyclic tasks management\n * mechanism. You can specify as many tasks in configuration as you need.\n * <p>\n * These tasks are designed to pull XMPP stanzas from specific data source like\n * SQL database, directory in the filesystem and so on. Each of these tasks must\n * extend <code>tigase.server.ssende.SenderTask</code> abstract class. Look in\n * specific tasks implementation for more detailed description how to use them.\n * <p>\n * Created: Fri Apr 20 11:11:25 2007\n * </p>\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StanzaSender extends AbstractMessageReceiver implements Configurable,\n\t\tStanzaHandler {\n\n\tprivate static final String INTERVAL_PROP_KEY = \"default-interval\";\n\tprivate static final long INTERVAL_PROP_VAL = 10;\n\tprivate static final String STANZA_LISTENERS_PROP_KEY = \"stanza-listeners\";\n\tprivate static final String TASK_CLASS_PROP_KEY = \"class-name\";\n\tprivate static final String TASK_INIT_PROP_KEY = \"init-string\";\n\tprivate static final String TASK_INTERVAL_PROP_KEY = \"interval\";\n\tprivate static final String JDBC_TASK_NAME = \"jdbc\";\n\tprivate static final String JDBC_TASK_CLASS = \"tigase.server.ssender.JDBCTask\";\n\tprivate static final String JDBC_TASK_INIT =\n\t\t\t\"jdbc:mysql://localhost/tigase?user=root&password=mypass&table=xmpp_stanza\";\n\tprivate static final long JDBC_INTERVAL = 10;\n\n\tprivate static final String DRUPAL_FORUM_TASK_NAME = \"drupal-forum\";\n\tprivate static final String DRUPAL_FORUM_TASK_CLASS =\n\t\t\t\"tigase.server.ssender.DrupalForumTask\";\n\tprivate static final String DRUPAL_FORUM_TASK_INIT =\n\t\t\t\"drupal_forum:mysql://localhost/tigase?user=root&password=mypass\";\n\tprivate static final long DRUPAL_FORUM_INTERVAL = 30;\n\n\tprivate static final String DRUPAL_COMMENTS_TASK_NAME = \"drupal-comments\";\n\tprivate static final String DRUPAL_COMMENTS_TASK_CLASS =\n\t\t\t\"tigase.server.ssender.DrupalCommentsTask\";\n\tprivate static final String DRUPAL_COMMENTS_TASK_INIT =\n\t\t\t\"drupal_comments:mysql://localhost/tigase?user=root&password=mypass\";\n\tprivate static final long DRUPAL_COMMENTS_INTERVAL = 10;\n\n\tprivate static final String FILE_TASK_NAME = \"file\";\n\tprivate static final String FILE_TASK_CLASS = \"tigase.server.ssender.FileTask\";\n\tprivate static final String FILE_TASK_INIT = File.separator + \"var\" + File.separator\n\t\t\t+ \"spool\" + File.separator + \"jabber\" + File.separator + \"*.stanza\";\n\tprivate static final long FILE_INTERVAL = 10;\n\tprivate static final String[] STANZA_LISTENERS_PROP_VAL = { JDBC_TASK_NAME,\n\t\t\tFILE_TASK_NAME, DRUPAL_COMMENTS_TASK_NAME };\n\tprivate static final String TASK_ACTIVE_PROP_KEY = \"active\";\n\tprivate static final boolean TASK_ACTIVE_PROP_VAL = false;\n\tpublic static final String MY_DOMAIN_NAME_PROP_KEY = \"domain-name\";\n\tpublic static String MY_DOMAIN_NAME_PROP_VAL = \"srecv.localhost\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(StanzaSender.class.getName());\n\n\tprivate static final SimpleParser parser = SingletonFactory.getParserInstance();\n\t// private long interval = INTERVAL_PROP_VAL;\n\tprivate Map<String, SenderTask> tasks_list = new LinkedHashMap<String, SenderTask>();\n\tprivate Timer tasks = new Timer(\"StanzaSender\", true);\n\n\t// Implementation of tigase.server.ServerComponent\n\n\t@Override\n\tpublic void release() {\n\t\tsuper.release();\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet) {\n\t\t// do nothing, this component is to send packets not to receive\n\t\t// (for now)\n\t}\n\n\t// Implementation of tigase.conf.Configurable\n\n\t@Override\n\tpublic void setProperties(final Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\n\t\tif (props.size() == 1) {\n\t\t\treturn;\n\t\t}\n\n\t\t// interval = (Long)props.get(INTERVAL_PROP_KEY);\n\t\tString[] config_tasks = (String[]) props.get(STANZA_LISTENERS_PROP_KEY);\n\t\tfor (String task_name : config_tasks) {\n\n\t\t\t// Reconfiguration code. Turn-off old task with that name.\n\t\t\tSenderTask old_task = tasks_list.get(task_name);\n\t\t\tif (old_task != null) {\n\t\t\t\told_task.cancel();\n\t\t\t}\n\n\t\t\tif ((Boolean) props.get(task_name + \"/\" + TASK_ACTIVE_PROP_KEY)) {\n\t\t\t\tString task_class = (String) props.get(task_name + \"/\" + TASK_CLASS_PROP_KEY);\n\t\t\t\tString task_init = (String) props.get(task_name + \"/\" + TASK_INIT_PROP_KEY);\n\t\t\t\tlong task_interval = (Long) props.get(task_name + \"/\" + TASK_INTERVAL_PROP_KEY);\n\t\t\t\ttry {\n\t\t\t\t\tSenderTask task = (SenderTask) Class.forName(task_class).newInstance();\n\t\t\t\t\tJID taskName = getComponentId().copyWithResource(task_name);\n\t\t\t\t\ttask.setName(taskName);\n\t\t\t\t\ttask.init(this, task_init);\n\n\t\t\t\t\t// Install new task\n\t\t\t\t\ttasks_list.put(task_name, task);\n\t\t\t\t\ttasks.scheduleAtFixedRate(task, task_interval * SECOND, task_interval * SECOND);\n\n\t\t\t\t\tlog.config(\"Initialized task: \" + task_name + \", class: \" + task_class\n\t\t\t\t\t\t\t+ \", init: \" + task_init + \", interval: \" + task_interval);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Can not initialize stanza listener: \", e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(final Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\t\tdefs.put(INTERVAL_PROP_KEY, INTERVAL_PROP_VAL);\n\n\t\tif ((Boolean) params.get(GEN_TEST)) {\n\t\t\tdefs.put(FILE_TASK_NAME + \"/\" + TASK_ACTIVE_PROP_KEY, true);\n\t\t} else {\n\t\t\tdefs.put(FILE_TASK_NAME + \"/\" + TASK_ACTIVE_PROP_KEY, TASK_ACTIVE_PROP_VAL);\n\t\t}\n\t\tdefs.put(FILE_TASK_NAME + \"/\" + TASK_CLASS_PROP_KEY, FILE_TASK_CLASS);\n\t\tdefs.put(FILE_TASK_NAME + \"/\" + TASK_INIT_PROP_KEY, FILE_TASK_INIT);\n\t\tdefs.put(FILE_TASK_NAME + \"/\" + TASK_INTERVAL_PROP_KEY, FILE_INTERVAL);\n\n\t\tif ((Boolean) params.get(GEN_TEST)) {\n\t\t\tdefs.put(JDBC_TASK_NAME + \"/\" + TASK_ACTIVE_PROP_KEY, true);\n\t\t} else {\n\t\t\tdefs.put(JDBC_TASK_NAME + \"/\" + TASK_ACTIVE_PROP_KEY, TASK_ACTIVE_PROP_VAL);\n\t\t}\n\t\tdefs.put(JDBC_TASK_NAME + \"/\" + TASK_CLASS_PROP_KEY, JDBC_TASK_CLASS);\n\t\tdefs.put(JDBC_TASK_NAME + \"/\" + TASK_INIT_PROP_KEY, JDBC_TASK_INIT);\n\t\tdefs.put(JDBC_TASK_NAME + \"/\" + TASK_INTERVAL_PROP_KEY, JDBC_INTERVAL);\n\n\t\tString repo_uri = DRUPAL_COMMENTS_TASK_INIT;\n\t\tif (params.get(GEN_CONF + \"drupal-db-uri\") != null) {\n\t\t\trepo_uri = (String) params.get(GEN_CONF + \"drupal-db-uri\");\n\t\t} else {\n\t\t\tif (params.get(RepositoryFactory.GEN_USER_DB_URI) != null) {\n\t\t\t\trepo_uri = (String) params.get(RepositoryFactory.GEN_USER_DB_URI);\n\t\t\t} // end of if (params.get(GEN_USER_DB_URI) != null)\n\t\t}\n\n\t\tList<String> listeners = new ArrayList<String>();\n\t\tlisteners.addAll(Arrays.asList(STANZA_LISTENERS_PROP_VAL));\n\n\t\tString task_name = DRUPAL_COMMENTS_TASK_NAME;\n\t\tlisteners.add(task_name);\n\t\tdefs.put(task_name + \"/\" + TASK_ACTIVE_PROP_KEY, false);\n\t\tdefs.put(task_name + \"/\" + TASK_CLASS_PROP_KEY, DRUPAL_COMMENTS_TASK_CLASS);\n\t\tdefs.put(task_name + \"/\" + TASK_INTERVAL_PROP_KEY, DRUPAL_COMMENTS_INTERVAL);\n\t\tdefs.put(task_name + \"/\" + TASK_INIT_PROP_KEY, repo_uri\n\t\t\t\t+ \"&jid=drupal-comments@srecv.\" + getDefHostName());\n\n\t\tdefs.put(STANZA_LISTENERS_PROP_KEY, listeners.toArray(new String[0]));\n\t\tif (params.get(GEN_VIRT_HOSTS) != null) {\n\t\t\tMY_DOMAIN_NAME_PROP_VAL =\n\t\t\t\t\t\"ssend.\" + ((String) params.get(GEN_VIRT_HOSTS)).split(\",\")[0];\n\t\t} else {\n\t\t\tMY_DOMAIN_NAME_PROP_VAL = \"ssend.\" + DNSResolverFactory.getInstance().getDefaultHosts()[0];\n\t\t}\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic void handleStanza(String stanza) {\n\t\tparseXMLData(stanza);\n\t}\n\n\t@Override\n\tpublic void handleStanza(Packet stanza) {\n\t\taddOutPacket(stanza);\n\t}\n\n\t@Override\n\tpublic void handleStanzas(Queue<Packet> results) {\n\t\taddOutPackets(results);\n\t}\n\n\tprivate void parseXMLData(String data) {\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\tparser.parse(domHandler, data.toCharArray(), 0, data.length());\n\t\tQueue<Element> elems = domHandler.getParsedElements();\n\t\twhile (elems != null && elems.size() > 0) {\n\t\t\tElement elem = elems.poll();\n\t\t\ttry {\n\t\t\t\tPacket result = Packet.packetInstance(elem);\n\t\t\t\taddOutPacket(result);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tlog.info(\"Packet stringprep addressing problem, dropping packet: \" + elem);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/test/EchoComponent.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.test;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Sep 30, 2010 1:07:13 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class EchoComponent extends AbstractMessageReceiver {\n\tprivate static final Logger log = Logger.getLogger(EchoComponent.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tlog.log(Level.FINEST, \"Received: {0}\", packet);\n\n\t\tPacket result = packet.swapStanzaFromTo();\n\n\t\taddOutPacket(result);\n\t\tlog.log(Level.FINEST, \"Sent back: {0}\", result);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/test/TestComponent.java",
    "content": "/*\n * TestComponent.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.test;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collections;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.script.Bindings;\nimport tigase.conf.ConfigurationException;\n\n/**\n * A test component used to demonstrate API and for running different kinds of\n * tests on the Tigase server - generate local traffic for performance and load tests.\n * Created: Nov 28, 2009 9:22:36 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TestComponent\n\t\t\t\textends AbstractMessageReceiver {\n\tprivate static final String ABUSE_ADDRESS_KEY     = \"abuse-address\";\n\tprivate static final String BAD_WORDS_KEY         = \"bad-words\";\n\tprivate static final String BAD_WORDS_VAR         = \"badWords\";\n\tprivate static final String[] INITIAL_BAD_WORDS   = { \"word1\", \"word2\", \"word3\" };\n\tprivate static final String[] INITIAL_WHITE_LIST  = { \"admin@localhost\" };\n\tprivate static final String NOTIFICATION_FREQ_KEY = \"notification-freq\";\n\tprivate static final String PREPEND_TEXT_KEY      = \"log-prepend\";\n\tprivate static final String SECURE_LOGGING_KEY    = \"secure-logging\";\n\tprivate static final String WHITE_LIST_VAR        = \"whiteList\";\n\tprivate static final String WHITELIST_KEY         = \"white-list\";\n\tprivate static final Logger log                   =\n\t\tLogger.getLogger(TestComponent.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JID abuseAddress = null;\n\n\t/**\n\t * This might be changed in one threads while it is iterated in\n\t * processPacket(...) in another thread. We expect that changes are very rare\n\t * and small, most of operations are just iterations.\n\t */\n\tprivate Set<String> badWords      = new CopyOnWriteArraySet<String>();\n\tprivate int delayCounter          = 0;\n\tprivate long messagesCounter      = 0;\n\tprivate int notificationFrequency = 10;\n\tprivate String prependText        = \"Spam detected: \";\n\tprivate long spamCounter          = 0;\n\tprivate long totalSpamCounter     = 0;\n\n\t/**\n\t * This might be changed in one threads while it is iterated in\n\t * processPacket(...) in another thread. We expect that changes are very rare\n\t * and small, most of operations are just contains(...).\n\t */\n\tprivate Set<String> whiteList = new ConcurrentSkipListSet<String>();\n\tprivate boolean secureLogging = false;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic synchronized void everyMinute() {\n\t\tsuper.everyMinute();\n\t\tif ((++delayCounter) >= notificationFrequency) {\n\t\t\taddOutPacket(Message.getMessage(getComponentId(), abuseAddress, StanzaType.chat,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Detected spam messages: \" + spamCounter,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Spam counter\", null, newPacketId(\"spam-\")));\n\t\t\tdelayCounter = 0;\n\t\t\tspamCounter  = 0;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs = super.getDefaults(params);\n\n\t\tCollections.addAll(badWords, INITIAL_BAD_WORDS);\n\t\tCollections.addAll(whiteList, INITIAL_WHITE_LIST);\n\t\tdefs.put(BAD_WORDS_KEY, INITIAL_BAD_WORDS);\n\t\tdefs.put(WHITELIST_KEY, INITIAL_WHITE_LIST);\n\t\tdefs.put(PREPEND_TEXT_KEY, prependText);\n\t\tdefs.put(SECURE_LOGGING_KEY, secureLogging);\n\t\tdefs.put(ABUSE_ADDRESS_KEY, \"admin@localhost\");\n\t\tdefs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"spam\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Spam filtering\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getName(), \"Spam messages found\", totalSpamCounter, Level.INFO);\n\t\tlist.add(getName(), \"All messages processed\", messagesCounter, Level.FINE);\n\t\tif (list.checkLevel(Level.FINEST)) {\n\n\t\t\t// Some very expensive statistics generation code...\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().hashCode();\n\t\t}\n\n\t\t// This should not happen, every packet must have a destination\n\t\t// address, but maybe our SPAM checker is used for checking\n\t\t// strange kind of packets too....\n\t\tif (packet.getStanzaFrom() != null) {\n\t\t\treturn packet.getStanzaFrom().hashCode();\n\t\t}\n\n\t\t// If this really happens on your system you should look carefully\n\t\t// at packets arriving to your component and decide a better way\n\t\t// to calculate hashCode\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(BAD_WORDS_VAR, badWords);\n\t\tbinds.put(WHITE_LIST_VAR, whiteList);\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\n\t\t// Is this packet a message?\n\t\tif (\"message\" == packet.getElemName()) {\n\t\t\tupdateServiceDiscoveryItem(getName(), \"messages\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Messages processed: [\" + (++messagesCounter) + \"]\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t true);\n\n\t\t\tJID from = packet.getStanzaFrom();\n\n\t\t\t// Is sender on the whitelist?\n\t\t\tif (!whiteList.contains(from.getBareJID().toString())) {\n\n\t\t\t\t// The sender is not on whitelist so let's check the content\n\t\t\t\tString body = packet.getElemCDataStaticStr(Message.MESSAGE_BODY_PATH);\n\n\t\t\t\tif ((body != null) &&!body.isEmpty()) {\n\t\t\t\t\tbody = body.toLowerCase();\n\t\t\t\t\tfor (String word : badWords) {\n\t\t\t\t\t\tif (body.contains(word)) {\n\t\t\t\t\t\t\tlog.finest(prependText + packet.toString(secureLogging));\n\t\t\t\t\t\t\t++spamCounter;\n\t\t\t\t\t\t\tupdateServiceDiscoveryItem(getName(), \"spam\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Spam caught: [\" + (++totalSpamCounter) + \"]\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t true);\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Not a SPAM, return it for further processing\n\t\tPacket result = packet.swapStanzaFromTo();\n\n\t\taddOutPacket(result);\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tCollections.addAll(badWords, (String[]) props.get(BAD_WORDS_KEY));\n\t\tCollections.addAll(whiteList, (String[]) props.get(WHITELIST_KEY));\n\t\tprependText   = (String) props.get(PREPEND_TEXT_KEY);\n\t\tsecureLogging = (Boolean) props.get(SECURE_LOGGING_KEY);\n\t\ttry {\n\t\t\tabuseAddress = JID.jidInstance((String) props.get(ABUSE_ADDRESS_KEY));\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.warning(\"Incorrect abuseAddress, stringprep error: \" +\n\t\t\t\t\t\t\t\t\t(String) props.get(ABUSE_ADDRESS_KEY));\n\t\t}\n\t\tnotificationFrequency = (Integer) props.get(NOTIFICATION_FREQ_KEY);\n\t\tupdateServiceDiscoveryItem(getName(), null, getDiscoDescription(), \"automation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"spam-filtering\", true, \"tigase:x:spam-filter\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"tigase:x:spam-reporting\");\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/19\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/websocket/WebSocketClientConnectionManager.java",
    "content": "/*\n * WebSocketClientConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.websocket;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport tigase.conf.ConfigurationException;\nimport tigase.net.SocketType;\nimport tigase.server.xmppclient.XMPPIOProcessor;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n * Class implements basic support allowing clients to connect using WebSocket\n * protocol\n *\n * @author andrzej\n */\npublic class WebSocketClientConnectionManager\n\t\t\t\textends tigase.server.xmppclient.ClientConnectionManager {\n\t\n\tprivate static final String XMLNS_FRAMING = \"urn:ietf:params:xml:ns:xmpp-framing\";\n\tprivate static final String PROTOCOL_VERSIONS_KEY = \"protocol-versions\";\n\tprivate static final String[] PROTOCOL_VERSIONS_DEF = { WebSocketHybi.ID };\n\t\n\tprivate static final WebSocketProtocolIfc[] SUPPORTED_PROTOCOL_VERSIONS = { new WebSocketHybi(), new WebSocketHixie76() };\n\t\n\tprivate WebSocketProtocolIfc[] enabledProtocolVersions = null;\n\t\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String,Object> defs = super.getDefaults(params);\n\t\tdefs.put(PROTOCOL_VERSIONS_KEY, PROTOCOL_VERSIONS_DEF);\n\t\treturn defs;\n\t}\n\t\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Websocket connection manager\";\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tif (props.containsKey(PROTOCOL_VERSIONS_KEY)) {\n\t\t\tString[] versions = (String[]) props.get(PROTOCOL_VERSIONS_KEY);\n\t\t\tList<WebSocketProtocolIfc> value = new ArrayList<WebSocketProtocolIfc>();\n\t\t\tfor (String version : versions) {\n\t\t\t\tfor (WebSocketProtocolIfc v : SUPPORTED_PROTOCOL_VERSIONS) {\n\t\t\t\t\tif (version.equals(v.getId())) {\n\t\t\t\t\t\tvalue.add(v);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tenabledProtocolVersions = value.toArray(new WebSocketProtocolIfc[value.size()]);\n\t\t}\n\t\tsuper.setProperties(props);\n\t}\n\t\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn new int[] { 5290 };\n\t}\n\n\t@Override\n\tprotected int[] getDefSSLPorts() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected XMPPIOService<Object> getXMPPIOServiceInstance() {\n\t\treturn new WebSocketXMPPIOService<Object>(enabledProtocolVersions);\n\t}\n\t\n\t@Override\n\tprotected String prepareStreamClose(XMPPIOService<Object> serv) {\n\t\tif (isPreRFC(serv)) {\n\t\t\treturn super.prepareStreamClose(serv);\n\t\t}\n\t\treturn \"<close xmlns='urn:ietf:params:xml:ns:xmpp-framing' />\";\n\t}\n\t\n\t@Override\n\tprotected String prepareStreamOpen(XMPPIOService<Object> serv, String id, String hostname) {\n\t\tif (isPreRFC(serv)) {\n\t\t\treturn super.prepareStreamOpen(serv, id, hostname);\n\t\t}\t\t\n\t\treturn \"<open\" + \" xmlns='\" + XMLNS_FRAMING + \"'\" + \" from='\" + hostname + \"'\" \n\t\t\t\t+ \" id='\" + id + \"'\" + \" version='1.0' xml:lang='en' />\";\n\t}\n\t\n\t@Override\n\tprotected String prepareStreamError(XMPPIOService<Object> serv, List<Element> err_el) {\n\t\tif (isPreRFC(serv)) {\n\t\t\treturn super.prepareStreamError(serv, err_el);\n\t\t}\t\t\t\n\t\tStreamError streamError\t= StreamError.getByCondition(err_el.get(0).getName());\t\n\t\t\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, streamError);\n\t\t}\t\t\n\t\t\n\t\treturn \"<stream:error xmlns:stream=\\\"http://etherx.jabber.org/streams\\\">\" + err_el.get(0).toString() + \"</stream:error>\";\n\t}\n\t\n\t@Override\n\tprotected String prepareStreamError(XMPPIOService<Object> serv, StreamError streamError, String hostname) {\n\t\tif (isPreRFC(serv)) {\n\t\t\treturn super.prepareStreamError(serv, streamError, hostname);\n\t\t}\t\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, streamError);\n\t\t}\t\t\n\t\treturn \"<open\" + \" xmlns='\" + XMLNS_FRAMING + \"'\" + \" from='\" + hostname + \"'\" \n\t\t\t\t+ \" id='tigase-error-tigase'\" + \" version='1.0' xml:lang='en' />\" \n\t\t\t\t+ \"<stream:error xmlns:stream=\\\"http://etherx.jabber.org/streams\\\">\"\n\t\t\t\t+ \"<\" + streamError.getCondition() + \" xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\"\n\t\t\t\t+ \"</stream:error>\" + \"<close xmlns='\" + XMLNS_FRAMING + \"'/>\";\n\t}\n\t\n\t@Override\n\tprotected String prepareSeeOtherHost(XMPPIOService<Object> serv, String hostname, BareJID see_other_host) {\n\t\tif (isPreRFC(serv)) {\n\t\t\treturn super.prepareSeeOtherHost(serv, hostname, see_other_host);\n\t\t}\t\t\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, StreamError.SeeOtherHost);\n\t\t}\t\t\t\t\n\t\tboolean ssl = SocketType.ssl == ((SocketType) serv.getSessionData().get(\"socket\"));\n\t\tint localPort = serv.getLocalPort();\n\t\tString see_other_uri = (ssl ? \"wss://\" : \"ws://\") + see_other_host + \":\" + localPort + \"/\";\n\t\treturn \"<open\" + \" xmlns='\" + XMLNS_FRAMING + \"'\" + \" from='\" +  (hostname != null ? hostname : getDefVHostItem()) + \"'\"\n\t\t\t\t+ \" id='tigase-error-tigase'\" + \" version='1.0' xml:lang='en' />\"\n\t\t\t\t+ \"<close xmlns='urn:ietf:params:xml:ns:xmpp-framing' see-other-uri='\" + see_other_uri + \"' />\";\n\t}\t\n\t\n\t@Override\n\tprotected void preprocessStreamFeatures(XMPPIOService<Object> serv, Element elem_features) {\n\t\tif (!isPreRFC(serv)) {\n\t\t\telem_features.setAttribute(\"xmlns:stream\", \"http://etherx.jabber.org/streams\");\n\t\t}\n\t}\n\t\n\tprivate boolean isPreRFC(XMPPIOService<Object> serv) {\n\t\treturn serv == null || ((WebSocketXMPPIOService<Object>) serv).getWebSocketXMPPSpec() == WebSocketXMPPIOService.WebSocketXMPPSpec.hybi;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/10/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/websocket/WebSocketHixie76.java",
    "content": "/*\n * WebSocketHixie76.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport tigase.net.SocketType;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class implements Hixie-76 version of WebSocket protocol specification\n * which is used in connection handshaking as well as in frameing/deframing of\n * data sent over WebSocket connection\n * \n * @see <a href=\"https://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76\">WebSocket Hixie-76 specification</a>\n *\n * @author andrzej\n */\npublic class WebSocketHixie76 implements WebSocketProtocolIfc {\n\t\n\tprivate static final Logger log = Logger.getLogger(WebSocketHixie76.class.getCanonicalName());\n\n\tpublic static final String ID = \"hixie-76\";\n\t\n\tprivate static final String RESPONSE_HEADER =\n\t\t\"HTTP/1.1 101 Switching Protocols\\r\\n\" + \"Upgrade: WebSocket\\r\\n\" +\n\t\t\"Connection: Upgrade\\r\\n\" + \"Access-Control-Allow-Origin: *\\r\\n\" +\n\t\t\"Access-Control-Allow-Methods: GET, POST, OPTIONS\\r\\n\" +\n\t\t\"Access-Control-Allow-Headers: Content-Type\\r\\n\" +\n\t\t\"Access-Control-Max-Age: 86400\\r\\n\";\t\n\t\n\tprivate static final String HOST_KEY\t\t= \"Host\";\n\tprivate static final String ORIGIN_KEY\t\t= \"Origin\";\n\tprivate static final String WS_KEY1_KEY\t\t= \"Sec-WebSocket-Key1\";\n\tprivate static final String WS_KEY2_KEY\t\t= \"Sec-WebSocket-Key2\";\n\tprivate static final String WS_ORIGIN_KEY\t= \"Sec-WebSocket-Origin\";\n\tprivate static final String WS_LOCATION_KEY\t= \"Sec-WebSocket-Location\";\t\n\t\n\tprivate static final byte[] FRAME_HEADER = new byte[] { (byte) 0x00 };\n\tprivate static final byte[] FRAME_FOOTER = new byte[] { (byte) 0xFF };\n\t\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\t\n\t@Override\n\tpublic boolean handshake(WebSocketXMPPIOService service, Map<String, String> headers, byte[] buf) throws NoSuchAlgorithmException, IOException {\n\t\tif (headers.containsKey(WS_VERSION_KEY)) {\n\t\t\treturn false;\n\t\t}\t\n\n\t\tbyte[] secBufArr = new byte[16];\n\t\tLong secKey1 = decodeHyxie76SecKey(headers.get(WS_KEY1_KEY));\n\t\tLong secKey2 = decodeHyxie76SecKey(headers.get(WS_KEY2_KEY));\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"WS-KEY1 = {0}\", secKey1);\n\t\t\tlog.log(Level.FINEST, \"WS-KEY2 = {0}\", secKey2);\n\t\t}\n\t\tuintToBytes(secBufArr, 0, secKey1);\n\t\tuintToBytes(secBufArr, 4, secKey2);\n\t\tif (buf[buf.length - 9] != '\\n') {\n\t\t\tthrow new IOException(\"buf[len-9] != \\\\n!!\");\n\t\t}\n\t\tfor (int j = 8; j > 0; j--) {\n\t\t\tsecBufArr[8 + 8 - j] = buf[buf.length - j];\n\t\t}\n\n\t\tMessageDigest md = MessageDigest.getInstance(\"MD5\");\n\t\tbyte[] resp = md.digest(secBufArr);\n\n\t\tStringBuilder response = new StringBuilder(RESPONSE_HEADER.length() * 2);\n\t\tresponse.append(RESPONSE_HEADER);\n\n\t\tresponse.append(\"Content-Length: \").append(resp.length).append(\"\\r\\n\");\n\t\tresponse.append(WS_PROTOCOL_KEY).append(\": \");\n\t\tif (headers.get(WS_PROTOCOL_KEY).contains(\"xmpp-framing\")) {\n\t\t\tresponse.append(\"xmpp-framing\");\n\t\t} else {\n\t\t\tresponse.append(\"xmpp\");\n\t\t}\n\t\tresponse.append(\"\\r\\n\");\t\t\n\t\tif (headers.containsKey(ORIGIN_KEY)) {\n\t\t\tresponse.append(WS_ORIGIN_KEY).append(\": \").append(headers.get(ORIGIN_KEY)).append(\"\\r\\n\");\n\t\t}\n\n\t\tboolean ssl = SocketType.ssl == ((SocketType) service.getSessionData().get(\"socket\"));\n\t\tint localPort = service.getLocalPort();\n\t\tString location = (ssl ? \"wss://\" : \"ws://\")\n\t\t\t\t+ headers.get(HOST_KEY) + (((ssl && localPort == 443) || (!ssl && localPort == 80) || headers.get(HOST_KEY).contains(\":\")) ? \"\" : (\":\" + localPort)) + \"/\";\n\t\tresponse.append(WS_LOCATION_KEY).append(\": \").append(location).append(\"\\r\\n\");\n\n\t\tresponse.append(\"\\r\\n\");\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"sending response = \\n{0}\", response.toString());\n\t\t}\n\n\t\tbyte[] respBytes = response.toString().getBytes();\n\t\tByteBuffer out = ByteBuffer.allocate(respBytes.length + 16);\n\t\tout.put(respBytes);\n\t\tout.put(resp);\n\t\tout.flip();\n\t\tservice.writeBytes(out);\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic ByteBuffer decodeFrame(WebSocketXMPPIOService service, ByteBuffer buf) {\n\t\tif (!buf.hasRemaining()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"no content remainging to process\");\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tint position   = buf.position();\n\t\tbyte type = buf.get();\n\t\t\n\t\tlog.finest(\"read type = \" + type);\n\t\t\n\t\tif ((type & 0x80) != 0x80) {\n\t\t\tint idx = position + 1;\n\t\t\tint remaining = buf.remaining();\n\t\t\tlog.finest(\"remaining = \" + remaining + \" on position \" + position);\n\t\t\twhile ((remaining - ((idx-position))) >= 0) {\n\t\t\t\tlog.finest(\"checking byte at \" + idx + \" = \" + buf.get(idx));\n\t\t\t\tif (buf.get(idx) != ((byte) 0xFF)) {\n\t\t\t\t\tidx++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlog.finest(\"found data of \" + ((idx-position)-1) + \" bytes\");\n\t\t\t\tbyte[] data = new byte[(idx-position)-1];\n\t\t\t\tbuf.get(data);\n\t\t\t\tbuf.position(buf.position()+1);\n\t\t\t\tlog.finest(\"read data = \" + new String(data));\n\t\t\t\treturn ByteBuffer.wrap(data);\n\t\t\t}\n\t\t\tbuf.position(position);\n\t\t\treturn null;\n\t\t} else {\n\t\t\tlong len = 0;\n\t\t\tbyte b = 0;\n\t\t\twhile (((b=buf.get()) & 0x80 ) == 0x80) {\n\t\t\t\tlen = (len * 128) + (b & 0x7f);\n\t\t\t}\n\t\t\tlen = (len * 128) + (b & 0x7f);\n\t\t\t\n\t\t\tif (len == 0) {\n\t\t\t\t// close request\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"closing connection due to client request\");\n\t\t\t\t}\n\t\t\t\tservice.setState(WebSocketXMPPIOService.State.closed);\n\t\t\t\t//service.forceStop();\n\n\t\t\t\treturn null;\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif (buf.remaining() < len) {\n\t\t\t\tbuf.position(position);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t\n\t\t\tbyte[] data = new byte[(int) len];\n\t\t\tbuf.get(data);\n\t\t\treturn ByteBuffer.wrap(data);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void encodeFrameAndWrite(WebSocketXMPPIOService service, ByteBuffer buf) throws IOException {\n\t\tservice.writeBytes(ByteBuffer.wrap(FRAME_HEADER));\n\t\tservice.writeBytes(buf);\n\t\tservice.writeBytes(ByteBuffer.wrap(FRAME_FOOTER));\n\t}\n\n\t@Override\n\tpublic void closeConnection(WebSocketXMPPIOService service) {\n\t\tif (!service.isConnected())\n\t\t\treturn;\n\n\t\tservice.setState(WebSocketXMPPIOService.State.closed);\n\t\tservice.writeBytes(ByteBuffer.wrap(new byte[] { (byte) 0xFF, (byte) 0x00 }));\n\t}\n\t\n\tprivate void uintToBytes(byte[] arr, int offset, long val) {\n\t\tfor (int i=3; i>=0; i--) {\n\t\t\tarr[offset + i] = (byte) (val % 256);\n\t\t\tval = val / 256;\n\t\t}\n\t}\n\t\n\tprivate Long decodeHyxie76SecKey(String data) {\n\t\tlong result = 0;\n\t\tint spaces = 0;\n\t\t\n\t\tfor (char ch : data.trim().toCharArray()) {\n\t\t\tswitch (ch) {\n\t\t\t\tcase '0':\n\t\t\t\t\tresult = result * 10 + 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '1':\n\t\t\t\t\tresult = result * 10 + 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '2':\n\t\t\t\t\tresult = result * 10 + 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '3':\n\t\t\t\t\tresult = result * 10 + 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '4':\n\t\t\t\t\tresult = result * 10 + 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '5':\n\t\t\t\t\tresult = result * 10 + 5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '6':\n\t\t\t\t\tresult = result * 10 + 6;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '7':\n\t\t\t\t\tresult = result * 10 + 7;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '8':\n\t\t\t\t\tresult = result * 10 + 8;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '9':\n\t\t\t\t\tresult = result * 10 + 9;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ' ':\n\t\t\t\t\tspaces++;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn result / spaces;\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/websocket/WebSocketHybi.java",
    "content": "/*\n * WebSocketHybi.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport tigase.util.Base64;\n\nimport java.io.IOException;\nimport java.nio.BufferUnderflowException;\nimport java.nio.ByteBuffer;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.server.websocket.WebSocketXMPPIOService.State.closing;\n\n/**\n * Class implements Hybi (RFC compatible) version of WebSocket protocol specification\n * which is used in connection handshaking as well as in frameing/deframing of\n * data sent over WebSocket connection\n * \n * @see <a href=\"http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-13\">WebSocket HyBi specification</a>\n * \n * @author andrzej\n */\npublic class WebSocketHybi implements WebSocketProtocolIfc {\n\n\tprivate static final Logger log = Logger.getLogger(WebSocketHybi.class.getCanonicalName());\n\t\n\tpublic static final String ID = \"hybi\";\n\t\n\tprivate static final String GUID           = \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\";\t\n\tprivate static final String RESPONSE_HEADER =\n\t\t\"HTTP/1.1 101 Switching Protocols\\r\\n\" + \"Upgrade: websocket\\r\\n\" +\n\t\t\"Connection: Upgrade\\r\\n\" + \"Access-Control-Allow-Origin: *\\r\\n\" +\n\t\t// Removed header below as it creates issues with connectivity using IE11 \n//\t\t\"Access-Control-Allow-Methods: GET, POST, OPTIONS\\r\\n\" +\n\t\t\"Access-Control-Allow-Headers: Content-Type\\r\\n\" +\n\t\t\"Access-Control-Max-Age: 86400\\r\\n\";\n\n\tprivate static final String WS_ACCEPT_KEY   = \"Sec-WebSocket-Accept\";\n\tprivate static final String WS_KEY_KEY      = \"Sec-WebSocket-Key\";\n\n\tprivate static final String CLOSE_CODE = \"close-code\";\n\tprivate static final boolean ALLOW_UNMASKED_FROM_CLIENT = Boolean.getBoolean(\"ws-allow-unmasked-frames\");\n\tprivate static final int PROTOCOL_ERROR = 1003;\n\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\t\n\t@Override\n\tpublic boolean handshake(WebSocketXMPPIOService service, Map<String, String> headers, byte[] buf) throws NoSuchAlgorithmException, IOException {\n\t\tif (!headers.containsKey(WS_VERSION_KEY)) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tStringBuilder response = new StringBuilder(RESPONSE_HEADER.length() * 2);\n\t\tresponse.append(RESPONSE_HEADER);\n\n\t\tint version = Integer.parseInt(headers.get(WS_VERSION_KEY));\n\t\tString key = headers.get(WS_KEY_KEY) + GUID;\n\n\t\tMessageDigest md = MessageDigest.getInstance(\"SHA1\");\n\t\tbyte[] resp = md.digest(key.getBytes());\n\n\t\tresponse.append(WS_PROTOCOL_KEY).append(\": \");\n\t\tif (headers.get(WS_PROTOCOL_KEY).contains(\"xmpp-framing\")) {\n\t\t\tresponse.append(\"xmpp-framing\");\n\t\t} else {\n\t\t\tresponse.append(\"xmpp\");\n\t\t}\n\t\tresponse.append(\"\\r\\n\");\n\t\tresponse.append(WS_ACCEPT_KEY + \": \");\n\t\tresponse.append(Base64.encode(resp));\n\t\tresponse.append(\"\\r\\n\");\n\t\tresponse.append(\"\\r\\n\");\n\t\tservice.maskingKey = new byte[4];\n\t\tservice.writeRawData(response.toString());\n\t\t\t\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic ByteBuffer decodeFrame(WebSocketXMPPIOService service, ByteBuffer buf) {\n\t\tif (!buf.hasRemaining()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, no content remainging to process\", new Object[] { service });\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tboolean masked = false;\n\t\tbyte type      = 0x00;\n\t\tint position   = buf.position();\n\t\tByteBuffer unmasked = null;\n\t\t\n\t\ttry {\n\t\t\tif (service.frameLength == -1) {\n\t\t\t\ttype = buf.get();\n\t\t\t\tif ((type & 0x0F) == 0x08) {\n\n\t\t\t\t\t// close request\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, closing connection due to client request {1}\", \n\t\t\t\t\t\t\t\tnew Object[] { service, String.format(\"%02X \", type) });\n\t\t\t\t\t}\n\t\t\t\t\tservice.setState(closing);\n\t\t\t\t\tcloseConnection(service, null);\n\t\t\t\t\t//service.forceStop();\n\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tbyte b2 = buf.get();\n\n\t\t\t\t// check if content is masked\n\t\t\t\tmasked = (b2 & 0x80) == 0x80;\n\t\t\t\tif (!masked && !ALLOW_UNMASKED_FROM_CLIENT) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, closing connection due to protocol error - unmasked frame sent by client {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { service, String.format(\"%02X \", type) });\n\t\t\t\t\t}\n\t\t\t\t\tcloseConnection(service, PROTOCOL_ERROR);\n\t\t\t\t\t//service.forceStop();\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\n\t\t\t\t// ignore sign bit\n\t\t\t\tservice.frameLength = (b2 & 0x7F);\n\t\t\t\tif (service.frameLength > 125) {\n\t\t\t\t\t// if frame length is bigger than 125 then\n\t\t\t\t\t// if is 126 - size is short (unsigned short)\n\t\t\t\t\t// is is 127 - size is long\n\t\t\t\t\tservice.frameLength = (service.frameLength == 126)\n\t\t\t\t\t\t\t? (buf.getShort() & 0xffff)\n\t\t\t\t\t\t\t: buf.getLong();\n\t\t\t\t}\n\t\t\t\tif (masked) {\n\n\t\t\t\t\t// if content is masked get masking key\n\t\t\t\t\tbuf.get(service.maskingKey);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (buf.remaining() >= service.frameLength) {\n\t\t\t\tbyte[] data = new byte[(int) service.frameLength];\n\n\t\t\t\tbuf.get(data);\n\n\t\t\t\t// if content is masked then unmask content\n\t\t\t\tif (masked) {\n\t\t\t\t\tbyte[] maskingKey = service.maskingKey;\n\t\t\t\t\tfor (int i = 0; i < data.length; i++) {\n\t\t\t\t\t\tdata[i] = (byte) (data[i] ^ maskingKey[i % 4]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunmasked = ByteBuffer.wrap(data);\n\t\t\t\tservice.frameLength = -1;\n\t\t\t} else {\n\t\t\t\t// not enought data so reset buffer position\n\t\t\t\tbuf.position(position);\n\t\t\t\tservice.frameLength = -1;\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (service.frameLength == -1) {\n\n\t\t\t\t// we need to ignore pong frame\n\t\t\t\tif ((type & 0x0A) == 0x0A) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, ignoring pong frame\", new Object[] { service });\n\t\t\t\t\t}\n\t\t\t\t\tunmasked = null;\n\t\t\t\t} // if it ping request send pong response\n\t\t\t\telse if ((type & 0x09) == 0x09) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Socket: {0}, sending response on ping frame\", new Object[] { service });\n\t\t\t\t\t}\n\t\t\t\t\ttype = (byte) (((byte) (type ^ 0x09)) | 0x0A);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tByteBuffer header = createFrameHeader(type, unmasked.remaining());\n\n\t\t\t\t\t\tservice.writeInProgress.lock();\n\t\t\t\t\t\tservice.writeBytes(header);\n\t\t\t\t\t\tservice.writeBytes(unmasked);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tservice.writeInProgress.unlock();\n\t\t\t\t\t}\n\t\t\t\t\tunmasked = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (BufferUnderflowException ex) {\n\t\t\t// if for some reason we do not have full frame header then we need to \n\t\t\t// reset buffer to original position and wait for the rest of data\n\t\t\tbuf.position(position);\n\t\t\tservice.frameLength = -1;\n\t\t\tunmasked = null;\n\t\t}\n\n\t\treturn unmasked;\n\t}\n\n\t@Override\n\tpublic void encodeFrameAndWrite(WebSocketXMPPIOService service, ByteBuffer buf) throws IOException {\n\t\tint size = buf.remaining();\n\n\t\t// set type as finally part (0x80) of message of type text (0x01)\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Socket: {0}, sending encoded data size = {1}\", new Object[] { service, size });\n\t\t}\n\n\t\tByteBuffer bbuf = createFrameHeader((byte) 0x81, size);\n\n\t\t// send frame header\n\t\tservice.writeBytes(bbuf);\n\n\t\tservice.writeBytes(buf);\t\t\t\t\t\t\t\n\t}\n\t\n\t@Override\n\tpublic void closeConnection(WebSocketXMPPIOService service) {\n\t\tif (!service.isConnected())\n\t\t\treturn;\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Socket: {0}, sending close frame\", service);\n\t\t}\n\n\t\tservice.setState(WebSocketXMPPIOService.State.closed);\n\t\tInteger code = (Integer) service.getSessionData().get(CLOSE_CODE);\n\t\tint len = 0;\n\t\tif (code != null) {\n\t\t\tlen += 2;\n\t\t}\n\t\tByteBuffer bbuf = createFrameHeader((byte) 0x88, len);\n\t\tservice.writeBytes(bbuf);\n\t\tif (code != null) {\n\t\t\tByteBuffer buf = ByteBuffer.allocate(2);\n\t\t\tbuf.putShort(code.shortValue());\n\t\t\tbuf.flip();\n\t\t\tservice.writeBytes(buf);\n\t\t}\n\t}\n\n\tprivate void closeConnection(WebSocketXMPPIOService service, Integer code) {\n\t\tif (code != null)\n\t\t\tservice.getSessionData().put(CLOSE_CODE, code);\n\t\tswitch (service.getState()) {\n\t\t\tcase closing:\n\t\t\t\tservice.setState(WebSocketXMPPIOService.State.closed);\n\t\t\t\tbreak;\n\t\t\tcase handshaked:\n\t\t\t\tservice.setState(WebSocketXMPPIOService.State.closing);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t\n\t/**\n\t * Create WebSocket frame header with specific type and size\n\t *\n\t * @param type\n\t * @param size\n\t * \n\t */\n\tprivate ByteBuffer createFrameHeader(byte type, int size) {\n\t\tByteBuffer bbuf = ByteBuffer.allocate(12);\n\n\t\tbbuf.put(type);\n\t\tif (size <= 125) {\n\t\t\tbbuf.put((byte) size);\n\t\t} else if (size <= 0xFFFF) {\n\t\t\tbbuf.put((byte) 0x7E);\n\t\t\tbbuf.putShort((short) size);\n\t\t} else {\n\t\t\tbbuf.put((byte) 0x7F);\n\t\t\tbbuf.putLong((long) size);\n\t\t}\n\t\tbbuf.flip();\n\n\t\treturn bbuf;\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/websocket/WebSocketProtocolIfc.java",
    "content": "/*\n * WebSocketProtocolIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Map;\n\n/**\n * Interface which needs to be implemented by any implemention of version of\n * WebSocket protocol. \n * \n * Currently we have stable version but there were older not compatible with \n * current so it may be that new will come in future - also not compatible.\n * \n * @author andrzej\n */\npublic interface WebSocketProtocolIfc {\n\t\n\t/**\n\t * HTTP header used by WebSocket to pass used version of WebSocket protocol\n\t * from client to server\n\t */\n    public static final String WS_VERSION_KEY  = \"Sec-WebSocket-Version\";\n\t/**\n\t * HTTP header which contains name of subprotocol which should be used over\n\t * established WebSocket connection\n\t */\n\tstatic final String WS_PROTOCOL_KEY = \"Sec-WebSocket-Protocol\";\n\t\n\t/**\n\t * Method to retrieve string identifier of implementation of protcol version\n\t * \n\t * @return \n\t */\n\tString getId();\n\t\n\t/**\n\t * Method responsible for handshaking of WebSocket using proper version of\n\t * protocol.\n\t * \n\t * @param service\n\t * @param headers\n\t * @param buf\n\t * @return false - if implementation is not able to handshake using this\n\t *\t\t\t\t\tversion of protocol, in other case return true\n\t * @throws NoSuchAlgorithmException\n\t * @throws IOException \n\t */\n\tboolean handshake(WebSocketXMPPIOService service, Map<String,String> headers, byte[] buf) throws NoSuchAlgorithmException, IOException;\n\t\n\t/**\n\t * Method responsible for decoding data received from socket and returning \n\t * data after extracting it from WebSocket frame.\n\t * \n\t * @param service\n\t * @param buf\n\t * @return decoded data or null if not full frame is available in input buffer\n\t */\n\tByteBuffer decodeFrame(WebSocketXMPPIOService service, ByteBuffer buf);\n\t\n\t/**\n\t * Method encodes data into WebSocket frame and writes it to passed service\n\t * \n\t * @param service\n\t * @param buf\n\t * @throws IOException\n\t */\n\tvoid encodeFrameAndWrite(WebSocketXMPPIOService service, ByteBuffer buf) throws IOException;\n\t\n\t/**\n\t * Method closes connection by sending close frame\n\t * @param service\n\t */\n\tvoid closeConnection(WebSocketXMPPIOService service);\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/websocket/WebSocketXMPPIOService.java",
    "content": "/*\n * WebSocketXMPPIOService.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.websocket;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.xmpp.XMPPIOService;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.CharBuffer;\nimport java.nio.charset.CharacterCodingException;\nimport java.nio.charset.CoderResult;\nimport java.nio.charset.MalformedInputException;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class implements basic support for WebSocket protocol. It extends\n * XMPPIOService so it can be used instead of XMPPIOService in\n * ClientConnectionManager to allow web clients to connect to it without using\n * BOSH extension.\n *\n * @param <RefObject>\n */\npublic class WebSocketXMPPIOService<RefObject>\n\t\t\t\textends XMPPIOService<RefObject> {\n\tprivate static final String BAD_REQUEST    = \"HTTP/1.0 400 Bad request\\r\\n\\r\\n\";\n\tprivate static final String CONNECTION_KEY = \"Connection\";\n\tprivate static final Logger log            =\n\t\tLogger.getLogger(WebSocketXMPPIOService.class.getCanonicalName());\n\n\tprivate static final String CLOSE_EL = \"close\";\n\tprivate static final String OPEN_EL = \"open\";\n\tprivate static final String XMLNS_FRAMING = \"urn:ietf:params:xml:ns:xmpp-framing\";\n\t\n\tpublic static enum WebSocketXMPPSpec {\n\t\thybi,\n\t\txmpp\n\t}\n\n\tpublic enum State {\n\t\t// begining state - used when we retrieve data from\n\t\t// connection to detect if connection is able to be\n\t\t// upgraded to WebSocket\n\t\thandshaking,\n\t\t// after WebSocket handshake is completed - can send data\n\t\thandshaked,\n\t\t// when server sent close request\n\t\tclosing,\n\t\t// when server sent close request and received\n\t\t// close request from client\n\t\tclosed\n\t}\n\n\t/* static variables used by WebSocket protocol */\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\tprotected long frameLength  = -1;\n\tprotected byte[] maskingKey = null;\n\tprivate byte[] partialData = null;\n\t\n\t// internal properties\n\t//private boolean websocket = false;\n\tprivate State state = State.handshaking;\n\tprivate boolean started   = false;\n\n\tprivate final WebSocketProtocolIfc[] protocols;\n\tprivate WebSocketProtocolIfc protocol = null;\n\tprivate WebSocketXMPPSpec webSocketXMPPSpec = WebSocketXMPPSpec.hybi;\n\t\n\tpublic WebSocketXMPPIOService(WebSocketProtocolIfc[] enabledProtocols) {\n\t\tthis.protocols = enabledProtocols;\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tprotocol.closeConnection(this);\n\t\tsuper.stop(); //To change body of generated methods, choose Tools | Templates.\n\t}\n\n\tprotected State getState() {\n\t\treturn state;\n\t}\n\n\tprotected void setState(State state) {\n\t\tthis.state = state;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void addReceivedPacket(Packet packet) {\n\t\tif (packet.getXMLNS() == XMLNS_FRAMING) {\n\t\t\t// it is framing packet, so it should be <open/> or <close/>\n\t\t\tif (packet.getElemName() == OPEN_EL) {\n\t\t\t\twebSocketXMPPSpec = WebSocketXMPPSpec.xmpp;\n\t\t\t\txmppStreamOpened(packet.getElement().getAttributes());\n\t\t\t\treturn;\n\t\t\t} else if (packet.getElemName() == CLOSE_EL) {\n\t\t\t\txmppStreamClosed();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tsuper.addReceivedPacket(packet); //To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t@Override\n\tprotected void processSocketData() throws IOException {\n\t\tState oldState = state;\n\t\tsuper.processSocketData();\n\t\tif (state != oldState && oldState == State.handshaked) {\n\t\t\tprotocol.closeConnection(this);\n\t\t}\n\t}\n\n\tprotected WebSocketXMPPSpec getWebSocketXMPPSpec() {\n\t\treturn webSocketXMPPSpec;\n\t}\n\t\n\t@Override\n\tprotected String prepareStreamClose() {\n\t\tif (webSocketXMPPSpec == WebSocketXMPPSpec.hybi)\n\t\t\treturn \"</stream:stream>\";\n\t\treturn \"<close xmlns='urn:ietf:params:xml:ns:xmpp-framing' />\";\n\t}\t\t\n\n\t@Override\n\tprotected char[] readData() throws IOException {\n\t\tByteBuffer cb = super.readBytes();\n\n\t\tif (cb == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// handling partialy decoded frame\n\t\tif (partialData != null) {\n\t\t\tByteBuffer oldtmp = cb;\n\t\t\tcb = ByteBuffer.allocate(partialData.length + oldtmp.remaining());\n\t\t\tcb.order(oldtmp.order());\n\t\t\tcb.put(partialData);\n\t\t\tcb.put(oldtmp);\n\t\t\tcb.flip();\n\t\t\toldtmp.clear();\n\t\t\tpartialData = null;\n\t\t}\n\t\t\n\t\tif (state != State.handshaking) {\n\n\t\t\t\n\t\t\t// data needs to be decoded fully not just first frame!!\n\t\t\tByteBuffer tmp = ByteBuffer.allocate(cb.remaining());\t\n\t\t\t// here we got buffer overflow\n\t\t\tByteBuffer decoded = null;\n\t\t\twhile (cb.hasRemaining() && (decoded = decodeFrame(cb)) != null) {\n\t\t\t\t//decoded = decodeFrame(cb);\n\t\t\t\tif (decoded != null && decoded.hasRemaining()) {\n\t\t\t\t\ttmp.put(decoded);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// handling data which were not decoded - not complete data\n\t\t\tif (cb.hasRemaining()) {\n\t\t\t\tpartialData = new byte[cb.remaining()];\n\t\t\t\tcb.get(partialData);\n\t\t\t}\n\t\t\t\n\t\t\t// compact buffer after reading all frames\n\t\t\tcb.compact();\n\t\t\t\n\t\t\tif (tmp.capacity() > 0) {\n\t\t\t\ttmp.flip();\n\t\t\t}\n\t\t\tcb = tmp; \n\t\t}\n\t\tif (started) {\n\t\t\treturn decode(cb);\n\t\t}\n\t\t\n\t\tif (!cb.hasRemaining()) {\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\ttry {\n/*\t\t\tif (!started && (cb.get(0) != (byte) 'G')) {\n\t\t\t\tstarted = true;\n\n\t\t\t\treturn decode(cb);\n\t\t\t}*/\n\t\t\t\n\t\t\tint remaining = cb.remaining();\n\t\t\tbyte[] buf = new byte[remaining];\n\t\t\t\n\t\t\tcb.get(buf, 0, remaining);\n\t\t\t//pos += read;\n\t\t\tcb.compact();\n\t\t\tint pos = remaining;\n\t\t\tif ((pos > 100) &&\n\t\t\t\t\t(((buf[pos - 1] == '\\n') && (buf[pos - 1] == buf[pos - 3])) ||\n\t\t\t\t\t ((buf[pos - 9] == '\\n') && (buf[pos - 9] == buf[pos - 11])))) {\n\t\t\t\tstarted = true;\n\t\t\t\tprocessWebSocketHandshake(buf);\n\t\t\t\t//websocket = true;\n\t\t\t\tif (protocol != null)\n\t\t\t\t\tstate = State.handshaked;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpartialData = buf;\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"exception processing websocket handshake\", ex);\n\t\t\t}\n\t\t\tthis.forceStop();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Custom implementation of writeData function which encodes data\n\t * in WebSocket protocol frames\n\t *\n\t * @param data\n\t */\n\t@Override\n\tprotected void writeData(final String data) {\n\n\t\t// Try to lock the data writing method\n\t\t// If cannot lock and nothing to send, just leave\n\t\tboolean locked = writeInProgress.tryLock();\n\n\t\t// Otherwise wait.....\n\t\tif (!locked) {\n\t\t\tif (data == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\twriteInProgress.lock();\n\t\t}\n\t\ttry {\n\t\t\tif (state != State.handshaking) {\n\t\t\t\ttry {\n\t\t\t\t\tif (data != null) {\t\t\t\t\t\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"sending data = {0}\", data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tByteBuffer buf = encode(data);\n\t\t\t\t\t\tprotocol.encodeFrameAndWrite(this, buf);\n\n\t\t\t\t\t\t//buf.compact();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\twriteBytes(null);\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"exception writing data\", ex);\n\t\t\t\t\t}\n\t\t\t\t\tforceStop();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsuper.writeData(data);\n\t\t\t}\n\t\t} finally {\n\t\t\twriteInProgress.unlock();\n\t\t}\n\t}\n\n\t/**\n\t * Process data from internal temporary buffer used to decode HTTP request\n\t * used by WebSocket protocol to switch protocol to WebSocket protocol\n\t *\n\t * @throws NoSuchAlgorithmException\n\t * @throws IOException\n\t */\n\tprivate void processWebSocketHandshake(byte[] buf) throws NoSuchAlgorithmException, IOException {\n\t\tHashMap<String, String> headers = new HashMap<String, String>();\n\t\tint i = parseHttpHeaders(buf, headers);\n\n\t\tif (!headers.containsKey(CONNECTION_KEY) ||\n\t\t\t\t!headers.get(CONNECTION_KEY).contains(\"Upgrade\")) {\n\t\t\twriteRawData(BAD_REQUEST);\n\t\t\t\n\t\t\tdumpHeaders(headers);\n\t\t\tforceStop();\n\t\t\treturn;\n\t\t}\n\t\tif (!headers.containsKey(WebSocketProtocolIfc.WS_PROTOCOL_KEY) ||\n\t\t\t\t!headers.get(WebSocketProtocolIfc.WS_PROTOCOL_KEY).contains(\"xmpp\")) {\n\t\t\twriteRawData(BAD_REQUEST);\n\n\t\t\tdumpHeaders(headers);\n\t\t\tforceStop();\n\t\t\treturn;\n\t\t}\n\n\t\ti=0;\n\t\twhile (protocol == null && i < protocols.length) {\n\t\t\tif (protocols[i].handshake(this, headers, buf)) {\n\t\t\t\tprotocol = protocols[i];\n\t\t\t} else {\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (protocol == null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"could not find implementation for WebSocket protocol for {0}\", this);\n\t\t\t}\n\t\t\tdumpHeaders(headers);\n\t\t\tforceStop();\n\t\t}\n\t}\n\n\tprotected int parseHttpHeaders(byte[] buf, Map<String, String> headers) {\n\t\tint i                           = 0;\n\n\t\twhile (buf[i] != '\\n') {\n\t\t\ti++;\n\t\t}\n\t\ti++;\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"parsing request = \\n{0}\", new String(buf));\n\t\t}\n\n\t\tStringBuilder builder = new StringBuilder(64);\n\t\tString key            = null;\n\n\t\tboolean skipWhitespace = false;\n\t\tfor (; i < buf.length; i++) {\n\t\t\tswitch (buf[i]) {\n\t\t\t\tcase ':':\n\t\t\t\t\tif (key == null) {\n\t\t\t\t\t\tkey = builder.toString().trim();\n\t\t\t\t\t\tbuilder = new StringBuilder(64);\n\t\t\t\t\t\tskipWhitespace = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilder.append((char) buf[i]);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase '\\r':\n\t\t\t\t\theaders.put(key, builder.toString().trim());\n\t\t\t\t\tkey = null;\n\t\t\t\t\tbuilder = new StringBuilder(64);\n\t\t\t\t\tif (buf[i + 2] == '\\r') {\n\t\t\t\t\t\ti += 3;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ' ':\n\t\t\t\tcase '\\t':\n\t\t\t\t\tif (!skipWhitespace) {\n\t\t\t\t\t\tbuilder.append((char) buf[i]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tskipWhitespace = false;\n\t\t\t\t\tbuilder.append((char) buf[i]);\n\t\t\t}\n\t\t}\n\t\treturn i;\n\t}\n\t\n\t@Override\n\tprotected void writeBytes(ByteBuffer data) {\n\t\tsuper.writeBytes(data);\n\t}\n\n\t/**\n\t * Decode data encoded in WebSocket frames from buffer\n\t *\n\t * @param buf\n\t * \n\t */\n\tprivate ByteBuffer decodeFrame(ByteBuffer buf) {\n\t\treturn protocol.decodeFrame(this, buf);\n\t}\n\n\t/**\n\t * Decode data from buffer to chars array\n\t *\n\t * @param tmpBuffer\n\t * \n\t * @throws MalformedInputException\n\t */\n\tprivate char[] decode(ByteBuffer tmpBuffer) throws MalformedInputException {\n\t\tif (tmpBuffer == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tchar[] result = null;\n\n\t\t// Restore the partial bytes for multibyte UTF8 characters\n\t\tif (partialCharacterBytes != null) {\n\t\t\tByteBuffer oldTmpBuffer = tmpBuffer;\n\n\t\t\ttmpBuffer = ByteBuffer.allocate(partialCharacterBytes.length +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\toldTmpBuffer.remaining() + 2);\n\t\t\ttmpBuffer.put(partialCharacterBytes);\n\t\t\ttmpBuffer.put(oldTmpBuffer);\n\t\t\ttmpBuffer.flip();\n\t\t\toldTmpBuffer.clear();\n\t\t\tpartialCharacterBytes = null;\n\t\t}\n\t\tif (cb.capacity() < tmpBuffer.remaining() * 4) {\n\t\t\tcb = CharBuffer.allocate(tmpBuffer.remaining() * 4);\n\t\t}\n\n\t\tCoderResult cr = decoder.decode(tmpBuffer, cb, false);\n\n\t\tif (cr.isMalformed()) {\n\t\t\tthrow new MalformedInputException(tmpBuffer.remaining());\n\t\t}\n\t\tif (cb.remaining() > 0) {\n\t\t\tcb.flip();\n\t\t\tresult = new char[cb.remaining()];\n\t\t\tcb.get(result);\n\t\t}\n\t\tif (cr.isUnderflow() && (tmpBuffer.remaining() > 0)) {\n\n\t\t\t// Save the partial bytes of a multibyte character such that they\n\t\t\t// can be restored on the next read.\n\t\t\tpartialCharacterBytes = new byte[tmpBuffer.remaining()];\n\t\t\ttmpBuffer.get(partialCharacterBytes);\n\t\t}\n\t\ttmpBuffer.clear();\n\t\tcb.clear();\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Encode string into buffer\n\t *\n\t * @param data\n\t * \n\t * @throws CharacterCodingException\n\t */\n\tprivate ByteBuffer encode(String data) throws CharacterCodingException {\n\t\tByteBuffer dataBuffer = null;\n\n\t\tencoder.reset();\n\n\t\t// dataBuffer = encoder.encode(CharBuffer.wrap(data, idx_start,\n\t\t// idx_offset));\n\t\tdataBuffer = encoder.encode(CharBuffer.wrap(data));\n\t\tencoder.flush(dataBuffer);\n\n\t\t// dataBuffer.flip();\n\t\treturn dataBuffer;\n\t}\n\t\n\tpublic void dumpHeaders(Map<String,String> headers) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tStringBuilder builder = new StringBuilder(1000);\n\t\t\tfor(Map.Entry<String,String> entry : headers.entrySet()) {\n\t\t\t\tbuilder.append(\"KEY = \");\n\t\t\t\tbuilder.append(entry.getKey());\n\t\t\t\tbuilder.append(\"VALUE = \");\n\t\t\t\tbuilder.append(entry.getValue());\n\t\t\t\tbuilder.append('\\n');\n\t\t\t}\n\t\t\t\n\t\t\tlog.log(Level.FINEST, \"received headers = \\n{0}\", builder.toString());\n\t\t}\t\t\n\t}\n\t\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/19\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/ClientConnectionManager.java",
    "content": "/*\n * ClientConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.server.xmppclient;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.conf.ConfigurationException;\nimport tigase.net.IOService;\nimport tigase.net.SocketThread;\nimport tigase.net.SocketType;\nimport tigase.server.*;\nimport tigase.util.Base64;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.RoutingsContainer;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.C2SDeliveryErrorProcessor;\n\nimport javax.net.ssl.TrustManager;\nimport java.io.IOException;\nimport java.security.cert.CertificateEncodingException;\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.zip.Deflater;\n\n/**\n * Class ClientConnectionManager Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ClientConnectionManager\n\t\textends ConnectionManager<XMPPIOService<Object>> {\n\tprotected static final String FORCE_REDIRECT_TO_KEY = \"force-redirect-to\";\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ClientConnectionManager.class\n\t\t\t.getName());\n\tprivate static final String ROUTING_ENTRY_PROP_KEY = \".+\";\n\tprivate static final String ROUTING_MODE_PROP_KEY = \"multi-mode\";\n\tprivate static final String ROUTINGS_PROP_KEY = \"routings\";\n\tprivate static final long SOCKET_CLOSE_WAIT_PROP_DEF = 1;\n\tprivate static final String SOCKET_CLOSE_WAIT_PROP_KEY = \"socket-close-wait\";\n\tprivate static final String TLS_WANT_CLIENT_AUTH_ENABLED_KEY =\n\t\t\t\"tls-want-client-auth-enabled\";\n\tprivate static final String XMLNS = \"jabber:client\";\n\tprivate static final boolean TLS_WANT_CLIENT_AUTH_ENABLED_DEF = false;\n\tprivate static final boolean ROUTING_MODE_PROP_VAL = true;\n\n\t//~--- fields ---------------------------------------------------------------\n\t//private final Map<String, XMPPProcessorIfc> processors = new ConcurrentHashMap<String,\n//    XMPPProcessorIfc>();\n\tprivate final ReceiverTimeoutHandler stoppedHandler = newStoppedHandler();\n\tprivate final ReceiverTimeoutHandler startedHandler = newStartedHandler();\n\tprivate final ClientTrustManagerFactory clientTrustManagerFactory =\n\t\t\tnew ClientTrustManagerFactory();\n\t/**\n\t * Field description\n\t */\n\tprotected RoutingsContainer routings = null;\n\t/**\n\t * Field description\n\t */\n\tprotected SeeOtherHostIfc see_other_host_strategy = null;\n\tprivate long socket_close_wait_time =\n\t\t\tSOCKET_CLOSE_WAIT_PROP_DEF;\n\t/**\n\t * This is mostly for testing purpose. We want to investigate massive (10k\n\t * per node) connections drops at the same time during tests with Tsung. I\n\t * suspect this might be due to problems with one of the tsung VMs working\n\t * in the cluster generating load. If I am right then all disconnects should\n\t * come from only one or just a few machines. If I am not right disconnects\n\t * should be distributed evenly among all Tsung IPs.\n\t */\n\tprivate IPMonitor ipMonitor = new IPMonitor();\n\tprivate boolean tlsWantClientAuthEnabled = TLS_WANT_CLIENT_AUTH_ENABLED_DEF;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t * @param packet\n\t * @param newAddress\n\t * @param command_sessionId\n\t * @param serv\n\t * @return a value of <code>JID</code>\n\t */\n\tprotected JID changeDataReceiver(Packet packet, JID newAddress,\n\t\t\t\t\t\t\t\t\t String command_sessionId, XMPPIOService<Object> serv) {\n\t\tif (serv != null) {\n\t\t\tString serv_sessionId = (String) serv.getSessionData().get(IOService\n\t\t\t\t\t.SESSION_ID_KEY);\n\n\t\t\tif (serv_sessionId.equals(command_sessionId)) {\n\t\t\t\tJID old_receiver = serv.getDataReceiver();\n\n\t\t\t\tserv.setDataReceiver(newAddress);\n\n\t\t\t\treturn old_receiver;\n\t\t\t} else {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"Incorrect session ID, ignoring data redirect for: {0}, expected: {1}, received: {2}\",\n\t\t\t\t\t\tnew Object[]{newAddress,\n\t\t\t\t\t\t\t\tserv_sessionId, command_sessionId});\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic ClientTrustManagerFactory getClientTrustManagerFactory() {\n\t\treturn clientTrustManagerFactory;\n\t}\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn new int[]{5222};\n\t}\n\n\t@Override\n\tprotected int[] getDefSSLPorts() {\n\t\treturn new int[]{5223};\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = super.getDefaults(params);\n\t\tBoolean r_mode = (Boolean) params.get(getName() + \"/\" +\n\t\t\t\tROUTINGS_PROP_KEY + \"/\" + ROUTING_MODE_PROP_KEY);\n\t\tString see_other_host_class = (String) params.get(SeeOtherHostIfc\n\t\t\t\t.CM_SEE_OTHER_HOST_CLASS_PROPERTY);\n\n\t\tsee_other_host_strategy = getSeeOtherHostInstance(see_other_host_class);\n\t\tprops.put(SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_KEY, see_other_host_class);\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.getDefaults(props, params);\n\t\t}\n\t\tif (r_mode == null) {\n\t\t\tprops.put(ROUTINGS_PROP_KEY + \"/\" + ROUTING_MODE_PROP_KEY, ROUTING_MODE_PROP_VAL);\n\n\t\t\t// If the server is configured as connection manager only node then\n\t\t\t// route packets to SM on remote host where is default routing\n\t\t\t// for external component.\n\t\t\t// Otherwise default routing is to SM on localhost\n\t\t\tif (params.get(\"config-type\").equals(GEN_CONFIG_CS) && (params.get(GEN_EXT_COMP) !=\n\t\t\t\t\tnull)) {\n\t\t\t\tString[] comp_params = ((String) params.get(GEN_EXT_COMP)).split(\",\");\n\n\t\t\t\tprops.put(ROUTINGS_PROP_KEY + \"/\" + ROUTING_ENTRY_PROP_KEY, DEF_SM_NAME + \"@\" +\n\t\t\t\t\t\tcomp_params[1]);\n\t\t\t} else {\n\t\t\t\tprops.put(ROUTINGS_PROP_KEY + \"/\" + ROUTING_ENTRY_PROP_KEY, DEF_SM_NAME + \"@\" +\n\t\t\t\t\t\tDNSResolverFactory.getInstance().getDefaultHost());\n\t\t\t}\n\t\t}\n\t\tprops.put(SOCKET_CLOSE_WAIT_PROP_KEY, SOCKET_CLOSE_WAIT_PROP_DEF);\n\t\tprops.put(TLS_WANT_CLIENT_AUTH_ENABLED_KEY, TLS_WANT_CLIENT_AUTH_ENABLED_DEF);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"c2s\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Client connection manager\";\n\t}\n\n\tprivate List<Element> getFeatures(XMPPIOService service) {\n\t\tList<Element> results = new LinkedList<Element>();\n\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tElement[] features = proc.supStreamFeatures(service);\n\n\t\t\tif (features != null) {\n\t\t\t\tresults.addAll(Arrays.asList(features));\n\t\t\t}    // end of if (features != null)\n\t\t}      // end of for ()\n\n\t\treturn results;\n\t}\n\n\tprivate JID getFromAddress(String id) {\n\t\treturn JID.jidInstanceNS(getName(), getDefHostName().getDomain(), id);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t * <p>\n\t * <br><br>\n\t * <p>\n\t * Let's assume user should send something at least once every 24 hours....\n\t */\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 24 * HOUR;\n\t}\n\n\t@Override\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def * 10;\n\t}\n\n\t/**\n\t * Method retrieves object of particular class implementing {@link SeeOtherHostIfc}\n\t *\n\t * @param see_other_host_class class of {@link SeeOtherHostIfc} implementation\n\t * @return a value of <code>SeeOtherHostIfc</code>\n\t */\n\tpublic SeeOtherHostIfc getSeeOtherHostInstance(String see_other_host_class) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Configuring see_other_host strategy for: \" + see_other_host_class);\n\t\t}\n\t\tif (see_other_host_class == null) {\n\t\t\tsee_other_host_class = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL;\n\t\t}\n\t\tif (see_other_host_class.equals(\"none\")) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tsee_other_host_strategy = (SeeOtherHostIfc) Class.forName(see_other_host_class)\n\t\t\t\t\t.newInstance();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not instantiate see_other_host strategy for class: \" +\n\t\t\t\t\tsee_other_host_class, e);\n\t\t}\n\n\t\treturn see_other_host_strategy;\n\t}\n\n\t@Override\n\tprotected XMPPIOService<Object> getXMPPIOServiceInstance() {\n\t\treturn new XMPPIOService<Object>();\n\t}\n\n\tprivate XMPPResourceConnection getXMPPSession(Packet p) {\n\t\tXMPPIOService<Object> serv = getXMPPIOService(p);\n\n\t\treturn (serv == null)\n\t\t\t\t? null\n\t\t\t\t: (XMPPResourceConnection) serv.getSessionData().get(\"xmpp-session\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\t\tif ((packet.getPacketFrom() != null) && getComponentId().getBareJID().equals(packet\n\t\t\t\t.getPacketFrom().getBareJID())) {\n\t\t\treturn packet.getPacketFrom().hashCode();\n\t\t} else {\n\t\t\treturn packet.getTo().hashCode();\n\t\t}\n\t}\n\n\tprotected boolean isAllowed(XMPPIOService<Object> serv, String hostname) {\n\t\tVHostItem vhost = this.vHostManager.getVHostItem(hostname);\n\t\tif (vhost != null) {\n\t\t\tint[] allowedPorts = vhost.getC2SPortsAllowed();\n\t\t\tif (allowedPorts != null && Arrays.binarySearch(allowedPorts, serv.getLocalPort()) < 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t * @return a value of <code>ReceiverTimeoutHandler</code>\n\t */\n\tprotected ReceiverTimeoutHandler newStartedHandler() {\n\t\treturn new StartedHandler();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t * @return a value of <code>ReceiverTimeoutHandler</code>\n\t */\n\tprotected ReceiverTimeoutHandler newStoppedHandler() {\n\t\treturn new StoppedHandler();\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprotected String prepareSeeOtherHost(XMPPIOService<Object> serv, String hostname, BareJID see_other_host) {\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, StreamError.SeeOtherHost);\n\t\t}\n\n\t\tInteger redirect_port = (Integer) serv.getSessionData().get(FORCE_REDIRECT_TO_KEY);\n\n\t\treturn \"<stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t+ \" id='tigase-error-tigase'\" + \" from='\" + (hostname != null ? hostname : getDefVHostItem()) + \"'\"\n\t\t\t\t+ \" version='1.0' xml:lang='en'>\"\n\t\t\t\t+ see_other_host_strategy.getStreamError(\"urn:ietf:params:xml:ns:xmpp-streams\",\n\t\t\t\tsee_other_host, redirect_port).toString()\n\t\t\t\t+ \"</stream:stream>\";\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected String prepareStreamClose(XMPPIOService<Object> serv) {\n\t\treturn \"</stream:stream>\";\n\t}\n\n\tprotected String prepareStreamError(XMPPIOService<Object> serv, List<Element> err_el) {\n\t\tStreamError streamError = StreamError.getByCondition(err_el.get(0).getName());\n\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, streamError);\n\t\t}\n\t\treturn \"<stream:error>\" + err_el.get(0).toString() + \"</stream:error>\";\n\t}\n\n\tprotected String prepareStreamError(XMPPIOService<Object> serv, StreamError streamError, String hostname) {\n\t\tfor (XMPPIOProcessor proc : processors) {\n\t\t\tproc.streamError(serv, streamError);\n\t\t}\n\t\treturn \"<?xml version='1.0'?><stream:stream\" + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t+ \" id='tigase-error-tigase'\" + \" from='\" + (hostname != null ? hostname : getDefVHostItem()) + \"'\"\n\t\t\t\t+ \" version='1.0' xml:lang='en'>\" + \"<stream:error>\"\n\t\t\t\t+ \"<\" + streamError.getCondition() + \" xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\"\n\t\t\t\t+ \"</stream:error>\" + \"</stream:stream>\";\n\t}\n\n\tprotected String prepareStreamOpen(XMPPIOService<Object> serv, String id, String hostname) {\n\t\treturn \"<?xml version='1.0'?><stream:stream\" + \" xmlns='\" +\n\t\t\t\tXMLNS + \"'\" + \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" +\n\t\t\t\thostname + \"'\" + \" id='\" + id + \"'\" + \" version='1.0' xml:lang='en'>\";\n\t}\n\n\tprotected void preprocessStreamFeatures(XMPPIOService<Object> serv, Element elem_features) {\n\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t * @param packet\n\t */\n\tprotected void processCommand(Packet packet) {\n\t\tXMPPIOService<Object> serv = getXMPPIOService(packet);\n\t\tIq iqc = (Iq) packet;\n\n\t\tswitch (iqc.getCommand()) {\n\t\t\tcase GETFEATURES:\n\t\t\t\tif (iqc.getType() == StanzaType.result) {\n\t\t\t\t\tList<Element> features = getFeatures(serv);\n\t\t\t\t\tElement elem_features = new Element(\"stream:features\");\n\n\t\t\t\t\telem_features.addChildren(features);\n\t\t\t\t\telem_features.addChildren(Command.getData(iqc));\n\n\t\t\t\t\tpreprocessStreamFeatures(serv, elem_features);\n\n\t\t\t\t\tPacket result = Packet.packetInstance(elem_features, null, null);\n\n\t\t\t\t\t// Is it actually needed?? Yes, it is needed, IOService is\n\t\t\t\t\t// looked up based on this.\n\t\t\t\t\tresult.setPacketTo(iqc.getTo());\n\t\t\t\t\twritePacketToSocket(result);\n\t\t\t\t}    // end of if (packet.getType() == StanzaType.get)\n\n\t\t\t\tbreak;\n\n\t\t\tcase USER_LOGIN:\n\t\t\t\tString jid = Command.getFieldValue(iqc, \"user-jid\");\n\n\t\t\t\tif (jid != null) {\n\t\t\t\t\tif (serv != null) {\n\t\t\t\t\t\tBareJID fromJID = null;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfromJID = BareJID.bareJIDInstance(jid);\n\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\tlog.log(Level.SEVERE, null, ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((fromJID != null) && ((see_other_host_strategy != null) &&\n\t\t\t\t\t\t\t\tsee_other_host_strategy.isEnabled(vHostManager.getVHostItem(fromJID.getDomain()),\n\t\t\t\t\t\t\t\t\t\tSeeOtherHostIfc.Phase.LOGIN))) {\n\t\t\t\t\t\t\tBareJID see_other_host = see_other_host_strategy.findHostForJID(fromJID,\n\t\t\t\t\t\t\t\t\tgetDefHostName());\n\n\t\t\t\t\t\t\tInteger redirect_port = (Integer) serv.getSessionData().get(FORCE_REDIRECT_TO_KEY);\n\n\t\t\t\t\t\t\tif ((see_other_host != null)\n\t\t\t\t\t\t\t\t\t&& (redirect_port != null\n\t\t\t\t\t\t\t\t\t|| see_other_host_strategy.isRedirectionRequired(getDefHostName(), see_other_host))) {\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t\"Sending redirect for {0} to host {1}, connection {2}.\",\n\t\t\t\t\t\t\t\t\t\t\tnew Object[]{fromJID,\n\t\t\t\t\t\t\t\t\t\t\t\t\tsee_other_host, serv});\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tString redirectMessage = prepareSeeOtherHost(serv, fromJID.getDomain(), see_other_host);\n\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tSocketThread.removeSocketService(serv);\n\t\t\t\t\t\t\t\t\tserv.writeRawData(redirectMessage);\n\t\t\t\t\t\t\t\t\tserv.processWaitingPackets();\n\t\t\t\t\t\t\t\t\tThread.sleep(socket_close_wait_time);\n\t\t\t\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tserv.setUserJid(jid);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tserv.setUserJid(jid);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"Missing XMPPIOService for USER_LOGIN command: {0}\", iqc);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlog.log(Level.WARNING, \"Missing user-jid for USER_LOGIN command: {0}\", iqc);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase STARTZLIB:\n\t\t\t\tif (serv != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Starting zlib compression: {0}\", serv);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tElement compressed = Command.getData(iqc, \"compressed\", null);\n\t\t\t\t\t\tPacket p_compressed = Packet.packetInstance(compressed, null, null);\n\n\t\t\t\t\t\t// SocketThread readThread = SocketThread.getInstance();\n\t\t\t\t\t\tSocketThread.removeSocketService(serv);\n\n\t\t\t\t\t\t// writePacketToSocket(serv, p_proceed);\n\t\t\t\t\t\tserv.addPacketToSend(p_compressed);\n\t\t\t\t\t\tserv.processWaitingPackets();\n\t\t\t\t\t\tserv.startZLib(Deflater.BEST_COMPRESSION);\n\n\t\t\t\t\t\t// serv.call();\n\t\t\t\t\t\tSocketThread.addSocketService(serv);\n\t\t\t\t\t} catch (IOException ex) {\n\t\t\t\t\t\tlog.log(Level.INFO, \"Problem enabling zlib compression on the connection: \",\n\t\t\t\t\t\t\t\tex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't find sevice for STARTZLIB command: {0}\", iqc);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase STARTTLS:\n\t\t\t\tif (serv != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Starting TLS for connection: {0}\", serv);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// Note:\n\t\t\t\t\t\t// If you send <proceed> packet to client you must expect\n\t\t\t\t\t\t// instant response from the client with TLS handshaking\n\t\t\t\t\t\t// data before you will call startTLS() on server side.\n\t\t\t\t\t\t// So the initial handshaking data might be lost as they\n\t\t\t\t\t\t// will be processed in another thread reading data from the\n\t\t\t\t\t\t// socket.\n\t\t\t\t\t\t// That's why below code first removes service from reading\n\t\t\t\t\t\t// threads pool and then sends <proceed> packet and starts\n\t\t\t\t\t\t// TLS.\n\t\t\t\t\t\tElement proceed = Command.getData(iqc, \"proceed\", null);\n\t\t\t\t\t\tPacket p_proceed = Packet.packetInstance(proceed, null, null);\n\n\t\t\t\t\t\t// SocketThread readThread = SocketThread.getInstance();\n\t\t\t\t\t\tSocketThread.removeSocketService(serv);\n\n\t\t\t\t\t\tString hostname = (String) serv.getSessionData().get(IOService.HOSTNAME_KEY);\n\t\t\t\t\t\tVHostItem vhost = getVHostItem(hostname);\n\n\t\t\t\t\t\tTrustManager[] x = clientTrustManagerFactory.getManager(vhost);\n\t\t\t\t\t\tboolean wantClientAuth = clientTrustManagerFactory.isTlsWantClientAuthEnabled(vhost);\n\t\t\t\t\t\tboolean needClientAuth = clientTrustManagerFactory.isTlsNeedClientAuthEnabled(vhost);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"TLS: wantClientAuth=\" + wantClientAuth + \"; needClientAuth=\" + needClientAuth\n\t\t\t\t\t\t\t\t\t+ \" for connection {0}\", serv);\n\n\t\t\t\t\t\tserv.setX509TrustManagers(x);\n\n\t\t\t\t\t\tserv.addPacketToSend(p_proceed);\n\t\t\t\t\t\tserv.processWaitingPackets();\n\n\t\t\t\t\t\tserv.startTLS(false, wantClientAuth, needClientAuth);\n\t\t\t\t\t\tSocketThread.addSocketService(serv);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Error starting TLS: {0}\", e);\n\t\t\t\t\t\tserv.forceStop();\n\t\t\t\t\t}    // end of try-catch\n\t\t\t\t} else {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't find sevice for STARTTLS command: {0}\", iqc);\n\t\t\t\t}      // end of else\n\n\t\t\t\tbreak;\n\n\t\t\tcase REDIRECT:\n\t\t\t\tString command_sessionId = Command.getFieldValue(iqc, \"session-id\");\n\t\t\t\tJID newAddress = iqc.getFrom();\n\t\t\t\tJID old_receiver = changeDataReceiver(iqc, newAddress, command_sessionId, serv);\n\n\t\t\t\tif (old_receiver != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"Redirecting data for sessionId: {0}, to: {1}\",\n\t\t\t\t\t\t\t\tnew Object[]{command_sessionId,\n\t\t\t\t\t\t\t\t\t\tnewAddress});\n\t\t\t\t\t}\n\n\t\t\t\t\tPacket response = null;\n\n\t\t\t\t\tresponse = iqc.commandResult(null);\n\t\t\t\t\tCommand.addFieldValue(response, \"session-id\", command_sessionId);\n\t\t\t\t\tCommand.addFieldValue(response, \"action\", \"activate\");\n\t\t\t\t\tresponse.getElement().setAttribute(\"to\", newAddress.toString());\n\t\t\t\t\taddOutPacket(response);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Connection for REDIRECT command does not exist, ignoring \" + \"packet: \" +\n\t\t\t\t\t\t\t\t\t\t\"{0}\", iqc.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase STREAM_CLOSED:\n\t\t\t\tbreak;\n\n\t\t\tcase GETDISCO:\n\t\t\t\tbreak;\n\n\t\t\tcase CLOSE:\n\t\t\t\tif (serv != null) {\n\t\t\t\t\tString streamClose = prepareStreamClose(serv);\n\t\t\t\t\tList<Element> err_el = packet.getElement().getChildrenStaticStr(Iq\n\t\t\t\t\t\t\t.IQ_COMMAND_PATH);\n\t\t\t\t\tboolean moreToSend = false;\n\n\t\t\t\t\tif ((err_el != null) && (err_el.size() > 0)) {\n\t\t\t\t\t\tstreamClose = prepareStreamError(serv, err_el) + streamClose;\n\t\t\t\t\t\tmoreToSend = true;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Sending stream close to the client: {0}\", streamClose);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tserv.getSessionData().put(XMPPIOService.STREAM_CLOSING, true);\n\t\t\t\t\t\tserv.writeRawData(streamClose);\n\t\t\t\t\t\tif (moreToSend) {\n\n\t\t\t\t\t\t\t// This is kind of a workaround. serv.stop() is supposed\n\t\t\t\t\t\t\t// to wait\n\t\t\t\t\t\t\t// until all data are sent to the client, however, even\n\t\t\t\t\t\t\t// then there\n\t\t\t\t\t\t\t// is still a chance, that the connection is closed\n\t\t\t\t\t\t\t// before data\n\t\t\t\t\t\t\t// reached the client\n\t\t\t\t\t\t\tThread.sleep(socket_close_wait_time);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t}\n\t\t\t\t\tserv.stop();\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Attempt to stop non-existen service for packet: {0}, Service already stopped?\",\n\t\t\t\t\t\t\t\tiqc);\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (serv != null) else\n\n\t\t\t\tbreak;\n\n\t\t\tcase CHECK_USER_CONNECTION:\n\t\t\t\tif (serv != null) {\n\n\t\t\t\t\t// It's ok, the session has been found, respond with OK.\n\t\t\t\t\taddOutPacket(iqc.okResult((String) null, 0));\n\t\t\t\t} else {\n\n\t\t\t\t\t// Session is no longer active, respond with an error.\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddOutPacket(Authorization.ITEM_NOT_FOUND.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\t\"Connection gone.\", false));\n\t\t\t\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t\t\t\t// Hm, error already, ignoring...\n\t\t\t\t\t\tlog.log(Level.INFO, \"Error packet is not really expected here: {0}\", iqc\n\t\t\t\t\t\t\t\t.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase STREAM_MOVED:\n\t\t\t\tif (processors != null) {\n\t\t\t\t\tfor (XMPPIOProcessor processor : processors) {\n\n\t\t\t\t\t\t// handled |= processor.processCommand(packet);\n\t\t\t\t\t\tprocessor.processCommand(serv, packet);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\twritePacketToSocket(iqc);\n\n\t\t\t\tbreak;\n\t\t}    // end of switch (pc.getCommand())\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet.toStringSecure());\n\t\t}\n\t\tif (packet.isCommand() && (packet.getCommand() != Command.OTHER)) {\n\t\t\tprocessCommand(packet);\n\t\t} else {\n\t\t\tif (!writePacketToSocket(packet)) {\n\n\t\t\t\t// Connection closed or broken, send message back to the SM\n\t\t\t\t// if this is not IQ result...\n\t\t\t\t// Ignore also all presence packets with available, unavailble\n\t\t\t\tprocessUndeliveredPacket(packet, null, \"The user connection is no longer active.\");\n\n\t\t\t\t// In case the SessionManager lost synchronization for any\n\t\t\t\t// reason, let's\n\t\t\t\t// notify it that the user connection no longer exists.\n\t\t\t\t// But in case of mass-disconnects we might have lot's of\n\t\t\t\t// presences\n\t\t\t\t// floating around, so just skip sending stream_close for all\n\t\t\t\t// the\n\t\t\t\t// offline presences\n\t\t\t\tif ((packet.getType() != StanzaType.unavailable) && (packet.getPacketFrom() !=\n\t\t\t\t\t\tnull)) {\n\t\t\t\t\tif (packet.getStanzaTo() != null) {\n\t\t\t\t\t\tPacket command = Command.STREAM_CLOSED_UPDATE.getPacket(packet.getStanzaTo(),\n\t\t\t\t\t\t\t\tpacket.getPacketFrom(), StanzaType.set, UUID.randomUUID().toString());\n\n\t\t\t\t\t\tcommand.setPacketFrom(packet.getPacketTo());\n\t\t\t\t\t\tcommand.setPacketTo(packet.getPacketFrom());\n\n\t\t\t\t\t\t// Note! we don't want to receive response to this\n\t\t\t\t\t\t// request,\n\t\t\t\t\t\t// thus STREAM_CLOSED_UPDATE instead of STREAM_CLOSED\n\t\t\t\t\t\taddOutPacket(command);\n\n\t\t\t\t\t\t// addOutPacketWithTimeout(command, stoppedHandler, 15l,\n\t\t\t\t\t\t// TimeUnit.SECONDS);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\"Sending a command to close the remote session for non-existen {0} connection: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[]{getName(),\n\t\t\t\t\t\t\t\t\t\t\tcommand.toStringSecure()});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\"Stream close update without an user JID, skipping for packet: {0}\",\n\t\t\t\t\t\t\t\t\tnew Object[]{packet});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of else\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(XMPPIOService<Object> serv) {\n\n\t\t// String id = getUniqueId(serv);\n\t\tJID id = serv.getConnectionId();\n\n\t\t// String hostname =\n\t\t// (String)serv.getSessionData().get(serv.HOSTNAME_KEY);\n\t\tPacket p = null;\n\n\t\twhile ((p = serv.getReceivedPackets().poll()) != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing socket data: {0} from connection: {1}\",\n\t\t\t\t\t\tnew Object[]{p.toStringSecure(),\n\t\t\t\t\t\t\t\tid});\n\t\t\t}\n\n\t\t\t// Sometimes xmlns is not set for the packet. Usually it does not\n\t\t\t// cause any problems but when the packet is sent over the s2s, ext\n\t\t\t// or cluster connection it may be quite problematic.\n\t\t\t// Let's force jabber:client xmlns for all packets received from c2s\n\t\t\t// connection\n\t\t\t// Ups, some packets like starttls or sasl-auth have own XMLNS,\n\t\t\t// overwriting it here is not really a good idea. We have to check\n\t\t\t// first\n\t\t\t// if the xmlns is not set and then force it to jabber:client\n\t\t\tif (p.getAttributeStaticStr(Packet.XMLNS_ATT) == null) {\n\t\t\t\tp.setXMLNS(XMLNS);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"XMLNS set for packet: {0} from connection: {1}\",\n\t\t\t\t\t\t\tnew Object[]{p.toStringSecure(),\n\t\t\t\t\t\t\t\t\tid});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If client is sending packet with 'from' attribute set then packets\n\t\t\t// are being duplicated in clustered environment, so best it would be\n\t\t\t// to remove 'from' attribute as it will be set later during processing\n\t\t\t// by SessionManager\n\t\t\tif (p.getStanzaFrom() != null) {\n\t\t\t\tp.initVars(null, p.getStanzaTo());\n\t\t\t}\n\n\t\t\t// p.setPacketFrom(getFromAddress(id));\n\t\t\tp.setPacketFrom(id);\n\n\t\t\tJID receiver = serv.getDataReceiver();\n\n\t\t\tif (receiver != null) {\n\t\t\t\tp.setPacketTo(serv.getDataReceiver());\n\t\t\t\taddOutPacket(p);\n\t\t\t} else {\n\n\t\t\t\t// Hm, receiver is not set yet..., ignoring\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\"Hm, receiver is not set yet stream open was not send by a client or server misconfiguration..., ignoring: {0}, connection: {1}\",\n\t\t\t\t\t\t\tnew Object[]{p.toStringSecure(),\n\t\t\t\t\t\t\t\t\tserv});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// TODO: Implement sending 'req' attributes by the server too\n\t\t}    // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\ttry {\n\t\t\t// is there a point in trying to redeliver stanza of type error?\n\t\t\tif (packet.getType() == StanzaType.error || packet.getType() == StanzaType.result)\n\t\t\t\treturn false;\n\n\t\t\t// we should not send errors for presences as Presence module does not\n\t\t\t// allow to send presence with type error from users and presences\n\t\t\t// with type error resulting from presences sent to barejid are\n\t\t\t// messing up a lot on client side. moreover presences with type\n\t\t\t// unavailable will be send by Presence plugin from SessionManager\n\t\t\t// when session will be closed just after sending this errors\n\t\t\tif (packet.getElemName() == Presence.ELEM_NAME) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (packet.getElemName() == Message.ELEM_NAME) {\n\t\t\t\t// we should mark this message packet so that SM will know that it is\n\t\t\t\t// resent from here due to connection failure\n\t\t\t\tPacket result = C2SDeliveryErrorProcessor.makeDeliveryError(packet, stamp);\n\n\t\t\t\tprocessOutPacket(result);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tprocessOutPacket(Authorization.RECIPIENT_UNAVAILABLE\n\t\t\t\t\t.getResponseMessage(packet, errorMessage, true));\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tlog.log(Level.FINER, \"exception prepareing request for returning error, data = {0}\",\n\t\t\t\t\tpacket);\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\t}\n\n\tprivate void sendTlsHandshakeCompletedToSessionManager(XMPPIOService<Object> serv) {\n\t\tfinal String id = (String) serv.getSessionData().get(IOService.SESSION_ID_KEY);\n\n\t\tif (id == null) {\n\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\tlog.log(Level.FINEST, \"Handshake complete. No session-id. Command not sent.\");\n\t\t\treturn;\n\t\t}\n\n\t\tboolean send = false;\n\n\t\tPacket command = Command.TLS_HANDSHAKE_COMPLETE.getPacket(serv.getConnectionId(), serv.getDataReceiver(),\n\t\t\t\tStanzaType.set, this.newPacketId(\"c2s-\"), Command.DataType.submit);\n\n\t\tCommand.addFieldValue(command, \"session-id\", id);\n\n\t\tif ((serv.getLocalCertificate() != null)) {\n\t\t\ttry {\n\t\t\t\tString encodedLocalCertificate = Base64.encode(serv.getLocalCertificate().getEncoded());\n\t\t\t\tCommand.addFieldValue(command, \"local-certificate\", encodedLocalCertificate);\n\t\t\t\tsend = true;\n\t\t\t} catch (CertificateEncodingException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't encode certificate\", e);\n\t\t\t}\n\t\t}\n\n\t\tif (serv.getTlsUniqueId() != null) {\n\t\t\tString data = Base64.encode(serv.getTlsUniqueId());\n\t\t\tCommand.addFieldValue(command, \"tls-unique-id\", data);\n\t\t\tsend = true;\n\t\t}\n\n\t\tif ((serv.getPeerCertificate() != null)) {\n\t\t\ttry {\n\t\t\t\tString encodedPeerCertificate = Base64.encode(serv.getPeerCertificate().getEncoded());\n\t\t\t\tCommand.addFieldValue(command, \"peer-certificate\", encodedPeerCertificate);\n\t\t\t\tsend = true;\n\t\t\t} catch (CertificateEncodingException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can't encode certificate\", e);\n\t\t\t}\n\t\t}\n\t\tif (send)\n\t\t\taddOutPacket(command);\n\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.log(Level.FINEST, \"Handshake complete send={0}, command={1}\", new Object[]{send, command});\n\t}\n\n\t@Override\n\tpublic void serviceStarted(XMPPIOService<Object> service) {\n\t\tsuper.serviceStarted(service);\n\n\t\tString id = getUniqueId(service);\n\t\tJID connectionId = getFromAddress(id);\n\n\t\tservice.setConnectionId(connectionId);\n\t\tservice.setProcessors(processors);\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService<Object> service) {\n\t\tboolean result = super.serviceStopped(service);\n\n\t\txmppStreamClosed(service);\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tclientTrustManagerFactory.setProperties(props);\n\t\tif (props.get(SOCKET_CLOSE_WAIT_PROP_KEY) != null) {\n\t\t\tsocket_close_wait_time = (Long) props.get(SOCKET_CLOSE_WAIT_PROP_KEY);\n\t\t}\n\t\tprocessors = XMPPIOProcessorsFactory.updateIOProcessors(this, processors, props);\n\t\tif (props.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for\n\t\t\t// the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\n\t\tString see_other_host_class = (String) props.get(SeeOtherHostIfc\n\t\t\t\t.CM_SEE_OTHER_HOST_CLASS_PROP_KEY);\n\n\t\tsee_other_host_strategy = getSeeOtherHostInstance(see_other_host_class);\n\t\tif (see_other_host_strategy != null) {\n\t\t\tsee_other_host_strategy.setProperties(props);\n\t\t}\n\n\t\tboolean routing_mode = (Boolean) props.get(ROUTINGS_PROP_KEY + \"/\" +\n\t\t\t\tROUTING_MODE_PROP_KEY);\n\n\t\troutings = new RoutingsContainer(routing_mode);\n\n\t\tint idx = (ROUTINGS_PROP_KEY + \"/\").length();\n\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(ROUTINGS_PROP_KEY + \"/\") && !entry.getKey().equals(\n\t\t\t\t\tROUTINGS_PROP_KEY + \"/\" + ROUTING_MODE_PROP_KEY)) {\n\t\t\t\troutings.addRouting(entry.getKey().substring(idx), (String) entry.getValue());\n\t\t\t}    // end of if (entry.getKey().startsWith(ROUTINGS_PROP_KEY + \"/\"))\n\t\t}      // end of for ()\n\t\tif (props.containsKey(TLS_WANT_CLIENT_AUTH_ENABLED_KEY)) {\n\t\t\ttlsWantClientAuthEnabled = (Boolean) props.get(TLS_WANT_CLIENT_AUTH_ENABLED_KEY);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void socketAccepted(XMPPIOService serv, SocketType type) {\n\t\tif (type == SocketType.ssl) {\n\t\t\tClientTrustManagerFactory factory = getClientTrustManagerFactory();\n\t\t\tTrustManager[] x = factory.getManager((XMPPIOService<Object>) serv);\n\t\t\tserv.setX509TrustManagers(x);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tsuper.start();\n\t\tipMonitor = new IPMonitor();\n\t\tipMonitor.start();\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tsuper.stop();\n\t\tipMonitor.stopThread();\n\t}\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(XMPPIOService<Object> serv) {\n\t\tsendTlsHandshakeCompletedToSessionManager(serv);\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(XMPPIOService<Object> serv) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Stream closed: {0}\", serv.getConnectionId());\n\t\t}\n\n\t\t// It might be a Bosh service in which case it is ignored here.\n\t\t// The method may be called more than one time for a single\n\t\t// connection but we want to send a notification just once\n\t\tif ((serv.getXMLNS() == XMLNS) && (serv.getSessionData().get(\"stream-closed\") ==\n\t\t\t\tnull)) {\n\t\t\tserv.getSessionData().put(\"stream-closed\", \"stream-closed\");\n\t\t\tipMonitor.addDisconnect(serv.getRemoteAddress());\n\t\t\tif (serv.getDataReceiver() != null) {\n\t\t\t\tPacket command = Command.STREAM_CLOSED.getPacket(serv.getConnectionId(), serv\n\t\t\t\t\t\t.getDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\tString userJid = serv.getUserJid();\n\n\t\t\t\tif (userJid != null) {\n\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userJid);\n\t\t\t\t}\n\n\t\t\t\t// In case of mass-disconnects, adjust the timeout properly\n\t\t\t\taddOutPacketWithTimeout(command, stoppedHandler, 120l, TimeUnit.SECONDS);\n\t\t\t\tlog.log(Level.FINE, \"Service stopped, sending packet: {0}\", command);\n\n\t\t\t\t//// For testing only.\n\t\t\t\t// System.out.println(\"Service stopped: \" +\n\t\t\t\t// service.getUniqueId());\n\t\t\t\t// Thread.dumpStack();\n\t\t\t\t//// For testing only.\n\t\t\t\t// System.out.println(\"Service stopped: \" +\n\t\t\t\t// service.getUniqueId());\n\t\t\t\t// Thread.dumpStack();\n\t\t\t\tprocessSocketData(serv);\n\n\t\t\t\tif (userJid != null) {\n\t\t\t\t\tcommand = Command.STREAM_FINISHED.getPacket(serv.getConnectionId(), serv\n\t\t\t\t\t\t\t.getDataReceiver(), StanzaType.set, UUID.randomUUID().toString());\n\t\t\t\t\taddOutPacket(command);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.fine(\"Service stopped, before stream:stream received\");\n\t\t\t}\n\t\t\tserv.stop();\n\t\t}\n\t}\n\n\t@Override\n\tpublic String xmppStreamError(XMPPIOService<Object> serv, List<Element> err_el) {\n\t\treturn prepareStreamError(serv, err_el);\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\t@Override\n\tpublic String xmppStreamOpened(XMPPIOService<Object> serv, Map<String,\n\t\t\tString> attribs) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Stream opened: {0}\", attribs);\n\t\t}\n\n\t\tString lang = attribs.get(\"xml:lang\");\n\t\tfinal String hostname = attribs.get(\"to\");\n\t\tfinal String from = attribs.get(\"from\");\n\t\tBareJID fromJID = null;\n\n\t\tif (from != null) {\n\t\t\ttry {\n\t\t\t\tfromJID = BareJID.bareJIDInstance(from);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tlog.log(Level.CONFIG, \"From JID violates RFC6122 (XMPP:Address Format): \", ex);\n\n\t\t\t\treturn prepareStreamError(serv, StreamError.ImproperAddressing, null);\n\t\t\t}    // end of: try-catch\n\t\t}      // end of: if (from != null) {\n\t\tif (lang == null) {\n\t\t\tlang = \"en\";\n\t\t}\n\t\tif (hostname == null) {\n\t\t\treturn prepareStreamError(serv, StreamError.ImproperAddressing, null);\n\t\t}    // end of if (hostname == null)\n\t\tif (!isLocalDomain(hostname)) {\n\t\t\treturn prepareStreamError(serv, StreamError.HostUnknown, hostname);\n\t\t}    // end of if (!hostnames.contains(hostname))\n\t\tif (!isAllowed(serv, hostname)) {\n\t\t\treturn prepareStreamError(serv, StreamError.PolicyViolation, hostname);\n\t\t}\n\t\tInteger redirect_port = (Integer) serv.getSessionData().get(FORCE_REDIRECT_TO_KEY);\n\n\t\tif ((fromJID != null) && (see_other_host_strategy != null)\n\t\t\t\t&& see_other_host_strategy.isEnabled(vHostManager.getVHostItem(fromJID.getDomain()),\n\t\t\t\tSeeOtherHostIfc.Phase.OPEN)) {\n\t\t\tBareJID see_other_host = see_other_host_strategy.findHostForJID(fromJID,\n\t\t\t\t\tgetDefHostName());\n\n\t\t\tif ((see_other_host != null)\n\t\t\t\t\t&& (redirect_port != null\n\t\t\t\t\t|| see_other_host_strategy.isRedirectionRequired(getDefHostName(), see_other_host))) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Sending redirect for {0} to host {1}, connection {2}.\",\n\t\t\t\t\t\t\tnew Object[]{fromJID,\n\t\t\t\t\t\t\t\t\tsee_other_host, serv});\n\t\t\t\t}\n\n\t\t\t\treturn prepareSeeOtherHost(serv, fromJID.getDomain(), see_other_host);\n\t\t\t}\n\t\t}\n\n\t\tString id = (String) serv.getSessionData().get(IOService.SESSION_ID_KEY);\n\n\t\tif (id == null) {\n\t\t\tid = UUID.randomUUID().toString();\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"No Session ID, generating a new one: {0}\", id);\n\t\t\t}\n\t\t\tserv.getSessionData().put(IOService.SESSION_ID_KEY, id);\n\t\t\tserv.setXMLNS(XMLNS);\n\t\t\tserv.getSessionData().put(IOService.HOSTNAME_KEY, hostname);\n\t\t\tserv.setDataReceiver(JID.jidInstanceNS(routings.computeRouting(hostname)));\n\n\t\t\tString streamOpenData = prepareStreamOpen(serv, id, hostname);\n\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Writing raw data to the socket: {0}\", streamOpenData);\n\t\t\t}\n\t\t\twriteRawData(serv, streamOpenData);\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"DONE\");\n\t\t\t}\n\n\t\t\tPacket streamOpen = Command.STREAM_OPENED.getPacket(serv.getConnectionId(), serv\n\t\t\t\t\t.getDataReceiver(), StanzaType.set, this.newPacketId(\"c2s-\"), Command.DataType\n\t\t\t\t\t.submit);\n\n\t\t\tCommand.addFieldValue(streamOpen, \"session-id\", id);\n\t\t\tCommand.addFieldValue(streamOpen, \"hostname\", hostname);\n\t\t\tCommand.addFieldValue(streamOpen, \"xml:lang\", lang);\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Sending a system command to SM: {0}\", streamOpen);\n\t\t\t}\n\t\t\taddOutPacketWithTimeout(streamOpen, startedHandler, 45l, TimeUnit.SECONDS);\n\n\t\t\tsendTlsHandshakeCompletedToSessionManager(serv);\n\t\t\tlog.log(Level.FINER, \"DONE 2\");\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Session ID is: {0}\", id);\n\t\t\t}\n\t\t\twriteRawData(serv, prepareStreamOpen(serv, id, hostname));\n\t\t\tfinal SocketType socket = (SocketType) serv.getSessionData().get(\"socket\");\n\t\t\tboolean ssl = socket.equals(SocketType.ssl);\n\t\t\taddOutPacket(Command.GETFEATURES.getPacket(serv.getConnectionId(), serv\n\t\t\t\t\t.getDataReceiver(), StanzaType.get, (ssl ? \"ssl_\" : \"\") + UUID.randomUUID().toString(), null));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate class StartedHandler\n\t\t\timplements ReceiverTimeoutHandler {\n\t\t@Override\n\t\tpublic void responseReceived(Packet packet, Packet response) {\n\n\t\t\t// We are now ready to ask for features....\n\t\t\tXMPPIOService<Object> serv = getXMPPIOService(response);\n\t\t\tif (serv != null) {\n\t\t\t\tSocketType socket = (SocketType) serv.getSessionData().get(\"socket\");\n\t\t\t\tboolean ssl = socket.equals(SocketType.ssl);\n\t\t\t\taddOutPacket(Command.GETFEATURES.getPacket(packet.getFrom(), packet.getTo(),\n\t\t\t\t\t\tStanzaType.get, (ssl ? \"ssl_\" : \"\") + UUID.randomUUID().toString(), null));\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void timeOutExpired(Packet packet) {\n\n\t\t\t// If we still haven't received confirmation from the SM then\n\t\t\t// the packet either has been lost or the server is overloaded\n\t\t\t// In either case we disconnect the connection.\n\t\t\tlog.log(Level.INFO, \"No response within time limit received for a packet: {0}\",\n\t\t\t\t\tpacket.toStringSecure());\n\n\t\t\tXMPPIOService<Object> serv = getXMPPIOService(packet.getFrom().toString());\n\n\t\t\tif (serv != null) {\n\t\t\t\tserv.stop();\n\t\t\t} else {\n\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\"Attempt to stop non-existen service for packet: {0}, Service already stopped?\",\n\t\t\t\t\t\tpacket);\n\t\t\t}    // end of if (serv != null) else\n\t\t}\n\t}\n\n\tprivate class StoppedHandler\n\t\t\timplements ReceiverTimeoutHandler {\n\t\t@Override\n\t\tpublic void responseReceived(Packet packet, Packet response) {\n\n\t\t\t// Great, nothing to worry about.\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Response for stop received...\");\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void timeOutExpired(Packet packet) {\n\n\t\t\t// Ups, doesn't look good, the server is either oveloaded or lost\n\t\t\t// a packet.\n\t\t\tlog.log(Level.INFO, \"No response within time limit received for a packet: {0}\",\n\t\t\t\t\tpacket.toStringSecure());\n\t\t\taddOutPacketWithTimeout(packet, stoppedHandler, 60l, TimeUnit.SECONDS);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/ClientTrustManagerFactory.java",
    "content": "package tigase.server.xmppclient;\n\nimport java.security.KeyStore;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.TrustManagerFactory;\nimport javax.net.ssl.X509TrustManager;\n\nimport tigase.cert.CertificateEntry;\nimport tigase.cert.CertificateUtil;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.XMPPIOService;\n\npublic class ClientTrustManagerFactory {\n\n\tpublic static final String CA_CERT_PATH = \"clientCertCA\";\n\n\tpublic static final String CERT_REQUIRED_KEY = \"clientCertRequired\";\n\n\tprivate final static char[] EMPTY_PASS = new char[0];\n\n\tprivate static final Logger log = Logger.getLogger(ClientTrustManagerFactory.class.getName());\n\n\tprivate final ArrayList<X509Certificate> acceptedIssuers = new ArrayList<X509Certificate>();\n\n\tprivate TrustManager[] defaultTrustManagers;\n\n\tprivate final TrustManager[] emptyTrustManager;\n\n\tprivate final KeyStore keystore;\n\n\tprivate boolean peerCertificateRequired = false;\n\n\tprivate TrustManagerFactory tmf;\n\n\tprivate final ConcurrentHashMap<VHostItem, TrustManager[]> trustManagers = new ConcurrentHashMap<VHostItem, TrustManager[]>();\n\n\tpublic ClientTrustManagerFactory() {\n\t\tthis.emptyTrustManager = new TrustManager[] { new X509TrustManager() {\n\n\t\t\t@Override\n\t\t\tpublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic X509Certificate[] getAcceptedIssuers() {\n\t\t\t\treturn new X509Certificate[0];\n\t\t\t}\n\t\t} };\n\t\ttry {\n\t\t\tkeystore = KeyStore.getInstance(KeyStore.getDefaultType());\n\t\t\tkeystore.load(null, EMPTY_PASS);\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t\ttry {\n\t\t\tthis.tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\tprotected X509Certificate[] getAcceptedIssuers() {\n\t\treturn acceptedIssuers.toArray(new X509Certificate[] {});\n\t}\n\n\tpublic TrustManager[] getManager(final VHostItem vHost) {\n\t\tTrustManager[] result = trustManagers.get(vHost);\n\n\t\tif (result == null) {\n\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\tlog.finest(\"Creating new TrustManager for VHost \" + vHost);\n\n\t\t\tresult = defaultTrustManagers;\n\t\t\tString path = vHost.getData(CA_CERT_PATH);\n\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\tlog.finest(\"CA cert path=\" + path + \" for VHost \" + vHost);\n\t\t\tif (path != null) {\n\t\t\t\tTrustManager[] tmp = loadTrustedCert(path);\n\t\t\t\tif (tmp != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.finest(\"Using custom TrustManager for VHost \" + vHost);\n\t\t\t\t\tresult = tmp;\n\t\t\t\t\ttrustManagers.put(vHost, result);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (log.isLoggable(Level.FINEST))\n\t\t\tlog.finest(\"Found TrustManager for VHost \" + vHost);\n\n\t\treturn result;\n\t}\n\n\tpublic TrustManager[] getManager(final XMPPIOService<Object> serv) {\n\t\treturn isActive() ? emptyTrustManager : null;\n\t}\n\n\tpublic boolean isActive() {\n\t\treturn acceptedIssuers.size() > 0;\n\t}\n\n\tpublic boolean isTlsNeedClientAuthEnabled(final VHostItem vhost) {\n\t\tBoolean result = vhost.getData(CERT_REQUIRED_KEY);\n\t\tif (result == null)\n\t\t\tresult = peerCertificateRequired;\n\t\treturn result;\n\t}\n\n\tpublic boolean isTlsWantClientAuthEnabled(final VHostItem vhost) {\n\t\tTrustManager[] tmp = getManager(vhost);\n\t\treturn tmp != null && tmp.length > 0;\n\t}\n\n\tprotected TrustManager[] loadTrustedCert(String caCertFile) {\n\t\ttry {\n\t\t\tCertificateEntry certEntry = CertificateUtil.loadCertificate(caCertFile);\n\t\t\tCertificate[] chain = certEntry.getCertChain();\n\n\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\tlog.finest(\"Loaded certificate from file \" + caCertFile + \" : \" + certEntry);\n\n\t\t\tif (chain != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\tlog.finest(\"Loaded cert chain: \" + Arrays.toString(chain));\n\t\t\t\tfor (Certificate cert : chain) {\n\t\t\t\t\tif (cert instanceof X509Certificate) {\n\t\t\t\t\t\tX509Certificate crt = (X509Certificate) cert;\n\t\t\t\t\t\tString alias = crt.getSubjectX500Principal().getName();\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\t\tlog.finest(\"Adding certificate to keystore: alias=\" + alias + \"; cert=\" + crt);\n\n\t\t\t\t\t\tkeystore.setCertificateEntry(alias, crt);\n\t\t\t\t\t\tacceptedIssuers.add(crt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmf.init(keystore);\n\t\t\treturn tmf.getTrustManagers();\n\t\t\t// this.saslExternalAvailable = true;\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't create TrustManager with certificate from file.\", e);\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic void setProperties(Map<String, Object> props) {\n\t\tif (props.containsKey(CERT_REQUIRED_KEY)) {\n\t\t\tthis.peerCertificateRequired = (Boolean) props.get(CERT_REQUIRED_KEY);\n\t\t}\n\t\tif (props.containsKey(CA_CERT_PATH)) {\n\t\t\tthis.defaultTrustManagers = loadTrustedCert((String) props.get(CA_CERT_PATH));\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/IPMonitor.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppclient;\n\nimport java.util.LinkedHashSet;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Logger;\n\n/**\n * Created: Sep 11, 2009 12:39:04 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class IPMonitor extends Thread {\n\n  private static final Logger log =\n    Logger.getLogger(IPMonitor.class.getName());\n\n\tprivate boolean stopped = false;\n\tprivate static final int MAX_SIZE = 50;\n\tprivate static final long CLEANUP_RATE = 10000;\n\tprivate static final long DISC_THRESHOLD = 200;\n\tprivate long[] ip_cnts = new long[MAX_SIZE];\n\tprivate LinkedHashSet<String> ips = new LinkedHashSet<String>();\n\tprivate LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();\n\tprivate Timer timer = new Timer(\"IPMonitor Timer\");\n\n\tpublic IPMonitor() {\n\t\tsuper();\n\t\tsetName(IPMonitor.class.getSimpleName());\n\t\tsetDaemon(true);\n\t\tfor (int i = 0; i < ip_cnts.length; i++) {\n\t\t\tip_cnts[i] = 0;\n\t\t}\n\t}\n\n\tpublic void addDisconnect(String ip) {\n\t\tqueue.offer(ip);\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\ttimer.scheduleAtFixedRate(new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tfor (String ip : ips) {\n\t\t\t\t\tint idx = Math.abs(ip.hashCode() % ip_cnts.length);\n\t\t\t\t\tif (ip_cnts[idx] > DISC_THRESHOLD) {\n\t\t\t\t\t\tlog.warning(\"Many disconnects for IP: \" + ip + \" - \" + ip_cnts[idx]);\n\t\t\t\t\t}\n\t\t\t\t\tip_cnts[idx] = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}, CLEANUP_RATE, CLEANUP_RATE);\n\t\twhile (!stopped) {\n\t\t\ttry {\n\t\t\t\tString ip = queue.poll(10, TimeUnit.SECONDS);\n\t\t\t\tif (ip != null) {\n\t\t\t\t\tint idx = Math.abs(ip.hashCode()) % ip_cnts.length;\n\t\t\t\t\t++ip_cnts[idx];\n\t\t\t\t\tif (ips.size() < MAX_SIZE) {\n\t\t\t\t\t\tips.add(ip);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.warning(\"Error processing queue: \" + e);\n\t\t\t}\n\t\t}\n\t\ttimer.cancel();\n\t}\n\n\tpublic void stopThread() {\n\t\tstopped = true;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHost.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.vhosts.VHostManagerIfc;\nimport tigase.xml.Element;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.xmpp.JID;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Default and basic implementation of SeeOtherHost returning same host as the\n * initial one\n *\n * @author Wojtek\n */\npublic class SeeOtherHost implements SeeOtherHostIfc {\n\n\tprivate static final Logger log = Logger.getLogger(SeeOtherHost.class.getName());\n\tpublic static final String REDIRECTION_ENABLED = \"see-other-host-redirect-enabled\";\n\t\n\tprotected List<BareJID> defaultHost = null;\n\tprivate ArrayList<Phase> active = new ArrayList<Phase>();\n\tprotected VHostManagerIfc vHostManager = null;\n\n\t@Override\n\tpublic BareJID findHostForJID(BareJID jid, BareJID host) {\n\t\tif (defaultHost != null && !defaultHost.isEmpty()) {\n\t\t\treturn defaultHost.get( 0 );\n\t\t} else {\n\t\t\treturn host;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tList<VHostItem.DataType> types = new ArrayList<VHostItem.DataType>();\n\t\ttypes.add(new VHostItem.DataType( REDIRECTION_ENABLED, \"see-other-host redirection enabled\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Boolean.class, Boolean.TRUE ) );\n\t\tVHostItem.registerData( types );\n\t}\n\n\t@Override\n\tpublic void setProperties(final Map<String, Object> props) {\n\t\tif (props.containsKey(SeeOtherHostIfc.CM_SEE_OTHER_HOST_ACTIVE)) {\n\t\t\t\n\t\t\tString[] phase =  ((String)props.get(SeeOtherHostIfc.CM_SEE_OTHER_HOST_ACTIVE)).split( \";\");\n\t\t\tfor ( String ph : phase) {\n\t\t\t\ttry {\n\t\t\t\t\tactive.add( Phase.valueOf( ph ) );\n\t\t\t\t} catch ( IllegalArgumentException e ) {\n\t\t\t\t\tlog.log( Level.FINEST, \"unsupported phase configuration item: \" + ph + e  );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tactive.add( Phase.OPEN );\n\t\t}\n\t\tlog.log( Level.CONFIG, props.get( \"component-id\" ) + \" :: see-other-redirect active in: \" + Arrays.asList( active ) );\n\n\t\tif ((props.containsKey(SeeOtherHostIfc.CM_SEE_OTHER_HOST_DEFAULT_HOST))\n\t\t\t&& !props.get(SeeOtherHostIfc.CM_SEE_OTHER_HOST_DEFAULT_HOST).toString().trim().isEmpty()) {\n\t\t\tdefaultHost = new ArrayList<BareJID>();\n\t\t\tfor (String host : ((String) props.get(SeeOtherHostIfc.CM_SEE_OTHER_HOST_DEFAULT_HOST)).split(\",\")) {\n\t\t\t\ttry {\n\t\t\t\t\tdefaultHost.add(BareJID.bareJIDInstance(host));\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.CONFIG, \"From JID violates RFC6122 (XMPP:Address Format): \", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCollections.sort(defaultHost);\n\t\t} else {\n\t\t\tdefaultHost = null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setNodes(List<JID> nodes) {\n\t\t log.log(Level.CONFIG, \"Action invalid for current implementation.\");\n\t}\n\n\t@Override\n\tpublic boolean isEnabled(VHostItem vHost, Phase ph) {\n\t\treturn (boolean) vHost.getData( REDIRECTION_ENABLED )\n\t\t\t\t\t && active.contains( ph );\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHostDB.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author:$\n * $Date$\n *\n */\npackage tigase.server.xmppclient;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xmpp.BareJID;\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.UserNotFoundException;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Extended implementation of SeeOtherHost using redirect information from\n * database\n * \n */\npublic class SeeOtherHostDB extends SeeOtherHostHashed {\n\n\tprivate static final Logger log = Logger.getLogger(SeeOtherHostDB.class.getName());\n\n\tpublic static final String SEE_OTHER_HOST_TABLE = \"tig_see_other_hosts\";\n\tpublic static final String SEE_OTHER_HOST_DB_URL_KEY = CM_SEE_OTHER_HOST_CLASS_PROP_KEY\n\t\t\t+ \"/\" + \"db-url\";\n\tpublic static final String SEE_OTHER_HOST_DB_QUERY_KEY =\n\t\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"get-host-query\";\n\tpublic static final String DB_GET_ALL_DATA_DB_QUERY_KEY =\n\t\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"get-all-data-query\";\n\tpublic static final String GET_ALL_QUERY_TIMEOUT_QUERY_KEY =\n\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"get-all-query-timeout\";\n\n\t\n\tpublic static final String SERIAL_ID = \"sid\";\n\tpublic static final String USER_ID = \"uid\";\n\tpublic static final String NODE_ID = \"node_id\";\n\n\tpublic static final String DEF_DB_GET_HOST_QUERY = \" select * from tig_users, \"\n\t\t\t+ SEE_OTHER_HOST_TABLE + \" where tig_users.uid = \" + SEE_OTHER_HOST_TABLE + \".\"\n\t\t\t+ USER_ID + \" and user_id = ?\";\n\n\tprivate static final String DEF_DB_GET_ALL_DATA_QUERY =\n\t\t\t\"select user_id, node_id from tig_users, \" + SEE_OTHER_HOST_TABLE\n\t\t\t\t\t+ \" where tig_users.uid = \" + SEE_OTHER_HOST_TABLE + \".\" + USER_ID;\n\n\tprivate static final String CREATE_STATS_TABLE = \"create table \" + SEE_OTHER_HOST_TABLE\n\t\t\t+ \" ( \" + SERIAL_ID + \" serial,\" + USER_ID + \" bigint NOT NULL, \"\n\t\t\t+ NODE_ID + \" varchar(2049) NOT NULL, \" + \" primary key (\" + SERIAL_ID + \"), \"\n\t\t\t+ \" constraint tig_see_other_host_constr foreign key (\" + USER_ID\n\t\t\t+ \") references tig_users (\" + USER_ID + \")\" + \")\";\n\n\tprivate static final String DERBY_CREATE_STATS_TABLE = \"create table \" + SEE_OTHER_HOST_TABLE\n\t\t\t+ \" ( \" + SERIAL_ID + \" bigint generated by default as identity not null,\" + USER_ID + \" bigint  NOT NULL, \"\n\t\t\t+ NODE_ID + \" varchar(2049) NOT NULL, \" + \" primary key (\" + SERIAL_ID + \"), \"\n\t\t\t+ \" constraint tig_see_other_host_constr foreign key (\" + USER_ID\n\t\t\t+ \") references tig_users (\" + USER_ID + \")\" + \")\";\n\n\tprivate static final String SQLSERVER_CREATE_STATS_TABLE = \"create table \" + SEE_OTHER_HOST_TABLE\n\t\t\t+ \" ( \" + SERIAL_ID + \" [bigint] IDENTITY(1,1),\" + USER_ID + \" bigint NOT NULL, \"\n\t\t\t+ NODE_ID + \" nvarchar(2049) NOT NULL, \" + \" primary key (\" + SERIAL_ID + \"), \"\n\t\t\t+ \" constraint tig_see_other_host_constr foreign key (\" + USER_ID\n\t\t\t+ \") references tig_users (\" + USER_ID + \")\" + \")\";\n\n\n\tprivate static final int DEF_QUERY_TIME_OUT = 0;\n\n\tprivate String get_host_query = DEF_DB_GET_HOST_QUERY;\n\tprivate String get_all_data_query = DEF_DB_GET_ALL_DATA_QUERY;\n\tprivate String get_host_DB_url = \"\";\n\n\tprivate DataRepository data_repo = null;\n\tprivate Map<BareJID, BareJID> redirectsMap =\n\t\t\tnew ConcurrentSkipListMap<BareJID, BareJID>();\n\n\t// Methods\n\n\t@Override\n\tpublic BareJID findHostForJID(BareJID jid, BareJID host) {\n\n\t\t\n\t\t\n\t\tBareJID see_other_host = redirectsMap.get(jid);\n\t\tif (see_other_host != null) {\n\t\t\treturn see_other_host;\n\t\t} else {\n\t\t\tsee_other_host = host;\n\t\t}\n\n\t\ttry {\n\t\t\tsee_other_host = queryDB(jid);\n\t\t} catch (Exception ex) {\n\t\t\tsee_other_host = super.findHostForJID(jid, host);\n\t\t\tlog.log(Level.SEVERE, \"DB lookup failed, fallback to SeeOtherHostHashed: \", ex);\n\t\t}\n\n\t\treturn see_other_host;\n\t}\n\n\t@Override\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\t\tsuper.getDefaults(defs, params);\n\n\t\tif (params.containsKey(\"--user-db-uri\")) {\n\t\t\tget_host_DB_url = (String) params.get(\"--user-db-uri\");\n\t\t}\n\t\tdefs.put(SEE_OTHER_HOST_DB_URL_KEY, get_host_DB_url);\n\t\tdefs.put(SEE_OTHER_HOST_DB_QUERY_KEY, get_host_query);\n\t\tdefs.put(DB_GET_ALL_DATA_DB_QUERY_KEY, get_all_data_query);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) {\n\t\tsuper.setProperties(props);\n\n\t\tif ((props.containsKey(SEE_OTHER_HOST_DB_URL_KEY))\n\t\t\t\t&& !props.get(SEE_OTHER_HOST_DB_URL_KEY).toString().trim().isEmpty()) {\n\t\t\tget_host_DB_url = props.get(SEE_OTHER_HOST_DB_URL_KEY).toString().trim();\n\t\t}\n\t\tprops.put(SEE_OTHER_HOST_DB_URL_KEY, get_host_DB_url);\n\n\t\tif ((props.containsKey(SEE_OTHER_HOST_DB_QUERY_KEY))\n\t\t\t\t&& !props.get(SEE_OTHER_HOST_DB_QUERY_KEY).toString().trim().isEmpty()) {\n\t\t\tget_host_query = props.get(SEE_OTHER_HOST_DB_QUERY_KEY).toString().trim();\n\t\t}\n\t\tprops.put(SEE_OTHER_HOST_DB_QUERY_KEY, get_host_query);\n\n\t\tif ((props.containsKey(DB_GET_ALL_DATA_DB_QUERY_KEY))\n\t\t\t\t&& !props.get(DB_GET_ALL_DATA_DB_QUERY_KEY).toString().trim().isEmpty()) {\n\t\t\tget_all_data_query = props.get(DB_GET_ALL_DATA_DB_QUERY_KEY).toString().trim();\n\t\t}\n\t\tprops.put(DB_GET_ALL_DATA_DB_QUERY_KEY, get_all_data_query);\n\n\t\ttry {\n\t\t\tinitRepository(get_host_DB_url, null);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"Cannot initialize connection to database: \", ex);\n\t\t}\n\t}\n\n\tpublic void initRepository(String conn_str, Map<String, String> map)\n\t\t\tthrows SQLException, ClassNotFoundException, IllegalAccessException,\n\t\t\tInstantiationException, DBInitException {\n\n\t\tlog.log(Level.INFO, \"Initializing dbAccess for db connection url: {0}\", conn_str);\n\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, map);\n\n\t\tcheckDB();\n\n\t\tdata_repo.initPreparedStatement(get_host_query, get_host_query);\n\t\tdata_repo.initPreparedStatement(get_all_data_query, get_all_data_query);\n\t\tqueryAllDB();\n\t}\n\n\t/**\n\t * Performs database check, creates missing schema if necessary\n\t *\n\t * @throws SQLException\n\t */\n\tprivate void checkDB() throws SQLException {\n\t\tDataRepository.dbTypes databaseType = data_repo.getDatabaseType();\n\t\tswitch ( databaseType ) {\n\t\t\tcase derby:\n\t\t\t\tdata_repo.checkTable( SEE_OTHER_HOST_TABLE, DERBY_CREATE_STATS_TABLE );\n\t\t\t\tbreak;\n\t\t\tcase jtds:\n\t\t\tcase sqlserver:\n\t\t\t\tdata_repo.checkTable( SEE_OTHER_HOST_TABLE, SQLSERVER_CREATE_STATS_TABLE );\n\t\t\t\tbreak;\n\t\t\tcase postgresql:\n\t\t\tcase mysql:\n\t\t\tdefault:\n\t\t\t\tdata_repo.checkTable( SEE_OTHER_HOST_TABLE, CREATE_STATS_TABLE );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate BareJID queryDB(BareJID user) throws UserNotFoundException, SQLException,\n\t\t\tTigaseStringprepException {\n\n\t\tPreparedStatement get_host = data_repo.getPreparedStatement(user, get_host_query);\n\n\t\tResultSet rs = null;\n\n\t\tsynchronized (get_host) {\n\t\t\ttry {\n\t\t\t\tget_host.setString(1, user.toString());\n\n\t\t\t\trs = get_host.executeQuery();\n\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\treturn BareJID.bareJIDInstance(rs.getString(NODE_ID));\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UserNotFoundException(\"Item does not exist for user: \" + user);\n\t\t\t\t} // end of if (isnext) else\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void queryAllDB() throws SQLException {\n\n\t\tPreparedStatement get_all = data_repo.getPreparedStatement(null, get_all_data_query);\n\t\tget_all.setQueryTimeout(DEF_QUERY_TIME_OUT);\n\n\t\tResultSet rs = null;\n\n\t\tsynchronized (get_all) {\n\t\t\ttry {\n\t\t\t\trs = get_all.executeQuery();\n\n\t\t\t\twhile (rs.next()) {\n\t\t\t\t\tString user_jid = rs.getString(\"user_id\");\n\t\t\t\t\tString node_jid = rs.getString(NODE_ID);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tBareJID user = BareJID.bareJIDInstance(user_jid);\n\t\t\t\t\t\tBareJID node = BareJID.bareJIDInstance(node_jid);\n\t\t\t\t\t\tredirectsMap.put(user, node);\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.warning(\"Invalid user's or node's JID: \" + user_jid + \", \" + node_jid);\n\t\t\t\t\t}\n\t\t\t\t} // end of if (isnext) else\n\t\t\t} finally {\n\t\t\t\tdata_repo.release(null, rs);\n\t\t\t}\n\t\t}\n\t\t\n\t\tlog.info(\"Loaded \" + redirectsMap.size() + \" redirect definitions from database.\");\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHostDualIP.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport tigase.cluster.ClusterConnectionManager.REPO_ITEM_UPDATE_TYPE;\n\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.disteventbus.EventHandler;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.sql.SQLException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.cluster.ClusterConnectionManager.EVENTBUS_REPO_ITEM_EVENT_XMLNS;\nimport static tigase.cluster.ClusterConnectionManager.REPO_ITEM_EVENT_NAME;\nimport static tigase.server.xmppclient.SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_KEY;\n\n/**\n * Extended implementation of SeeOtherHost using redirect information from\n * database based on cluster_nodes table.\n *\n */\npublic class SeeOtherHostDualIP\n\t\textends SeeOtherHostHashed\n\t\timplements EventHandler {\n\n\tprivate static final Logger log = Logger.getLogger( SeeOtherHostDualIP.class.getName() );\n\n\tpublic static final String SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t = CM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"fallback-redirection-host\";\n\n\tprivate BareJID fallback_host = null;\n\n\tpublic static final String SEE_OTHER_HOST_DATA_SOURCE_KEY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t = CM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"data-source\";\n\tpublic static final String SEE_OTHER_HOST_DATA_SOURCE_VALUE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t = SeeOtherHostDualIPSQLRepository.class.getName();\n\n\tpublic static final String SEE_OTHER_HOST_DB_URL_KEY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t = CM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"db-url\";\n\n\tprotected String get_host_DB_url = \"\";\n\n\tprivate DualIPRepository repo = null;\n\n\tprivate final Map<BareJID, BareJID> redirectsMap = Collections.synchronizedMap(new HashMap());\n\n\tprivate final EventBus eventBus = EventBusFactory.getInstance();\n\n\t@Override\n\tpublic BareJID findHostForJID( BareJID jid, BareJID host ) {\n\n\t\t// get default host identification\n\t\tBareJID see_other_host = super.findHostForJID( jid, host );\n\n\t\t// lookup resolution in redirection map\n\t\tBareJID redirection;\n\t\tredirection = redirectsMap.get( see_other_host );\n\n\t\tif ( redirection == null ){\n\t\t\t// let's try querying the table again\n\t\t\treloadRedirection();\n\t\t\tredirection = redirectsMap.get( see_other_host );\n\t\t}\n\n\t\tif ( redirection == null && fallback_host != null ){\n\t\t\t// let's use default fallback redirection if present\n\t\t\tredirection = fallback_host;\n\t\t}\n\n\t\treturn redirection;\n\t}\n\n\t@Override\n\tpublic void onEvent( String name, String xmlns, Element event ) {\n\n\t\tElement child = event.getChild( \"repo-item\" );\n\n\t\tString actionAttr = child.getAttributeStaticStr( \"action\" );\n\t\tString hostnameStr = child.getAttributeStaticStr( \"hostname\" );\n\t\tString secondaryStr = child.getAttributeStaticStr( \"secondary\" );\n\n\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\tlog.log( Level.FINE, \"Procesing clusterItem event: {0} with action: {1}, hostname: {2}, secondary: {3}\",\n\t\t\t\t\t\t\t new Object[] { event, actionAttr, hostnameStr, secondaryStr } );\n\t\t}\n\n\t\tREPO_ITEM_UPDATE_TYPE action;\n\t\tif ( null != actionAttr ){\n\t\t\taction = REPO_ITEM_UPDATE_TYPE.valueOf( actionAttr );\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tBareJID hostname;\n\t\tif ( null != hostnameStr ){\n\t\t\thostname = BareJID.bareJIDInstanceNS( hostnameStr );\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tBareJID secondary = null;\n\t\tif ( null != secondaryStr && !secondaryStr.trim().isEmpty() ){\n\t\t\tsecondary = BareJID.bareJIDInstanceNS( secondaryStr );\n\t\t}\n\n\t\tBareJID oldItem;\n\t\tswitch ( action ) {\n\t\t\tcase ADDED:\n\t\t\tcase UPDATED:\n\t\t\t\toldItem = redirectsMap.put( hostname, secondary );\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"Redirection item :: hostname: {0}, secondary: {1}, added/updated! Replaced: {2}\",\n\t\t\t\t\t\t\t\t\t new Object[] { hostname, secondary, oldItem } );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase REMOVED:\n\t\t\t\toldItem = redirectsMap.remove( hostname );\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"Redirection item :: hostname: {0}, {1}\",\n\t\t\t\t\t\t\t\t\t new Object[] { hostname, ( oldItem != null ? \"removed\" : \"was not present in redirection map\" ) } );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setNodes( List<JID> connectedNodes ) {\n\t\tsuper.setNodes( connectedNodes );\n\n\t\treloadRedirection();\n\t}\n\n\t@Override\n\tpublic void getDefaults( Map<String, Object> defs, Map<String, Object> params ) {\n\t\tsuper.getDefaults( defs, params );\n\n\t\tif ( params.containsKey( \"--user-db-uri\" ) ){\n\t\t\tget_host_DB_url = (String) params.get( \"--user-db-uri\" );\n\t\t} else if ( params.containsKey( \"--\" + SEE_OTHER_HOST_DB_URL_KEY ) ){\n\t\t\tget_host_DB_url = (String) params.get( \"--\" + SEE_OTHER_HOST_DB_URL_KEY );\n\t\t}\n\t\tdefs.put( SEE_OTHER_HOST_DB_URL_KEY, get_host_DB_url );\n\n\t\tif ( params.containsKey( \"--\" + SEE_OTHER_HOST_DATA_SOURCE_KEY ) ){\n\t\t\tdefs.put( SEE_OTHER_HOST_DATA_SOURCE_KEY, params.get( \"--\" + SEE_OTHER_HOST_DATA_SOURCE_KEY ) );\n\t\t}\n\n\t\tif ( params.containsKey( \"--\" + SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY ) ){\n\t\t\tBareJID bareJIDInstance;\n\t\t\ttry {\n\t\t\t\tbareJIDInstance = BareJID.bareJIDInstance( (String) params.get( \"--\" + SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY ) );\n\t\t\t\tfallback_host = bareJIDInstance;\n\t\t\t\tdefs.put( SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY, fallback_host );\n\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\tlog.log( Level.SEVERE, \"Problem creating default redirection JID\", ex );\n\t\t\t}\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void setProperties( Map<String, Object> props ) {\n\t\tsuper.setProperties( props );\n\n\t\tif ( ( props.containsKey( SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY ) )\n\t\t\t\t && !props.get( SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY ).toString().trim().isEmpty() ){\n\n\t\t\tBareJID bareJIDInstance;\n\t\t\ttry {\n\t\t\t\tbareJIDInstance = BareJID.bareJIDInstance( (String) props.get( SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY ).toString().trim() );\n\t\t\t\tfallback_host = bareJIDInstance;\n\t\t\t\tprops.put( SEE_OTHER_HOST_FALLBACK_REDIRECTION_KEY, fallback_host );\n\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\tlog.log( Level.SEVERE, \"Problem creating default redirection JID\", ex );\n\t\t\t}\n\t\t}\n\n\t\tif ( ( props.containsKey( SEE_OTHER_HOST_DB_URL_KEY ) )\n\t\t\t\t && !props.get( SEE_OTHER_HOST_DB_URL_KEY ).toString().trim().isEmpty() ){\n\t\t\tget_host_DB_url = props.get( SEE_OTHER_HOST_DB_URL_KEY ).toString().trim();\n\t\t}\n\t\tprops.put( SEE_OTHER_HOST_DB_URL_KEY, get_host_DB_url );\n\n\t\tString repo_class = (String) props.get( SEE_OTHER_HOST_DATA_SOURCE_KEY );\n\n\t\ttry {\n\t\t\tClass<?> cls = null;\n\t\t\tif ( null == repo_class ){\n\t\t\t\tcls = RepositoryFactory.getRepoClass( DualIPRepository.class, get_host_DB_url );\n\t\t\t} else if ( \"eventbus\".equals( repo_class.trim().toLowerCase() ) ){\n\t\t\t\tif ( log.isLoggable( Level.CONFIG ) ){\n\t\t\t\t\tlog.log( Level.CONFIG, \"Using Evenbus as a source of DualIP data\" );\n\t\t\t\t}\n\t\t\t\teventBus.addHandler( REPO_ITEM_EVENT_NAME, EVENTBUS_REPO_ITEM_EVENT_XMLNS, this );\n\t\t\t} else {\n\t\t\t\tcls = ModulesManagerImpl.getInstance().forName( repo_class );\n\t\t\t}\n\n\t\t\tif ( null != cls ){\n\n\t\t\t\tif ( log.isLoggable( Level.CONFIG ) ){\n\t\t\t\t\tlog.log( Level.CONFIG, \"Using {0} class for DualIP repository\", cls );\n\t\t\t\t}\n\t\t\t\tDualIPRepository repoTmp = (DualIPRepository) cls.newInstance();\n\n\t\t\t\tif ( repo == null ){\n\t\t\t\t\trepo = repoTmp;\n\t\t\t\t}\n\n\t\t\t\trepo.setProperties( props );\n\n\t\t\t\trepo.initRepository( get_host_DB_url, null );\n\n\t\t\t\treloadRedirection();\n\t\t\t}\n\n\t\t} catch ( Exception ex ) {\n\t\t\tlog.log( Level.SEVERE, \"Cannot initialize connection to database: \", ex );\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isRedirectionRequired( BareJID defaultHost, BareJID redirectionHost ) {\n\t\treturn redirectsMap.get( defaultHost ) != null\n\t\t\t\t\t ? !redirectsMap.get( defaultHost ).equals( redirectionHost )\n\t\t\t\t\t : false;\n\t}\n\n\tprotected void reloadRedirection() {\n\t\t// reload redirections from\n\t\tif ( null == repo ){\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tfinal Map<BareJID, BareJID> queryAllDB = repo.queryAllDB();\n\t\t\tif ( null != queryAllDB ){\n\t\t\t\tredirectsMap.clear();\n\t\t\t\tredirectsMap.putAll( queryAllDB );\n\t\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\t\tlog.log( Level.FINE, \"Reloaded redirection items: \" + Arrays.asList( redirectsMap ) );\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( Exception ex ) {\n\t\t\tlog.log( Level.SEVERE, \"Reloading redirection items failed: \", ex );\n\t\t}\n\t}\n\n\tpublic interface DualIPRepository extends Repository {\n\n\t\tpublic static final String HOSTNAME_ID = \"hostname\";\n\t\tpublic static final String SECONDARY_HOSTNAME_ID = \"secondary\";\n\n\t\tMap<BareJID, BareJID> queryAllDB() throws SQLException;\n\n\t\tvoid setProperties( Map<String, Object> props );\n\n\t\tvoid getDefaults( Map<String, Object> defs, Map<String, Object> params );\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHostDualIPSQLRepository.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.server.xmppclient;\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.Repository;\nimport tigase.db.RepositoryFactory;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.TigaseStringprepException;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n *\n * @author Wojtek\n */\n@Repository.Meta( supportedUris = { \"jdbc:[^:]+:.*\" } )\nclass SeeOtherHostDualIPSQLRepository implements SeeOtherHostDualIP.DualIPRepository {\n\n\tpublic static final String CLUSTER_NODES_TABLE = \"cluster_nodes\";\n\tpublic static final String DB_GET_ALL_DATA_DB_QUERY_KEY = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"get-all-data-query\";\n\tpublic static final String GET_ALL_QUERY_TIMEOUT_QUERY_KEY = SeeOtherHostIfc.CM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"get-all-query-timeout\";\n\tprivate static final String DEF_DB_GET_ALL_DATA_QUERY = \"select * from \" + CLUSTER_NODES_TABLE;\n\tprivate static final int DEF_QUERY_TIME_OUT = 10;\n\tprivate String get_all_data_query = DEF_DB_GET_ALL_DATA_QUERY;\n\tprivate int query_timeout = DEF_QUERY_TIME_OUT;\n\tprivate DataRepository data_repo = null;\n\n\tprivate static final Logger log = Logger.getLogger(SeeOtherHostDualIPSQLRepository.class.getName() );\n\n\t@Override\n\tpublic void getDefaults( Map<String, Object> defs, Map<String, Object> params ) {\n\t\tif ( params.containsKey( \"--\" + DB_GET_ALL_DATA_DB_QUERY_KEY ) ){\n\t\t\tget_all_data_query = (String) params.get( \"--\" + DB_GET_ALL_DATA_DB_QUERY_KEY );\n\t\t}\n\t\tdefs.put( DB_GET_ALL_DATA_DB_QUERY_KEY, get_all_data_query );\n\t\tif ( params.containsKey( \"--\" + GET_ALL_QUERY_TIMEOUT_QUERY_KEY ) ){\n\t\t\tquery_timeout = Integer.parseInt( (String) params.get( \"--\" + GET_ALL_QUERY_TIMEOUT_QUERY_KEY ) );\n\t\t}\n\t\tdefs.put( GET_ALL_QUERY_TIMEOUT_QUERY_KEY, query_timeout );\n\t}\n\n\t@Override\n\tpublic void initRepository( String conn_str, Map<String, String> map ) throws DBInitException {\n\t\ttry {\n\t\t\tlog.log( Level.INFO, \"Initializing dbAccess for db connection url: {0}\", conn_str );\n\t\t\tdata_repo = RepositoryFactory.getDataRepository( null, conn_str, map );\n\t\t\tcheckDB();\n\t\t\tdata_repo.initPreparedStatement( get_all_data_query, get_all_data_query );\n\t\t} catch ( ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException ex ) {\n\t\t\tthrow new DBInitException( \"Repository initialization failed\", ex );\n\t\t}\n\t}\n\n\t/**\n\t * Performs database check\n\t *\n\t * @throws SQLException\n\t */\n\tprivate void checkDB() throws SQLException {\n\t\tif ( !data_repo.checkTable( CLUSTER_NODES_TABLE ) ){\n\t\t\tthrow new SQLException( \"Nodes redirection table doesn't exits!\" );\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<BareJID, BareJID> queryAllDB() throws SQLException {\n\t\tMap<BareJID, BareJID> result = new ConcurrentSkipListMap<BareJID, BareJID>();\n\t\tif ( data_repo == null ){\n\t\t\treturn null;\n\t\t}\n\t\tPreparedStatement get_all = data_repo.getPreparedStatement( null, get_all_data_query );\n\t\tget_all.setQueryTimeout( DEF_QUERY_TIME_OUT );\n\t\tResultSet rs = null;\n\t\tsynchronized ( get_all ) {\n\t\t\ttry {\n\t\t\t\trs = get_all.executeQuery();\n\t\t\t\twhile ( rs.next() ) {\n\t\t\t\t\tString user_jid = rs.getString( HOSTNAME_ID );\n\t\t\t\t\tString node_jid = rs.getString( SECONDARY_HOSTNAME_ID );\n\t\t\t\t\ttry {\n\t\t\t\t\t\tBareJID hostname_hid = BareJID.bareJIDInstance( user_jid );\n\t\t\t\t\t\tBareJID secondary = BareJID.bareJIDInstance( node_jid );\n\t\t\t\t\t\tresult.put( hostname_hid, secondary );\n\t\t\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\t\t\tlog.warning( \"Invalid host or secondary hostname JID: \" + user_jid + \", \" + node_jid );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdata_repo.release( null, rs );\n\t\t\t}\n\t\t}\n\t\tlog.info( \"Loaded \" + result.size() + \" redirect definitions from database.\" );\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void setProperties( Map<String, Object> props ) {\n\t\tif ( ( props.containsKey( DB_GET_ALL_DATA_DB_QUERY_KEY ) ) && !props.get( DB_GET_ALL_DATA_DB_QUERY_KEY ).toString().trim().isEmpty() ){\n\t\t\tget_all_data_query = props.get( DB_GET_ALL_DATA_DB_QUERY_KEY ).toString().trim();\n\t\t}\n\t\tprops.put( DB_GET_ALL_DATA_DB_QUERY_KEY, get_all_data_query );\n\t\tif ( ( props.containsKey( GET_ALL_QUERY_TIMEOUT_QUERY_KEY ) ) && !props.get( GET_ALL_QUERY_TIMEOUT_QUERY_KEY ).toString().trim().isEmpty() ){\n\t\t\tquery_timeout = Integer.parseInt( props.get( GET_ALL_QUERY_TIMEOUT_QUERY_KEY ).toString().trim() );\n\t\t}\n\t\tprops.put( GET_ALL_QUERY_TIMEOUT_QUERY_KEY, query_timeout );\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHostHashed.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author:$\n * $Date$\n *\n */\npackage tigase.server.xmppclient;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Arrays;\nimport tigase.xmpp.BareJID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.logging.Logger;\nimport tigase.xmpp.JID;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Default implementation for cluster environment of SeeOtherHostIfc returning\n * redirect host based on the hash value of the user's JID\n *\n * @author Wojtek\n */\n//public class SeeOtherHostHashed implements SeeOtherHostIfc {\npublic class SeeOtherHostHashed extends SeeOtherHost {\n\n//\tprotected List<BareJID> defaultHost = null;\n\tprotected List<BareJID> connectedNodes = new CopyOnWriteArrayList<BareJID>();\n\tprivate static final Logger log = Logger.getLogger(SeeOtherHostHashed.class.getName());\n\n\t@Override\n\tpublic BareJID findHostForJID(BareJID jid, BareJID host) {\n\t\tint hash = Math.abs(jid.hashCode());\n\t\tif (defaultHost !=null\n\t\t\t&& !defaultHost.isEmpty()\n\t\t\t&& connectedNodes.contains( defaultHost.get( hash % defaultHost.size() ) ) ) {\n\t\t\t\treturn defaultHost.get( hash % defaultHost.size() );\n\t\t} else if (connectedNodes.size() > 0 ) {\n\t\t\treturn connectedNodes.get( hash % connectedNodes.size());\n\t\t} else {\n\t\t\treturn host;\n\t\t}\n\t}\n\n\n\t@Override\n\tpublic void setNodes(List<JID> connectedNodes) {\n\t\tsynchronized (this) {\n\t\t\tJID[] arr_in = connectedNodes.toArray(new JID[connectedNodes.size()]);\n\t\t\tBareJID[] arr_out = new BareJID[arr_in.length];\n\t\t\t\n\t\t\tfor (int i=0; i<arr_in.length; i++) {\n\t\t\t\tarr_out[i] = BareJID.bareJIDInstanceNS(null, arr_in[i].getDomain());\n\t\t\t}\n\n\t\t\tArrays.sort(arr_out);\n\t\t\tthis.connectedNodes = new CopyOnWriteArrayList<BareJID>(arr_out);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/SeeOtherHostIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author:$\n * $Date$\n *\n */\n\npackage tigase.server.xmppclient;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.vhosts.VHostItem;\nimport tigase.vhosts.VHostManagerIfc;\nimport tigase.xml.Element;\n\nimport java.util.List;\nimport java.util.Map;\nimport tigase.xmpp.JID;\n\n/**\n * @author Wojtek\n */\npublic interface SeeOtherHostIfc {\n\tpublic static final String CM_SEE_OTHER_HOST_CLASS_PROPERTY = \"--cm-see-other-host\";\n\n\tpublic static final String CM_SEE_OTHER_HOST_CLASS_PROP_KEY = \"cm-see-other-host\";\n\n\tpublic static final String CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL =\n\t\t\t\"tigase.server.xmppclient.SeeOtherHost\";\n\tpublic static final String CM_SEE_OTHER_HOST_CLASS_PROP_DEF_VAL_CLUSTER =\n\t\t\t\"tigase.server.xmppclient.SeeOtherHostHashed\";\n\n\t// default properties\n\tpublic static final String CM_SEE_OTHER_HOST_DEFAULT_HOST =\n\t\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"default-host\";\n\tpublic static final String CM_SEE_OTHER_HOST_DEFAULT_PORT =\n\t\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"default-port\";\n\tpublic static final String CM_SEE_OTHER_HOST_ACTIVE =\n\t\t\tCM_SEE_OTHER_HOST_CLASS_PROP_KEY + \"/\" + \"active\";\n\n\tpublic static enum Phase {\n\t\tOPEN, LOGIN, OTHER\n\t}\n\n\n\t// ~--- methods -------------------------------------------------------------\n\t/**\n\t * Finds an appropriate host for a given JID\n\t *\n\t * @param jid\n\t *          is a user JID extracted from the stream open attributes\n\t * @param host\n\t *          is \"this\" host to which the user is now connected and which calls\n\t *          the method\n\t * @return BareJID of possible host to which the user should connect or NULL\n\t */\n\tBareJID findHostForJID(BareJID jid, BareJID host);\n\n\t/**\n\t * Sets list of available nodes in cluster environment\n\t *\n\t * @param nodes current list of nodes\n\t */\n\tvoid setNodes(List<JID> nodes);\n\n\t// ~--- properties ----------------------------------------------------------\n\tvoid getDefaults( Map<String, Object> defs, Map<String, Object> params );\n\n\tvoid setProperties( Map<String, Object> props );\n\n\t/**\n\t * Returns Element object containing stream:error message\n\t *\n\t * @param xmlns xml namespace of the element\n\t * @param destination BareJID address of the redirect destination\n\t * @return element containing stream:error message\n\t */\n\tdefault Element getStreamError( String xmlns, BareJID destination, Integer port ) {\n\t\tElement error = new Element( \"stream:error\" );\n\t\tElement seeOtherHost = new Element( \"see-other-host\", destination.toString() + (port != null ? \":\"+port : \"\") );\n\n\t\tseeOtherHost.setXMLNS( xmlns );\n\t\terror.addChild( seeOtherHost );\n\n\t\treturn error;\n\t}\n\n\t/**\n\t * Performs check whether redirect is enabled in the given phase\n\t * by default see-other-host redirect is only active in stream:open phase\n\t *\n\t * @param vHost vHost for which redirection should be performed\n\t * @param ph phase for which the check should be performed\n\t * @return boolean value indicating whether to perform or not redirect for\n\t * the phase passed as argument\n\t */\n\tboolean isEnabled(VHostItem vHost, Phase ph);\n\n\t/**\n\t * Method validates whether a redirection for a particular hostname and\n\t * resulting redirection hastname is required\n\t *\n\t * @param defaultHost     default hostname of the particular machine\n\t * @param redirectionHost destination hostname\n\t *\n\t * @return {@code true} if the redirection is required, otherwise\n\t *         {@code false}\n\t */\n\tdefault boolean isRedirectionRequired( BareJID defaultHost, BareJID redirectionHost ) {\n\t\treturn !defaultHost.equals( redirectionHost );\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/StreamErrorCounterIOProcessor.java",
    "content": "/*\n * StreamErrorCounterIOProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport java.io.IOException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\nimport tigase.stats.CounterValue;\nimport tigase.stats.StatisticsList;\nimport tigase.xml.Element;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n *\n * @author andrzej\n */\npublic class StreamErrorCounterIOProcessor implements XMPPIOProcessor {\n\n\tpublic static final String ID = \"stream-error-counter\";\n\t\n\tprivate String compName;\n\tprivate ErrorStatisticsHolder holder = new ErrorStatisticsHolder(); \n\t\n\t@Override\n\tpublic String getId() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tholder.getStatistics(compName, list);\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPIOService service) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processIncoming(XMPPIOService service, Packet packet) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean processOutgoing(XMPPIOService service, Packet packet) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void packetsSent(XMPPIOService service) throws IOException {\n\t}\n\n\t@Override\n\tpublic void processCommand(XMPPIOService service, Packet packet) {\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService service, boolean streamClosed) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void setConnectionManager(ConnectionManager connectionManager) {\n\t\tcompName = connectionManager.getName();\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) {\n\t}\n\n\t@Override\n\tpublic void streamError(XMPPIOService service, StreamError streamError) {\n\t\tif (streamError == null)\n\t\t\tstreamError = StreamError.UndefinedCondition;\n\t\t\n\t\tholder.count(streamError);\n\t}\n\t\n\tpublic static class ErrorStatisticsHolder {\n\t\t\n\t\tprivate static final String[] ERROR_NAMES;\n\t\t\n\t\tstatic {\n\t\t\tint count = StreamError.values().length;\n\t\t\tERROR_NAMES = new String[count];\n\t\t\tStreamError[] vals = StreamError.values();\n\t\t\tfor (int i=0; i<vals.length; i++) {\n\t\t\t\tString name = vals[i].getCondition();\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\t\tfor (String part : name.split(\"-\")) {\n\t\t\t\t\tsb.append(Character.toUpperCase(part.charAt(0)));\n\t\t\t\t\tsb.append(part.substring(1));\n\t\t\t\t}\n\t\t\t\tERROR_NAMES[i] = sb.toString();\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic static String[] getErrorNames() {\n\t\t\treturn ERROR_NAMES;\n\t\t}\n\n\t\t\n\t\tprivate final CounterValue[] counters;\n\t\t\n\t\tpublic ErrorStatisticsHolder() {\n\t\t\tcounters = new CounterValue[ERROR_NAMES.length];\n\t\t\tfor (int i=0; i<counters.length; i++) {\n\t\t\t\tcounters[i] = new CounterValue(ERROR_NAMES[i], Level.FINER);\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void count(StreamError val) {\n\t\t\tcounters[val.ordinal()].inc();\n\t\t}\n\n\t\n\t\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\t\tfor (CounterValue c : counters) {\n\t\t\t\tlist.add(compName, \"StreamErrorStats/\" + c.getName() + \"ErrorsNumber\", c.getValue(), c.getLevel());\n\t\t\t}\n\t\t}\t\t\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/StreamManagementIOProcessor.java",
    "content": "/*\n * StreamManagementIOProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport tigase.net.IOServiceListener;\nimport tigase.net.SocketThread;\nimport tigase.server.*;\nimport tigase.stats.StatisticsList;\nimport tigase.util.TimerTask;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.XMPPIOService;\n\nimport java.io.IOException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class implements XEP-0198 Stream Management\n * \n * @author andrzej\n */\npublic class StreamManagementIOProcessor implements XMPPIOProcessor {\n\n\tprivate static final Logger log = Logger.getLogger(StreamManagementIOProcessor.class.getCanonicalName());\n\t\n\tpublic static final String XMLNS = \"urn:xmpp:sm:3\";\n\n\t// used tag names\n\tprivate static final String ACK_NAME = \"a\";\n\tprivate static final String ENABLE_NAME = \"enable\";\n\tprivate static final String ENABLED_NAME = \"enabled\";\n\tprivate static final String REQ_NAME = \"r\";\n\tprivate static final String RESUME_NAME = \"resume\";\n\tprivate static final String RESUMED_NAME = \"resumed\";\n\t\n\t// used attribute names\n\tprivate static final String H_ATTR = \"h\";\n\tprivate static final String LOCATION_ATTR = \"location\";\n\tprivate static final String RESUME_ATTR = \"resume\";\n\tprivate static final String MAX_ATTR = \"max\";\n\tprivate static final String PREVID_ATTR = \"previd\";\n\t\t\n\t// various strings used as key to store data in maps\n\tprivate static final String ACK_REQUEST_COUNT_KEY = \"ack-request-count\";\n\tprivate static final int DEF_ACK_REQUEST_COUNT_VAL = 10;\n\tprivate static final String[] DELAY_PATH = { Message.ELEM_NAME, \"delay\" };\n\tprivate static final String DELAY_XMLNS = \"urn:xmpp:delay\";\n\tprivate static final String INGORE_UNDELIVERED_PRESENCE_KEY = \"ignore-undelivered-presence\";\n\tprivate static final String IN_COUNTER_KEY = XMLNS + \"_in\";\n\tprivate static final String MAX_RESUMPTION_TIMEOUT_KEY = XMLNS + \"_resumption-timeout\";\n\tprivate static final String MAX_RESUMPTION_TIMEOUT_PROP_KEY = \"max-resumption-timeout\";\n\tprivate static final String OUT_COUNTER_KEY = XMLNS + \"_out\";\n\tprivate static final String RESUMPTION_TASK_KEY = XMLNS + \"_resumption-task\";\n\tprivate static final String RESUMPTION_TIMEOUT_PROP_KEY = \"resumption-timeout\";\n\tprivate static final String RESUMPTION_TIMEOUT_START_KEY = \"resumption-timeout-start\";\n\tprivate static final String STREAM_ID_KEY = XMLNS + \"_stream_id\";\n\t\n\tprivate static final Element[] FEATURES = { new Element(\"sm\", new String[] { \"xmlns\" },\n\t\t\tnew String[] { XMLNS }) };\n\t\n\tprivate static final SimpleDateFormat formatter;\n\tprivate final ConcurrentHashMap<String,XMPPIOService> services = new ConcurrentHashMap<String,XMPPIOService>();\n\t\n\tprivate boolean ignoreUndeliveredPresence = true;\n\tprivate int max_resumption_timeout = 15 * 60;\n\tprivate int resumption_timeout = 60;\n\tprivate int ack_request_count = DEF_ACK_REQUEST_COUNT_VAL;\n\t\n\tprivate ConnectionManager connectionManager;\n\t\t\n\tstatic {\n\t\tformatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tformatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\t\n\t\n\t/**\n\t * Method returns true if XMPPIOService has enabled SM.\n\t * \n\t * @param service\n\t * \n\t */\n\tpublic static boolean isEnabled(XMPPIOService service) {\n\t\treturn service.getSessionData().containsKey(IN_COUNTER_KEY);\n\t}\n\t\n\tprivate static boolean isResumptionEnabled(XMPPIOService service) {\n\t\treturn service.getSessionData().containsKey(STREAM_ID_KEY);\n\t}\n\t\n\tpublic StreamManagementIOProcessor() {\n\t}\n\n\t@Override\n\tpublic String getId() {\n\t\treturn XMLNS;\n\t}\n\t\n\t@Override\n\tpublic void setConnectionManager(ConnectionManager connectionManager) {\n\t\tthis.connectionManager = connectionManager;\n\t}\t\n\t\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPIOService service) {\n\t\t// user jid may not be set yet because is is set during resource binding\n\t\t// while this feature should be advertised just after authentication of \n\t\t// connection\n\t\t/*if (service.getUserJid() == null)\n\t\t\treturn null;*/\n\t\t\n\t\treturn FEATURES;\n\t}\n\t\n\t@Override\n\tpublic boolean processIncoming(XMPPIOService service, Packet packet) {\t\t\n\t\tif (!isEnabled(service)) {\n\t\t\tif (packet.getXMLNS() != XMLNS) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (packet.getElemName() == ENABLE_NAME) {\n\t\t\t\tOutQueue outQueue = newOutQueue();\n\t\t\t\tservice.getSessionData().putIfAbsent(OUT_COUNTER_KEY, outQueue);\n\t\t\t\tservice.getSessionData().putIfAbsent(IN_COUNTER_KEY, newCounter());\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tString id = null;\n\t\t\t\tString location = null;\n\t\t\t\tint timeout = resumption_timeout;\n\n\t\t\t\tif (resumption_timeout > 0 && packet.getElement().getAttributeStaticStr(RESUME_ATTR) != null) {\n\t\t\t\t\toutQueue.setResumptionEnabled(true);\n\t\t\t\t\tString maxStr = packet.getElement().getAttributeStaticStr(MAX_ATTR);\n\t\t\t\t\tif (maxStr != null) {\n\t\t\t\t\t\ttimeout = Math.min(max_resumption_timeout, Integer.parseInt(maxStr));\n\t\t\t\t\t}\n\t\t\t\t\tid = UUID.randomUUID().toString();\n\t\t\t\t\tlocation = connectionManager.getDefHostName().toString();\n\t\t\t\t\tservice.getSessionData().putIfAbsent(STREAM_ID_KEY, id);\n\t\t\t\t\tservice.getSessionData().put(MAX_RESUMPTION_TIMEOUT_KEY, timeout);\n\t\t\t\t\t\n\t\t\t\t\tservices.put(id, service);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tservice.writeRawData(\"<\" + ENABLED_NAME + \" xmlns='\" + XMLNS + \"'\"\n\t\t\t\t\t\t\t+ ( id != null ? \" id='\" + id + \"' \" + RESUME_ATTR + \"='true' \"+ MAX_ATTR + \"='\" + timeout + \"'\" : \"\" )\n\t\t\t\t\t\t\t+ ( location != null ? \" \" + LOCATION_ATTR + \"='\" + location + \"'\" : \"\" ) + \" />\");\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"{0}, started StreamManagement with resumption timeout set to = {1}\", \n\t\t\t\t\t\t\t\tnew Object[] { service.toString(), (id != null ? resumption_timeout : null) });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (IOException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, service.toString() + \", exception during sending <enabled/>, stopping...\", ex);\n\t\t\t\t\t}\n\t\t\t\t\tservice.forceStop();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (packet.getElemName() == RESUME_NAME) {\n\t\t\t\tString h = packet.getElement().getAttributeStaticStr(H_ATTR);\n\t\t\t\tString id = packet.getElement().getAttributeStaticStr(PREVID_ATTR);\n\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\tresumeStream(service, id, Integer.parseInt(h));\n\t\t\t\t} catch (IOException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, service.toString() + \", exception while resuming stream for user \" \n\t\t\t\t\t\t\t\t+ service.getUserJid() + \" with id \" + id, ex);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tservice.forceStop();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (packet.getXMLNS() == XMLNS) {\n\t\t\tif (packet.getElemName() == ACK_NAME) {\n\t\t\t\tString valStr = packet.getAttributeStaticStr(H_ATTR);\n\t\t\t\t\n\t\t\t\tint val = Integer.parseInt(valStr);\n\t\t\t\tOutQueue outQueue = (OutQueue) service.getSessionData().get(OUT_COUNTER_KEY);\n\t\t\t\tif (outQueue != null) {\n\t\t\t\t\toutQueue.ack(val);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"{0}, outQueue already null while processing: {1}\", new Object[] { service, packet });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (packet.getElemName() == REQ_NAME) {\n\t\t\t\tint value = ((Counter) service.getSessionData().get(IN_COUNTER_KEY)).get();\n\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\tservice.writeRawData(\"<\" + ACK_NAME + \" xmlns='\" + XMLNS \n\t\t\t\t\t\t\t+ \"' \" + H_ATTR + \"='\" + String.valueOf(value) + \"'/>\");\n\t\t\t\t}\n\t\t\t\tcatch (IOException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, service.toString() + \", exception during sending <a/> as \"\n\t\t\t\t\t\t\t\t+ \"response for <r/>, not stopping serivce as it \"\n\t\t\t\t\t\t\t\t+ \"will be stopped after processing all incoming data...\", ex);\n\t\t\t\t\t}\n\t\t\t\t\t//service.forceStop();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t((Counter) service.getSessionData().get(IN_COUNTER_KEY)).inc();\n\t\t\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean processOutgoing(XMPPIOService service, Packet packet) {\n\t\tif (!isEnabled(service) || packet.getXMLNS() == XMLNS) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tOutQueue outQueue = (OutQueue) service.getSessionData().get(OUT_COUNTER_KEY);\t\t\n\t\toutQueue.append(packet);\n\t\t\n\t\treturn service.getSessionData().containsKey(RESUMPTION_TASK_KEY);\n\t}\n\t\n\t@Override\n\tpublic void packetsSent(XMPPIOService service) throws IOException {\n\t\tif (!isEnabled(service))\n\t\t\treturn;\n\t\t\n\t\tOutQueue outQueue = (OutQueue) service.getSessionData().get(OUT_COUNTER_KEY);\t\t\n\t\tif (outQueue != null && shouldRequestAck(service, outQueue)) {\n\t\t\tservice.writeRawData(\"<\" + REQ_NAME + \" xmlns='\" + XMLNS + \"' />\");\n\t\t}\n\t}\n\t\n\t/**\n\t * Override this method to define a custom behaviour for request ack.\n\t * The default implementation will request an ack if there are more than {@link #ack_request_count}\n\t * packets waiting, so you probably want to OR your behaviour with this.\n\t */\n\tprotected boolean shouldRequestAck(XMPPIOService service, OutQueue outQueue) {\n\t\treturn outQueue.waitingForAck() >= ack_request_count;\n\t}\n\t\n\t@Override\n\tpublic void processCommand(XMPPIOService service, Packet pc) {\n\t\tString cmdId = Command.getFieldValue(pc, \"cmd\");\n\t\tif (\"stream-moved\".equals(cmdId)) {\n\t\t\tString newConn = Command.getFieldValue(pc, \"new-conn-jid\");\n\t\t\t\n\t\t\tString id = (String) service.getSessionData().get(STREAM_ID_KEY);\n\t\t\t\n\t\t\t\n\t\t\tJID newConnJid = JID.jidInstanceNS(newConn);\n\t\t\tXMPPIOService newService = connectionManager.getXMPPIOService(newConnJid.getResource());\n\t\t\t\n\t\t\t// if connection was closed during resumption, then close\n\t\t\t// old connection as it would not be able to resume \n\t\t\tif (newService != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"stream for user {2} moved from {0} to {1}\", new Object[] { \n\t\t\t\t\t\tservice.getConnectionId(), newService.getConnectionId(), newService.getUserJid() });\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tnewService.setUserJid(service.getUserJid());\n\t\t\t\t\tCounter inCounter = (Counter) newService.getSessionData().get(IN_COUNTER_KEY);\n\t\t\t\t\tnewService.writeRawData(\"<\" + RESUMED_NAME + \" xmlns='\" + XMLNS + \"' \" + PREVID_ATTR + \"='\" \n\t\t\t\t\t\t\t+ id + \"' \" + H_ATTR + \"='\" + inCounter.get() + \"' />\");\n\n\t\t\t\t\tservice.getSessionData().put(\"stream-closed\", \"stream-closed\");\n\t\t\t\t\tservices.put(id, newService);\n\t\t\t\t\t\n\t\t\t\t\t// resending packets thru new connection\n\t\t\t\t\tOutQueue outQueue = (OutQueue) newService.getSessionData().get(OUT_COUNTER_KEY);\n\t\t\t\t\tList<OutQueue.Entry> packetsToResend = new ArrayList<OutQueue.Entry>(outQueue.getQueue());\n\t\t\t\t\tfor (OutQueue.Entry entry : packetsToResend) {\n\t\t\t\t\t\tPacket packetToResend = entry.getPacketWithStamp();\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"{0}, resuming stream with id = {1} resending unacked packet = {2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { service, id, packetToResend });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewService.addPacketToSend(packetToResend);\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t// if there is any packet waiting we need to write them to socket\n\t\t\t\t\t// and to do that we need to call processWaitingPackets();\n\t\t\t\t\tif (!packetsToResend.isEmpty()) {\n\t\t\t\t\t\tif (newService.writeInProgress.tryLock()) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tnewService.processWaitingPackets();\n\t\t\t\t\t\t\t\tSocketThread.addSocketService(newService);\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING, newService + \"Exception during writing packets: \", e);\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tnewService.stop();\n\t\t\t\t\t\t\t\t} catch (Exception e1) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.WARNING, newService + \"Exception stopping XMPPIOService: \", e1);\n\t\t\t\t\t\t\t\t}    // end of try-catch\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tnewService.writeInProgress.unlock();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (IOException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"could not confirm session resumption for user = \" \n\t\t\t\t\t\t\t\t+ newService.getUserJid(), ex);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// remove new connection if resumption failed\n\t\t\t\t\tservices.remove(id, service);\n\t\t\t\t\tservices.remove(id, newService);\n\t\t\t\t}\n\t\t\t}\t\n\t\t\telse {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"no new service available for user {0} to resume from {1},\"\n\t\t\t\t\t\t\t+ \" already closed?\", new Object[] { service.getUserJid(), service });\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"closing old service {0} for user {1}\", new Object[] { service, \n\t\t\t\t\tservice.getUserJid()});\n\t\t\t}\n\t\t\t\n\t\t\t// stopping old service\n\t\t\tconnectionManager.serviceStopped(service);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService service, boolean streamClosed) {\n\t\tif (!isEnabled(service)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, service stopped - StreamManagement disabled\", new Object[] { service });\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tString id = (String) service.getSessionData().get(STREAM_ID_KEY);\n\t\t\n\t\tif (streamClosed) {\n\t\t\tservice.getSessionData().remove(STREAM_ID_KEY);\n\t\t}\n\t\t\t\t\n//\t\ttry {\n//\t\t\tthrow new Exception();\n//\t\t} catch (Throwable ex) {\n//\t\t\tlog.log(Level.WARNING, \"resumption timeout started, stream close = \" + streamClosed, ex);\n//\t\t\tex.printStackTrace();\n//\t\t}\n\t\tLong resumptionTimeoutStart = (Long) service.getSessionData().get(RESUMPTION_TIMEOUT_START_KEY);\n\t\tif (resumptionTimeoutStart != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, service stopped - checking resumption timeout\", new Object[] { service });\n\t\t\t}\n\t\t\t// if resumptionTimeoutStart is set let's check if resumption was \n\t\t\t// not started for longer time than twice value of resumption_timeout\n\t\t\tif (((System.currentTimeMillis() - resumptionTimeoutStart) > (2 * resumption_timeout * 1000))\n\t\t\t\t|| streamClosed) {\n\t\t\t\t// if so we should assume that resumption failed so we should \n\t\t\t\t// send errors, remove reference to service and stop this service\n\t\t\t\tservices.remove(id, service);\n\t\t\t\tservice.clearWaitingPackets();\n\t\t\t\tconnectionManager.serviceStopped(service);\n\t\t\t\t// for case in which task was started but later </stream:stream> was found in remaining data\n\t\t\t\tTimerTask timerTask = (TimerTask) service.getSessionData().get(RESUMPTION_TASK_KEY);\n\t\t\t\tif (timerTask != null)\n\t\t\t\t\ttimerTask.cancel();\n\t\t\t\tsendErrorsForQueuedPackets(service);\t\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\t\t\t\n\t\t// some buggy client (ie. Psi) may close stream without sending stream \n\t\t// close which forces us to thread this stream as broken and waiting for \n\t\t// resumption but those clients are not compatible with XEP-0198 and \n\t\t// resumption so this should not happen\n\t\tif (isResumptionEnabled(service)) {\n\t\t\tif (service.getSessionData().getOrDefault(XMPPIOService.STREAM_CLOSING, false) == Boolean.TRUE) {\n\t\t\t\tservices.remove(id, service);\n\t\t\t\tconnectionManager.serviceStopped(service);\n\t\t\t\tsendErrorsForQueuedPackets(service);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!services.containsKey(id)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, service stopped - resumption enabled but service not available\", new Object[] { service });\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// ConnectionManager must not be notified about closed connection\n\t\t\t// but connection needs to be closed so this is this case we still \n\t\t\t// return false to call forceStop but we remove IOServiceListener\n\t\t\tservice.setIOServiceListener((IOServiceListener) null);\n\t\t\t\t\n\t\t\tint resumptionTimeout = (Integer) service.getSessionData().get(MAX_RESUMPTION_TIMEOUT_KEY);\n\t\t\tsynchronized (service) {\n\t\t\t\tif (!service.getSessionData().containsKey(RESUMPTION_TASK_KEY)) {\t\t\t\t\t\n\t\t\t\t\tTimerTask timerTask = new ResumptionTimeoutTask(service);\n\t\t\t\t\tservice.getSessionData().put(RESUMPTION_TASK_KEY, timerTask);\n\t\t\t\t\tconnectionManager.addTimerTask(timerTask, resumptionTimeout * 1000);\n\t\t\t\t\t\n\t\t\t\t\t// set timestamp of begining of resumption to be able to detect\n\t\t\t\t\t// if something went wrong during resumption and service is\n\t\t\t\t\t// still kept in connection manager services as active service\n\t\t\t\t\t// after twice as long as resumption timeout\n\t\t\t\t\tservice.getSessionData().put(RESUMPTION_TIMEOUT_START_KEY, System.currentTimeMillis());\n\t\t\t\t\tservice.clearWaitingPackets();\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, service stopped - resumption enabled and timeout started\", new Object[] { service });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn false;\n\t\t}\n\t\telse if (id != null) {\n\t\t\tservices.remove(id, service);\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, service stopped - resumption disabled, sending unacked packets\", new Object[] { service });\n\t\t}\t\t\n\t\t\n\t\tservice.clearWaitingPackets();\n\t\tconnectionManager.serviceStopped(service);\n\t\tsendErrorsForQueuedPackets(service);\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String,Object> props) {\n\t\tif (props.containsKey(MAX_RESUMPTION_TIMEOUT_PROP_KEY)) {\n\t\t\tthis.max_resumption_timeout = (Integer) props.get(MAX_RESUMPTION_TIMEOUT_PROP_KEY);\n\t\t}\n\t\tif (props.containsKey(RESUMPTION_TIMEOUT_PROP_KEY)) {\n\t\t\tthis.resumption_timeout = (Integer) props.get(RESUMPTION_TIMEOUT_PROP_KEY);\n\t\t}\n\t\tif (props.containsKey(INGORE_UNDELIVERED_PRESENCE_KEY)) {\n\t\t\tthis.ignoreUndeliveredPresence = (Boolean) props.get(INGORE_UNDELIVERED_PRESENCE_KEY);\n\t\t}\n\t\tif (props.containsKey(ACK_REQUEST_COUNT_KEY)) {\n\t\t\tthis.ack_request_count = (Integer) props.get(ACK_REQUEST_COUNT_KEY);\n\t\t}\n\t}\n\t\n\t/**\n\t * Method responsible for starting process of stream resumption\n\t * \n\t * @param service\n\t * @param id\n\t * @param h\n\t * @throws IOException \n\t */\n\tprivate void resumeStream(XMPPIOService service, String id, int h) throws IOException {\n\t\tXMPPIOService oldService = services.get(id);\n\t\tif (oldService == null || !isSameUser(oldService, service)) {\n\t\t\t// should send failed!\n\t\t\tservice.writeRawData(\"<failed xmlns='\" + XMLNS + \"'>\" \n\t\t\t\t\t+ \"<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>\"\n\t\t\t\t\t+ \"</failed>\");\t\t\t\t\n\t\t\treturn;\t\n\t\t}\n\n\t\t// if stream has resource binded then we should not resume\n\t\tif (service.getUserJid() != null && JID.jidInstanceNS(service.getUserJid()).getResource() != null) {\n\t\t\tservice.writeRawData(\"<failed xmlns='\" + XMLNS + \"'>\"\n\t\t\t\t\t+ \"<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>\"\n\t\t\t\t\t+ \"</failed>\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif (services.remove(id, oldService)) {\n\t\t\tsynchronized (oldService) {\n\t\t\t\tTimerTask timerTask = (TimerTask) oldService.getSessionData().remove(RESUMPTION_TASK_KEY);\n\t\t\t\tif (timerTask != null) {\n\t\t\t\t\ttimerTask.cancel();\n\t\t\t\t}\n\t\t\t\toldService.getSessionData().put(RESUMPTION_TASK_KEY, true);\n\t\t\t\toldService.clearWaitingPackets();\n\t\t\t}\n\n\t\t\t// get old out queue\n\t\t\tOutQueue outQueue = (OutQueue) oldService.getSessionData().get(OUT_COUNTER_KEY);\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"{0}, resuming stream with id = {1} with {2} packets waiting for ack, local h = {3} and remote h = {4}\",\n\t\t\t\t\t\tnew Object[] { service, id, outQueue.waitingForAck(), outQueue.get(), h });\n\t\t\t}\n\t\t\toutQueue.ack(h);\n\n\t\t\t// move required data from old XMPPIOService session data to new service session data\n\t\t\tservice.getSessionData().put(OUT_COUNTER_KEY, outQueue);\n\t\t\tservice.getSessionData().put(MAX_RESUMPTION_TIMEOUT_KEY, \n\t\t\t\t\toldService.getSessionData().get(MAX_RESUMPTION_TIMEOUT_KEY));\n\t\t\tservice.getSessionData().put(IN_COUNTER_KEY, \n\t\t\t\t\toldService.getSessionData().get(IN_COUNTER_KEY));\n\t\t\tservice.getSessionData().put(STREAM_ID_KEY, \n\t\t\t\t\toldService.getSessionData().get(STREAM_ID_KEY));\n\t\t\t\n\t\t\t// send notification to session manager about change of connection \n\t\t\t// used for session\n\t\t\tPacket cmd = Command.STREAM_MOVED.getPacket(service.getConnectionId(), \n\t\t\t\t\tservice.getDataReceiver(), StanzaType.set, \"moved\");\n\t\t\tcmd.setPacketFrom(service.getConnectionId());\n\t\t\tcmd.setPacketTo(service.getDataReceiver());\n\t\t\tCommand.addFieldValue(cmd, \"old-conn-jid\", oldService.getConnectionId().toString());\n\t\t\tconnectionManager.processOutPacket(cmd);\n\t\t}\n\t\telse {\n\t\t\t// should send failed!\n\t\t\tservice.writeRawData(\"<failed xmlns='\" + XMLNS + \"'>\" \n\t\t\t\t\t+ \"<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>\"\n\t\t\t\t\t+ \"</failed>\");\n\t\t}\n\t}\n\t\n\t/**\n\t * Verifies if connections are authenticate for same bare jid\n\t * \n\t * @param oldService\n\t * @param newService\n\t * @return true - only when bare jids are the same\n\t */\n\tprivate boolean isSameUser(XMPPIOService oldService, XMPPIOService newService) {\n\t\tif (oldService.getUserJid() == null || newService.getUserJid() == null)\n\t\t\treturn false;\n\t\t\n\t\tJID oldUserJid = JID.jidInstanceNS(oldService.getUserJid());\n\t\tJID newUserJid = JID.jidInstanceNS(newService.getUserJid());\n\t\t\n\t\treturn oldUserJid.getBareJID().equals(newUserJid.getBareJID());\n\t}\n\t\n\t/**\n\t * Method responsible for sending recipient-unavailable error for all not acked packets\n\t * \n\t * @param service \n\t */\n\tprivate void sendErrorsForQueuedPackets(XMPPIOService service) {\n\t\tservice.clearWaitingPackets();\n\t\t\n\t\tOutQueue outQueue = (OutQueue) service.getSessionData().remove(OUT_COUNTER_KEY);\t\t\n\t\tif (outQueue != null) {\n\t\t\tOutQueue.Entry e = null;\n\t\t\t\n\t\t\twhile ((e = outQueue.queue.poll()) != null) {\n\t\t\t\tconnectionManager.processUndeliveredPacket(e.getPacketWithStamp(), e.stamp, null);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t}\n\n\t@Override\n\tpublic void streamError(XMPPIOService service, StreamError streamErrorName) {\n\t}\n\t\n\t/**\n\t * ResumptionTimeoutTask class is used for handing of timeout used during \n\t * session resumption\n\t */\n\tprivate class ResumptionTimeoutTask extends TimerTask {\n\n\t\tprivate final XMPPIOService service;\n\t\t\n\t\tpublic ResumptionTimeoutTask(XMPPIOService service) {\n\t\t\tthis.service = service;\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void run() {\t\n\t\t\tString id = (String) service.getSessionData().get(STREAM_ID_KEY);\t\t\t\n\t\t\tif (services.remove(id, service)) {\n\t\t\t\t//service.getSessionData().put(SERVICE_STOP_ALLOWED_KEY, true);\n\t\t\t\tservice.clearWaitingPackets();\n\t\t\t\tconnectionManager.serviceStopped(service);\n\t\t\t\tsendErrorsForQueuedPackets(service);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tprotected Counter newCounter() {\n\t\treturn new Counter();\n\t}\n\t\n\tprotected OutQueue newOutQueue() {\n\t\treturn new OutQueue();\n\t}\n\t\n\t/**\n\t * Counter class implements proper counter with overflow from 2^32-1 to 0\n\t */\n\tpublic static class Counter {\n\t\t\n\t\tprivate int counter = 0;\n\t\t\n\t\t/**\n\t\t * Increment counter\n\t\t */\n\t\tpublic void inc() {\n\t\t\tcounter++;\n\t\t\tif (counter < 0)\n\t\t\t\tcounter = 0;\n\t\t}\n\t\t\n\t\t/**\n\t\t * Get value of counter.\n\t\t * \n\t\t * \n\t\t */\n\t\tpublic int get() {\n\t\t\treturn counter;\n\t\t}\n\t\t\t\t\n\t\t/**\n\t\t * Sets value of a counter - use only for testing!\n\t\t * \n\t\t * @param value \n\t\t */\n\t\tprotected void setCounter(int value) {\n\t\t\tthis.counter = value;\n\t\t}\n\t}\n\t\n\t/**\n\t * OutQueue class implements queue of outgoing packets waiting for ack\n\t * with implementation of removing acked elements when id of acked packet \n\t * is passed\n\t */\n\tpublic static class OutQueue extends Counter {\n\t\t\n\t\tprivate final ArrayDeque<Entry> queue = new ArrayDeque<Entry>();\n\t\t\n\t\tprivate boolean resumptionEnabled = false;\n\t\t\n\t\t/**\n\t\t * Append packet to waiting for ack queue\n\t\t * \n\t\t * @param packet \n\t\t */\n\t\tpublic void append(Packet packet) {\n\t\t\tif (!packet.wasProcessedBy(XMLNS)) {\n\t\t\t\tpacket.processedBy(XMLNS);\n\n\t\t\t\tqueue.offer(new Entry(packet));\n\t\t\t\tinc();\n\t\t\t}\n\t\t}\n\t\t\n\t\t/**\n\t\t * Confirm delivery of packets up to count passed as value\n\t\t * \n\t\t * @param value \n\t\t */\n\t\tpublic void ack(int value) {\t\t\t\n\t\t\tint count = get() - value;\n\t\t\t\n\t\t\tif (count < 0) {\n\t\t\t\tcount = (Integer.MAX_VALUE - value) + get() + 1;\n\t\t\t}\n\t\t\t\n\t\t\twhile (count < queue.size()) {\n\t\t\t\tqueue.poll();\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void setResumptionEnabled(boolean enabled) {\n\t\t\tresumptionEnabled = enabled;\n\t\t}\n\t\t\n\t\t/**\n\t\t * Returns size of queue containing packets waiting for ack\n\t\t * \n\t\t * \n\t\t */\n\t\tpublic int waitingForAck() {\n\t\t\treturn queue.size();\n\t\t}\n\t\t\n\t\t/**\n\t\t * Method returns internal queue with packets waiting for ack - use testing \n\t\t * only!\n\t\t * \n\t\t * \n\t\t */\n\t\tprotected ArrayDeque<Entry> getQueue() {\n\t\t\treturn queue;\n\t\t}\n\t\t\n\t\tpublic class Entry {\n\t\t\tprivate final Packet packet;\n\t\t\tprivate final long stamp = System.currentTimeMillis();\n\t\t\t\n\t\t\tpublic Entry(Packet packet) {\n\t\t\t\tthis.packet = packet;\n\t\t\t}\n\t\t\t\n\t\t\tpublic Packet getPacketWithStamp() {\n\t\t\t\tif (packet.getElemName() != Iq.ELEM_NAME && !packet.isXMLNSStaticStr(DELAY_PATH, DELAY_XMLNS)) {\n\t\t\t\t\tString stamp = null;\n\t\t\t\t\tsynchronized (formatter) {\n\t\t\t\t\t\tstamp = formatter.format(this.stamp);\n\t\t\t\t\t}\n\t\t\t\t\tString from = packet.getStanzaTo() != null ? packet.getStanzaTo().getDomain() : packet.getPacketTo().getDomain();\n\t\t\t\t\tElement x = new Element( \"delay\", new String[] {\n\t\t\t\t\t\t\"from\", \"stamp\", \"xmlns\" }, new String[] { from, stamp, \"urn:xmpp:delay\" } );\n\t\t\t\t\tpacket.getElement().addChild(x);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\treturn packet;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/XMPPIOProcessor.java",
    "content": "/*\n * XMPPIOProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport java.io.IOException;\nimport java.util.Map;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\nimport tigase.stats.StatisticsList;\nimport tigase.xml.Element;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n *\n * @author andrzej\n */\npublic interface XMPPIOProcessor {\n\n\t/**\n\t * Returns identifier of processor\n\t * \n\t * \n\t */\n\tString getId();\n\t\n\t/**\n\t * Returns statistics generated by this processor\n\t * \n\t * @param list \n\t */\n\tvoid getStatistics(StatisticsList list);\n\t\n\t/**\n\t * Returns array of features added by this processor\n\t * \n\t * @param service\n\t * \n\t */\n\tElement[] supStreamFeatures(XMPPIOService service);\n\t\n\t/**\n\t * Process packets read from socket as they are sent to SessionManager.\n\t * \n\t * @param service\n\t * @param packet\n\t * @return true if packet should not be forwarded\n\t */\n\tboolean processIncoming(XMPPIOService service, Packet packet);\n\t\n\t/**\n\t * Process outgoing packets as they are added to XMPPIOService outgoing \n\t * packets queue.\n\t * \n\t * @param service\n\t * @param packet\n\t * @return true if packet should be removed\n\t */\n\tboolean processOutgoing(XMPPIOService service, Packet packet);\n\n\t/**\n\t * Method is called when all waiting data was written to socket.\n\t * \n\t * @param service\n\t * @throws IOException \n\t */\n\tvoid packetsSent(XMPPIOService service) throws IOException;\n\t\n\t/**\n\t * Process command execution which may be sent from other component and \n\t * should be processed by processor\n\t * \n\t * @param packet \n\t */\n\tvoid processCommand(XMPPIOService service, Packet packet);\n\t\n\t/**\n\t * Method called when XMPPIOService is closed.\n\t * \n\t * @param service \n\t * @param streamClosed \n\t * @return true if connecton manager should not be notified about stopping \n\t *\t\t\t\tof this service\n\t */\n\tboolean serviceStopped(XMPPIOService service, boolean streamClosed);\n\t\n\t/**\n\t * Sets connection manager instance for which this XMPPIOProcessor is used\n\t * \n\t * @param connectionManager \n\t */\n\tvoid setConnectionManager(ConnectionManager connectionManager);\n\t\n\t/**\n\t * Method used for setting properties\n\t * \n\t * @param props \n\t */\n\tvoid setProperties(Map<String,Object> props);\n\t\n\t/** \n\t * Method called when XMPP stream error is about to be sent\n\t * \n\t * @param service\n\t * @param streamErrorName \n\t */\n\tvoid streamError(XMPPIOService service, StreamError streamError);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppclient/XMPPIOProcessorsFactory.java",
    "content": "/*\n * XMPPIOProcessorsFactory.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.ConnectionManager;\n\n/**\n *\n * @author andrzej\n */\npublic class XMPPIOProcessorsFactory {\n\n\tprivate static final Logger log = Logger.getLogger(XMPPIOProcessorsFactory.class.getCanonicalName());\n\t\n\tprivate static final String IO_PROCESSORS_PROP_KEY = \"processors\";\n\t\n\tprivate static final Map<String,String> DEF_PROCESSORS = new HashMap<String,String>();\n\t\n\tstatic {\n\t\tDEF_PROCESSORS.put(StreamManagementIOProcessor.XMLNS, StreamManagementIOProcessor.class.getCanonicalName());\n\t\tDEF_PROCESSORS.put(StreamErrorCounterIOProcessor.ID, StreamErrorCounterIOProcessor.class.getCanonicalName());\n\t}\n\t\n\tpublic static XMPPIOProcessor[] updateIOProcessors(ConnectionManager connectionManager,\n\t\t\tXMPPIOProcessor[] activeProcessors, Map<String,Object> props) {\n\t\t\n\t\tif (props.containsKey(IO_PROCESSORS_PROP_KEY)) {\n\t\t\tString[] processorsArr = (String[]) props.get(IO_PROCESSORS_PROP_KEY);\n\t\t\tList<XMPPIOProcessor> processors = new ArrayList<XMPPIOProcessor>();\n\t\t\t\n\t\t\tif (processorsArr != null) {\t\t\t\n\t\t\t\tfor (String procStr : processorsArr) {\n\t\t\t\t\tString[] procStrArr = procStr.split(\"=\");\n\t\t\t\t\tString procId = procStrArr[0];\n\t\t\t\t\tString procClass = procStrArr.length > 1 ? procStrArr[1] : DEF_PROCESSORS.get(procId);\n\t\t\t\t\t\n\t\t\t\t\tXMPPIOProcessor proc = findProcessor(activeProcessors, procId, procClass);\n\t\t\t\t\t\n\t\t\t\t\tif (proc != null) {\n\t\t\t\t\t\tproc.setConnectionManager(connectionManager);\n\t\t\t\t\t\t\n\t\t\t\t\t\tMap<String,Object> procSettings = getProcSettings(props, procId);\n\t\t\t\t\t\tproc.setProperties(procSettings);\n\t\t\t\t\t\t\n\t\t\t\t\t\tprocessors.add(proc);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t\n\t\t\treturn processors.toArray(new XMPPIOProcessor[processors.size()]);\n\t\t}\n\t\t\n\t\treturn activeProcessors;\n\t}\n\t\n\tpublic static Map<String,Object> getProcSettings(Map<String,Object> props, String procId) {\n\t\t\n\t\tMap<String,Object> results = new HashMap<String,Object>();\n\t\t\n\t\tString keyPrefix = IO_PROCESSORS_PROP_KEY + \"/\" + procId + \"/\";\n\t\t\t\t\n\t\tfor (Map.Entry<String,Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(keyPrefix)) {\n\t\t\t\tString key = entry.getKey().replace(keyPrefix, \"\");\n\t\t\t\tif (key != null && !key.isEmpty()) {\n\t\t\t\t\tresults.put(key, entry.getValue());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn results;\n\t}\n\t\n\tpublic static XMPPIOProcessor findProcessor(XMPPIOProcessor[] activeProcessors, String procId, String procClassName) {\n\t\tClass<? extends XMPPIOProcessor> procCls = null;\n\t\ttry {\n\t\t\tprocCls = (Class<? extends XMPPIOProcessor>) ModulesManagerImpl.getInstance().forName(procClassName);\n\t\t} catch (ClassNotFoundException ex) {\n\t\t\t// we ignore this exception\n\t\t}\n\t\t\n\t\tfor (XMPPIOProcessor proc : activeProcessors) {\n\t\t\tif (procId.equals(proc.getId()) && proc.getClass().equals(procCls)) {\n\t\t\t\treturn proc;\n\t\t\t}\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"looking for XMPP processors of id = {0} of class {1} and found {2}\", \n\t\t\t\t\t\tnew Object[]{procId, procClassName, procCls != null ? procCls.toString() : \"null\"});\n\t\t\t}\n\t\t\treturn procCls.newInstance() ;\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppcomponent/ComponentConnectionManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppcomponent;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TreeMap;\nimport java.util.UUID;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.ConfigurationException;\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\nimport tigase.disco.XMPPService;\nimport tigase.net.ConnectionType;\nimport tigase.net.SocketType;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\nimport tigase.util.Algorithms;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Class ComponentConnectionManager\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ComponentConnectionManager extends ConnectionManager<XMPPIOService<Object>>\n\t\timplements XMPPService {\n\n\t/** Field description */\n\tpublic static final String SECRET_PROP_KEY = \"secret\";\n\n\t/** Field description */\n\tpublic static final String PORT_ROUTING_TABLE_PROP_KEY = \"routing-table\";\n\n\t/** Field description */\n\tpublic static final String PACK_ROUTED_KEY = \"pack-routed\";\n\n\t/** Field description */\n\tpublic static final String RETURN_SERVICE_DISCO_KEY = \"service-disco\";\n\n\t/** Field description */\n\tpublic static final boolean RETURN_SERVICE_DISCO_VAL = true;\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_KEY = \"identity-type\";\n\n\t/** Field description */\n\tpublic static final String IDENTITY_TYPE_VAL = \"generic\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ComponentConnectionManager.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tpublic int[] PORTS = { 5555 };\n\n\t/** Field description */\n\tpublic String PORT_LOCAL_HOST_PROP_VAL = \"localhost\";\n\n\t/** Field description */\n\tpublic String PORT_REMOTE_HOST_PROP_VAL = \"comp-1.localhost\";\n\n\t/** Field description */\n\tpublic ConnectionType PORT_TYPE_PROP_VAL = ConnectionType.accept;\n\n\t/** Field description */\n\tpublic SocketType PORT_SOCKET_PROP_VAL = SocketType.plain;\n\n\t/** Field description */\n\tpublic String SECRET_PROP_VAL = \"someSecret\";\n\n\t/** Field description */\n\tpublic String[] PORT_ROUTING_TABLE_PROP_VAL = { PORT_REMOTE_HOST_PROP_VAL,\n\t\t\t\".*@\" + PORT_REMOTE_HOST_PROP_VAL, \".*\\\\.\" + PORT_REMOTE_HOST_PROP_VAL };\n\n\t/** Field description */\n\tpublic boolean PACK_ROUTED_VAL = false;\n\tprivate ServiceEntity serviceEntity = null;\n\tprivate boolean pack_routed = PACK_ROUTED_VAL;\n\n\t// private boolean service_disco = RETURN_SERVICE_DISCO_VAL;\n\tprivate String identity_type = IDENTITY_TYPE_VAL;\n\tprivate String service_id = \"it doesn't matter\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tString config_type = (String) params.get(\"config-type\");\n\n\t\tif (config_type.equals(GEN_CONFIG_SM)) {\n\t\t\tPACK_ROUTED_VAL = true;\n\t\t\tPORT_TYPE_PROP_VAL = ConnectionType.accept;\n\t\t}\n\n\t\tif (config_type.equals(GEN_CONFIG_CS)) {\n\t\t\tPACK_ROUTED_VAL = true;\n\t\t\tPORT_TYPE_PROP_VAL = ConnectionType.connect;\n\t\t\tPORT_IFC_PROP_VAL = new String[] { \"localhost\" };\n\t\t}\n\n\t\tboolean def_found = false;\n\n\t\tfor (String key : params.keySet()) {\n\t\t\tString gen_ext_comp = GEN_EXT_COMP;\n\n\t\t\tif (key.startsWith(GEN_EXT_COMP)) {\n\t\t\t\tString end = key.substring(GEN_EXT_COMP.length());\n\n\t\t\t\tif (getName().endsWith(end)) {\n\t\t\t\t\tgen_ext_comp = key;\n\t\t\t\t}    // end of if (getName().endsWith(end))\n\n\t\t\t\tif (params.get(gen_ext_comp) != null) {\n\t\t\t\t\tdef_found = true;\n\t\t\t\t\tlog.config(\"Found default configuration: \" + (String) params.get(gen_ext_comp));\n\n\t\t\t\t\tString[] comp_params = ((String) params.get(gen_ext_comp)).split(\",\");\n\t\t\t\t\tint idx = 0;\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tPORT_LOCAL_HOST_PROP_VAL = comp_params[idx++];\n\t\t\t\t\t\tlog.config(\"Setting PORT_LOCAL_HOST_PROP_VAL to \" + PORT_LOCAL_HOST_PROP_VAL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tPORT_REMOTE_HOST_PROP_VAL = comp_params[idx++];\n\t\t\t\t\t\tlog.config(\"Setting PORT_REMOTE_HOST_PROP_VAL to \" + PORT_REMOTE_HOST_PROP_VAL);\n\t\t\t\t\t\tPORT_ROUTING_TABLE_PROP_VAL = new String[] { PORT_REMOTE_HOST_PROP_VAL };\n\n\t\t\t\t\t\tif (config_type.equals(GEN_CONFIG_CS)) {\n\t\t\t\t\t\t\tPORT_IFC_PROP_VAL = new String[] { PORT_REMOTE_HOST_PROP_VAL };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tPORTS[0] = Integer.decode(comp_params[idx++]);\n\t\t\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\t\t\tlog.warning(\"Incorrect component port number: \" + comp_params[idx - 1]);\n\t\t\t\t\t\t\tPORTS[0] = 5555;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlog.config(\"Setting PORTS[0] to \" + PORTS[0]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tSECRET_PROP_VAL = comp_params[idx++];\n\t\t\t\t\t\tlog.config(\"Setting SECRET_PROP_VAL to \" + SECRET_PROP_VAL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tif (comp_params[idx++].equals(\"ssl\")) {\n\t\t\t\t\t\t\tPORT_SOCKET_PROP_VAL = SocketType.plain;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlog.config(\"Setting PORT_SOCKET_PROP_VAL to \" + PORT_SOCKET_PROP_VAL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tif (comp_params[idx++].equals(\"accept\")) {\n\t\t\t\t\t\t\tPORT_TYPE_PROP_VAL = ConnectionType.accept;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tPORT_TYPE_PROP_VAL = ConnectionType.connect;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlog.config(\"Setting PORT_TYPE_PROP_VAL to \" + PORT_TYPE_PROP_VAL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (comp_params.length >= idx + 1) {\n\t\t\t\t\t\tPORT_ROUTING_TABLE_PROP_VAL = new String[] { comp_params[idx++] };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (config_type.equals(GEN_CONFIG_COMP)) {\n\n\t\t\t\t\t\t\t// This is specialized configuration for a single\n\t\t\t\t\t\t\t// external component so all traffic should go through\n\t\t\t\t\t\t\t// the external component (it acts as like s2s component)\n\t\t\t\t\t\t\tPORT_ROUTING_TABLE_PROP_VAL = new String[] { \".*\" };\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tString regex_host = PORT_REMOTE_HOST_PROP_VAL.replace(\".\", \"\\\\.\");\n\n\t\t\t\t\t\t\tPORT_ROUTING_TABLE_PROP_VAL = new String[] { regex_host, \".*@\" + regex_host,\n\t\t\t\t\t\t\t\t\t\".*\\\\.\" + regex_host };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( !def_found) {\n\t\t\tPORT_LOCAL_HOST_PROP_VAL = \"localhost\";\n\t\t\tPORT_REMOTE_HOST_PROP_VAL = getName() + \".localhost\";\n\n\t\t\tString regex_host = PORT_REMOTE_HOST_PROP_VAL.replace(\".\", \"\\\\.\");\n\n\t\t\tPORT_ROUTING_TABLE_PROP_VAL = new String[] { regex_host, \".*@\" + regex_host,\n\t\t\t\t\t\".*\\\\.\" + regex_host };\n\t\t}    // end of if (!def_found)\n\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tprops.put(PACK_ROUTED_KEY, PACK_ROUTED_VAL);\n\t\tprops.put(RETURN_SERVICE_DISCO_KEY, RETURN_SERVICE_DISCO_VAL);\n\t\tprops.put(IDENTITY_TYPE_KEY, IDENTITY_TYPE_VAL);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tif ((jid != null) && getName().equals(jid.getLocalpart())) {\n\t\t\treturn serviceEntity.getDiscoInfo(node);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\t\tif (getName().equals(jid.getLocalpart())) {\n\t\t\treturn serviceEntity.getDiscoItems(node, null);\n\t\t} else {\n\t\t\treturn Arrays.asList(serviceEntity.getDiscoItem(null,\n\t\t\t\t\tBareJID.toString(getName(), jid.toString())));\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Processing packet: \" + packet.getElemName() + \", type: \" + packet.getType());\n\t\t}\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet);\n\t\t}\n\n\t\tif ((packet.getStanzaTo() != null) && packet.getStanzaTo().equals(getComponentId())) {\n\t\t\ttry {\n\t\t\t\taddOutPacket(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t\t\t\t\t\"Not implemented\", true));\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.warning(\"Packet processing exception: \" + e);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (pack_routed && packet.getElemName() != \"route\") {\n\t\t\twritePacketToSocket(packet.packRouted());\n\t\t} else {\n\t\t\twritePacketToSocket(packet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(XMPPIOService<Object> serv) {\n\t\tPacket p = null;\n\n\t\twhile ((p = serv.getReceivedPackets().poll()) != null) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Processing packet: \" + p.getElemName() + \", type: \" + p.getType());\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Processing socket data: \" + p);\n\t\t\t}\n\n\t\t\tif (p.getElemName().equals(\"handshake\")) {\n\t\t\t\tprocessHandshake(p, serv);\n\t\t\t} else {\n\t\t\t\tPacket result = p;\n\n\t\t\t\tif (p.isRouted()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = p.unpackRouted();\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.warning(\"Packet stringprep addressing problem, dropping packet: \" + p);\n\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (p.isRouted())\n\n\t\t\t\taddOutPacket(result);\n\t\t\t}\n\t\t}        // end of while ()\n\n\t\treturn null;\n\t}\n\t\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\t// readd packet - this may be good as we would retry to send packet \n\t\t// which delivery failed due to IO error\n\t\taddPacket(packet);\n\t\treturn true;\n\t}\t\n\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\n\t\t// TODO: handle this somehow\n\t}\n\n\t@Override\n\tpublic void serviceStarted(XMPPIOService<Object> serv) {\n\t\tsuper.serviceStarted(serv);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"c2c connection opened: \" + serv.getRemoteAddress() + \", type: \"\n\t\t\t\t\t+ serv.connectionType().toString() + \", id=\" + serv.getUniqueId());\n\t\t}\n\n//  String addr =\n//    (String)service.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY);\n//  addRouting(addr);\n\t\t// addRouting(serv.getRemoteHost());\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect :\n\n\t\t\t\t// Send init xmpp stream here\n\t\t\t\t// XMPPIOService serv = (XMPPIOService)service;\n\t\t\t\tString compName = (String) serv.getSessionData().get(PORT_LOCAL_HOST_PROP_KEY);\n\t\t\t\tString data = \"<stream:stream\" + \" xmlns='jabber:component:accept'\"\n\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" to='\" + compName + \"'\" + \">\";\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"cid: \" + (String) serv.getSessionData().get(\"cid\") + \", sending: \" + data);\n\t\t\t\t}\n\n\t\t\t\tserv.xmppStreamOpen(data);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService<Object> service) {\n\t\tboolean result = super.serviceStopped(service);\n\n\t\tif (result) {\n\t\t\tMap<String, Object> sessionData = service.getSessionData();\n\t\t\tString[] routings = (String[]) sessionData.get(PORT_ROUTING_TABLE_PROP_KEY);\n\n\t\t\tupdateRoutings(routings, false);\n\n\t\t\tConnectionType type = service.connectionType();\n\n\t\t\tif (type == ConnectionType.connect) {\n\t\t\t\taddWaitingTask(sessionData);\n\n\t\t\t\t// reconnectService(sessionData, connectionDelay);\n\t\t\t}    // end of if (type == ConnectionType.connect)\n\n\t\t\t// removeRouting(serv.getRemoteHost());\n\t\t\tString addr = (String) sessionData.get(PORT_REMOTE_HOST_PROP_KEY);\n\n\t\t\tremoveComponentDomain(addr);\n\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.fine(\"Disonnected from: \" + addr);\n\t\t\t}\n\n\t\t\tupdateServiceDiscovery(addr, \"XEP-0114 disconnected\");\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tpack_routed = (Boolean) props.get(PACK_ROUTED_KEY);\n\n\t\t// service_disco = (Boolean)props.get(RETURN_SERVICE_DISCO_KEY);\n\t\tidentity_type = (String) props.get(IDENTITY_TYPE_KEY);\n\n\t\t// serviceEntity = new ServiceEntity(getName(), \"external\", \"XEP-0114\");\n\t\tserviceEntity = new ServiceEntity(\"XEP-0114 \" + getName(), null, \"XEP-0114\");\n\t\tserviceEntity.addIdentities(new ServiceIdentity(\"component\", identity_type,\n\t\t\t\t\"XEP-0114 \" + getName()));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(XMPPIOService<Object> service) {}\n\n\t@Override\n\tpublic void xmppStreamClosed(XMPPIOService<Object> serv) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Stream closed.\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic String xmppStreamOpened(XMPPIOService<Object> service, Map<String, String> attribs) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(\"Stream opened: \" + attribs.toString());\n\t\t}\n\n\t\tswitch (service.connectionType()) {\n\t\t\tcase connect : {\n\t\t\t\tString id = attribs.get(\"id\");\n\n\t\t\t\tservice.getSessionData().put(XMPPIOService.SESSION_ID_KEY, id);\n\n\t\t\t\tString secret = (String) service.getSessionData().get(SECRET_PROP_KEY);\n\n\t\t\t\ttry {\n\t\t\t\t\tString digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Calculating digest: id=\" + id + \", secret=\" + secret + \", digest=\"\n\t\t\t\t\t\t\t\t+ digest);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn \"<handshake>\" + digest + \"</handshake>\";\n\t\t\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Can not generate digest for pass phrase.\", e);\n\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcase accept : {\n\t\t\t\tString hostname = attribs.get(\"to\");\n\n\t\t\t\tservice.getSessionData().put(XMPPIOService.HOSTNAME_KEY, hostname);\n\n\t\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\t\tservice.getSessionData().put(XMPPIOService.SESSION_ID_KEY, id);\n\n\t\t\t\treturn \"<stream:stream\" + \" xmlns='jabber:component:accept'\"\n\t\t\t\t\t\t+ \" xmlns:stream='http://etherx.jabber.org/streams'\" + \" from='\" + hostname + \"'\"\n\t\t\t\t\t\t\t+ \" id='\" + id + \"'\" + \">\";\n\t\t\t}\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\n\t\treturn null;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn PORTS;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t * \n\t * We should not really close external component connection at all, so let's\n\t * say something like: 1000 days...\n\t */\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 1000 * 24 * HOUR;\n\t}\n\n\t@Override\n\tprotected Map<String, Object> getParamsForPort(int port) {\n\t\tMap<String, Object> defs = new TreeMap<String, Object>();\n\n\t\tdefs.put(SECRET_PROP_KEY, SECRET_PROP_VAL);\n\t\tdefs.put(PORT_LOCAL_HOST_PROP_KEY, PORT_LOCAL_HOST_PROP_VAL);\n\t\tdefs.put(PORT_ROUTING_TABLE_PROP_KEY, PORT_ROUTING_TABLE_PROP_VAL);\n\t\tdefs.put(PORT_TYPE_PROP_KEY, PORT_TYPE_PROP_VAL);\n\t\tdefs.put(PORT_SOCKET_PROP_KEY, PORT_SOCKET_PROP_VAL);\n\t\tdefs.put(PORT_REMOTE_HOST_PROP_KEY, PORT_REMOTE_HOST_PROP_VAL);\n\t\tdefs.put(PORT_IFC_PROP_KEY, PORT_IFC_PROP_VAL);\n\t\tdefs.put(MAX_RECONNECTS_PROP_KEY, (int) (30 * MINUTE));\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tprotected String getServiceId(Packet packet) {\n\t\treturn service_id;\n\t}\n\n\t@Override\n\tprotected String getUniqueId(XMPPIOService<Object> serv) {\n\n\t\t// return (String)serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY);\n\t\treturn service_id;\n\t}\n\n\t@Override\n\tprotected XMPPIOService<Object> getXMPPIOServiceInstance() {\n\t\treturn new XMPPIOService<Object>();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void processHandshake(Packet p, XMPPIOService<Object> serv) {\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect : {\n\t\t\t\tString data = p.getElemCData();\n\n\t\t\t\tif (data == null) {\n\t\t\t\t\tString[] routings = (String[]) serv.getSessionData().get(PORT_ROUTING_TABLE_PROP_KEY);\n\n\t\t\t\t\tupdateRoutings(routings, true);\n\n\t\t\t\t\tString addr = (String) serv.getSessionData().get(PORT_REMOTE_HOST_PROP_KEY);\n\n\t\t\t\t\taddComponentDomain(addr);\n\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.fine(\"Connected to: \" + addr);\n\t\t\t\t\t}\n\n\t\t\t\t\tupdateServiceDiscovery(addr, \"XEP-0114 connected\");\n\t\t\t\t} else {\n\t\t\t\t\tlog.warning(\"Incorrect packet received: \" + p);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase accept : {\n\t\t\t\tString digest = p.getElemCData();\n\t\t\t\tString id = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\t\t\t\tString secret = (String) serv.getSessionData().get(SECRET_PROP_KEY);\n\n\t\t\t\ttry {\n\t\t\t\t\tString loc_digest = Algorithms.hexDigest(id, secret, \"SHA\");\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Calculating digest: id=\" + id + \", secret=\" + secret + \", digest=\"\n\t\t\t\t\t\t\t\t+ loc_digest);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((digest != null) && digest.equals(loc_digest)) {\n\t\t\t\t\t\tPacket resp = Packet.packetInstance(new Element(\"handshake\"));\n\n\t\t\t\t\t\twritePacketToSocket(serv, resp);\n\n\t\t\t\t\t\tString[] routings = (String[]) serv.getSessionData().get(PORT_ROUTING_TABLE_PROP_KEY);\n\n\t\t\t\t\t\tupdateRoutings(routings, true);\n\n\t\t\t\t\t\tString addr = (String) serv.getSessionData().get(XMPPIOService.HOSTNAME_KEY);\n\n\t\t\t\t\t\taddComponentDomain(addr);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.fine(\"Connected to: \" + addr);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdateServiceDiscovery(addr, \"XEP-0114 connected\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.info(\"Handshaking passwords don't match, disconnecting...\");\n\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"Handshaking error.\", e);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\t}\n\n\tprivate void updateRoutings(String[] routings, boolean add) {\n\t\tif (add) {\n\t\t\tlog.info(\"Adding routings: \" + Arrays.toString(routings));\n\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\taddRegexRouting(route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.warning(\"Can not add regex routing '\" + route + \"' : \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.info(\"Removing routings: \" + Arrays.toString(routings));\n\n\t\t\tfor (String route : routings) {\n\t\t\t\ttry {\n\t\t\t\t\tremoveRegexRouting(route);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.warning(\"Can not remove regex routing '\" + route + \"' : \" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void updateServiceDiscovery(String jid, String name) {\n\t\tServiceEntity item = new ServiceEntity(jid, null, name);\n\n\t\t// item.addIdentities(new ServiceIdentity(\"component\", identity_type, name));\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Modifing service-discovery info: \" + item.toString());\n\t\t}\n\n\t\tserviceEntity.addItems(item);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/CID.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppserver;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jan 7, 2010 12:51:33 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CID {\n\tprivate static final Logger log = Logger.getLogger(CID.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int hash = 3;\n\tprivate String localHost = null;\n\tprivate String remoteHost = null;\n\tprivate String to_string = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param cid\n\t */\n\tpublic CID(String cid) {\n\t\tString[] cid_a = cid.split(\"@\");\n\n\t\tthis.localHost = cid_a[0].intern();\n\t\tthis.remoteHost = cid_a[1].intern();\n\t\tupdateToString();\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t *\n\t * @param localHost\n\t * @param remoteHost\n\t */\n\tpublic CID(String localHost, String remoteHost) {\n\t\tthis.localHost = ((localHost == null) ? null : localHost.intern());\n\t\tthis.remoteHost = ((remoteHost == null) ? null : remoteHost.intern());\n\t\tupdateToString();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (o instanceof CID) {\n\t\t\treturn (localHost == ((CID) o).localHost) && (remoteHost == ((CID) o).remoteHost);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getLocalHost() {\n\t\treturn localHost;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getRemoteHost() {\n\t\treturn remoteHost;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn hash;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn to_string;\n\t}\n\n\tprivate void updateToString() {\n\t\tthis.to_string = \"\" + this.localHost + \"@\" + this.remoteHost;\n\t\thash = 47 * hash + ((this.localHost != null) ? this.localHost.hashCode() : 0);\n\t\thash = 47 * hash + ((this.remoteHost != null) ? this.remoteHost.hashCode() : 0);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/CIDConnections.java",
    "content": "/*\n * CIDConnections.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.PacketErrorTypeException;\n\nimport tigase.net.ConnectionType;\nimport tigase.net.SocketType;\nimport tigase.util.DNSEntry;\nimport tigase.util.DNSResolverFactory;\n\nimport java.net.UnknownHostException;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Jun 14, 2010 12:32:49 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CIDConnections {\n\tprivate static final Logger log              =\n\t\tLogger.getLogger(CIDConnections.class.getName());\n//\tprivate static final Timer outgoingOpenTasks = new Timer(\"S2S outgoing open tasks\",\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t true);\n\t// TODO: #1195 - estimate proper default value \n\tprivate static int outgoingOpenTasksSize = Runtime.getRuntime().availableProcessors();\n\t\n\tprivate static ScheduledExecutorService outgoingOpenTasks = \n\t\t\tExecutors.newScheduledThreadPool(outgoingOpenTasksSize);\n\n\tpublic static void setOutgoingOpenThreadsSize(int size) {\n\t\tif (outgoingOpenTasksSize != size) {\n\t\t\toutgoingOpenTasksSize = size;\n\t\t\tScheduledExecutorService scheduler = outgoingOpenTasks;\n\t\t\toutgoingOpenTasks = Executors.newScheduledThreadPool(outgoingOpenTasksSize);\n\t\t\tscheduler.shutdown();\n\t\t}\n\t}\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CID cid                                       = null;\n\tprivate S2SConnectionSelector connectionSelector      = null;\n\tprivate long firstWaitingTime                         = 0;\n\tprivate S2SConnectionHandlerIfc<S2SIOService> handler = null;\n\tprivate int max_in_conns                              = 4;\n\tprivate int max_out_conns                             = 4;\n\tprivate int max_out_conns_per_ip                      = 2;\n\tprivate long max_waiting_time                         = 15 * 60 * 1000;\n\tprivate boolean testMode                              = Boolean.getBoolean(\"test\");\n\tprivate ReentrantLock sendInProgress                  = new ReentrantLock();\n\tprivate AtomicBoolean outgoingOpenInProgress          = new AtomicBoolean(false);\n\tprivate Set<S2SConnection> outgoing_handshaking       =\n\t\tnew ConcurrentSkipListSet<S2SConnection>();\n\tprivate Set<S2SConnection> outgoing = new ConcurrentSkipListSet<S2SConnection>();\n\tprivate Set<S2SConnection> incoming = new ConcurrentSkipListSet<S2SConnection>();\n\n\t/**\n\t * (SessionID, dbKey) pairs\n\t */\n\tprivate Map<String, String> dbKeys                   =\n\t\tnew ConcurrentSkipListMap<String, String>();\n\tprivate ConcurrentLinkedQueue<Packet> waitingPackets =\n\t\tnew ConcurrentLinkedQueue<Packet>();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param cid\n\t * @param handler\n\t * @param selector\n\t * @param maxInConns\n\t * @param maxOutConns\n\t * @param maxOutConnsPerIP\n\t * @param max_waiting_time\n\t */\n\tpublic CIDConnections(CID cid, S2SConnectionHandlerIfc<S2SIOService> handler,\n\t\t\t\t\t\t\t\t\t\t\t\tS2SConnectionSelector selector, int maxInConns, int maxOutConns,\n\t\t\t\t\t\t\t\t\t\t\t\tint maxOutConnsPerIP, long max_waiting_time) {\n\t\tthis.cid                  = cid;\n\t\tthis.handler              = handler;\n\t\tthis.connectionSelector   = selector;\n\t\tthis.max_in_conns         = maxInConns;\n\t\tthis.max_out_conns        = maxOutConns;\n\t\tthis.max_out_conns_per_ip = maxOutConnsPerIP;\n\t\tthis.max_waiting_time     = max_waiting_time;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void resetOutgoingInProgress() {\n\t\toutgoingOpenInProgress.set(false);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean getOutgoingInProgress() {\n\t\treturn outgoingOpenInProgress.get();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sessId\n\t * @param key\n\t */\n\tpublic void addDBKey(String sessId, String key) {\n\t\tdbKeys.put(sessId, key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void addIncoming(S2SIOService serv) {\n\t\tS2SConnection s2s_conn = serv.getS2SConnection();\n\n\t\tif (s2s_conn == null) {\n\t\t\ts2s_conn = new S2SConnection(handler, serv.getRemoteAddress());\n\t\t\ts2s_conn.setS2SIOService(serv);\n\t\t\tserv.setS2SConnection(s2s_conn);\n\t\t}\n\n\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\t\tif (cid != null) {\n\t\t\t// using additional mapping/masking of incoming connections to allow \n\t\t\t// usage of intermediate server also for incoming connections\n\t\t\tString serverName = handler.getServerNameForDomain(cid.getRemoteHost());\n\t\t\tserv.getSessionData().put(S2SIOService.CERT_REQUIRED_DOMAIN, serverName);\n\t\t}\n\t\t\n\t\t// TODO: check if this should be moved inside the IF\n\t\tincoming.add(s2s_conn);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void connectionAuthenticated(S2SIOService serv, CID cid) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"{0}, connection is authenticated.\", serv);\n\t\t}\n\t\tserv.addCID(cid);\n\t\tif (serv.connectionType() == ConnectionType.connect) {\n\n\t\t\t// Release the 'lock'\n\t\t\toutgoingOpenInProgress.set(false);\n\n\t\t\tS2SConnection s2s_conn = serv.getS2SConnection();\n\n\t\t\toutgoing_handshaking.remove(s2s_conn);\n\t\t\toutgoing.add(s2s_conn);\n\t\t\tsendPacket(null);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param sessionId\n\t */\n\tpublic void connectionAuthenticated(String sessionId, CID cid) {\n\t\tS2SConnection s2s_conn = getS2SConnectionForSessionId(sessionId);\n\n\t\tif (s2s_conn != null) {\n\t\t\tconnectionAuthenticated(s2s_conn.getS2SIOService(), cid);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void connectionStopped(S2SIOService serv) {\n\t\tS2SConnection s2s_conn = serv.getS2SConnection();\n\n\t\tif (s2s_conn == null) {\n\t\t\tlog.log(Level.INFO, \"s2s_conn not set for serv: {0}\", serv);\n\n\t\t\treturn;\n\t\t}\n\t\tif (serv.getSessionId() != null) {\n\t\t\tdbKeys.remove(serv.getSessionId());\n\t\t}\n\t\tswitch (serv.connectionType()) {\n\t\tcase connect :\n\n\t\t\t// Release the 'lock'\n\t\t\toutgoingOpenInProgress.set(false);\n\t\t\toutgoing.remove(s2s_conn);\n\t\t\toutgoing_handshaking.remove(s2s_conn);\n\t\t\tif (!waitingPackets.isEmpty()) {\n\t\t\t\tcheckOpenConnections();\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase accept :\n\t\t\tincoming.remove(s2s_conn);\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key_sessionId\n\t *\n\t * \n\t */\n\tpublic String getDBKey(String key_sessionId) {\n\t\treturn dbKeys.get(key_sessionId);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getDBKeysCount() {\n\t\treturn dbKeys.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getIncomingCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : incoming) {\n\t\t\tif (s2SConnection.isConnected()) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getIncomingTLSCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : incoming) {\n\t\t\tS2SIOService serv = s2SConnection.getS2SIOService();\n\n\t\t\tif (serv.isConnected() &&\n\t\t\t\t\t(serv.getSessionData().get(S2SIOService.CERT_CHECK_RESULT) != null)) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getMaxOutConns() {\n\t\treturn this.max_out_conns;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getMaxOutConnsPerIP() {\n\t\treturn this.max_out_conns_per_ip;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getOutgoingCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : outgoing) {\n\t\t\tif (s2SConnection.isConnected()) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getOutgoingHandshakingCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : outgoing_handshaking) {\n\t\t\tif (s2SConnection.isConnected()) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getOutgoingTLSCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : outgoing) {\n\t\t\tS2SIOService serv = s2SConnection.getS2SIOService();\n\n\t\t\tif (serv.isConnected() &&\n\t\t\t\t\t(serv.getSessionData().get(S2SIOService.CERT_CHECK_RESULT) != null)) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sessionId\n\t *\n\t * \n\t */\n\tpublic S2SConnection getS2SConnectionForSessionId(String sessionId) {\n\t\tS2SConnection s2s_conn = null;\n\n\t\tfor (S2SConnection s2sc : incoming) {\n\t\t\tif ((s2sc.getS2SIOService() != null) &&\n\t\t\t\t\tsessionId.equals(s2sc.getS2SIOService().getSessionId())) {\n\t\t\t\ts2s_conn = s2sc;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (s2s_conn == null) {\n\t\t\tfor (S2SConnection s2sc : outgoing) {\n\t\t\t\tif ((s2sc.getS2SIOService() != null) &&\n\t\t\t\t\t\tsessionId.equals(s2sc.getS2SIOService().getSessionId())) {\n\t\t\t\t\ts2s_conn = s2sc;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (s2s_conn == null) {\n\t\t\tfor (S2SConnection s2sc : outgoing_handshaking) {\n\t\t\t\tif ((s2sc.getS2SIOService() != null) &&\n\t\t\t\t\t\tsessionId.equals(s2sc.getS2SIOService().getSessionId())) {\n\t\t\t\t\ts2s_conn = s2sc;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn s2s_conn;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getWaitingControlCount() {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2sc : incoming) {\n\t\t\tresult += s2sc.getWaitingControlCount();\n\t\t}\n\t\tfor (S2SConnection s2sc : outgoing) {\n\t\t\tresult += s2sc.getWaitingControlCount();\n\t\t}\n\t\tfor (S2SConnection s2sc : outgoing_handshaking) {\n\t\t\tresult += s2sc.getWaitingControlCount();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getWaitingCount() {\n\t\treturn waitingPackets.size();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param port_props\n\t */\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\t\tS2SConnection s2s_conn =\n\t\t\t(S2SConnection) port_props.get(S2SIOService.S2S_CONNECTION_KEY);\n\n\t\tif (s2s_conn == null) {\n\t\t\tlog.log(Level.INFO, \"s2s_conn not set for serv: {0}\", port_props);\n\n\t\t\treturn;\n\t\t}\n\n\t\tConnectionType type = (ConnectionType) port_props.get(\"type\");\n\n\t\tif (type != null) {\n\t\t\tswitch (type) {\n\t\t\tcase connect :\n\n\t\t\t\t// Release the 'lock'\n\t\t\t\toutgoingOpenInProgress.set(false);\n\t\t\t\toutgoing.remove(s2s_conn);\n\t\t\t\toutgoing_handshaking.remove(s2s_conn);\n\t\t\t\tif (!this.waitingPackets.isEmpty()) {\n\t\t\t\t\tcheckOpenConnections();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase accept :\n\t\t\t\tthis.incoming.remove(s2s_conn);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.INFO, \"ConnectionType not set for serv: {0}\", port_props);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param sessionId\n\t * @param packet\n\t * \n\t */\n\tpublic boolean sendControlPacket(String sessionId, Packet packet) {\n\n\t\t// Seraching for a correct connection\n\t\t// TODO: speed it up somehow, maybe verify can be only sent to incoming\n\t\t// and result to outgoing? Check it out\n\t\tS2SConnection s2s_conn = getS2SConnectionForSessionId(sessionId);\n\n\t\tif (s2s_conn != null) {\n\t\t\ts2s_conn.addControlPacket(packet);\n\t\t\ts2s_conn.sendAllControlPackets();\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Control packet: {0} could not be sent as there is no connection \" +\n\t\t\t\t\t\t\t\t\"for the session id: {1}\", new Object[] { packet,\n\t\t\t\t\t\t\t\tsessionId });\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param verify_req\n\t */\n\tpublic void sendHandshakingOnly(final Packet verify_req) {\n\t\toutgoingOpenTasks.schedule(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\ttry {\n\t\t\t\t\t// using additional domain name mapping to allow usage of intermediate server\n\t\t\t\t\tString serverName = handler.getServerNameForDomain(cid.getRemoteHost());\n\t\t\t\t\t\n\t\t\t\t\tDNSEntry dns_entry     = DNSResolverFactory.getInstance().getHostSRV_Entry(serverName);\n\t\t\t\t\tS2SConnection s2s_conn = new S2SConnection(handler, dns_entry.getIp());\n\n\t\t\t\t\ts2s_conn.addControlPacket(verify_req);\n\n\t\t\t\t\tMap<String, Object> port_props = new TreeMap<String, Object>();\n\t\t\t\t\tport_props.put(S2SIOService.CERT_REQUIRED_DOMAIN, serverName);\n\n\t\t\t\t\tport_props.put(S2SIOService.HANDSHAKING_ONLY_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t S2SIOService.HANDSHAKING_ONLY_KEY);\n\n\t\t\t\t\t// it looks like we are sending verify requests only on handshaking-only\n\t\t\t\t\t// connection so there is only one domain for verification\n\t\t\t\t\tport_props.put(S2SIOService.HANDSHAKING_DOMAIN_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\t verify_req.getStanzaTo().toString());\n\t\t\t\t\tinitNewConnection(dns_entry.getIp(), dns_entry.getPort(), s2s_conn, port_props);\n\t\t\t\t} catch (UnknownHostException ex) {\n\t\t\t\t\tlog.log(Level.INFO, \"Remote host not found: \" + cid.getRemoteHost(), ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}, 0, TimeUnit.MILLISECONDS);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void sendPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Sending packets.\");\n\t\t}\n\t\tif (packet != null) {\n\t\t\tif ((firstWaitingTime == 0) || waitingPackets.isEmpty()) {\n\t\t\t\tfirstWaitingTime = System.currentTimeMillis();\n\t\t\t}\n\t\t\twaitingPackets.offer(packet);\n\t\t}\n\t\tif (sendInProgress.tryLock()) {\n\t\t\ttry {\n\t\t\t\tboolean packetSent = false;\n\t\t\t\tPacket waiting     = null;\n\n\t\t\t\twhile ((waiting = waitingPackets.peek()) != null) {\n\t\t\t\t\tS2SConnection s2s_conn = getOutgoingConnection(waiting);\n\n\t\t\t\t\tif (s2s_conn != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (s2s_conn.isConnected()) {\n\t\t\t\t\t\t\t\tpacketSent = s2s_conn.sendPacket(waiting);\n\t\t\t\t\t\t\t\twaitingPackets.poll();\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Packet: {0} sent over connection: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] { waiting,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t s2s_conn.getS2SIOService() });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"There was a closed connection available - removing \"\n\t\t\t\t\t\t\t\t\t\t\t+ \"connection {0} from set of active connections\", s2s_conn);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toutgoing.remove(s2s_conn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\t\t\"A problem sending packet, connection broken? Retrying later. {0}\",\n\t\t\t\t\t\t\t\t\t\t\twaiting);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t\"There is no connection available to send the packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\twaiting);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!packetSent) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\"No packet could be sent, trying to open more connections: {0}\", cid);\n\t\t\t\t\t}\n\t\t\t\t\tcheckOpenConnections();\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\"Some packets were sent, not trying to open more connections: {0}\",\n\t\t\t\t\t\t\t\t\t\tcid);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tsendInProgress.unlock();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void checkOpenConnections() {\n\t\tif (outgoingOpenInProgress.compareAndSet(false, true)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Scheduling task for openning a new connection for: {0}\",\n\t\t\t\t\t\t\t\tcid);\n\t\t\t}\n\t\t\toutgoingOpenTasks.schedule(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tboolean result = false;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\t\"Running scheduled task for openning a new connection for: {0}\",\n\t\t\t\t\t\t\t\t\t\t\tcid);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = openOutgoingConnections();\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t\"uncaughtException in the connection opening thread: \", e);\n\t\t\t\t\t} finally {}\n\t\t\t\t\tif (!result) {\n\t\t\t\t\t\toutgoingOpenInProgress.set(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 0, TimeUnit.MILLISECONDS);\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Outgoing open in progress, skipping for: {0}\", cid);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate int getOpenForIP(String ip) {\n\t\tint result = 0;\n\n\t\tfor (S2SConnection s2SConnection : outgoing) {\n\t\t\tif (ip.equals(s2SConnection.getIPAddress())) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\t\tfor (S2SConnection s2SConnection : outgoing_handshaking) {\n\t\t\tif (ip.equals(s2SConnection.getIPAddress())) {\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate S2SConnection getOutgoingConnection(Packet packet) {\n\t\treturn connectionSelector.selectConnection(packet, outgoing);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate void initNewConnection(String ip, int port, S2SConnection s2s_conn,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Map<String, Object> port_props) {\n\t\toutgoing_handshaking.add(s2s_conn);\n\t\tport_props.put(S2SIOService.S2S_CONNECTION_KEY, s2s_conn);\n\t\tport_props.put(\"remote-ip\", ip);\n\t\tport_props.put(\"local-hostname\", cid.getLocalHost());\n\t\tport_props.put(\"remote-hostname\", cid.getRemoteHost());\n\t\tport_props.put(\"ifc\", new String[] { ip });\n\t\tport_props.put(\"socket\", SocketType.plain);\n\t\tport_props.put(\"type\", ConnectionType.connect);\n\t\tport_props.put(\"srv-type\", \"_xmpp-server._tcp\");\n\t\tport_props.put(\"port-no\", port);\n\t\tport_props.put(\"cid\", cid);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"STARTING new connection: {0}\", cid);\n\t\t\tlog.log(Level.FINEST, \"{0} connection params: {1}\",\n\t\t\t\t\t\t\tnew Object[] { cid, port_props });\n\t\t}\n\t\thandler.initNewConnection(port_props);\n\t}\n\n\tprivate boolean openOutgoingConnections() {\n\t\tboolean result = false;\n\n\t\ttry {\n\n\t\t\t// Check whether all active connections are still active\n\t\t\tfor (S2SConnection out_conn : outgoing) {\n\t\t\t\tif (!out_conn.isConnected()) {\n\t\t\t\t\toutgoing.remove(out_conn);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Removing inactive connection: {0}\", out_conn);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (firstWaitingTime + max_waiting_time <= System.currentTimeMillis()) {\n\t\t\t\tsendPacketsBack();\n\t\t\t\tfirstWaitingTime = 0;\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"S2S Timeout expired, sending back: {0}\", waitingPackets);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tint all_outgoing = outgoing.size() + outgoing_handshaking.size();\n\n\t\t\tif (all_outgoing >= max_out_conns) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"Exceeded max number of outgoing connections, not doing anything: {0}\",\n\t\t\t\t\t\t\t\t\tall_outgoing);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Checking DNS for host: {0} for: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { cid.getRemoteHost(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t cid });\n\t\t\t}\n\n\t\t\t// During TTS automated tests we send ping for 200 non-existen domains. On some\n\t\t\t// configurations DNS check for 200 non-existen domains takes forever, so here we\n\t\t\t// have a shortcut to speed the test up.\n\t\t\t// To be sure we do this only for vhosts without a '.' character which are used\n\t\t\t// during TTS tests.\n\t\t\tif (testMode) {\n\t\t\t\tif (cid.getRemoteHost().startsWith(\"vhost-\") &&\n\t\t\t\t\t\t!cid.getRemoteHost().contains(\".\")) {\n\t\t\t\t\tthrow new UnknownHostException(cid.getRemoteHost());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// using additional domain name mapping to allow usage of intermediate server\n\t\t\tString serverName = handler.getServerNameForDomain(cid.getRemoteHost());\n\t\t\t\t\t\n\t\t\t// Check DNS entries\n\t\t\tDNSEntry[] dns_entries = DNSResolverFactory.getInstance().getHostSRV_Entries(serverName);\n\n\t\t\t// Activate 'missing' connections\n\t\t\tfor (DNSEntry dNSEntry : dns_entries) {\n\t\t\t\tint openForIP = getOpenForIP(dNSEntry.getIp());\n\n\t\t\t\tfor (int i = openForIP; i < max_out_conns_per_ip; i++) {\n\t\t\t\t\tif (dNSEntry.getIp().equals(\"127.0.0.1\")) {\n\n\t\t\t\t\t\t// DNS misconfiguration for the remote server (icq.jabber.cz for\n\t\t\t\t\t\t// example)\n\t\t\t\t\t\t// Now we assume: UnknownHostException\n\t\t\t\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\t\t\t\tlog.log(Level.INFO, \"DNS misconfiguration for domain: {0}, for: {1}\",\n\t\t\t\t\t\t\t\t\t\t\tnew Object[] { cid.getRemoteHost(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t cid });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthrow new UnknownHostException(\"DNS misconfiguration for domain: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t cid.getRemoteHost());\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create a new connection\n\t\t\t\t\tS2SConnection s2s_conn         = new S2SConnection(handler, dNSEntry.getIp());\n\t\t\t\t\tMap<String, Object> port_props = new TreeMap<String, Object>();\n\t\t\t\t\tport_props.put(S2SIOService.CERT_REQUIRED_DOMAIN, serverName);\n\n\t\t\t\t\tinitNewConnection(dNSEntry.getIp(), dNSEntry.getPort(), s2s_conn, port_props);\n\t\t\t\t\tresult = true;\n\t\t\t\t\tif (++all_outgoing >= max_out_conns) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (UnknownHostException ex) {\n\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\"Remote host not found: \" + cid.getRemoteHost() + \", for: \" + cid, ex);\n\t\t\tsendPacketsBack();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate void sendPacketsBack() {\n\t\tPacket p = null;\n\n\t\twhile ((p = waitingPackets.poll()) != null) {\n\t\t\ttry {\n\t\t\t\thandler.addOutPacket(Authorization.REMOTE_SERVER_NOT_FOUND.getResponseMessage(p,\n\t\t\t\t\t\t\t\t\"S2S - destination host not found\", true));\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Packet: {0} processing exception: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { p.toString(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t e });\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/18\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/ConnectionHandlerIfc.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimerTask;\nimport java.util.concurrent.TimeUnit;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface ConnectionHandlerIfc here.\n *\n *\n * Created: Wed Jun 11 22:13:31 2008\n *\n * @param <IO>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ConnectionHandlerIfc<IO extends XMPPIOService<?>> {\n\tboolean writePacketToSocket(IO serv, Packet packet);\n\n\tvoid writePacketsToSocket(IO serv, Queue<Packet> packets);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/LocalhostException.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPException;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 7, 2010 5:25:55 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class LocalhostException extends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic LocalhostException() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param msg\n\t */\n\tpublic LocalhostException(String msg) {\n\t\tsuper(msg);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param cause\n\t */\n\tpublic LocalhostException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param msg\n\t * @param cause\n\t */\n\tpublic LocalhostException(String msg, Throwable cause) {\n\t\tsuper(msg, cause);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/NotLocalhostException.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPException;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Sep 2, 2010 4:11:34 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NotLocalhostException extends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic NotLocalhostException() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param msg\n\t */\n\tpublic NotLocalhostException(String msg) {\n\t\tsuper(msg);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param cause\n\t */\n\tpublic NotLocalhostException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param msg\n\t * @param cause\n\t */\n\tpublic NotLocalhostException(String msg, Throwable cause) {\n\t\tsuper(msg, cause);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/OutgoingState.java",
    "content": "package tigase.server.xmppserver;\n\n/**\n * Enum description\n *\n */\npublic enum OutgoingState {\n\n\tNULL,\n\tCONNECTING,\n\tHANDSHAKING,\n\tOK\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SConnection.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jun 14, 2010 1:19:55 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class S2SConnection implements Comparable<S2SConnection> {\n\tprivate static final Logger log = Logger.getLogger(S2SConnection.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate S2SConnectionHandlerIfc<S2SIOService> handler = null;\n\tprivate String ipAddress = null;\n\tprivate S2SIOService service = null;\n\tprivate OutgoingState conn_state = OutgoingState.NULL;\n\n\t/**\n\t * Control packets for s2s connection establishing\n\t */\n\tprivate ConcurrentLinkedQueue<Packet> waitingControlPackets = new ConcurrentLinkedQueue<Packet>();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param handler\n\t * @param ip\n\t */\n\tpublic S2SConnection(S2SConnectionHandlerIfc<S2SIOService> handler, String ip) {\n\t\tthis.handler = handler;\n\t\tthis.ipAddress = ip;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void addControlPacket(Packet packet) {\n\t\twaitingControlPackets.add(packet);\n\t}\n\n\t@Override\n\tpublic int compareTo(S2SConnection o) {\n\t\treturn hashCode() - o.hashCode();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getIPAddress() {\n\t\treturn ipAddress;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic S2SIOService getS2SIOService() {\n\t\treturn service;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getWaitingControlCount() {\n\t\treturn waitingControlPackets.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean isConnected() {\n\t\treturn (service != null) && service.isConnected();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void sendAllControlPackets() {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tfor (Packet packet : waitingControlPackets) {\n\t\t\t\tlog.log(Level.FINEST, \"Sending on connection: {0} control packet: {1}\",\n\t\t\t\t\t\tnew Object[] { service,\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\t\t}\n\n\t\thandler.writePacketsToSocket(service, waitingControlPackets);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t *\n\t * @throws IOException\n\t */\n\tpublic boolean sendPacket(Packet packet) throws IOException {\n\t\treturn handler.writePacketToSocket(service, packet);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void setS2SIOService(S2SIOService serv) {\n\t\tthis.service = serv;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"S2S: \" + service;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SConnectionHandlerIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.TimeUnit;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 11:40:28 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n *\n * @param <IO>\n */\npublic interface S2SConnectionHandlerIfc<IO extends XMPPIOService<?>> {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param serv {@link S2SIOService} for which stream features should be retrieved\n\t *\n\t * @return list of stream features\n\t */\n\tpublic List<Element> getStreamFeatures(S2SIOService serv);\n\n\t//~--- methods --------------------------------------------------------------\n\n\tboolean addOutPacket(Packet packet);\n\n\tvoid addTimerTask(tigase.util.TimerTask task, long delay, TimeUnit unit);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tCIDConnections getCIDConnections(CID cid, boolean createNew)\n\t\t\tthrows NotLocalhostException, LocalhostException;\n\n\tBareJID getDefHostName();\n\n\t/**\n\t * Returns secret used for particular domain\n\t *\n\t * @param domain for which secret should be returned\n\t * \n\t * @return for particular domain\n\t * @throws NotLocalhostException if the domain is not local\n\t */\n\tString getSecretForDomain( String domain ) throws NotLocalhostException;\n\n\tString getServerNameForDomain( String domain );\n\n\t//~--- methods --------------------------------------------------------------\n\n\tvoid initNewConnection(Map<String, Object> port_props);\n\n\t/**\n\t * Checks if TLS is required for particular domain\n\t *\n\t * @param domain for which secret should be returned\n\t *\n\t * @return boolean indicating whether TLS is required\n\t */\n\tboolean isTlsRequired(String domain);\n        \n\tboolean isTlsWantClientAuthEnabled();\n\t\n\tboolean isTlsNeedClientAuthEnabled();\n\t\n\tboolean sendVerifyResult(String elem_name, CID connCid, CID keyCid, Boolean valid,\n\t\t\tString key_sessionId, String serv_sessionId, String cdata, boolean handshakingOnly);\n\n\tboolean sendVerifyResult(String elem_name, CID connCid, CID keyCid, Boolean valid,\n\t\t\tString key_sessionId, String serv_sessionId, String cdata, boolean handshakingOnly, Element errorElem);\n\n\tboolean writePacketToSocket(IO serv, Packet packet);\n\n\tvoid writePacketsToSocket(IO serv, Queue<Packet> packets);\n\n\tvoid writeRawData(IO serv, String strError);\n\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SConnectionManager.java",
    "content": "/*\n * S2SConnectionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimerTask;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.script.Bindings;\nimport tigase.cert.CertificateUtil;\nimport tigase.conf.ConfigurationException;\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\nimport tigase.server.xmppserver.proc.Dialback;\nimport tigase.server.xmppserver.proc.PacketChecker;\nimport tigase.server.xmppserver.proc.StartTLS;\nimport tigase.server.xmppserver.proc.StartZlib;\nimport tigase.server.xmppserver.proc.StreamError;\nimport tigase.server.xmppserver.proc.StreamFeatures;\nimport tigase.server.xmppserver.proc.StreamOpen;\nimport tigase.stats.StatisticsList;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Created: Jun 14, 2010 11:59:38 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class S2SConnectionManager\n\t\t\t\textends ConnectionManager<S2SIOService>\n\t\t\t\timplements S2SConnectionHandlerIfc<S2SIOService> {\n\t/** Field description */\n\tpublic static final String CID_CONNECTIONS_BIND = \"cidConnections\";\n\n\t/** Field description */\n\tpublic static final String CID_CONNECTIONS_TASKS_THREADS_KEY =\n\t\t\t\"cid-connections-tasks-threads\";\n\n\t/** Field description */\n\tpublic static final String MAX_CONNECTION_INACTIVITY_TIME_PROP_KEY =\n\t\t\t\"max-inactivity-time\";\n\n\t/** Field description */\n\tpublic static final String MAX_INCOMING_CONNECTIONS_PROP_KEY = \"max-in-conns\";\n\n\t/** Field description */\n\tpublic static final int MAX_INCOMING_CONNECTIONS_PROP_VAL = 4;\n\n\t/** Field description */\n\tpublic static final String MAX_OUT_PER_IP_CONNECTIONS_PROP_KEY = \"max-out-per-ip-conns\";\n\n\t/** Field description */\n\tpublic static final int MAX_OUT_PER_IP_CONNECTIONS_PROP_VAL = 1;\n\n\t/** Field description */\n\tpublic static final String MAX_OUT_TOTAL_CONNECTIONS_PROP_KEY = \"max-out-total-conns\";\n\n\t/** Field description */\n\tpublic static final int MAX_OUT_TOTAL_CONNECTIONS_PROP_VAL = 1;\n\n\t/** Field description */\n\tpublic static final String MAX_PACKET_WAITING_TIME_PROP_KEY = \"max-packet-waiting-time\";\n\n\t/** Field description */\n\tpublic static final String S2S_CONNECTION_SELECTOR_PROP_KEY = \"s2s-conn-selector\";\n\n\t/** Field description */\n\tpublic static final String S2S_CONNECTION_SELECTOR_PROP_VAL =\n\t\t\t\"tigase.server.xmppserver.S2SRandomSelector\";\n\n\t/** Field description */\n\tpublic static final String S2S_DOMAIN_MAPPING_PROP_KEY = \"s2s-domain-mapping\";\n\t\n\t/** Field description */\n\tpublic static final String S2S_DOMAIN_MAPPING_PROP_VAL = \"\";\n\n\t/** Field description */\n\tpublic static final String S2S_HT_TRAFFIC_THROTTLING_PROP_VAL =\n\t\t\t\"xmpp:15k:0:disc,bin:120m:0:disc\";\n\n\t/** Field description */\n\tprotected static final String DB_RESULT_EL_NAME = \"db:result\";\n\n\t/** Field description */\n\tprotected static final String DB_VERIFY_EL_NAME = \"db:verify\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(S2SConnectionManager.class\n\t\t\t.getName());\n\tprivate static final String PROCESSORS_CONF_PROP_KEY = \"processors-conf\";\n\tprivate static final String XMLNS_CLIENT_VAL         = \"jabber:client\";\n\tprivate static final String XMLNS_SERVER_VAL         = \"jabber:server\";\n\n\t/** Field description */\n\tpublic static final long MAX_PACKET_WAITING_TIME_PROP_VAL = 7 * MINUTE;\n\n\t/** Field description */\n\tpublic static final long MAX_CONNECTION_INACTIVITY_TIME_PROP_VAL = 15 * MINUTE;\n\n\t/** Field description */\n\n\t// TODO: #1195 - estimate proper default value\n\tpublic static final int CID_CONNECTIONS_TASKS_THREADS_VAL = Runtime.getRuntime()\n\t\t\t.availableProcessors();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate S2SConnectionSelector connSelector = null;\n\n\t/**\n\t * <code>maxPacketWaitingTime</code> keeps the maximum time packets can wait\n\t * for sending in ServerPacketQueue. Packets are put in the queue only when\n\t * connection to remote server is not established so effectively this timeout\n\t * specifies the maximum time for connecting to remote server. If this time is\n\t * exceeded then no more reconnecting attempts are performed and packets are\n\t * sent back with error information.\n\t *\n\t * Default TCP/IP timeout is 300 seconds so we can follow this convention but\n\t * administrator can set different timeout in server configuration.\n\t */\n\tprivate long maxPacketWaitingTime   = MAX_PACKET_WAITING_TIME_PROP_VAL;\n\tprivate int  maxOUTTotalConnections = MAX_OUT_TOTAL_CONNECTIONS_PROP_VAL;\n\tprivate int  maxOUTPerIPConnections = MAX_OUT_PER_IP_CONNECTIONS_PROP_VAL;\n\tprivate int  maxINConnections       = MAX_INCOMING_CONNECTIONS_PROP_VAL;\n\tprivate long maxInactivityTime      = MAX_CONNECTION_INACTIVITY_TIME_PROP_VAL;\n\n\t/**\n\t * Outgoing and incoming connections for a given domains pair (localdomain,\n\t * remotedomain)\n\t */\n\tprotected Map<CID, CIDConnections> cidConnections = new ConcurrentHashMap<CID,\n\t\t\tCIDConnections>(10000);\n\t\n\t/**\n\t * Holds list of manually entered mappings which provide substitutions for domains\n\t * matching pattens with names of servers to which we should connect.\n\t */\n\tprivate DomainServerNameMapper domainServerNameMapper = new DomainServerNameMapper();\n\n\t/**\n\t * List of processors which should handle all traffic incoming from the\n\t * network. In most cases if not all, these processors handle just protocol\n\t * traffic, all the rest traffic should be passed on to MR.\n\t */\n\tprivate Map<String, S2SProcessor> processorsMap = new LinkedHashMap<String, S2SProcessor>(\n\t\t\t10);\n\tprivate List<S2SProcessor> processors = Collections.emptyList();\n\tprivate Map<String, S2SProcessor> filters = new LinkedHashMap<String, S2SProcessor>(10);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutPacket(Packet packet) {\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\t@Override\n\tpublic void addTimerTask(tigase.util.TimerTask task, long delay, TimeUnit unit) {\n\t\tsuper.addTimerTask(task, delay, unit);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic void addTimerTask(TimerTask task, long delay, TimeUnit unit) {\n\t\tsuper.addTimerTask(task, delay, unit);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean handlesNonLocalDomains() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\n\t\t// Calculate hash code from the destination domain name to make sure packets\n\t\t// for\n\t\t// a single domain are processed by the same thread to avoid race condition\n\t\t// creating new connection data structures for a destination domain\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().getDomain().hashCode();\n\t\t}\n\n\t\t// Otherwise, it might be a control packet which can be processed by single\n\t\t// thread\n\t\treturn 1;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(CID_CONNECTIONS_BIND, cidConnections);\n\t}\n\n\t@Override\n\tpublic void initNewConnection(Map<String, Object> port_props) {\n\t\taddWaitingTask(port_props);\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\t\t}\n\t\tif ((packet.getStanzaTo() == null) || packet.getStanzaTo().getDomain().trim()\n\t\t\t\t.isEmpty()) {\n\t\t\tlog.log(Level.WARNING, \"Missing ''to'' attribute, ignoring packet...{0}\" +\n\t\t\t\t\t\"\\n This most likely happens due to missconfiguration of components\" +\n\t\t\t\t\t\" domain names.\", packet);\n\n\t\t\treturn;\n\t\t}\n\t\tif ((packet.getStanzaFrom() == null) || packet.getStanzaFrom().getDomain().trim()\n\t\t\t\t.isEmpty()) {\n\t\t\tlog.log(Level.WARNING, \"Missing ''from'' attribute, ignoring packet...{0}\", packet);\n\n\t\t\treturn;\n\t\t}\n\n\t\tString to_hostname = packet.getStanzaTo().getDomain();\n\n\t\ttry {\n\n\t\t\t// Code commented out below is not needed anymore\n\t\t\t// following call below takes care of hostnames checking:\n\t\t\t// getCIDConnections(cid, true);\n\t\t\t//// Check whether addressing is correct:\n\t\t\t//\n\t\t\t//// We don't send packets to local domains trough s2s, there\n\t\t\t//// must be something wrong with configuration\n\t\t\t// if (isLocalDomainOrComponent(to_hostname)) {\n\t\t\t//\n\t\t\t//// Ups, remote hostname is the same as one of local hostname??\n\t\t\t//// Internal loop possible, we don't want that....\n\t\t\t//// Let's send the packet back....\n\t\t\t// if (log.isLoggable(Level.INFO)) {\n\t\t\t// log.log(Level.INFO, \"Packet addresses to localhost,\"\n\t\t\t// + \" I am not processing it: {0}\", packet);\n\t\t\t// }\n\t\t\t//\n\t\t\t// addOutPacket(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t// \"S2S - not delivered. Server missconfiguration.\", true));\n\t\t\t//\n\t\t\t// return;\n\t\t\t// }\n\t\t\t//\n\t\t\tString from_hostname = packet.getStanzaFrom().getDomain();\n\n\t\t\t// Code commented out below is not needed anymore\n\t\t\t// following call below takes care of hostnames checking:\n\t\t\t// getCIDConnections(cid, true);\n\t\t\t//// I think from_hostname needs to be different from to_hostname at\n\t\t\t//// this point... or s2s doesn't make sense\n\t\t\t//\n\t\t\t//// All hostnames go through String.intern()\n\t\t\t// if (to_hostname == from_hostname) {\n\t\t\t// log.log(Level.WARNING,\n\t\t\t// \"Dropping incorrect packet - from_hostname == to_hostname: {0}\",\n\t\t\t// packet);\n\t\t\t//\n\t\t\t// return;\n\t\t\t// }\n\t\t\tCID cid = new CID(from_hostname, to_hostname);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Connection ID is: {0}\", cid);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tCIDConnections cid_conns     = getCIDConnections(cid, true);\n\t\t\t\tPacket         server_packet = packet.copyElementOnly();\n\n\t\t\t\tserver_packet.getElement().removeAttribute(\"xmlns\");\n\t\t\t\tcid_conns.sendPacket(server_packet);\n\t\t\t} catch (NotLocalhostException e) {\n\t\t\t\taddOutPacket(Authorization.NOT_ACCEPTABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\"S2S - Incorrect source address - none of any local virtual hosts or components.\",\n\t\t\t\t\t\ttrue));\n\t\t\t} catch (LocalhostException e) {\n\t\t\t\taddOutPacket(Authorization.NOT_ACCEPTABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\"S2S - Incorrect destinationaddress - one of local virtual hosts or components.\",\n\t\t\t\t\t\ttrue));\n\t\t\t}\n\t\t} catch (PacketErrorTypeException e) {\n\t\t\tlog.log(Level.WARNING, \"Packet processing exception: {0}\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(S2SIOService serv) {\n\t\tQueue<Packet> packets = serv.getReceivedPackets();\n\t\tPacket        p       = null;\n\t\tQueue<Packet> results = new ArrayDeque<Packet>(2);\n\n\t\twhile ((p = packets.poll()) != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing socket data: {0}\", p);\n\t\t\t}\n\t\t\tif (p.getXMLNS() == null) {\n\t\t\t\tp.setXMLNS(XMLNS_SERVER_VAL);\n\t\t\t}\n\n\t\t\tboolean processed = false;\n\n\t\t\tfor (S2SProcessor proc : processors) {\n\t\t\t\tprocessed |= proc.process(p, serv, results);\n\t\t\t\twritePacketsToSocket(serv, results);\n\t\t\t}\n\t\t\tif (!processed) {\n\t\t\t\tfor (S2SProcessor filter : filters.values()) {\n\t\t\t\t\tprocessed |= filter.process(p, serv, results);\n\t\t\t\t\twritePacketsToSocket(serv, results);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!processed) {\n\n\t\t\t\t// Sometimes xmlns is not set for the packet. Usually it does not\n\t\t\t\t// cause any problems but when the packet is sent over the s2s, ext\n\t\t\t\t// or cluster connection it may be quite problematic.\n\t\t\t\t// Let's force jabber:client xmlns for all packets received from s2s\n\t\t\t\t// connection\n\t\t\t\t// In theory null does not hurt, but if the packet goes through the\n\t\t\t\t// cluster\n\t\t\t\t// connection is gets cluster XMLNS\n\t\t\t\tif ((p.getXMLNS() == XMLNS_SERVER_VAL) || (p.getXMLNS() == null)) {\n\t\t\t\t\tp.setXMLNS(XMLNS_CLIENT_VAL);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tif (isLocalDomainOrComponent(p.getStanzaTo().getDomain())) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Adding packet out: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\t\tp });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// TODO: not entirely sure if this is a good idea....\n\t\t\t\t\t\t// Let's check it out.\n\t\t\t\t\t\tp.setPermissions(Permissions.REMOTE);\n\t\t\t\t\t\taddOutPacket(p);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tserv.addPacketToSend(Authorization.NOT_ACCEPTABLE.getResponseMessage(p,\n\t\t\t\t\t\t\t\t\t\"Not a local virtual domain or component\", true));\n\t\t\t\t\t\t} catch (PacketErrorTypeException ex) {}\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.INFO, \"Unexpected exception for packet: \" + p, e);\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\t// readd packet - this may be good as we would retry to send packet \n\t\t// which delivery failed due to IO error\n\t\taddPacket(packet);\n\t\treturn true;\n\t}\n\t\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\t\tCID cid = (CID) port_props.get(\"cid\");\n\n\t\tif (cid == null) {\n\t\t\tlog.log(Level.WARNING, \"Protocol error cid not set for outgoing connection: {0}\",\n\t\t\t\t\tport_props);\n\n\t\t\treturn;\n\t\t}\n\n\t\tCIDConnections cid_conns = getCIDConnections(cid);\n\n\t\tif (cid_conns == null) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Protocol error cid_conns not found for outgoing connection: {0}\", port_props);\n\n\t\t\treturn;\n\t\t} else {\n\t\t\tcid_conns.reconnectionFailed(port_props);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int schedulerThreads() {\n\n\t\t// TODO: #1195 - estimate proper default value\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t@Override\n\tpublic boolean sendVerifyResult(String elem_name, CID connCid, CID keyCid,\n\t\t\tBoolean valid, String key_sessionId, String serv_sessionId, String cdata,\n\t\t\tboolean handshakingOnly) {\n\t\treturn this.sendVerifyResult(elem_name, connCid, keyCid, valid, key_sessionId, serv_sessionId, cdata, handshakingOnly, null);\n\t}\n\t\n\t@Override\n\tpublic boolean sendVerifyResult(String elem_name, CID connCid, CID keyCid,\n\t\t\tBoolean valid, String key_sessionId, String serv_sessionId, String cdata,\n\t\t\tboolean handshakingOnly, Element errorElem) {\t\n\t\tCIDConnections cid_conns = getCIDConnections(connCid);\n\n\t\tif (cid_conns != null) {\n\t\t\tStanzaType type = null;\n\t\t\tif (valid != null) {\n\t\t\t\tif (valid) {\n\t\t\t\t\ttype = StanzaType.valid;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttype = StanzaType.invalid;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (errorElem != null) {\n\t\t\t\ttype = StanzaType.error;\n\t\t\t}\n\t\t\tPacket verify_valid = getValidResponse(elem_name, keyCid, key_sessionId, type,\n\t\t\t\t\tcdata);\n\n\t\t\tif (errorElem != null) {\n\t\t\t\tverify_valid.getElement().addChild(errorElem);\n\t\t\t}\n\t\t\t\n\t\t\tif (handshakingOnly) {\n\t\t\t\tcid_conns.sendHandshakingOnly(verify_valid);\n\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn cid_conns.sendControlPacket(serv_sessionId, verify_valid);\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\"Can't find CID connections for cid: {0}, can't send verify response.\",\n\t\t\t\t\t\tkeyCid);\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void serviceStarted(S2SIOService serv) {\n\t\tsuper.serviceStarted(serv);\n\t\tlog.log(Level.FINEST, \"s2s connection opened: {0}\", serv);\n\t\tfor (S2SProcessor proc : processors) {\n\t\t\tproc.serviceStarted(serv);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(S2SIOService serv) {\n\t\tboolean result = super.serviceStopped(serv);\n\n\t\tif (result) {\n\t\t\tfor (S2SProcessor proc : processors) {\n\t\t\t\tproc.serviceStopped(serv);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(S2SIOService serv) {\n\t\tfor (S2SProcessor proc : processors) {\n\t\t\tproc.serviceStarted(serv);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeRawData(S2SIOService ios, String data) {\n\t\tsuper.writeRawData(ios, data);\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(S2SIOService serv) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"{0}, Stream closed.\", new Object[] { serv });\n\t\t}\n\t\tfor (S2SProcessor proc : processors) {\n\t\t\tproc.streamClosed(serv);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String xmppStreamOpened(S2SIOService serv, Map<String, String> attribs) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"{0}, Stream opened: {1}\", new Object[] { serv, attribs });\n\t\t}\n\n\t\tStringBuilder sb = new StringBuilder(256);\n\n\t\tfor (S2SProcessor proc : processors) {\n\t\t\tString res = proc.streamOpened(serv, attribs);\n\n\t\t\tif (res != null) {\n\t\t\t\tsb.append(res);\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"{0}, Sending stream open: {1}\", new Object[] { serv, sb });\n\t\t}\n\n\t\treturn (sb.length() == 0)\n\t\t\t\t? null\n\t\t\t\t: sb.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic CIDConnections getCIDConnections(CID cid, boolean createNew)\n\t\t\t\t\tthrows NotLocalhostException, LocalhostException {\n\t\tCIDConnections result = getCIDConnections(cid);\n\n\t\tif ((result == null) && createNew && (cid != null)) {\n\t\t\tresult = createNewCIDConnections(cid);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tprops.put(MAX_PACKET_WAITING_TIME_PROP_KEY, MAX_PACKET_WAITING_TIME_PROP_VAL /\n\t\t\t\tSECOND);\n\t\tprops.put(MAX_CONNECTION_INACTIVITY_TIME_PROP_KEY,\n\t\t\t\tMAX_CONNECTION_INACTIVITY_TIME_PROP_VAL / SECOND);\n\t\tprops.put(MAX_INCOMING_CONNECTIONS_PROP_KEY, MAX_INCOMING_CONNECTIONS_PROP_VAL);\n\t\tprops.put(MAX_OUT_TOTAL_CONNECTIONS_PROP_KEY, MAX_OUT_TOTAL_CONNECTIONS_PROP_VAL);\n\t\tprops.put(MAX_OUT_PER_IP_CONNECTIONS_PROP_KEY, MAX_OUT_PER_IP_CONNECTIONS_PROP_VAL);\n\t\tprops.put(S2S_CONNECTION_SELECTOR_PROP_KEY, S2S_CONNECTION_SELECTOR_PROP_VAL);\n\t\tprops.put(CID_CONNECTIONS_TASKS_THREADS_KEY, CID_CONNECTIONS_TASKS_THREADS_VAL);\n\t\tprops.put(S2S_DOMAIN_MAPPING_PROP_KEY, S2S_DOMAIN_MAPPING_PROP_VAL);\n\n\t\treturn props;\n\t}\n        \n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"s2s\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"S2S connection manager\";\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Secret is used in generation of dialback key\n\t */\n\t@Override\n\tpublic String getSecretForDomain(String domain) throws NotLocalhostException {\n\t\tVHostItem item = vHostManager.getVHostItem(domain);\n\t\tif (item == null) {\n\t\t\tif (this.isLocalDomainOrComponent(domain)) {\n\t\t\t\tint idx = domain.indexOf('.');\n\t\t\t\tif (idx > 0) {\n\t\t\t\t\tString        basedomain = domain.substring(idx + 1);\n\t\t\t\t\titem = vHostManager.getVHostItem(basedomain);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (item == null) {\n\t\t\t\t\titem = vHostManager.getVHostItem(vHostManager.getDefVHostItem().toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (item == null) {\n\t\t\tthrow new NotLocalhostException(\"This is not a valid localhost: \" + domain);\n\t\t}\n\t\t\n\t\treturn item.getS2sSecret();\n\t}\n\n\t@Override\n\tpublic String getServerNameForDomain(String domain) {\n\t\treturn domainServerNameMapper.getServerNameForDomain(domain);\n\t}\t\n\t\t\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getName(), \"CIDs number\", cidConnections.size(), Level.INFO);\n\t\tif (list.checkLevel(Level.FINEST)) {\n\t\t\tlong total_outgoing             = 0;\n\t\t\tlong total_outgoing_tls         = 0;\n\t\t\tlong total_outgoing_handshaking = 0;\n\t\t\tlong total_incoming             = 0;\n\t\t\tlong total_incoming_tls         = 0;\n\t\t\tlong total_dbKeys               = 0;\n\t\t\tlong total_waiting              = 0;\n\t\t\tlong total_waiting_control      = 0;\n\n\t\t\tfor (Map.Entry<CID, CIDConnections> cid_conn : cidConnections.entrySet()) {\n\t\t\t\tint outgoing             = cid_conn.getValue().getOutgoingCount();\n\t\t\t\tint outgoing_tls         = cid_conn.getValue().getOutgoingTLSCount();\n\t\t\t\tint outgoing_handshaking = cid_conn.getValue().getOutgoingHandshakingCount();\n\t\t\t\tint incoming             = cid_conn.getValue().getIncomingCount();\n\t\t\t\tint incoming_tls         = cid_conn.getValue().getIncomingTLSCount();\n\t\t\t\tint dbKeys               = cid_conn.getValue().getDBKeysCount();\n\t\t\t\tint waiting              = cid_conn.getValue().getWaitingCount();\n\t\t\t\tint waiting_control      = cid_conn.getValue().getWaitingControlCount();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\n\t\t\t\t\t// Throwable thr = new Throwable();\n\t\t\t\t\t//\n\t\t\t\t\t// thr.fillInStackTrace();\n\t\t\t\t\t// log.log(Level.FINEST, \"Called from: \", thr);\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"CID: {0}, OUT: {1}, OUT_HAND: {2}, IN: {3}, dbKeys: {4}, \" +\n\t\t\t\t\t\t\t\"waiting: {5}, waiting_control: {6}\", new Object[] {\n\t\t\t\t\t\tcid_conn.getKey(), outgoing, outgoing_handshaking, incoming, dbKeys, waiting,\n\t\t\t\t\t\t\t\twaiting_control\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal_outgoing             += outgoing;\n\t\t\t\ttotal_outgoing_tls         += outgoing_tls;\n\t\t\t\ttotal_outgoing_handshaking += outgoing_handshaking;\n\t\t\t\ttotal_incoming             += incoming;\n\t\t\t\ttotal_incoming_tls         += incoming_tls;\n\t\t\t\ttotal_dbKeys               += dbKeys;\n\t\t\t\ttotal_waiting              += waiting;\n\t\t\t\ttotal_waiting_control      += waiting_control;\n\t\t\t}\n\t\t\tlist.add(getName(), \"Total outgoing\", total_outgoing, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total outgoing TLS\", total_outgoing_tls, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total outgoing handshaking\", total_outgoing_handshaking, Level\n\t\t\t\t\t.FINEST);\n\t\t\tlist.add(getName(), \"Total incoming\", total_incoming, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total incoming TLS\", total_incoming_tls, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total DB keys\", total_dbKeys, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total waiting\", total_waiting, Level.FINEST);\n\t\t\tlist.add(getName(), \"Total control waiting\", total_waiting_control, Level.FINEST);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<Element> getStreamFeatures(S2SIOService serv) {\n\t\tList<Element> results = new ArrayList<Element>(10);\n\n\t\tfor (S2SProcessor proc : processors) {\n\t\t\tproc.streamFeatures(serv, results);\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t@Override\n\tpublic boolean isTlsRequired(String domain) {\n\t\tVHostItem item = vHostManager.getVHostItemDomainOrComponent(domain);\n\t\treturn item.isTlsRequired();\n\t}\n\t\n\t@Override\n\tpublic boolean isTlsWantClientAuthEnabled() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isTlsNeedClientAuthEnabled() {\n\t\treturn false;\n\t}\n\t\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.containsKey(CID_CONNECTIONS_TASKS_THREADS_KEY)) {\n\t\t\tCIDConnections.setOutgoingOpenThreadsSize((Integer) props.get(\n\t\t\t\t\tCID_CONNECTIONS_TASKS_THREADS_KEY));\n\t\t}\n\t\tif (props.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\n\t\t// it needs to be here as we need properties for plugins\n\t\t// TODO: Make used processors list a configurable thing\n\t\tprocessorsMap.clear();\n\t\tprocessorsMap.put(Dialback.class.getSimpleName(), new Dialback());\n\t\tprocessorsMap.put(StartTLS.class.getSimpleName(), new StartTLS());\n\t\tprocessorsMap.put(StartZlib.class.getSimpleName(), new StartZlib());\n\t\tprocessorsMap.put(StreamError.class.getSimpleName(), new StreamError());\n\t\tprocessorsMap.put(StreamFeatures.class.getSimpleName(), new StreamFeatures());\n\t\tprocessorsMap.put(StreamOpen.class.getSimpleName(), new StreamOpen());\n\t\tfor (S2SProcessor proc : processorsMap.values()) {\n\t\t\tMap<String, Object> proc_props = new ConcurrentHashMap<String, Object>(4);\n\n\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\tif (entry.getKey().startsWith(PROCESSORS_CONF_PROP_KEY)) {\n\t\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t\tif (nodes.length > 2) {\n\t\t\t\t\t\tString[] ids = nodes[1].split(\",\");\n\n\t\t\t\t\t\tif (Arrays.binarySearch(ids, proc.getClass().getSimpleName()) >= 0) {\n\t\t\t\t\t\t\tproc_props.put(nodes[2], entry.getValue());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tproc.init(this, proc_props);\n\t\t}\n\t\tList<S2SProcessor> tmp_processors = new ArrayList<>(processorsMap.values());\n\t\tCollections.sort(tmp_processors);\n\t\tthis.processors = Collections.unmodifiableList(tmp_processors);\n\t\t\n\t\tfilters.clear();\n\t\tfilters.put(PacketChecker.class.getSimpleName(), new PacketChecker());\n\t\tfor (S2SProcessor filter : filters.values()) {\n\t\t\tMap<String, Object> proc_props = new ConcurrentHashMap<String, Object>(4);\n\n\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\tif (entry.getKey().startsWith(PROCESSORS_CONF_PROP_KEY)) {\n\t\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t\tif (nodes.length > 2) {\n\t\t\t\t\t\tString[] ids = nodes[1].split(\",\");\n\n\t\t\t\t\t\tif (Arrays.binarySearch(ids, filter.getClass().getSimpleName()) >= 0) {\n\t\t\t\t\t\t\tproc_props.put(nodes[2], entry.getValue());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfilter.init(this, proc_props);\n\t\t}\n\t\tmaxPacketWaitingTime = (Long) props.get(MAX_PACKET_WAITING_TIME_PROP_KEY) * SECOND;\n\t\tmaxInactivityTime = (Long) props.get(MAX_CONNECTION_INACTIVITY_TIME_PROP_KEY) *\n\t\t\t\tSECOND;\n\t\tmaxOUTTotalConnections = (Integer) props.get(MAX_OUT_TOTAL_CONNECTIONS_PROP_KEY);\n\t\tmaxOUTPerIPConnections = (Integer) props.get(MAX_OUT_PER_IP_CONNECTIONS_PROP_KEY);\n\t\tmaxINConnections       = (Integer) props.get(MAX_INCOMING_CONNECTIONS_PROP_KEY);\n\n\t\tString selector_str = (String) props.get(S2S_CONNECTION_SELECTOR_PROP_KEY);\n\n\t\ttry {\n\t\t\tconnSelector = (S2SConnectionSelector) Class.forName(selector_str).newInstance();\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Incorrect s2s connection selector class provided: {0}\",\n\t\t\t\t\tselector_str);\n\t\t\tlog.log(Level.SEVERE, \"Selector initialization exception: \", e);\n\t\t}\n\t\t\n\t\tString tmp = (String) props.get(S2S_DOMAIN_MAPPING_PROP_KEY);\n\t\tDomainServerNameMapper tmp_domainServerNameMapper = new DomainServerNameMapper();\n\t\tif (tmp != null) {\n\t\t\tfor(String part : tmp.split(\",\")) {\n\t\t\t\tString[] kv = part.split(\"=\");\n\t\t\t\tif (kv.length >= 2) {\n\t\t\t\t\ttmp_domainServerNameMapper.addEntry(kv[0], kv[1]);\n\t\t\t\t} \n\t\t\t}\n\t\t}\n\t\tdomainServerNameMapper = tmp_domainServerNameMapper;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn new int[] { 5269 };\n\t}\n\n\t/**\n\t * Method from ConnectionManager is overriden as it uses local value S2S_HT_TRAFFIC_THROTTLING_PROP_VAL\n\t * @return\n\t */\n\t@Override\n\tprotected String getDefTrafficThrottling() {\n\t\tString result = ST_TRAFFIC_THROTTLING_PROP_VAL;\n\n\t\tif (isHighThroughput()) {\n\t\t\tresult = S2S_HT_TRAFFIC_THROTTLING_PROP_VAL;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn maxInactivityTime;\n\t}\n\n\t@Override\n\tprotected S2SIOService getXMPPIOServiceInstance() {\n\t\treturn new S2SIOService();\n\t}\n\n\t@Override\n\tprotected boolean isHighThroughput() {\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected CIDConnections createNewCIDConnections(CID cid)\n\t\t\t\t\tthrows NotLocalhostException, LocalhostException {\n\t\tif (!isLocalDomainOrComponent(cid.getLocalHost())) {\n\t\t\tthrow new NotLocalhostException(\"This is not a valid localhost: \" + cid\n\t\t\t\t\t.getLocalHost());\n\t\t}\n\t\tif (isLocalDomainOrComponent(cid.getRemoteHost())) {\n\t\t\tthrow new LocalhostException(\"This is not a valid remotehost: \" + cid\n\t\t\t\t\t.getRemoteHost());\n\t\t}\n\n\t\tCIDConnections cid_conns = new CIDConnections(cid, this, connSelector,\n\t\t\t\tmaxINConnections, maxOUTTotalConnections, maxOUTPerIPConnections,\n\t\t\t\tmaxPacketWaitingTime);\n\n\t\tcidConnections.put(cid, cid_conns);\n\n\t\treturn cid_conns;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t// ~--- get methods ----------------------------------------------------------\n\tprivate CIDConnections getCIDConnections(CID cid) {\n\t\tif (cid == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn cidConnections.get(cid);\n\t}\n\n\tprivate Packet getValidResponse(String elem_name, CID cid, String id, StanzaType type,\n\t\t\tString cdata) {\n\t\tElement elem = new Element(elem_name);\n\n\t\tif (cdata != null) {\n\t\t\telem.setCData(cdata);\n\t\t}\n\t\tif (type != null) {\n\t\t\telem.addAttribute(\"type\", type.name());\n\t\t}\n\t\tif (id != null) {\n\t\t\telem.addAttribute(\"id\", id);\n\t\t}\n\n\t\tPacket result = Packet.packetInstance(elem, JID.jidInstanceNS(cid.getLocalHost()), JID\n\t\t\t\t.jidInstanceNS(cid.getRemoteHost()));\n\n\t\treturn result;\n\t}\n\t\n\tprotected static class DomainServerNameMapper {\n\t\t\n\t\tprivate class Entry implements Comparable<Entry>{\n\t\t\tprivate final String pattern;\n\t\t\tprivate final String serverName;\n\n\t\t\tpublic Entry(String pattern, String serverName) {\n\t\t\t\tthis.pattern = pattern.toLowerCase();\n\t\t\t\tthis.serverName = serverName;\n\t\t\t}\n\n\t\t\tpublic String getServerName() {\n\t\t\t\treturn serverName;\n\t\t\t}\n\n\t\t\tpublic boolean matches(String domain) {\n\t\t\t\tif (\"*\".equals(pattern)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn CertificateUtil.match(domain, pattern);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean equals(Object obj) {\n\t\t\t\tif (obj instanceof Entry) {\n\t\t\t\t\treturn pattern.equals(((Entry) obj).pattern);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\t@Override\n\t\t\tpublic int hashCode() {\n\t\t\t\treturn pattern.hashCode();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int compareTo(Entry o) {\n\t\t\t\tif (o.pattern.contains(\"*\")) {\n\t\t\t\t\tif (!pattern.contains(\"*\"))\n\t\t\t\t\t\treturn -1;\n\t\t\t\t} else {\n\t\t\t\t\tif (pattern.contains(\"*\"))\n\t\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tint val = (pattern.split(\".\").length - o.pattern.split(\".\").length) * -1;\n\t\t\t\tif (val != 0)\n\t\t\t\t\treturn val;\n\t\t\t\treturn o.pattern.length() - pattern.length();\n\t\t\t}\n\t\t}\n\t\t\n\t\tprivate List<Entry> entries = new ArrayList<Entry>();\n\t\t\n\t\tpublic DomainServerNameMapper() {}\n\t\t\n\t\tprotected void addEntry(String pattern, String serverName) {\n\t\t\t// clone list to fix possible concurrency issues with collection\n\t\t\t// could use CopyOnWriteArrayList but sorting this collection \n\t\t\t// is not possible on JDK7\n\t\t\tsynchronized (this) {\n\t\t\t\tList<Entry> entries = new ArrayList<Entry>(this.entries);\n\t\t\t\tEntry e = new Entry(pattern, serverName);\n\t\t\t\tentries.add(e);\n\t\t\t\tCollections.sort(entries);\n\t\t\t\tthis.entries = entries;\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic String getServerNameForDomain(String domain) {\n\t\t\tfor (Entry e : entries) {\n\t\t\t\tif (e.matches(domain))\n\t\t\t\t\treturn e.getServerName();\n\t\t\t}\n\t\t\treturn domain;\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tsb.append(getClass().getName()).append(\"[\");\n\t\t\tboolean first = true;\n\t\t\tfor (Entry e : entries) {\n\t\t\t\tif (!first)\n\t\t\t\t\tsb.append(\",\");\n\t\t\t\tsb.append(e.pattern);\n\t\t\t\tsb.append(\"=\");\n\t\t\t\tsb.append(e.serverName);\n\t\t\t\tfirst = false;\n\t\t\t} \n\t\t\tsb.append(\"]\");\n\t\t\treturn sb.toString();\n\t\t}\n\t\t\n\t}\n}\n\n\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n\n\n//~ Formatted in Tigase Code Convention on 13/10/15\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SConnectionSelector.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Set;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Jun 26, 2010 9:38:19 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface S2SConnectionSelector {\n\tS2SConnection selectConnection(Packet packet, Set<S2SConnection> outgoing);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SIOService.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jun 14, 2010 12:30:53 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class S2SIOService extends XMPPIOService<Object> {\n\tprivate static final Logger log = Logger.getLogger(S2SIOService.class.getName());\n\n\t/** Field description */\n\tpublic static final String S2S_CONNECTION_KEY = \"s2s-connection-key\";\n        public static final String HANDSHAKING_DOMAIN_KEY = \"handshaking-domain-key\";\n\tprotected static final String HANDSHAKING_ONLY_KEY = \"handshaking-only-key\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CIDConnections cid_conns = null;\n\tprivate String dbKey = null;\n\tprivate S2SConnection s2s_conn = null;\n\tprivate String session_id = null;\n\n///**\n// * This structure keeps a set of domains which are authorized to send or\n// * receive packets on this connection.\n// */\n//private Set<String> authenticatedDomains = new CopyOnWriteArraySet<String>();\n\n\t/**\n\t * This structure keeps a set of all CIDs reusing this connection. If the connection\n\t * goes down all CIDs must be notified.\n\t */\n\tprivate Set<CID> authenticatedCIDs = new CopyOnWriteArraySet<CID>();\n\n\t//~--- methods --------------------------------------------------------------\n\n///**\n// * Method description\n// *\n// *\n// * @param domain\n// */\n//public void addAuthenticatedDomain(String domain) {\n//  authenticatedDomains.add(domain);\n//}\n\n\t/**\n\t * Adds another connection id (CID) to the authenticated list for this connection\n\t *\n\t *\n\t * @param cid\n\t */\n\tpublic void addCID(CID cid) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, Adding CID to authenticated: {1}\", new Object[] { this, cid });\n\t\t}\n\n\t\tauthenticatedCIDs.add(cid);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n///**\n// * Method description\n// *\n// *\n// * \n// */\n//public Set<String> getAuthenticatedDomains() {\n//  return authenticatedDomains;\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Set<CID> getCIDs() {\n\t\treturn authenticatedCIDs;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic S2SConnection getS2SConnection() {\n\t\treturn s2s_conn;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getSessionId() {\n\t\treturn session_id;\n\t}\n\n///**\n// * Method description\n// *\n// *\n// * @param domain\n// *\n// * \n// */\n//public boolean isAuthenticated(String domain) {\n//  return authenticatedDomains.contains(domain);\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param cid\n\t *\n\t * \n\t */\n\tpublic boolean isAuthenticated(CID cid) {\n\t\treturn authenticatedCIDs.contains(cid);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean isAuthenticated() {\n\t\treturn authenticatedCIDs.size() > 0;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean isHandshakingOnly() {\n\t\treturn getSessionData().get(HANDSHAKING_ONLY_KEY) != null;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t */\n\tpublic void setDBKey(String key) {\n\t\tdbKey = key;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param s2s_conn\n\t */\n\tpublic void setS2SConnection(S2SConnection s2s_conn) {\n\t\tthis.s2s_conn = s2s_conn;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param session_id\n\t */\n\tpublic void setSessionId(String session_id) {\n\t\tthis.session_id = session_id;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String toString() {\n\t\tCID cid = (CID) getSessionData().get(\"cid\");\n\n\t\treturn \"CID: \" + cid + \", \" + super.toString();\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SProcessor.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 1:50:09 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface S2SProcessor extends Comparable<S2SProcessor> {\n\n\t/**\n\t * Returns order of processor which is used to set order in which processors\n\t * will be processing packet\n\t * \n\t * @return \n\t */\n\tpublic int order();\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void serviceStarted(S2SIOService serv);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void serviceStopped(S2SIOService serv);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t * @param serv\n\t * @param results\n\t */\n\tpublic void streamFeatures(S2SIOService serv, List<Element> results);\n\n\tvoid init(S2SConnectionHandlerIfc<S2SIOService> handler, Map<String,Object> props);\n\n\tboolean process(Packet p, S2SIOService serv, Queue<Packet> results);\n\n\tvoid streamClosed(S2SIOService serv);\n\n\tString streamOpened(S2SIOService serv, Map<String, String> attribs);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/S2SRandomSelector.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Random;\nimport java.util.Set;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jun 26, 2010 9:40:04 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class S2SRandomSelector implements S2SConnectionSelector {\n\tprivate static final Logger log = Logger.getLogger(S2SRandomSelector.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Random rand = new Random();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic S2SConnection selectConnection(Packet packet, Set<S2SConnection> outgoing) {\n\t\tint size = outgoing.size();\n\n\t\tif (size == 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tint pos = rand.nextInt(size);\n\t\tS2SConnection result = null;\n\t\tint i = -1;\n\n\t\tfor (S2SConnection s2SConnection : outgoing) {\n\t\t\tif (++i == pos) {\n\t\t\t\tresult = s2SConnection;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/ServerConnectionManager.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ConnectionManager;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPIOService;\n\nimport tigase.conf.ConfigurationException;\nimport tigase.net.ConnectionType;\nimport tigase.net.SocketType;\nimport tigase.stats.StatisticsList;\nimport tigase.util.Algorithms;\nimport tigase.util.DNSEntry;\nimport tigase.util.DNSResolverFactory;\nimport tigase.xml.Element;\n\nimport java.net.UnknownHostException;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TreeMap;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Class ServerConnectionManager\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ServerConnectionManager extends ConnectionManager<XMPPIOService<Object>>\n\t\timplements ConnectionHandlerIfc<XMPPIOService<Object>> {\n\tprivate static final String DB_RESULT_EL_NAME = \"db:result\";\n\tprivate static final String DB_VERIFY_EL_NAME = \"db:verify\";\n\n//public static final String HOSTNAMES_PROP_KEY = \"hostnames\";\n//public String[] HOSTNAMES_PROP_VAL =  {\"localhost\", \"hostname\"};\n\n\t/** Field description */\n\tpublic static final String MAX_PACKET_WAITING_TIME_PROP_KEY = \"max-packet-waiting-time\";\n\tprivate static final String RESULT_EL_NAME = \"result\";\n\tprivate static final String VERIFY_EL_NAME = \"verify\";\n\tprivate static final String XMLNS_DB_ATT = \"xmlns:db\";\n\tprivate static final String XMLNS_DB_VAL = \"jabber:server:dialback\";\n\tprivate static final String XMLNS_SERVER_VAL = \"jabber:server\";\n\tprivate static final String XMLNS_CLIENT_VAL = \"jabber:client\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(ServerConnectionManager.class.getName());\n\n\t/** Field description */\n\tpublic static final long MAX_PACKET_WAITING_TIME_PROP_VAL = 7 * MINUTE;\n\tprivate static Map<String, tigase.util.TimerTask> waitingTaskFutures = new LinkedHashMap<String,\n\t\ttigase.util.TimerTask>();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long new_connection_thread_counter = 0;\n\n//private String[] hostnames = HOSTNAMES_PROP_VAL;\n\n\t/**\n\t * <code>maxPacketWaitingTime</code> keeps the maximum time packets\n\t * can wait for sending in ServerPacketQueue. Packets are put in the\n\t * queue only when connection to remote server is not established so\n\t * effectively this timeout specifies the maximum time for connecting\n\t * to remote server. If this time is exceeded then no more reconnecting\n\t * attempts are performed and packets are sent back with error information.\n\t *\n\t * Default TCP/IP timeout is 300 seconds so we can follow this convention\n\t * but administrator can set different timeout in server configuration.\n\t */\n\tprivate long maxPacketWaitingTime = MAX_PACKET_WAITING_TIME_PROP_VAL;\n\n\t/**\n\t * Incoming (accept) services by sessionId. Some servers (EJabberd) opens\n\t * many connections for each domain, especially when in cluster mode.\n\t */\n\tprivate ConcurrentHashMap<String, XMPPIOService<Object>> incoming = new ConcurrentHashMap<String,\n\t\tXMPPIOService<Object>>(1000);\n\n\t/**\n\t * Services connected and authorized/authenticated\n\t */\n\tprivate Map<CID, ServerConnections> connectionsByLocalRemote = new ConcurrentHashMap<CID,\n\t\tServerConnections>(1000);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutPacket(Packet packet) {\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n//  Usually we want the server to do s2s for the external component too:\n//     if (params.get(GEN_VIRT_HOSTS) != null) {\n//       HOSTNAMES_PROP_VAL = ((String)params.get(GEN_VIRT_HOSTS)).split(\",\");\n//     } else {\n//       HOSTNAMES_PROP_VAL = DNSResolver.getDefHostNames();\n//     }\n//     ArrayList<String> vhosts =\n//       new ArrayList<String>(Arrays.asList(HOSTNAMES_PROP_VAL));\n//     for (Map.Entry<String, Object> entry: params.entrySet()) {\n//       if (entry.getKey().startsWith(GEN_EXT_COMP)) {\n//         String ext_comp = (String)entry.getValue();\n//         if (ext_comp != null) {\n//           String[] comp_params = ext_comp.split(\",\");\n//           vhosts.add(comp_params[1]);\n//         }\n//       }\n//       if (entry.getKey().startsWith(GEN_COMP_NAME)) {\n//         String comp_name_suffix = entry.getKey().substring(GEN_COMP_NAME.length());\n//         String c_name = (String)params.get(GEN_COMP_NAME + comp_name_suffix);\n//         for (String vhost: HOSTNAMES_PROP_VAL) {\n//           vhosts.add(c_name + \".\" + vhost);\n//         }\n//       }\n//     }\n//     HOSTNAMES_PROP_VAL = vhosts.toArray(new String[0]);\n//     hostnames = HOSTNAMES_PROP_VAL;\n//     props.put(HOSTNAMES_PROP_KEY, HOSTNAMES_PROP_VAL);\n\t\tprops.put(MAX_PACKET_WAITING_TIME_PROP_KEY, MAX_PACKET_WAITING_TIME_PROP_VAL);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"s2s\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Server connection manager\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\n\t\tint waiting_packets = 0;\n\t\tint open_s2s_connections = incoming.size();\n\t\tint connected_servers = 0;\n\t\tint server_connections_instances = connectionsByLocalRemote.size();\n\n\t\tfor (Map.Entry<CID, ServerConnections> entry : connectionsByLocalRemote.entrySet()) {\n\t\t\tServerConnections conn = entry.getValue();\n\n\t\t\twaiting_packets += conn.getWaitingPackets().size();\n\n\t\t\tif (conn.isOutgoingConnected()) {\n\t\t\t\t++open_s2s_connections;\n\t\t\t\t++connected_servers;\n\t\t\t}\n\n//    if (log.isLoggable(Level.FINEST)) {\n//      log.finest(\"s2s instance: \" + entry.getKey() +\n//              \", waitingQueue: \" + conn.getWaitingPackets().size() +\n//              \", outgoingIsNull(): \" + conn.outgoingIsNull() +\n//              \", outgoingActive: \" + conn.isOutgoingConnected() +\n//              \", OutgoingState: \" + conn.getOutgoingState().toString() +\n//              \", db_keys.size(): \" + conn.getDBKeysSize());\n//    }\n\t\t}\n\n\t\tlist.add(getName(), \"Open s2s connections\", open_s2s_connections, Level.FINE);\n\t\tlist.add(getName(), \"Packets queued\", waiting_packets, Level.FINE);\n\t\tlist.add(getName(), \"Connected servers\", connected_servers, Level.FINE);\n\t\tlist.add(getName(), \"Connection instances\", server_connections_instances, Level.FINER);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean handlesNonLocalDomains() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\n\t\t// Calculate hash code from the destination domain name to make sure packets for\n\t\t// a single domain are processed by the same thread to avoid race condition\n\t\t// creating new connection data structures for a destination domain\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\treturn packet.getStanzaTo().getDomain().hashCode();\n\t\t}\n\n\t\t// Otherwise, it might be a control packet which can be processed by single thread\n\t\treturn 1;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session_id\n\t *\n\t * \n\t */\n\tpublic boolean isIncomingValid(String session_id) {\n\t\tif (session_id == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tXMPPIOService<Object> serv = incoming.get(session_id);\n\n\t\tif ((serv == null) || (serv.getSessionData().get(\"valid\") == null)) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn (Boolean) serv.getSessionData().get(\"valid\");\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param serv\n\t */\n\tpublic synchronized void processDialback(Packet packet, XMPPIOService<Object> serv) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(serv + \", DIALBACK - \" + packet);\n\t\t}\n\n\t\tString local_hostname = packet.getStanzaTo().getDomain();\n\n\t\t// Check whether this is correct local host name...\n\t\tif ( !isLocalDomainOrComponent(local_hostname)) {\n\n\t\t\t// Ups, this hostname is not served by this server, return stream\n\t\t\t// error and close the connection....\n\t\t\tgenerateStreamError(\"host-unknown\", serv);\n\n\t\t\treturn;\n\t\t}\n\n\t\tString remote_hostname = packet.getStanzaFrom().getDomain();\n\n\t\t// And we don't want to accept any connection which is from remote\n\t\t// host name the same as one my localnames.......\n\t\tif (isLocalDomainOrComponent(remote_hostname)) {\n\n\t\t\t// Ups, remote hostname is the same as one of local hostname??\n\t\t\t// fake server or what? internal loop, we don't want that....\n\t\t\t// error and close the connection....\n\t\t\tgenerateStreamError(\"host-unknown\", serv);\n\n\t\t\treturn;\n\t\t}\n\n\t\tCID cid = getConnectionId(local_hostname, remote_hostname);\n\t\tServerConnections serv_conns = getServerConnections(cid);\n\t\tString session_id = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\t\tString serv_local_hostname = (String) serv.getSessionData().get(\"local-hostname\");\n\t\tString serv_remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n\t\tCID serv_cid = (serv_remote_hostname == null)\n\t\t\t? null : getConnectionId(serv_local_hostname, serv_remote_hostname);\n\n\t\tif ((serv_cid != null) &&!cid.equals(serv_cid)) {\n\t\t\tlog.info(serv + \", Somebody tries to reuse connection?\" + \" old_cid: \" + serv_cid\n\t\t\t\t\t+ \", new_cid: \" + cid);\n\t\t}\n\n\t\t// <db:result>\n\t\tif ((packet.getElemName() == RESULT_EL_NAME) || (packet.getElemName() == DB_RESULT_EL_NAME)) {\n\t\t\tif (packet.getType() == null) {\n\n\t\t\t\t// This is incoming connection with dialback key for verification\n\t\t\t\tif (packet.getElemCData() != null) {\n\n\t\t\t\t\t// db:result with key to validate from accept connection\n\t\t\t\t\tString db_key = packet.getElemCData();\n\n\t\t\t\t\t// initServiceMapping(local_hostname, remote_hostname, accept_jid, serv);\n\t\t\t\t\t// <db:result> with CDATA containing KEY\n\t\t\t\t\tElement elem = new Element(DB_VERIFY_EL_NAME, db_key, new String[] { \"id\", \"to\", \"from\",\n\t\t\t\t\t\t\tXMLNS_DB_ATT }, new String[] { session_id, remote_hostname, local_hostname,\n\t\t\t\t\t\t\tXMLNS_DB_VAL });\n\t\t\t\t\tPacket result = Packet.packetInstance(elem, null, null);\n\n\t\t\t\t\tif (serv_conns == null) {\n\t\t\t\t\t\tserv_conns = createNewServerConnections(cid, null);\n\t\t\t\t\t}\n\n\t\t\t\t\t// serv_conns.putDBKey(session_id, db_key);\n\t\t\t\t\tserv.getSessionData().put(\"remote-hostname\", remote_hostname);\n\t\t\t\t\tserv.getSessionData().put(\"local-hostname\", local_hostname);\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(serv + \", cid: \" + cid + \", sessionId: \" + session_id\n\t\t\t\t\t\t\t\t+ \", Counters: ioservices: \" + countIOServices() + \", s2s connections: \"\n\t\t\t\t\t\t\t\t\t+ countOpenConnections()\n\t\t\t\t\t\t\t\t\t\t+ (Packet.FULL_DEBUG ? \", all connections: \" + connectionsByLocalRemote : \"\"));\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !serv_conns.sendControlPacket(result) && serv_conns.needsConnection()) {\n\t\t\t\t\t\tcreateServerConnection(cid, result, serv_conns);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Incorrect dialback packet, it happens for some servers....\n\t\t\t\t\t// I don't know yet what software they use.\n\t\t\t\t\t// Let's just disconnect and signal unrecoverable conection error\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(serv + \", Incorrect diablack packet: \" + packet);\n\t\t\t\t\t}\n\n\t\t\t\t\tbouncePacketsBack(Authorization.SERVICE_UNAVAILABLE, cid);\n\t\t\t\t\tgenerateStreamError(\"bad-format\", serv);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// <db:result> with type 'valid' or 'invalid'\n\t\t\t\t// It means that session has been validated now....\n\t\t\t\t// XMPPIOService connect_serv = handshakingByHost_Type.get(connect_jid);\n\t\t\t\tswitch (packet.getType()) {\n\t\t\t\t\tcase valid :\n\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\tlog.finer(serv + \", Connection: \" + cid + \" is valid, adding to available services.\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tserv_conns.handleDialbackSuccess();\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault :\n\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\tlog.finer(serv + \", Connection: \" + cid + \" is invalid!! Stopping...\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tserv_conns.handleDialbackFailure();\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (packet.getType())\n\t\t\t}      // end of if (packet.getType() != null) else\n\t\t}        // end of if (packet != null && packet.getElemName().equals(\"db:result\"))\n\n\t\t// <db:verify> with type 'valid' or 'invalid'\n\t\tif ((packet.getElemName() == VERIFY_EL_NAME) || (packet.getElemName() == DB_VERIFY_EL_NAME)) {\n\t\t\tif (packet.getStanzaId() != null) {\n\t\t\t\tString forkey_session_id = packet.getStanzaId();\n\n\t\t\t\tif (packet.getType() == null) {\n\n\t\t\t\t\t// When type is NULL then it means this packet contains\n\t\t\t\t\t// data for verification\n\t\t\t\t\tif (packet.getElemCData() != null) {\n\t\t\t\t\t\tString db_key = packet.getElemCData();\n\n\t\t\t\t\t\t// This might be the first dialback packet from remote server\n//          serv.getSessionData().put(\"remote-hostname\", remote_hostname);\n//          serv.getSessionData().put(\"local-hostname\", local_hostname);\n//          serv_conns.addIncoming(session_id, serv);\n//          log.finest(\"cid: \" + cid + \", sessionId: \" + session_id\n//            + \", Counters: ioservices: \" + countIOServices()\n//            + \", s2s connections: \" + countOpenConnections());\n\t\t\t\t\t\t// initServiceMapping(local_hostname, remote_hostname, accept_jid, serv);\n\t\t\t\t\t\tString local_key = getLocalDBKey(cid, db_key, forkey_session_id, session_id);\n\n\t\t\t\t\t\tif (local_key == null) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.fine(serv + \", db key is not available for session ID: \" + forkey_session_id\n\t\t\t\t\t\t\t\t\t\t+ \", key for validation: \" + db_key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.fine(serv + \", Local key for cid=\" + cid + \" is \" + local_key);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tsendVerifyResult(local_hostname, remote_hostname, forkey_session_id,\n\t\t\t\t\t\t\t\t\tdb_key.equals(local_key), serv_conns, session_id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (packet.getElemName().equals(\"db:verify\"))\n\t\t\t\t} else {\n\n\t\t\t\t\t// Type is not null so this is packet with verification result.\n\t\t\t\t\t// If the type is valid it means accept connection has been\n\t\t\t\t\t// validated and we can now receive data from this channel.\n\t\t\t\t\tElement elem = new Element(DB_RESULT_EL_NAME, new String[] { \"type\", \"to\", \"from\",\n\t\t\t\t\t\t\tXMLNS_DB_ATT }, new String[] { packet.getType().toString(), remote_hostname,\n\t\t\t\t\t\t\tlocal_hostname, XMLNS_DB_VAL });\n\n\t\t\t\t\tsendToIncoming(forkey_session_id, Packet.packetInstance(elem, null, null));\n\t\t\t\t\tvalidateIncoming(forkey_session_id, (packet.getType() == StanzaType.valid));\n\t\t\t\t}    // end of if (packet.getType() == null) else\n\t\t\t} else {\n\n\t\t\t\t// Incorrect dialback packet, it happens for some servers....\n\t\t\t\t// I don't know yet what software they use.\n\t\t\t\t// Let's just disconnect and signal unrecoverable conection error\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.finer(serv + \", Incorrect diablack packet: \" + packet);\n\t\t\t\t}\n\n\t\t\t\tbouncePacketsBack(Authorization.SERVICE_UNAVAILABLE, cid);\n\t\t\t\tgenerateStreamError(\"bad-format\", serv);\n\t\t\t}\n\t\t}        // end of if (packet != null && packet.getType() != null)\n\t}\n\n\t@Override\n\tpublic void processPacket(Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet.toString());\n\t\t}\n\n\t\tif ( !packet.isCommand() ||!processCommand(packet)) {\n\t\t\tif (packet.getStanzaTo() == null) {\n\t\t\t\tlog.warning(\"Missing 'to' attribute, ignoring packet...\" + packet\n\t\t\t\t\t\t+ \"\\n This most likely happens due to missconfiguration of components\"\n\t\t\t\t\t\t\t+ \" domain names.\");\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (packet.getStanzaFrom() == null) {\n\t\t\t\tlog.warning(\"Missing 'from' attribute, ignoring packet...\" + packet);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Check whether addressing is correct:\n\t\t\tString to_hostname = packet.getStanzaTo().getDomain();\n\n\t\t\t// We don't send packets to local domains trough s2s, there\n\t\t\t// must be something wrong with configuration\n\t\t\tif (isLocalDomainOrComponent(to_hostname)) {\n\n\t\t\t\t// Ups, remote hostname is the same as one of local hostname??\n\t\t\t\t// Internal loop possible, we don't want that....\n\t\t\t\t// Let's send the packet back....\n\t\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\t\tlog.info(\"Packet addresses to localhost, I am not processing it: \" + packet);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"S2S - not delivered. Server missconfiguration.\", true));\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.warning(\"Packet processing exception: \" + e);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// I think from_hostname needs to be different from to_hostname at\n\t\t\t// this point... or s2s doesn't make sense\n\t\t\tString from_hostname = packet.getStanzaFrom().getDomain();\n\n\t\t\t// All hostnames go through String.intern()\n\t\t\tif (to_hostname == from_hostname) {\n\t\t\t\tlog.warning(\"Dropping incorrect packet - from_hostname == to_hostname: \" + packet);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tCID cid = getConnectionId(packet);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Connection ID is: \" + cid);\n\t\t\t}\n\n\t\t\tServerConnections serv_conn = getServerConnections(cid);\n\t\t\tPacket server_packet = packet.copyElementOnly();\n\n\t\t\tserver_packet.getElement().removeAttribute(\"xmlns\");\n\n//    if (server_packet.getXMLNS() == XMLNS_CLIENT_VAL) {\n//      server_packet.getElement().setXMLNS(XMLNS_SERVER_VAL);\n//    }\n\t\t\tif ((serv_conn == null)\n\t\t\t\t\t|| ( !serv_conn.sendPacket(server_packet) && serv_conn.needsConnection())) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Couldn't send packet, creating a new connection: \" + cid);\n\t\t\t\t}\n\n\t\t\t\tcreateServerConnection(cid, server_packet, serv_conn);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Packet seems to be sent correctly: \" + server_packet);\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of else\n\t}\n\n\t@Override\n\tpublic Queue<Packet> processSocketData(XMPPIOService<Object> serv) {\n\t\tQueue<Packet> packets = serv.getReceivedPackets();\n\t\tPacket p = null;\n\n\t\twhile ((p = packets.poll()) != null) {\n\n//    log.finer(\"Processing packet: \" + p.getElemName()\n//      + \", type: \" + p.getType());\n\t\t\tif (p.getXMLNS() == XMLNS_SERVER_VAL) {\n\t\t\t\tp.getElement().setXMLNS(XMLNS_CLIENT_VAL);\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(serv + \", Processing socket data: \" + p);\n\t\t\t}\n\n\t\t\tif (p.getXMLNS() == XMLNS_DB_VAL) {\n\t\t\t\tprocessDialback(p, serv);\n\t\t\t} else {\n\t\t\t\tif (p.getElemName() == \"error\") {\n\t\t\t\t\tprocessStreamError(p, serv);\n\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\tif (checkPacket(p, serv)) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(serv + \", Adding packet out: \" + p);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\taddOutPacket(p);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of else\n\t\t}      // end of while ()\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean processUndeliveredPacket(Packet packet, Long stamp, String errorMessage) {\n\t\t// readd packet - this may be good as we would retry to send packet \n\t\t// which delivery failed due to IO error\n\t\taddPacket(packet);\n\t\treturn true;\n\t}\n\t\n\t@Override\n\tpublic void reconnectionFailed(Map<String, Object> port_props) {\n\n\t\t// TODO: handle this somehow\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session_id\n\t * @param packet\n\t *\n\t * \n\t */\n\tpublic boolean sendToIncoming(String session_id, Packet packet) {\n\t\tXMPPIOService<Object> serv = incoming.get(session_id);\n\n\t\tif (serv != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(serv + \", Sending to incoming connection: \" + session_id + \" packet: \" + packet);\n\t\t\t}\n\n\t\t\treturn writePacketToSocket(serv, packet);\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Trying to send packet: \" + packet + \" to nonexisten connection with sessionId: \"\n\t\t\t\t\t\t+ session_id);\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void serviceStarted(XMPPIOService<Object> serv) {\n\t\tsuper.serviceStarted(serv);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"s2s connection opened: \" + serv);\n\t\t}\n\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect :\n\n\t\t\t\t// Send init xmpp stream here\n\t\t\t\t// XMPPIOService serv = (XMPPIOService)service;\n\t\t\t\tString data = \"<stream:stream\" + \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t\t+ \" xmlns='jabber:server'\" + \" xmlns:db='jabber:server:dialback'\" + \">\";\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(serv + \", sending: \" + data);\n\t\t\t\t}\n\n\t\t\t\tserv.xmppStreamOpen(data);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t}    // end of switch (service.connectionType())\n\t}\n\n\t@Override\n\tpublic boolean serviceStopped(XMPPIOService<Object> serv) {\n\t\tboolean result = super.serviceStopped(serv);\n\n\t\tif (result) {\n\t\t\tswitch (serv.connectionType()) {\n\t\t\t\tcase connect :\n\t\t\t\t\tString local_hostname = (String) serv.getSessionData().get(\"local-hostname\");\n\t\t\t\t\tString remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n\n\t\t\t\t\tif (remote_hostname == null) {\n\n\t\t\t\t\t\t// There is something wrong...\n\t\t\t\t\t\t// It may happen only when remote host connecting to Tigase\n\t\t\t\t\t\t// closed connection before it send any db:... packet\n\t\t\t\t\t\t// so remote domain is not known.\n\t\t\t\t\t\t// Let's do nothing for now.\n\t\t\t\t\t\tlog.info(serv + \", remote-hostname is NULL, local-hostname: \" + local_hostname\n\t\t\t\t\t\t\t\t+ \", local address: \" + serv.getLocalAddress() + \", remote address: \"\n\t\t\t\t\t\t\t\t\t+ serv.getRemoteAddress());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCID cid = getConnectionId(local_hostname, remote_hostname);\n\t\t\t\t\t\tServerConnections serv_conns = getServerConnections(cid);\n\n\t\t\t\t\t\tif (serv_conns == null) {\n\t\t\t\t\t\t\tlog.warning(\"There is no ServerConnections for stopped service: \" + serv + \", cid: \"\n\t\t\t\t\t\t\t\t\t+ cid);\n\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.finest(serv + \", Counters: ioservices: \" + countIOServices()\n\t\t\t\t\t\t\t\t\t\t+ \", s2s active conns: \" + countOpenConnections()\n\t\t\t\t\t\t\t\t\t\t\t+ (Packet.FULL_DEBUG\n\t\t\t\t\t\t\t\t\t\t\t\t? \", all connections: \" + connectionsByLocalRemote : \"\"));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tserv_conns.serviceStopped(serv);\n\n\t\t\t\t\t\tQueue<Packet> waiting = serv_conns.getWaitingPackets();\n\n\t\t\t\t\t\tif (waiting.size() > 0) {\n\t\t\t\t\t\t\tif (serv_conns.waitingTime() > maxPacketWaitingTime) {\n\t\t\t\t\t\t\t\tbouncePacketsBack(Authorization.REMOTE_SERVER_TIMEOUT, cid);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcreateServerConnection(cid, null, serv_conns);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase accept :\n\t\t\t\t\tString session_id = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\n\t\t\t\t\tif (session_id != null) {\n\t\t\t\t\t\tXMPPIOService<Object> rem = incoming.remove(session_id);\n\n\t\t\t\t\t\tif (rem == null) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.fine(serv + \", No service with given SESSION_ID: \" + session_id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tlog.finer(serv + \", Connection removed: \" + session_id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.fine(serv + \", session_id is null, didn't remove the connection\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tlog.severe(serv + \", Warning, program shouldn't reach that point.\");\n\n\t\t\t\t\tbreak;\n\t\t\t}    // end of switch (serv.connectionType())\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(serv + \", Counters: ioservices: \" + countIOServices() + \", s2s active conns: \"\n\t\t\t\t\t\t+ countOpenConnections()\n\t\t\t\t\t\t\t+ (Packet.FULL_DEBUG ? \", all connections: \" + connectionsByLocalRemote : \"\"));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\n//  hostnames = (String[])props.get(HOSTNAMES_PROP_KEY);\n//  if (hostnames == null || hostnames.length == 0) {\n//    log.warning(\"Hostnames definition is empty, setting 'localhost'\");\n//    hostnames = new String[] {\"localhost\"};\n//  } // end of if (hostnames == null || hostnames.length == 0)\n//  Arrays.sort(hostnames);\n//  addRouting(\"*\");\n\t\tmaxPacketWaitingTime = (Long) props.get(MAX_PACKET_WAITING_TIME_PROP_KEY);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void tlsHandshakeCompleted(XMPPIOService<Object> service) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session_id\n\t * @param valid\n\t */\n\tpublic void validateIncoming(String session_id, boolean valid) {\n\t\tXMPPIOService<Object> serv = incoming.get(session_id);\n\n\t\tif (serv != null) {\n\t\t\tserv.getSessionData().put(\"valid\", valid);\n\n\t\t\tif ( !valid) {\n\t\t\t\tserv.stop();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void xmppStreamClosed(XMPPIOService<Object> serv) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(serv + \", Stream closed: \" + getConnectionId(serv));\n\t\t}\n\t}\n\n\t@Override\n\tpublic String xmppStreamOpened(XMPPIOService<Object> serv, Map<String, String> attribs) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.finer(serv + \", Stream opened: \" + attribs.toString());\n\t\t}\n\n\t\tserv.getSessionData().put(\"xmlns\", XMLNS_SERVER_VAL);\n\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect : {\n\n\t\t\t\t// It must be always set for connect connection type\n\t\t\t\tString remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n\t\t\t\tString local_hostname = (String) serv.getSessionData().get(\"local-hostname\");\n\t\t\t\tCID cid = getConnectionId(local_hostname, remote_hostname);\n\t\t\t\tString remote_id = attribs.get(\"id\");\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(serv + \", Connect Stream opened for: \" + cid + \", session id\" + remote_id);\n\t\t\t\t}\n\n\t\t\t\tServerConnections serv_conns = getServerConnections(cid);\n\n\t\t\t\tif (serv_conns == null) {\n\t\t\t\t\tserv_conns = createNewServerConnections(cid, null);\n\t\t\t\t}\n\n\t\t\t\tserv_conns.addOutgoing(serv);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(serv + \", Counters: ioservices: \" + countIOServices() + \", s2s active conns: \"\n\t\t\t\t\t\t\t+ countOpenConnections()\n\t\t\t\t\t\t\t\t+ (Packet.FULL_DEBUG ? \", all connections: \" + connectionsByLocalRemote : \"\"));\n\t\t\t\t}\n\n\t\t\t\tserv.getSessionData().put(XMPPIOService.SESSION_ID_KEY, remote_id);\n\n\t\t\t\tString uuid = UUID.randomUUID().toString();\n\t\t\t\tString key = null;\n\n\t\t\t\ttry {\n\t\t\t\t\tkey = Algorithms.hexDigest(remote_id, uuid, \"SHA\");\n\t\t\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\t\t\tkey = uuid;\n\t\t\t\t}    // end of try-catch\n\n\t\t\t\tserv_conns.putDBKey(remote_id, key);\n\n\t\t\t\tElement elem = new Element(DB_RESULT_EL_NAME, key, new String[] { \"from\", \"to\",\n\t\t\t\t\t\tXMLNS_DB_ATT }, new String[] { local_hostname, remote_hostname, XMLNS_DB_VAL });\n\n\t\t\t\tserv_conns.addControlPacket(Packet.packetInstance(elem, null, null));\n\t\t\t\tserv_conns.sendAllControlPackets();\n\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tcase accept : {\n\t\t\t\tString remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n\t\t\t\tString local_hostname = (String) serv.getSessionData().get(\"local-hostname\");\n\t\t\t\tCID cid = getConnectionId(local_hostname, remote_hostname);\n\t\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(serv + \", Accept Stream opened for: \" + cid + \", session id: \" + id);\n\t\t\t\t}\n\n\t\t\t\tif (remote_hostname != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.fine(serv\n\t\t\t\t\t\t\t\t+ \", Opening stream for already established connection...., trying to turn\"\n\t\t\t\t\t\t\t\t\t+ \" on TLS????\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// We don't know hostname yet so we have to save session-id in\n\t\t\t\t// connection temp data\n\t\t\t\tserv.getSessionData().put(XMPPIOService.SESSION_ID_KEY, id);\n\t\t\t\tincoming.put(id, serv);\n\n\t\t\t\treturn \"<stream:stream\" + \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t\t\t+ \" xmlns='jabber:server'\" + \" xmlns:db='jabber:server:dialback'\" + \" id='\" + id + \"'\"\n\t\t\t\t\t\t\t+ \">\"\n\t\t\t\t;\n\t\t\t}\n\n\t\t\tdefault :\n\t\t\t\tlog.severe(serv + \", Warning, program shouldn't reach that point.\");\n\n\t\t\t\tbreak;\n\t\t}    // end of switch (serv.connectionType())\n\n\t\treturn null;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tprotected int[] getDefPlainPorts() {\n\t\treturn new int[] { 5269 };\n\t}\n\n\tprotected String getLocalDBKey(CID cid, String key, String forkey_sessionId,\n\t\t\tString asking_sessionId) {\n\t\tServerConnections serv_conns = getServerConnections(cid);\n\n\t\treturn (serv_conns == null) ? null : serv_conns.getDBKey(forkey_sessionId);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Let's assume s2s should send something at least once every 15 minutes....\n\t */\n\t@Override\n\tprotected long getMaxInactiveTime() {\n\t\treturn 15 * MINUTE;\n\t}\n\n\tprotected ServerConnections getServerConnections(CID cid) {\n\t\treturn connectionsByLocalRemote.get(cid);\n\t}\n\n\t@Override\n\tprotected XMPPIOService<Object> getXMPPIOServiceInstance() {\n\t\treturn new XMPPIOService<Object>();\n\t}\n\n\t@Override\n\tprotected boolean isHighThroughput() {\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected ServerConnections removeServerConnections(CID cid) {\n\t\treturn connectionsByLocalRemote.remove(cid);\n\t}\n\n\tprotected void sendVerifyResult(String from, String to, String forkey_sessionId, boolean valid,\n\t\t\tServerConnections serv_conns, String asking_sessionId) {\n\t\tString type = (valid ? \"valid\" : \"invalid\");\n\t\tElement result_el = new Element(DB_VERIFY_EL_NAME, new String[] { \"from\", \"to\", \"id\", \"type\",\n\t\t\t\tXMLNS_DB_ATT }, new String[] { from, to, forkey_sessionId, type, XMLNS_DB_VAL });\n\t\tPacket result = Packet.packetInstance(result_el, null, null);\n\n\t\tif ( !sendToIncoming(asking_sessionId, result)) {\n\t\t\tlog.warning(\"Can not send verification packet back: \" + result.toString());\n\t\t}\n\t}\n\n\tprivate void bouncePacketsBack(Authorization author, CID cid) {\n\t\tServerConnections serv_conns = getServerConnections(cid);\n\n\t\tif (serv_conns != null) {\n\t\t\tQueue<Packet> waiting = serv_conns.getWaitingPackets();\n\t\t\tPacket p = null;\n\n\t\t\twhile ((p = waiting.poll()) != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending packet back: \" + p);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(author.getResponseMessage(p, \"S2S - not delivered\", true));\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.info(\"Packet processing exception: \" + e);\n\t\t\t\t}\n\t\t\t}    // end of while (p = waitingPackets.remove(ipAddress) != null)\n\t\t} else {\n\t\t\tlog.info(\"No ServerConnections for cid: \" + cid);\n\t\t}\n\t}\n\n\tprivate boolean checkPacket(Packet packet, XMPPIOService<Object> serv) {\n\t\tJID packet_from = packet.getStanzaFrom();\n\t\tJID packet_to = packet.getStanzaTo();\n\n\t\tif ((packet_from == null) || (packet_to == null)) {\n\t\t\tgenerateStreamError(\"improper-addressing\", serv);\n\n\t\t\treturn false;\n\t\t}\n\n\t\tString remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n\n\t\tif ( !packet_from.getDomain().equals(remote_hostname)) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(serv + \", Invalid hostname from the remote server, expected: \" + remote_hostname);\n\t\t\t}\n\n\t\t\tgenerateStreamError(\"invalid-from\", serv);\n\n\t\t\treturn false;\n\t\t}\n\n\t\tString local_hostname = (String) serv.getSessionData().get(\"local-hostname\");\n\n\t\tif ( !packet_to.getDomain().equals(local_hostname)) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(serv + \", Invalid hostname of the local server, expected: \" + local_hostname);\n\t\t\t}\n\n\t\t\tgenerateStreamError(\"host-unknown\", serv);\n\n\t\t\treturn false;\n\t\t}\n\n\t\tString session_id = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\n\t\tif ( !isIncomingValid(session_id)) {\n\t\t\tlog.info(serv + \", Incoming connection hasn't been validated\");\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate int countOpenConnections() {\n\n\t\t// int open_s2s_connections = incoming.size();\n\t\tint open_s2s_connections = 0;\n\n\t\tfor (Map.Entry<CID, ServerConnections> entry : connectionsByLocalRemote.entrySet()) {\n\t\t\tServerConnections conn = entry.getValue();\n\n\t\t\tif (conn.isOutgoingConnected()) {\n\t\t\t\t++open_s2s_connections;\n\t\t\t}\n\t\t}\n\n\t\treturn open_s2s_connections;\n\t}\n\n\tprivate ServerConnections createNewServerConnections(CID cid, Packet packet) {\n\t\tServerConnections conns = new ServerConnections(this, cid);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Creating a new ServerConnections instance: {0}\", conns);\n\t\t}\n\n\t\tif (packet != null) {\n\n\t\t\t// XMLNS is processed through String.intern()\n\t\t\tif (packet.getElement().getXMLNS() == XMLNS_DB_VAL) {\n\t\t\t\tconns.addControlPacket(packet);\n\t\t\t} else {\n\t\t\t\tconns.addDataPacket(packet);\n\t\t\t}\n\t\t}\n\n\t\tconnectionsByLocalRemote.put(cid, conns);\n\n\t\treturn conns;\n\t}\n\n\t/**\n\t * Method <code>createServerConnection</code> is called only when a new\n\t * connection is needed for any reason for given hostnames combination.\n\t *\n\t * @param cid a <code>String</code> s2s connection ID (localhost@remotehost)\n\t * @param packet a <code>Packet</code> packet to send, should be passed to the\n\t * ServerConnections only when it was null.\n\t * @param serv_conn a <code>ServerConnections</code> which was called for\n\t * the packet.\n\t */\n\tprivate void createServerConnection(final CID cid, final Packet packet,\n\t\t\tfinal ServerConnections serv_conn) {\n\n\t\t// Create a new connection data structures first if it they does not yet exist\n\t\t// to avoid creating them within a separate thread, which leads to a multiple\n\t\t// instances of such structures and general protocol failure\n\t\tfinal ServerConnections sconn = ((serv_conn == null)\n\t\t\t? createNewServerConnections(cid, packet) : serv_conn);\n\n\t\tsconn.setConnecting();\n\t\tnew ConnectionWatchdogTask(sconn, cid.getLocalHost(), cid.getRemoteHost());\n\n\t\t// Spawning a new thread for each new server connection is not the most\n\t\t// optimal solution but I have no idea how to do it better and solve\n\t\t// the long DNS resolution problem.\n\t\t// On the other hand, new server connections are not opened as often\n\t\t// so it should not be a big problem. Let's see how it works.\n\t\tThread new_connection_thread = new Thread(\"NewServerConnection-\"\n\t\t\t+ (++new_connection_thread_counter)) {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tcreateServerConnectionInThread(cid, packet, sconn);\n\t\t\t}\n\t\t};\n\n\t\tnew_connection_thread.start();\n\t}\n\n\tprivate void createServerConnectionInThread(CID cid, Packet packet, ServerConnections serv_conn) {\n\t\tServerConnections conns = serv_conn;\n\t\tString localhost = cid.getLocalHost();\n\t\tString remotehost = cid.getRemoteHost();\n\n\t\tif (openNewServerConnection(localhost, remotehost)) {\n\n//    conns.setConnecting();\n//    new ConnectionWatchdogTask(conns, localhost, remotehost);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Connecting a new s2s service: \" + conns);\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Couldn't open a new s2s service: (UknownHost??) \" + conns);\n\t\t\t}\n\n\t\t\t// Can't establish connection...., unknown host??\n\t\t\tQueue<Packet> waitingPackets = conns.getWaitingPackets();\n\n\t\t\t// Well, is somebody injects a packet with the same sender and\n\t\t\t// receiver domain and this domain is not valid then we have\n\t\t\t// infinite loop here....\n\t\t\t// Let's try to handle this by dropping such packet.\n\t\t\t// It may happen as well that the source domain is different from\n\t\t\t// target domain and both are invalid, what then?\n\t\t\t// The best option would be to drop the packet if it is already an\n\t\t\t// error - remote-server-not-found....\n\t\t\t// For dialback packet just ignore the error completely as it means\n\t\t\t// remote server tries to connect from domain which doesn't exist\n\t\t\t// in DNS so no further action should be performed.\n\t\t\tPacket p = null;\n\n\t\t\twhile ((p = waitingPackets.poll()) != null) {\n\t\t\t\tif (p.getElement().getXMLNS() != XMLNS_DB_VAL) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddOutPacket(Authorization.REMOTE_SERVER_NOT_FOUND.getResponseMessage(p,\n\t\t\t\t\t\t\t\t\"S2S - destination host not found\", true));\n\t\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\t\tlog.warning(\"Packet: \" + p.toString() + \" processing exception: \" + e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconns.stopAll();\n\n\t\t\t// connectionsByLocalRemote.remove(cid);\n\t\t}\n\t}\n\n\tprivate void generateStreamError(String error_el, XMPPIOService<Object> serv) {\n\t\tElement error = new Element(\"stream:error\",\n\t\t\tnew Element[] {\n\t\t\t\tnew Element(error_el, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-streams\" }) }, null, null);\n\n\t\ttry {\n\t\t\twriteRawData(serv, error.toString());\n\n//    serv.writeRawData(error.toString());\n//    serv.writeRawData(\"</stream:stream>\");\n\t\t\tserv.stop();\n\t\t} catch (Exception e) {\n\t\t\tserv.forceStop();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate CID getConnectionId(String localhost, String remotehost) {\n\t\treturn new CID(localhost, remotehost);\n\t}\n\n\tprivate CID getConnectionId(Packet packet) {\n\t\treturn new CID(packet.getStanzaFrom().getDomain(), packet.getStanzaTo().getDomain());\n\t}\n\n\tprivate CID getConnectionId(XMPPIOService<Object> service) {\n\t\tString local_hostname = (String) service.getSessionData().get(\"local-hostname\");\n\t\tString remote_hostname = (String) service.getSessionData().get(\"remote-hostname\");\n\t\tCID cid = getConnectionId(local_hostname, remote_hostname);\n\n\t\treturn cid;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n//private void dumpCurrentStack(StackTraceElement[] stack) {\n//  StringBuilder sb = new StringBuilder();\n//  for (StackTraceElement st_el: stack) {\n//    sb.append(\"\\n\" + st_el.toString());\n//  }\n//  log.finest(sb.toString());\n//}\n\tprivate boolean openNewServerConnection(String localhost, String remotehost) {\n\n\t\t// dumpCurrentStack(Thread.currentThread().getStackTrace());\n\t\ttry {\n\t\t\tDNSEntry dns_entry = DNSResolverFactory.getInstance().getHostSRV_Entry(remotehost);\n\t\t\tMap<String, Object> port_props = new TreeMap<String, Object>();\n\n\t\t\tport_props.put(\"remote-ip\", dns_entry.getIp());\n\t\t\tport_props.put(\"local-hostname\", localhost);\n\t\t\tport_props.put(\"remote-hostname\", remotehost);\n\t\t\tport_props.put(\"ifc\", new String[] { dns_entry.getIp() });\n\t\t\tport_props.put(\"socket\", SocketType.plain);\n\t\t\tport_props.put(\"type\", ConnectionType.connect);\n\t\t\tport_props.put(\"port-no\", dns_entry.getPort());\n\n\t\t\tCID cid = getConnectionId(localhost, remotehost);\n\n\t\t\tport_props.put(\"cid\", cid);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"STARTING new connection: \" + cid);\n\t\t\t}\n\n\t\t\taddWaitingTask(port_props);\n\n\t\t\t// reconnectService(port_props, 5*SECOND);\n\t\t\treturn true;\n\t\t} catch (UnknownHostException e) {\n\t\t\tlog.info(\"UnknownHostException for host: \" + remotehost);\n\n\t\t\treturn false;\n\t\t}    // end of try-catch\n\t}\n\n\tprivate boolean processCommand(final Packet packet) {\n\n\t\t// XMPPIOService serv = getXMPPIOService(packet);\n\t\tswitch (packet.getCommand()) {\n\t\t\tcase STARTTLS :\n\t\t\t\tbreak;\n\n\t\t\tcase STREAM_CLOSED :\n\t\t\t\tbreak;\n\n\t\t\tcase GETDISCO :\n\t\t\t\tbreak;\n\n\t\t\tcase CLOSE :\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tbreak;\n\t\t}    // end of switch (pc.getCommand())\n\n\t\treturn false;\n\t}\n\n\tprivate void processStreamError(Packet packet, XMPPIOService<Object> serv) {\n\t\tAuthorization author = Authorization.RECIPIENT_UNAVAILABLE;\n\n\t\tif (packet.getElement().getChild(\"host-unknown\") != null) {\n\t\t\tauthor = Authorization.REMOTE_SERVER_NOT_FOUND;\n\t\t}\n\n\t\tCID cid = getConnectionId(serv);\n\n\t\tbouncePacketsBack(author, cid);\n\t\tserv.stop();\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class ConnectionWatchdogTask extends tigase.util.TimerTask {\n\t\tprivate ServerConnections conns = null;\n\t\tprivate String localhost = null;\n\t\tprivate String remotehost = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate ConnectionWatchdogTask(ServerConnections conns, String localhost, String remotehost) {\n\t\t\tthis.conns = conns;\n\t\t\tthis.localhost = localhost;\n\t\t\tthis.remotehost = remotehost;\n\n\t\t\tString key = localhost + remotehost;\n\t\t\ttigase.util.TimerTask task = waitingTaskFutures.get(key);\n\n\t\t\tif (task != null) {\n\t\t\t\ttask.cancel();\n\t\t\t}\n\n\t\t\taddTimerTask(this, 15, TimeUnit.SECONDS);\n\t\t\twaitingTaskFutures.put(key, task);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tString key = localhost + remotehost;\n\n\t\t\twaitingTaskFutures.remove(key);\n\n\t\t\tif (conns.getOutgoingState() != ServerConnections.OutgoingState.OK) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Connecting timeout expired, still connecting: \" + conns);\n\t\t\t\t}\n\n\t\t\t\tconns.stopAll();\n\n\t\t\t\tQueue<Packet> waiting = conns.getWaitingPackets();\n\n\t\t\t\tif (waiting.size() > 0) {\n\t\t\t\t\tif (conns.waitingTime() > maxPacketWaitingTime) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Max packets waiting time expired, sending all back: \" + conns);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbouncePacketsBack(Authorization.REMOTE_SERVER_TIMEOUT, conns.getCID());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Reconnecting: \" + conns);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcreateServerConnection(conns.getCID(), null, conns);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"No packets waiting in queue, giving up: \" + conns);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Connecting timeout expired: \" + conns);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/ServerConnections.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppserver;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.XMPPIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class ServerConnections here.\n *\n *\n * Created: Wed Jun 11 14:26:53 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ServerConnections {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log =\n\t\tLogger.getLogger(\"tigase.server.xmppserver.ServerConnections\");\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum OutgoingState {\n\t\tNULL, CONNECTING, HANDSHAKING, OK;\n\t}\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CID cid = null;\n\tprivate ConnectionHandlerIfc<XMPPIOService<Object>> handler = null;\n\n\t/**\n\t * Outgoing (connect) service for data packets.\n\t */\n\tprivate XMPPIOService<Object> outgoing = null;\n\tprivate OutgoingState conn_state = OutgoingState.NULL;\n\tprivate long receivedPackets = 0;\n\tprivate long sentPackets = 0;\n\n///**\n// * Incoming (accept) services session:id. Some servers (EJabberd) opens\n// * many connections for each domain, especially when in cluster mode.\n// */\n//private ConcurrentHashMap<String, XMPPIOService> incoming =\n//   new ConcurrentHashMap<String, XMPPIOService>();\n\n\t/**\n\t * Normal packets between users on different servers\n\t */\n\tprivate ConcurrentLinkedQueue<Packet> waitingPackets = new ConcurrentLinkedQueue<Packet>();\n\n\t/**\n\t * Controll packets for s2s connection establishing\n\t */\n\tprivate ConcurrentLinkedQueue<Packet> waitingControlPackets =\n\t\tnew ConcurrentLinkedQueue<Packet>();\n\tprivate ConcurrentHashMap<String, String> db_keys = new ConcurrentHashMap<String, String>();\n\n\t/**\n\t * Keeps the creation time. After some time the queue and all\n\t * packets waiting to send should become outdated and they\n\t * should be returned to sender and no more attempts to connect\n\t * to the remote server should be performed.\n\t */\n\tprivate long creationTime = System.currentTimeMillis();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>ServerConnections</code> instance.\n\t *\n\t *\n\t * @param handler\n\t * @param cid\n\t */\n\tpublic ServerConnections(ConnectionHandlerIfc<XMPPIOService<Object>> handler, CID cid) {\n\t\tthis.handler = handler;\n\t\tthis.cid = cid;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void addControlPacket(Packet packet) {\n\t\twaitingControlPackets.offer(packet);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void addDataPacket(Packet packet) {\n\t\tif (waitingPackets.size() == 0) {\n\t\t\tcreationTime = System.currentTimeMillis();\n\t\t}\n\n\t\twaitingPackets.offer(packet);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic synchronized void addOutgoing(XMPPIOService<Object> serv) {\n\t\tXMPPIOService<Object> old = outgoing;\n\n\t\tif (outgoing != serv) {\n\t\t\toutgoing = serv;\n\t\t\tconn_state = OutgoingState.HANDSHAKING;\n\t\t}\n\n\t\tif (old != null) {\n\t\t\tlog.info(\"Old outgoing connection: \" + old + \" replaced with new one: \" + outgoing);\n\t\t\told.forceStop();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic CID getCID() {\n\t\treturn cid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sessionId\n\t *\n\t * \n\t */\n\tpublic String getDBKey(String sessionId) {\n\t\treturn db_keys.get(sessionId);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic int getDBKeysSize() {\n\t\treturn db_keys.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic OutgoingState getOutgoingState() {\n\t\treturn conn_state;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Queue<Packet> getWaitingPackets() {\n\t\treturn waitingPackets;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic synchronized void handleDialbackFailure() {\n\t\tif (outgoing != null) {\n\t\t\toutgoing.forceStop();\n\t\t\toutgoing = null;\n\t\t}\n\n\t\tconn_state = OutgoingState.NULL;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic synchronized boolean handleDialbackSuccess() {\n\t\tif ((outgoing != null) && (conn_state == OutgoingState.HANDSHAKING)) {\n\t\t\tsetValid();\n\n\t\t\tArrayDeque<Packet> all = new ArrayDeque<Packet>();\n\t\t\tPacket packet = null;\n\n\t\t\twhile ((packet = waitingControlPackets.poll()) != null) {\n\t\t\t\tall.offer(packet);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending on connection: \" + outgoing + \" control packet: \" + packet);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsentPackets += waitingPackets.size();\n\n\t\t\twhile ((packet = waitingPackets.poll()) != null) {\n\t\t\t\tall.offer(packet);\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending on connection: \" + outgoing + \" packet: \" + packet);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thandler.writePacketsToSocket(outgoing, all);\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\tlog.warning(\"Something wrong, the method was called when the outgoing \"\n\t\t\t\t\t+ \"connection is null for cid: \" + cid);\n\t\t\toutgoing = null;\n\t\t\tconn_state = OutgoingState.NULL;\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t *\n\t * \n\t */\n\tpublic boolean isOutgoing(XMPPIOService<Object> serv) {\n\t\treturn serv == outgoing;\n\t}\n\n//public void addIncoming(String session_id, XMPPIOService serv) {\n//  if (serv == outgoing) {\n//    log.info(\"Adding outgoing connection as incoming, packet received on \"\n\t// + \"wrong connection? session_id: \" + session_id);\n//    return;\n//  }\n//  XMPPIOService old_serv = incoming.get(session_id);\n//  if (old_serv != null) {\n//    if (old_serv == serv) {\n//      log.info(\"Adding again the same handshaking service session_id: \"\n//        + session_id + \", unique_id: \" + serv.getUniqueId());\n//      return;\n//    } else {\n//      log.info(\"Adding new handshaking service when the old one for the\"\n//        + \" same session_id exists: \"\n//        + session_id + \", new_unique_id: \" + serv.getUniqueId()\n//        + \", old_unique_id: \" + old_serv.getUniqueId());\n//      old_serv.forceStop();\n//    }\n//  }\n//  incoming.put(session_id, serv);\n//}\n//public boolean sendToIncoming(String session_id, Packet packet) {\n//  XMPPIOService serv = incoming.get(session_id);\n//  if (serv != null) {\n//    return handler.writePacketToSocket(serv, packet);\n//  } else {\n//    return false;\n//  }\n//}\n//public void validateIncoming(String session_id, boolean valid) {\n//  XMPPIOService serv = incoming.get(session_id);\n//  if (serv != null) {\n//    serv.getSessionData().put(\"valid\", valid);\n//    if (!valid) {\n//      serv.stop();\n//    }\n//  }\n//}\n//public boolean isIncomingValid(String session_id) {\n//  if (session_id == null) {\n//    return false;\n//  }\n//  XMPPIOService serv = incoming.get(session_id);\n//  if (serv == null || serv.getSessionData().get(\"valid\") == null) {\n//    return false;\n//  } else {\n//    return (Boolean)serv.getSessionData().get(\"valid\");\n//  }\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean isOutgoingConnected() {\n\t\treturn (outgoing != null) && outgoing.isConnected();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean needsConnection() {\n\t\treturn (conn_state == OutgoingState.NULL);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean outgoingIsNull() {\n\t\treturn outgoing == null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param sessionId\n\t * @param dbKey\n\t */\n\tpublic void putDBKey(String sessionId, String dbKey) {\n\t\tdb_keys.put(sessionId, dbKey);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic synchronized boolean sendAllControlPackets() {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tfor (Packet packet : waitingControlPackets) {\n\t\t\t\tlog.finest(\"Sending on connection: \" + outgoing + \" control packet: \" + packet);\n\t\t\t}\n\t\t}\n\n\t\thandler.writePacketsToSocket(outgoing, waitingControlPackets);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t *\n\t * \n\t */\n\tpublic synchronized boolean sendControlPacket(Packet packet) {\n\t\tboolean result = false;\n\n\t\tif ((outgoing != null) && outgoing.isConnected()\n\t\t\t\t&& ((conn_state == OutgoingState.OK) || (conn_state == OutgoingState.HANDSHAKING))) {\n\t\t\tresult = handler.writePacketToSocket(outgoing, packet);\n\n\t\t\tif ( !result) {\n\t\t\t\toutgoing.forceStop();\n\t\t\t\toutgoing = null;\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sent on connection: \" + outgoing + \" control packet: \" + packet);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( !result) {\n\t\t\taddControlPacket(packet);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Connection not ready: \" + outgoing + \" control packet added to waiting: \"\n\t\t\t\t\t\t+ packet);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Describe <code>sendPacket</code> method here.\n\t *\n\t * @param packet a <code>Packet</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\tpublic synchronized boolean sendPacket(Packet packet) {\n\t\tboolean result = false;\n\n\t\tif ((outgoing != null) && outgoing.isConnected() && (conn_state == OutgoingState.OK)) {\n\t\t\tresult = handler.writePacketToSocket(outgoing, packet);\n\n\t\t\tif ( !result) {\n\t\t\t\toutgoing.forceStop();\n\t\t\t\toutgoing = null;\n\t\t\t} else {\n\t\t\t\t++sentPackets;\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sent on connection: \" + outgoing + \" packet sent: \" + packet);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( !result) {\n\t\t\taddDataPacket(packet);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Connection not ready: \" + outgoing + \" packet added to waiting: \"\n\t\t\t\t\t\t+ packet);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param serv\n\t */\n\tpublic void serviceStopped(XMPPIOService<Object> serv) {\n\t\tString session_id = (String) serv.getSessionData().get(XMPPIOService.SESSION_ID_KEY);\n\n\t\tif (session_id != null) {\n\t\t\tdb_keys.remove(session_id);\n\t\t} else {\n\t\t\tlog.info(\"Session_ID is null for: \" + serv);\n\t\t}\n\n\t\tif (serv == outgoing) {\n\t\t\toutgoing = null;\n\t\t\tconn_state = OutgoingState.NULL;\n\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Connection removed: \" + outgoing + \", session id: \" + session_id);\n\t\t\t}\n\n//    return;\n\t\t}\n\n//  XMPPIOService rem = incoming.remove(session_id);\n//  if (rem == null) {\n//    log.fine(\"No service with given SESSION_ID: \" + session_id);\n//  } else {\n//    log.finer(\"Connection removed: \" + session_id);\n//  }\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void setConnecting() {\n\t\tconn_state = OutgoingState.CONNECTING;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void setValid() {\n\t\tconn_state = OutgoingState.OK;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void stopAll() {\n\t\tif (outgoing != null) {\n\t\t\toutgoing.forceStop();\n\t\t\toutgoing = null;\n\t\t}\n\n\t\tconn_state = OutgoingState.NULL;\n\n//  Set<Map.Entry<String, XMPPIOService>> set = incoming.entrySet();\n//  for (Map.Entry<String, XMPPIOService> entry: set) {\n//    entry.getValue().forceStop();\n//    set.remove(entry);\n//  }\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"cid: \" + cid + \", conn_state: \" + conn_state.name() + \", outgoing: \" + outgoing\n\t\t\t\t+ \", waitingPackets: \" + waitingPackets.size() + \", controlPacket: \"\n\t\t\t\t\t+ waitingControlPackets.size() + \", db_keys: \" + db_keys.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long waitingTime() {\n\t\treturn (System.currentTimeMillis() - creationTime);\n\t}\n\n//public int incomingSize() {\n//  return incoming.size();\n//}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/Dialback.java",
    "content": "/*\n * Dialback.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.cert.CertCheckResult;\n\nimport tigase.net.ConnectionType;\n\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.CID;\nimport tigase.server.xmppserver.CIDConnections;\nimport tigase.server.xmppserver.LocalhostException;\nimport tigase.server.xmppserver.NotLocalhostException;\nimport tigase.server.xmppserver.S2SIOService;\n\nimport tigase.util.Algorithms;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.security.NoSuchAlgorithmException;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Dec 9, 2010 2:00:52 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Dialback\n\t\t\t\textends S2SAbstractProcessor {\n\tprivate static final Logger log                =\n\t\tLogger.getLogger(Dialback.class.getName());\n\tprivate static final Element features_required =\n\t\tnew Element(\"dialback\", new Element[] { new Element(\"required\") },\n\t\t\t\t\t\t\t\tnew String[] { \"xmlns\" }, new String[] { \"urn:xmpp:features:dialback\" });\n\tprivate static final Element features = new Element(\"dialback\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"urn:xmpp:features:dialback\" });\n\tprivate static final String REQUESTED_RESULT_DOMAINS_KEY =\n\t\t\"requested-result-domains-key\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate long authenticationTimeOut = 30;\n\n\t// Ejabberd does not request dialback after TLS (at least some versions don't)\n\tprivate boolean ejabberd_bug_workaround_active = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic Dialback() {\n\t\tsuper();\n\t\tif (System.getProperty(\"s2s-ejabberd-bug-workaround-active\") == null) {\n\t\t\tSystem.setProperty(\"s2s-ejabberd-bug-workaround-active\", \"true\");\n\t\t}\n\t\tejabberd_bug_workaround_active =\n\t\t\tBoolean.getBoolean(\"s2s-ejabberd-bug-workaround-active\");\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.Dialback.ordinal();\n\t}\n\t\n\t@Override\n\tpublic boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n\t\tCID cid         = (CID) serv.getSessionData().get(\"cid\");\n\t\tboolean skipTLS = (cid == null)\n\t\t\t\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t\t\t\t: skipTLSForHost(cid.getRemoteHost());\n\n\t\t// If this is a dialback packet, process it accordingly\n\t\tif (p.getXMLNS() == XMLNS_DB_VAL) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Processing dialback packet: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\tp });\n\t\t\t}\n\t\t\tprocessDialback(p, serv);\n\n\t\t\treturn true;\n\t\t}\n\n\t\t// If this is stream features, then it depends....\n\t\tif (p.isElement(FEATURES_EL, FEATURES_NS)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Stream features received packet: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t}\n\n\t\t\tCertCheckResult certCheckResult =\n\t\t\t\t(CertCheckResult) serv.getSessionData().get(S2SIOService.CERT_CHECK_RESULT);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, TLS Certificate check: {1}, packet: {2}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t certCheckResult, p });\n\t\t\t}\n\n\t\t\t// If TLS is not yet started (announced in stream features) then it is not\n\t\t\t// the right time for dialback yet\n\t\t\t// Some servers send starttls in stream features, even if TLS is already\n\t\t\t// initialized....\n\t\t\tif (p.isXMLNSStaticStr(FEATURES_STARTTLS_PATH, START_TLS_NS) &&\n\t\t\t\t\t(certCheckResult == null) &&!skipTLS) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Waiting for starttls, packet: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// If TLS has been started and it is a trusted peer, we do not need\n\t\t\t// dialback here\n\t\t\t// but... sometimes the remote server may request dialback anyway,\n\t\t\t// especially if they\n\t\t\t// do not trust us.\n\t\t\tif ((certCheckResult == CertCheckResult.trusted) &&\n\t\t\t\t\t!(p.isXMLNSStaticStr(FEATURES_DIALBACK_PATH, DIALBACK_NS))) {\n\t\t\t\tif (ejabberd_bug_workaround_active) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(\n\t\t\t\t\t\t\t\tLevel.FINEST,\n\t\t\t\t\t\t\t\t\"{0}, Ejabberd bug workaround active, proceeding to dialback anyway, packet: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(\n\t\t\t\t\t\t\t\tLevel.FINEST,\n\t\t\t\t\t\t\t\t\"{0}, TLS trusted peer, no dialback needed or requested, packet: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t\t\t}\n\n\t\t\t\t\tCIDConnections cid_conns;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcid_conns = handler.getCIDConnections(cid, true);\n\t\t\t\t\t\tcid_conns.connectionAuthenticated(serv, cid);\n\t\t\t\t\t} catch (NotLocalhostException ex) {\n\n\t\t\t\t\t\t// Should not happen....\n\t\t\t\t\t\tlog.log(Level.INFO, \"{0}, Incorrect local hostname, packet: {1}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t\t\t\tserv.forceStop();\n\t\t\t\t\t} catch (LocalhostException ex) {\n\n\t\t\t\t\t\t// Should not happen....\n\t\t\t\t\t\tlog.log(Level.INFO, \"{0}, Incorrect remote hostname name, packet: {1}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t\t\t\tserv.stop();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// we need to check if TLS is required\n\t\t\tif (!skipTLS && cid != null && !serv.getSessionData().containsKey(\"TLS\") \n\t\t\t\t\t&& handler.isTlsRequired(cid.getLocalHost())) {\n\t\t\t\tlog.log(Level.FINER, \"{0}, TLS is required for domain {1} but STARTTLS was not \"\n\t\t\t\t\t\t+ \"offered by {2} - policy-violation\", new Object[] { serv, \n\t\t\t\t\t\t\tcid.getLocalHost(), cid.getRemoteHost() });\n\t\t\t\tserv.forceStop();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\t// Nothing else can be done right now except the dialback\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Initializing dialback, packet: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p });\n\t\t\t}\n\t\t\tinitDialback(serv, serv.getSessionId());\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void serviceStarted(S2SIOService serv) {\n\t\thandler.addTimerTask(new AuthenticationTimer(serv), authenticationTimeOut,\n\t\t\t\t\t\t\t\t\t\t\t\t TimeUnit.SECONDS);\n\t}\n\n\t@Override\n\tpublic void streamFeatures(S2SIOService serv, List<Element> results) {\n\t\tCertCheckResult certCheckResult =\n\t\t\t(CertCheckResult) serv.getSessionData().get(S2SIOService.CERT_CHECK_RESULT);\n\n\t\tif (certCheckResult == CertCheckResult.trusted) {\n\t\t\tresults.add(features);\n\t\t} else {\n\t\t\tresults.add(features_required);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String streamOpened(S2SIOService serv, Map<String, String> attribs) {\n\t\tif (attribs.containsKey(\"version\")) {\n\n\t\t\t// Let's wait for stream features\n\t\t\treturn null;\n\t\t}\n\t\tswitch (serv.connectionType()) {\n\t\tcase connect :\n\t\t\tinitDialback(serv, attribs.get(\"id\"));\n\n\t\t\tbreak;\n\n\t\tdefault :\n\n\t\t// Ignore\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate void initDialback(S2SIOService serv, String remote_id) {\n\t\ttry {\n\t\t\tCID cid                  = (CID) serv.getSessionData().get(\"cid\");\n\n\t\t\tString secret = handler.getSecretForDomain(cid.getLocalHost());\n\t\t\tString key = Algorithms.generateDialbackKey(cid.getLocalHost(), cid.getRemoteHost(), \n                                        secret, remote_id);\n\n\t\t\tif (!serv.isHandshakingOnly()) {\n\t\t\t\tElement elem = new Element(DB_RESULT_EL_NAME, key, new String[] { XMLNS_DB_ATT },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { XMLNS_DB_VAL });\n\n\t\t\t\taddToResultRequested(serv, cid.getRemoteHost());\n\t\t\t\tserv.getS2SConnection().addControlPacket(Packet.packetInstance(elem,\n\t\t\t\t\t\t\t\tJID.jidInstanceNS(cid.getLocalHost()),\n\t\t\t\t\t\t\t\tJID.jidInstanceNS(cid.getRemoteHost())));\n\t\t\t}\n\t\t\tserv.getS2SConnection().sendAllControlPackets();\n\t\t} catch (NotLocalhostException ex) {\n\t\t\tgenerateStreamError(false, \"host-unknown\", serv);\n\t\t}\n\t}\n\n\tprivate void processDialback(Packet p, S2SIOService serv) {\n\n\t\t// Get the cid for which the connection has been created, the cid calculated\n\t\t// from the packet may be different though if the remote server tries to\n\t\t// multiplexing\n\t\tCID cid_main   = (CID) serv.getSessionData().get(\"cid\");\n\t\tCID cid_packet = new CID(p.getStanzaTo().getDomain(), p.getStanzaFrom().getDomain());\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, DIALBACK packet: {1}, CID_packet: {2}\",\n\t\t\t\t\t\t\tnew Object[] { serv,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t p, cid_packet });\n\t\t}\n\n\t\tCIDConnections cid_conns = null;\n\n\t\t// Some servers (ejabberd) do not send from/to attributes in the stream:open\n\t\t// which\n\t\t// violates the spec, they seem not to care though, so here we handle the\n\t\t// case.\n\t\tif (cid_main == null) {\n\n\t\t\t// This actually can only happen for 'accept' connection type\n\t\t\t// what we did not get in stream open we can get from here\n\t\t\tcid_main = cid_packet;\n\t\t\tserv.getSessionData().put(\"cid\", cid_main);\n\n\t\t\t// For debuging purposes only....\n\t\t\tserv.getSessionData().put(\"local-hostname\", cid_main.getLocalHost());\n\t\t\tserv.getSessionData().put(\"remote-hostname\", cid_main.getRemoteHost());\n\t\t}\n\t\ttry {\n\t\t\tcid_conns = handler.getCIDConnections(cid_main, true);\n\t\t} catch (NotLocalhostException ex) {\n\t\t\tlog.log(Level.FINER, \"{0} Incorrect local hostname: {1}\", new Object[] { serv, p });\n\t\t\tgenerateStreamError(false, \"host-unknown\", serv);\n\n\t\t\treturn;\n\t\t} catch (LocalhostException ex) {\n\t\t\tlog.log(Level.FINER, \"{0} Incorrect remote hostname: {1}\",\n\t\t\t\t\t\t\tnew Object[] { serv, p });\n\t\t\tgenerateStreamError(false, \"invalid-from\", serv);\n\n\t\t\treturn;\n\t\t}\n\t\tif (serv.connectionType() == ConnectionType.accept) {\n\t\t\tcid_conns.addIncoming(serv);\n\t\t}\n\n\t\tString remote_key = p.getElemCData();\n\n\t\t// Dummy dialback implementation for now....\n\t\tif ((p.getElemName() == RESULT_EL_NAME) || (p.getElemName() == DB_RESULT_EL_NAME)) {\n\t\t\tif (p.getType() == null) {\n\t\t\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\t\t\t\tboolean skipTls = this.skipTLSForHost(cid.getRemoteHost());\n\t\t\t\tif (!skipTls && !serv.getSessionData().containsKey(\"TLS\") && handler.isTlsRequired(cid.getLocalHost())) {\n\t\t\t\t\tlog.log(Level.FINER, \"{0}, rejecting S2S connection from {1} to {2} due to policy violation - STARTTLS is required\",\n\t\t\t\t\t\t\tnew Object[] { serv, cid.getRemoteHost(), cid.getLocalHost() });\n\t\t\t\t\thandler.sendVerifyResult(DB_RESULT_EL_NAME, cid_main, cid_packet, false, null, serv.getSessionId(), \n\t\t\t\t\t\t\tnull, false, new Element(\"error\", new Element[] {\n\t\t\t\t\t\t\t\tnew Element(\"policy-violation\", new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\tnew String[] { \"urn:ietf:params:xml:ns:xmpp-stanzas\" } )},\n\t\t\t\t\t\t\t\t\tnew String[] { \"type\" }, new String[] { \"cancel\" } ));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tString conn_sessionId = serv.getSessionId();\n\t\t\t\t\thandler.sendVerifyResult(DB_VERIFY_EL_NAME, cid_main, cid_packet, null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t conn_sessionId, null, p.getElemCData(), true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (p.getType() == StanzaType.valid) {\n\t\t\t\t\tif (wasResultRequested(serv, p.getStanzaFrom().toString())) {\n\n\t\t\t\t\t\t// serv.addCID(new CID(p.getStanzaTo().getDomain(),\n\t\t\t\t\t\t// p.getStanzaFrom().getDomain()));\n\t\t\t\t\t\tcid_conns.connectionAuthenticated(serv, cid_packet);\n\t\t\t\t\t} else if (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\t\"Received result with type valid for {0} but it was not requested!\",\n\t\t\t\t\t\t\t\t\t\tp.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(\n\t\t\t\t\t\t\t\tLevel.FINE,\n\t\t\t\t\t\t\t\t\"Invalid result for DB authentication: {0}, stopping connection: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { cid_packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t serv });\n\t\t\t\t\t}\n\t\t\t\t\tserv.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ((p.getElemName() == VERIFY_EL_NAME) || (p.getElemName() == DB_VERIFY_EL_NAME)) {\n\t\t\tif (p.getType() == null) {                          \n\t\t\t\tboolean result;\n\t\t\t\ttry {\n\t\t\t\t\tString secret = handler.getSecretForDomain(cid_packet.getLocalHost());                                \n\t\t\t\t\tString local_key = Algorithms.generateDialbackKey(cid_packet.getLocalHost(), \n                                                cid_packet.getRemoteHost(), secret, p.getStanzaId());\n\n\t\t\t\t\tif (local_key == null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\tlog.log(Level.FINER, \"The key is not available for connection CID: {0}, \"\n\t\t\t\t\t\t\t\t\t+ \"or the packet CID: {1} \", new Object[] { cid_main, cid_packet });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tresult = local_key != null && local_key.equals(remote_key);\n\t\t\t\t}\n\t\t\t\tcatch (NotLocalhostException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Could not retreive secret for \" + cid_packet.getLocalHost(), ex);\n\t\t\t\t\t}\n\t\t\t\t\tresult = false;\n\t\t\t\t}\n\t\t\t\thandler.sendVerifyResult(DB_VERIFY_EL_NAME, cid_main, cid_packet,\n\t\t\t\t\t\tresult , p.getStanzaId(), serv.getSessionId(), null, false);\n\t\t\t} else {\n\t\t\t\tif (wasVerifyRequested(serv, p.getStanzaFrom().toString())) {\n\t\t\t\t\thandler.sendVerifyResult(DB_RESULT_EL_NAME, cid_main, cid_packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t (p.getType() == StanzaType.valid), null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t p.getStanzaId(), null, false);\n\t\t\t\t\tif (p.getType() == StanzaType.valid) {\n\t\t\t\t\t\tcid_conns.connectionAuthenticated(p.getStanzaId(), cid_packet);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"received verify for {0} but it was not requested!\",\n\t\t\t\t\t\t\t\t\t\tp.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (serv.isHandshakingOnly()) {\n\t\t\t\t\tserv.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds domain to list of domains requested for result by service\n\t *\n\t * @param serv\n\t * @param domain\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void addToResultRequested(S2SIOService serv, String domain) {\n\t\tSet<String> requested =\n\t\t\t(Set<String>) serv.getSessionData().get(REQUESTED_RESULT_DOMAINS_KEY);\n\n\t\tif (requested == null) {\n\t\t\tSet<String> requested_tmp = new CopyOnWriteArraySet<String>();\n\n\t\t\trequested =\n\t\t\t\t(Set<String>) serv.getSessionData().putIfAbsent(REQUESTED_RESULT_DOMAINS_KEY,\n\t\t\t\t\trequested_tmp);\n\t\t\tif (requested == null) {\n\t\t\t\trequested = requested_tmp;\n\t\t\t}\n\t\t}\n\t\trequested.add(domain);\n\t}\n\n\t/**\n\t * Checks if result request for received domain was sent by service\n\t *\n\t * @param serv\n\t * @param domain\n\t * \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tprotected boolean wasResultRequested(S2SIOService serv, String domain) {\n\t\tSet<String> requested =\n\t\t\t(Set<String>) serv.getSessionData().get(REQUESTED_RESULT_DOMAINS_KEY);\n\n\t\treturn (requested != null) && requested.contains(domain);\n\t}\n\n\t/**\n\t * Checks if verify request for received domain was sent by service\n\t *\n\t * @see CIDConnections#sendHandshakingOnly\n\t * @param serv\n\t * @param domain\n\t * \n\t */\n\tprotected boolean wasVerifyRequested(S2SIOService serv, String domain) {\n\t\tString requested =\n\t\t\t(String) serv.getSessionData().get(S2SIOService.HANDSHAKING_DOMAIN_KEY);\n\n\t\treturn (requested != null) && requested.contains(domain);\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class AuthenticationTimer\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\tprivate S2SIOService serv = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate AuthenticationTimer(S2SIOService serv) {\n\t\t\tthis.serv = serv;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tif (!serv.isAuthenticated() && serv.isConnected()) {\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\"Connection not authenticated within timeout, stopping: {0}\", serv);\n\t\t\t\t}\n\t\t\t\tserv.stop();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/PacketChecker.java",
    "content": "\n/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.CID;\nimport tigase.server.xmppserver.S2SConnectionHandlerIfc;\nimport tigase.server.xmppserver.S2SIOService;\n\nimport tigase.util.DNSEntry;\nimport tigase.util.DNSResolverFactory;\n\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 10, 2010 5:53:57 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PacketChecker extends S2SAbstractProcessor {\n\n        private static final Logger log = Logger.getLogger(PacketChecker.class.getName());\n\n        private static final String ALLOW_PACKETS_FROM_OTHER_DOMAINS_MAP_KEY =\n                        \"allow-packets-from-other-domains-map\";\n        private static final String ALLOW_PACKETS_FROM_OTHER_DOMAINS_WITH_SAME_IP_KEY = \n                        \"allow-packets-from-other-domains-with-same-ip\";\n        private static final String ALLOW_PACKETS_FROM_OTHER_DOMAINS_WITH_SAME_IP_WHITELIST_KEY = \n                        \"allow-packets-from-other-domains-with-same-ip-whitelist\";\n        \n        private Map<String,String[]> allowedOtherDomainsMap = new ConcurrentHashMap<String,String[]>();\n        private boolean allowOtherDomainsWithSameIp = false;\n        private String[] allowedOtherDomainsWithSameIpWhitelist = null;\n        \n        //~--- methods --------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic int order() {\n\t\t\treturn 0;\n\t\t}\n\t\t\n        @Override\n        public void init(S2SConnectionHandlerIfc<S2SIOService> handler, Map<String, Object> props) {\n                super.init(handler, props);\n                \n                String allowOtherDomainsStr = (String) props.get(ALLOW_PACKETS_FROM_OTHER_DOMAINS_WITH_SAME_IP_KEY);\n                if (allowOtherDomainsStr != null) {\n                        allowOtherDomainsWithSameIp = Boolean.parseBoolean(allowOtherDomainsStr);\n                }\n                \n                String allowedOtherDomainsWhitelistStr = (String) props.get(ALLOW_PACKETS_FROM_OTHER_DOMAINS_WITH_SAME_IP_WHITELIST_KEY);\n                if (allowedOtherDomainsWhitelistStr != null) {\n                        allowedOtherDomainsWithSameIpWhitelist = allowedOtherDomainsWhitelistStr.split(\",\");\n                        Arrays.sort(allowedOtherDomainsWithSameIpWhitelist);\n                }\n                else {\n                        allowedOtherDomainsWithSameIpWhitelist = new String[0];\n                }\n\n                String allowedOtherDomainsMapStr = (String) props.get(ALLOW_PACKETS_FROM_OTHER_DOMAINS_MAP_KEY);\n                allowedOtherDomainsMap.clear();\n                if (allowedOtherDomainsMapStr != null) {\n                        for (String listOfDomainsStr : allowedOtherDomainsMapStr.split(\",\")) {\n                                String[] listOfDomains = listOfDomainsStr.split(\":\");\n                                Arrays.sort(listOfDomains);\n                                for (int i=0; i<listOfDomains.length; i++) {\n                                        allowedOtherDomainsMap.put(listOfDomains[i], listOfDomains);\n                                }\n                        }\n                }\n        }\n        \n        @Override\n        public boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n                if ((p.getXMLNS() == XMLNS_SERVER_VAL) || (p.getXMLNS() == XMLNS_CLIENT_VAL)) {\n                        if ((p.getStanzaFrom() == null) || (p.getStanzaFrom().getDomain().trim().isEmpty())\n                                || (p.getStanzaTo() == null) || p.getStanzaTo().getDomain().trim().isEmpty()) {\n                                generateStreamError(false, \"improper-addressing\", serv);\n\n                                return true;\n                        }\n\n                        CID cid = new CID(p.getStanzaTo().getDomain(), p.getStanzaFrom().getDomain());\n\n                        // String remote_hostname = (String) serv.getSessionData().get(\"remote-hostname\");\n                        if (!isAllowed(p, serv, cid)) {\n                                if (log.isLoggable(Level.FINER)) {\n                                        log.log(Level.FINER,\n                                                \"{0}, Invalid hostname from the remote server for packet: \"\n                                                + \"{1}, authenticated domains for this connection: {2}\", new Object[]{serv,\n                                                        p, serv.getCIDs()});\n                                }\n\n                                generateStreamError(false, \"invalid-from\", serv);\n\n                                return true;\n                        }\n                } else {\n                        if (log.isLoggable(Level.FINER)) {\n                                log.log(Level.FINER, \"{0}, Invalid namespace for packet: {1}\", new Object[]{serv, p});\n                        }\n\n                        generateStreamError(false, \"invalid-namespace\", serv);\n\n                        return true;\n                }\n\n                return false;\n        }\n        \n        /**\n         * Check if incoming packet is allowed on this connection\n         * \n         * @param p\n         * @param serv\n         * @param cid\n         * \n         */\n        protected boolean isAllowed(Packet p, S2SIOService serv, CID cid) {\n                boolean allowed  = serv.isAuthenticated(cid);\n                \n                // Some servers (e.g. Google) are sending packets from other domains than authenticated domain\n                // we should check it if we need to connect to that incompatible domain\n                if (!allowed && serv.isAuthenticated()) {\n                        String domain = p.getStanzaFrom().getDomain();\n\n                        // here we use mapping as DNS solution will not work in all cases\n                        String[] allowedOtherDomainsMapValue = allowedOtherDomainsMap.get(domain);\n                        if (allowedOtherDomainsMapValue != null) {\n                                ArrayList<CID> authenticatedCids = new ArrayList<CID>(serv.getCIDs());\n                                for (CID acid : authenticatedCids) {\n                                        if (Arrays.binarySearch(allowedOtherDomainsMapValue, acid.getRemoteHost()) >= 0) {\n                                                serv.addCID(cid);\n                                                allowed = true;\n                                                break;\n                                        }\n                                }\n                        }\n                        \n                        if (!allowed && allowOtherDomainsWithSameIp) {\n                                // we can enable it for all domains or only for whitelisted domains\n                                if (allowedOtherDomainsWithSameIpWhitelist.length == 0 \n                                        || Arrays.binarySearch(allowedOtherDomainsWithSameIpWhitelist, domain) >= 0) {\n                        \n                                        try {\n                                                DNSEntry[] entries = DNSResolverFactory.getInstance().getHostSRV_Entries(domain);\n                                                if (entries != null) {                                                \n                                                        String remoteAddress = serv.getRemoteAddress();\n                                                        for (DNSEntry entry : entries) {\n                                                                if (remoteAddress.equals(entry.getIp())) {\n                                                                        serv.addCID(cid);\n                                                                        allowed = true;\n                                                                        break;\n                                                                }\n                                                        }\n                                                }\n                                        } catch (UnknownHostException ex) {\n                                                log.log(Level.FINE, \"Unknown host for domain: {0}\", domain);\n                                        }\n                                }\n                        }\n                }\n                \n                return allowed;\n        }\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/S2SAbstractProcessor.java",
    "content": "/*\n * S2SAbstractProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.S2SConnectionHandlerIfc;\nimport tigase.server.xmppserver.S2SIOService;\nimport tigase.server.xmppserver.S2SProcessor;\nimport tigase.xml.Element;\n\n/**\n * Created: Dec 10, 2010 3:32:11 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class S2SAbstractProcessor\n\t\t\t\timplements S2SProcessor {\n\t\n\t// Order of enum values is important as it is an order in which packet \n\t// is processed by processors\n\tprotected static enum Order {\n\t\tStreamOpen,\t\t\t\t// 0\n\t\tStreamError,\t\t\t// 1\n\t\tStreamFeatures,\t\t\t// 2\n\t\tStartTLS,\t\t\t\t// 3\n\t\tStartZlib,\t\t\t\t// 4\n\t\tDialback\t\t\t\t// 5\n\t}\n\t\n\t/** Field description */\n\tprotected static final String DB_RESULT_EL_NAME = \"db:result\";\n\n\t/** Field description */\n\tprotected static final String DB_VERIFY_EL_NAME = \"db:verify\";\n\n\t/** Field description */\n\tprotected static final String DIALBACK_EL = \"dialback\";\n\n\t/** Field description */\n\tprotected static final String DIALBACK_NS = \"urn:xmpp:features:dialback\";\n\n\t/** Field description */\n\tprotected static final String FEATURES_EL = \"features\";\n\n\t/** Field description */\n\tprotected static final String FEATURES_NS = \"http://etherx.jabber.org/streams\";\n\n\t/** Field description */\n\tprotected static final String PROCEED_TLS_EL = \"proceed\";\n\n\t/** Field description */\n\tprotected static final String RESULT_EL_NAME = \"result\";\n\n\t/** Field description */\n\tprotected static final String START_TLS_EL = \"starttls\";\n\n\t/** Field description */\n\tprotected static final String START_TLS_NS = \"urn:ietf:params:xml:ns:xmpp-tls\";\n\n\t/** Field description */\n\tprotected static final String STREAM_FEATURES_EL = \"stream:features\";\n\n\t/** Field description */\n\tprotected static final String VERIFY_EL_NAME = \"verify\";\n\n\t/** Field description */\n\tprotected static final String VERSION_ATT_NAME = \"version\";\n\n\t/** Field description */\n\tprotected static final String XMLNS_CLIENT_VAL = \"jabber:client\";\n\n\t/** Field description */\n\tprotected static final String XMLNS_DB_ATT = \"xmlns:db\";\n\n\t/** Field description */\n\tprotected static final String XMLNS_DB_VAL = \"jabber:server:dialback\";\n\n\t/** Field description */\n\tprotected static final String XMLNS_SERVER_VAL = \"jabber:server\";\n\n\t/** Field description */\n\tprotected static final String[] FEATURES_STARTTLS_PATH = { FEATURES_EL, START_TLS_EL };\n\n\t/** Field description */\n\tprotected static final String[] FEATURES_DIALBACK_PATH = { FEATURES_EL, DIALBACK_EL };\n\tprivate static final Logger log                        =\n\t\tLogger.getLogger(S2SAbstractProcessor.class.getName());\n\n\t/** Field description */\n\tpublic static boolean FORCE_VERSION = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected S2SConnectionHandlerIfc<S2SIOService> handler = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param initStream\n\t * @param error_el\n\t * @param serv\n\t */\n\tpublic void generateStreamError(boolean initStream, String error_el,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tS2SIOService serv) {\n\t\tString strError = \"\";\n\n\t\tif (initStream) {\n\t\t\tstrError += \"<?xml version='1.0'?><stream:stream\" + \" xmlns='\" + XMLNS_SERVER_VAL +\n\t\t\t\t\t\t\t\t\t\"'\" + \" xmlns:stream='http://etherx.jabber.org/streams'\" +\n\t\t\t\t\t\t\t\t\t\" id='tigase-server-error'\" + \" from='\" + handler.getDefHostName() +\n\t\t\t\t\t\t\t\t\t\"'\" + \" xml:lang='en'>\";\n\t\t}\n\t\tstrError += \"<stream:error>\" + \"<\" + error_el +\n\t\t\t\t\t\t\t\t\" xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\" + \"</stream:error>\" +\n\t\t\t\t\t\t\t\t\"</stream:stream>\";\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tThrowable thr = new Throwable();\n\n\t\t\t\tthr.fillInStackTrace();\n\t\t\t\tlog.log(Level.FINEST, \"Called from: \", thr);\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending stream error: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\tstrError });\n\t\t\t}\n\t\t\thandler.writeRawData(serv, strError);\n\t\t\tserv.stop();\n\t\t} catch (Exception e) {\n\t\t\tserv.forceStop();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void init(S2SConnectionHandlerIfc<S2SIOService> handler,\n\t\t\t\t\t\t\t\t\t Map<String, Object> props) {\n\t\tthis.handler = handler;\n\t}\n\n\t@Override\n\tpublic boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void serviceStarted(S2SIOService serv) {}\n\n\t@Override\n\tpublic void serviceStopped(S2SIOService serv) {}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param hostname\n\t *\n\t * \n\t */\n\tpublic boolean skipTLSForHost(String hostname) {\n\n\t\t// TODO: this is slow, optimize it somehow!!!\n\t\t// Workaround for buggy servers having problems with establishing TLS over s2s\n\t\t// http://community.igniterealtime.org/thread/36206\n\t\t// http://community.igniterealtime.org/thread/30578\n\t\tString hostnames = System.getProperty(\"s2s-skip-tls-hostnames\");\n\n\t\tif (hostnames != null) {\n\t\t\tString[] hosts = hostnames.split(\",\");\n\n\t\t\tfor (String host : hosts) {\n\t\t\t\tif (hostname.equalsIgnoreCase(host)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void streamClosed(S2SIOService serv) {}\n\n\t@Override\n\tpublic void streamFeatures(S2SIOService serv, List<Element> results) {}\n\n\t@Override\n\tpublic String streamOpened(S2SIOService serv, Map<String, String> attribs) {\n\t\treturn null;\n\t}\n\t\n\t@Override\n\tpublic int compareTo(S2SProcessor proc) {\n\t\treturn (-1) * (proc.order() - order());\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/StartTLS.java",
    "content": "/*\n * StartTLS.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.CID;\nimport tigase.server.xmppserver.S2SIOService;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Queue;\n\n/**\n * Created: Dec 9, 2010 2:01:01 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StartTLS\n\t\t\t\textends S2SAbstractProcessor {\n\tprivate static final Logger log       = Logger.getLogger(StartTLS.class.getName());\n\tprivate static final Element features = new Element(START_TLS_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { START_TLS_NS });\n\tprivate static final Element features_required = new Element(START_TLS_EL, new Element[] { new Element( \"required\" ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { START_TLS_NS });\n\tprivate static final Element starttls_el = new Element(START_TLS_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { START_TLS_NS });\n\tprivate static final Element proceed_el = new Element(PROCEED_TLS_EL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { START_TLS_NS });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.StartTLS.ordinal();\n\t}\t\n\t\n\t@Override\n\tpublic boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n\t\tif (p.isElement(START_TLS_EL, START_TLS_NS)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending packet: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\tproceed_el });\n\t\t\t}\n\t\t\thandler.writeRawData(serv, proceed_el.toString());\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Starting TLS handshaking server side.\", serv);\n\t\t\t\t}\n\t\t\t\tserv.getSessionData().put(\"TLS\", \"TLS\");\n\t\t\t\tserv.startTLS(false, handler.isTlsWantClientAuthEnabled(), handler.isTlsNeedClientAuthEnabled());\n\t\t\t} catch (IOException ex) {\n\t\t\t\tlog.log(Level.INFO, \"Problem with TLS initialization.\", ex);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\tif (p.isElement(PROCEED_TLS_EL, START_TLS_NS)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Received TLS proceed.\", serv);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Starting TLS handshaking client side.\", serv);\n\t\t\t\t}\n\t\t\t\tserv.getSessionData().put(\"TLS\", \"TLS\");\n\t\t\t\tserv.startTLS(true, handler.isTlsWantClientAuthEnabled(), handler.isTlsNeedClientAuthEnabled());\n\t\t\t} catch (IOException ex) {\n\t\t\t\tlog.log(Level.INFO, \"Problem with TLS initialization.\", ex);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\tif (p.isElement(FEATURES_EL, FEATURES_NS)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Stream features received: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\tp });\n\t\t\t}\n\n\t\t\tCID cid         = (CID) serv.getSessionData().get(\"cid\");\n\t\t\tboolean skipTLS = (cid == null)\n\t\t\t\t\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t\t\t\t\t: skipTLSForHost(cid.getRemoteHost());\n\n\t\t\tif (p.isXMLNSStaticStr(FEATURES_STARTTLS_PATH, START_TLS_NS) &&!skipTLS) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending packet: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\t\t\tstarttls_el });\n\t\t\t\t}\n\t\t\t\thandler.writeRawData(serv, starttls_el.toString());\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void streamFeatures(S2SIOService serv, List<Element> results) {\n\t\tif (!serv.getSessionData().containsKey(\"TLS\")) {\n\t\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\t\t\tif (cid != null && !skipTLSForHost(cid.getRemoteHost()) \n\t\t\t\t\t&& handler.isTlsRequired(cid.getLocalHost())) {\n\t\t\t\tresults.add(features_required);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresults.add(features);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/StartZlib.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.xmppserver.S2SIOService;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 2:01:12 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StartZlib extends S2SAbstractProcessor {\n\tprivate static final Logger log = Logger.getLogger(StartZlib.class.getName());\n\tprivate static final Element features = new Element(\"compression\",\n\t\tnew Element[] { new Element(\"method\", \"zlib\") }, new String[] { \"xmlns\" },\n\t\tnew String[] { \"http://jabber.org/features/compress\" });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.StartZlib.ordinal();\n\t}\n\t\n\t@Override\n\tpublic void streamFeatures(S2SIOService serv, List<Element> results) {\n\n\t\t// results.add(features);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/StreamError.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.S2SIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 2:00:08 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StreamError extends S2SAbstractProcessor {\n\tprivate static final Logger log = Logger.getLogger(StreamError.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.StreamError.ordinal();\n\t}\n\t\n\t@Override\n\tpublic boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n\t\tif (p.getElemName() == \"error\") {\n\t\t\tserv.stop();\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/StreamFeatures.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.net.ConnectionType;\n\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.S2SIOService;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 2:00:25 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StreamFeatures extends S2SAbstractProcessor {\n\tprivate static final Logger log = Logger.getLogger(StreamFeatures.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.StreamFeatures.ordinal();\n\t}\n\t\n\t@Override\n\tpublic boolean process(Packet p, S2SIOService serv, Queue<Packet> results) {\n\t\tif (p.isElement(FEATURES_EL, FEATURES_NS)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Stream features received: {1}\", new Object[] { serv, p });\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String streamOpened(S2SIOService serv, Map<String, String> attribs) {\n\t\tif (attribs.containsKey(\"version\")) {\n\n\t\t\t// A version=1.0,  sending features\n\t\t\tif (serv.connectionType() == ConnectionType.accept) {\n\n\t\t\t\t// Send features only for accept connections\n\t\t\t\tList<Element> features = handler.getStreamFeatures(serv);\n\t\t\t\tElement featuresElement = new Element(STREAM_FEATURES_EL);\n\n\t\t\t\tfeaturesElement.addChildren(features);\n\n\t\t\t\t// do not send stattls feature to hosts in skip tls list\n\t\t\t\tif (attribs.containsKey(\"from\")) {\n\t\t\t\t\tif (skipTLSForHost(attribs.get(\"from\"))) {\n\t\t\t\t\t\tElement startTls = featuresElement.getChild(START_TLS_EL, START_TLS_NS);\n\t\t\t\t\t\tfeaturesElement.removeChild(startTls);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending stream features: {1}\", new Object[] { serv,\n\t\t\t\t\t\t\tfeaturesElement });\n\t\t\t\t}\n\n\t\t\t\tserv.addPacketToSend(Packet.packetInstance(featuresElement, null, null));\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppserver/proc/StreamOpen.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.server.xmppserver.proc;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.net.ConnectionType;\n\nimport tigase.server.xmppserver.CID;\nimport tigase.server.xmppserver.CIDConnections;\nimport tigase.server.xmppserver.LocalhostException;\nimport tigase.server.xmppserver.NotLocalhostException;\nimport tigase.server.xmppserver.S2SConnection;\nimport tigase.server.xmppserver.S2SIOService;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Dec 9, 2010 1:59:56 PM\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StreamOpen extends S2SAbstractProcessor {\n\tprivate static final Logger log = Logger.getLogger(StreamOpen.class.getName());\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int order() {\n\t\treturn Order.StreamOpen.ordinal();\n\t}\n\t\n\t@Override\n\tpublic void serviceStarted(S2SIOService serv) {\n\t\tswitch (serv.connectionType()) {\n\t\t\tcase connect:\n\t\t\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\n\t\t\t\tserv.getSessionData().put(S2SIOService.HOSTNAME_KEY, cid.getLocalHost());\n\n\t\t\t\t// Send init xmpp stream here\n\t\t\t\t// XMPPIOService serv = (XMPPIOService)service;\n\t\t\t\tString data =\n\t\t\t\t\t\t\"<stream:stream\" + \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t\t\t\t\t+ \" xmlns='jabber:server'\" + \" xmlns:db='jabber:server:dialback'\"\n\t\t\t\t\t\t\t\t+ \" from='\" + cid.getLocalHost() + \"'\" + \" to='\" + cid.getRemoteHost()\n\t\t\t\t\t\t\t\t+ \"'\" + \" version='1.0'>\";\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, sending: {1}\", new Object[] { serv, data });\n\t\t\t\t}\n\n\t\t\t\tS2SConnection s2s_conn =\n\t\t\t\t\t\t(S2SConnection) serv.getSessionData().get(S2SIOService.S2S_CONNECTION_KEY);\n\n\t\t\t\tif (s2s_conn == null) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Protocol error s2s_connection not set for outgoing connection: {0}\", serv);\n\t\t\t\t\tserv.stop();\n\t\t\t\t} else {\n\t\t\t\t\ts2s_conn.setS2SIOService(serv);\n\t\t\t\t\tserv.setS2SConnection(s2s_conn);\n\t\t\t\t}\n\n\t\t\t\tserv.xmppStreamOpen(data);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\t// Do nothing, more data should come soon...\n\t\t\t\tbreak;\n\t\t} // end of switch (service.connectionType())\n\t}\n\n\t@Override\n\tpublic void serviceStopped(S2SIOService serv) {\n\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\n\t\tif (cid == null) {\n\t\t\tif (serv.connectionType() == ConnectionType.connect) {\n\t\t\t\tlog.log(Level.WARNING, \"Protocol error cid not set for outgoing connection: {0}\",\n\t\t\t\t\t\tserv);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tCIDConnections cid_conns = handler.getCIDConnections(cid, false);\n\n\t\t\tif (cid_conns == null) {\n                                if (log.isLoggable(Level.FINE)) {\n                                        log.log(Level.FINE,\n\t\t\t\t\t\t\"Protocol error cid_conns not found for outgoing connection: {0}\", serv);\n                                }\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tcid_conns.connectionStopped(serv);\n\t\t\t}\n\t\t} catch (NotLocalhostException ex) {\n\t\t\tlog.log(Level.WARNING, \"Not a local host for cid: {0}\", cid);\n\t\t} catch (LocalhostException ex) {\n\t\t\tlog.log(Level.WARNING, \"A local host for cid: {0}\", cid);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String streamOpened(S2SIOService serv, Map<String, String> attribs) {\n\t\tCID cid = (CID) serv.getSessionData().get(\"cid\");\n\t\tString remote_hostname = attribs.get(\"from\");\n\t\tString local_hostname = attribs.get(\"to\");\n\t\tString version = attribs.get(VERSION_ATT_NAME);\n\t\tif (version != null) {\n\t\t\tserv.getSessionData().put(VERSION_ATT_NAME, version);\n\t\t}\n\n\t\tif (cid == null) {\n\t\t\tif ((remote_hostname != null) && (local_hostname != null)) {\n\t\t\t\tcid = new CID(local_hostname, remote_hostname);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tCIDConnections cid_conns = handler.getCIDConnections(cid, false);\n\n\t\t\tswitch (serv.connectionType()) {\n\t\t\t\tcase connect: {\n\n\t\t\t\t\t// It must be always set for connect connection type\n\t\t\t\t\tString remote_id = attribs.get(\"id\");\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Connect Stream opened for: {1}, session id{2}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv, cid, remote_id });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (cid_conns == null) {\n\n\t\t\t\t\t\t// This should actually not happen. Let's be clear here about\n\t\t\t\t\t\t// handling unexpected\n\t\t\t\t\t\t// cases.\n\t\t\t\t\t\tlog.log(\n\t\t\t\t\t\t\t\tLevel.WARNING,\n\t\t\t\t\t\t\t\t\"{0} This might be a bug in s2s code, should not happen.\"\n\t\t\t\t\t\t\t\t\t\t+ \" Missing CIDConnections for stream open to ''connect'' service type.\",\n\t\t\t\t\t\t\t\tserv);\n\t\t\t\t\t\tgenerateStreamError(false, \"internal-server-error\", serv);\n\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(\n\t\t\t\t\t\t\t\tLevel.FINEST,\n\t\t\t\t\t\t\t\t\"{0}, stream open for cid: {1}, outgoint: {2}, incoming: {3}\",\n\t\t\t\t\t\t\t\tnew Object[] { serv, cid, cid_conns.getOutgoingCount(),\n\t\t\t\t\t\t\t\t\t\tcid_conns.getIncomingCount() });\n\t\t\t\t\t}\n\n\t\t\t\t\tserv.setSessionId(remote_id);\n\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tcase accept: {\n\t\t\t\t\tif (local_hostname != null) {\n\t\t\t\t\t\tserv.getSessionData().put(S2SIOService.HOSTNAME_KEY, local_hostname);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Unknown local hostname.\", serv);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tString id = UUID.randomUUID().toString();\n\n\t\t\t\t\tserv.setSessionId(id);\n\n\t\t\t\t\tString stream_open =\n\t\t\t\t\t\t\t\"<stream:stream\" + \" xmlns:stream='http://etherx.jabber.org/streams'\"\n\t\t\t\t\t\t\t\t\t+ \" xmlns='jabber:server'\" + \" xmlns:db='jabber:server:dialback'\"\n\t\t\t\t\t\t\t\t\t+ \" id='\" + id + \"'\";\n\n\t\t\t\t\tif (cid != null) {\n\t\t\t\t\t\tstream_open +=\n\t\t\t\t\t\t\t\t\" from='\" + cid.getLocalHost() + \"'\" + \" to='\" + cid.getRemoteHost()\n\t\t\t\t\t\t\t\t\t\t+ \"'\";\n\n\t\t\t\t\t\tif (cid_conns == null) {\n\t\t\t\t\t\t\tcid_conns = handler.getCIDConnections(cid, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"{0}, Accept Stream opened for: {1}, session id: {2}\", new Object[] {\n\t\t\t\t\t\t\t\t\t\t\tserv, cid, id });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tserv.getSessionData().put(\"cid\", cid);\n\t\t\t\t\t\tcid_conns.addIncoming(serv);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"{0}, Accept Stream opened for unknown CID, session id: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { serv, id });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Spec examples show that the version should always be included but\n\t\t\t\t\t// this seems to break some servers.\n\t\t\t\t\tif (FORCE_VERSION || attribs.containsKey(\"version\")) {\n\t\t\t\t\t\tstream_open += \" version='1.0'\";\n\t\t\t\t\t}\n\t\t\t\t\tstream_open += \">\";\n\n\t\t\t\t\treturn stream_open;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tlog.log(Level.SEVERE, \"{0}, Warning, program shouldn't reach that point.\", serv);\n\n\t\t\t\t\tbreak;\n\t\t\t} // end of switch (serv.connectionType())\n\t\t} catch (NotLocalhostException ex) {\n\t\t\tgenerateStreamError(false, \"host-unknown\", serv);\n\t\t} catch (LocalhostException ex) {\n\t\t\tgenerateStreamError(false, \"invalid-from\", serv);\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\n// ~ Formatted in Sun Code Convention\n\n// ~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppsession/PacketDefaultHandler.java",
    "content": "/*\n * PacketDefaultHandler.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppsession;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Queue;\n\n/**\n * Describe class PacketDefaultHandler here.\n *\n *\n * Created: Fri Feb 2 15:08:58 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PacketDefaultHandler {\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(PacketDefaultHandler.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// private static TigaseRuntime runtime = TigaseRuntime.getTigaseRuntime();\n\t// private RosterAbstract roster_util =\n\t// RosterFactory.getRosterImplementation(true);\n\tprivate String[]     IGNORE_PACKETS  = { \"stream:features\" };\n\tprivate StanzaType[] IGNORE_TYPES    = { StanzaType.error };\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>PacketDefaultHandler</code> instance.\n\t *\n\t */\n\tpublic PacketDefaultHandler() {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t *\n\t *\n\t */\n\tpublic boolean canHandle(Packet packet, XMPPResourceConnection session) {\n\t\tif (session == null) {\n\t\t\treturn false;\n\t\t}    // end of if (session == null)\n\n\t\t// Cannot forward packet if there is no destination address\n\t\tif (packet.getStanzaTo() == null) {\n\n\t\t\t// If this is simple <iq type=\"result\"/> then ignore it\n\t\t\t// and consider it OK\n\t\t\tif ((packet.getElemName() == \"iq\") && (packet.getType() == StanzaType.result)) {\n\n\t\t\t\t// Nothing to do....\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"No ''to'' address, can''t deliver packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t *\n\t *\n\t */\n\tpublic boolean forward(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results) {\n\n\t\t// Processing of the packets which needs to be processed as quickly\n\t\t// as possible, direct presences from unsubscribed entities apparently\n\t\t// have high priority as they may come from MUC and must be delivered\n\t\t// before room history\n\t\t// if (packet.getElemName() == \"presence\") {\n\t\t// PresenceType pres_type = roster_util.getPresenceType(session, packet);\n\t\t// if ((prese_type == PresenceType.in_initial)\n\t\t// && (packet.getElemFrom() != null)\n\t\t// && (roster_util.isSubscribedTo(session, packet.getElemFrom())\n\t\t// || (DynamicRoster.getBuddyItem(session, settings,\n\t\t// packet.getElemFrom()) != null))) {\n\t\t// }\n\t\t// }\n\t\treturn false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t *\n\t *\n\t */\n\tpublic boolean preprocess(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results) {\n\t\tif (session != null) {\n\t\t\tsession.incPacketsCounter();\n\n\t\t\tXMPPSession parent = session.getParentSession();\n\n\t\t\tif (parent != null) {\n\t\t\t\tparent.incPacketsCounter();\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < IGNORE_PACKETS.length; i++) {\n\t\t\tif ((packet.getElemName() == IGNORE_PACKETS[i]) && (packet.getType() ==\n\t\t\t\t\tIGNORE_TYPES[i])) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t *\n\t *\n\t * @throws XMPPException\n\t */\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet.toStringSecure());\n\t\t}\n\t\ttry {\n\t\t\tJID to = packet.getStanzaTo();\n\t\t\tJID from = packet.getStanzaFrom();\n\n\t\t\t// If this is simple <iq type=\"result\"/> then ignore it\n\t\t\t// and consider it OK\n\t\t\tif ((to == null) && (packet.getElemName() == \"iq\") && (packet.getType() ==\n\t\t\t\t\tStanzaType.result)) {\n\n\t\t\t\t// Nothing to do....\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.isUserId(to.getBareJID()) && (from == null || !session.isUserId(from.getBareJID()) \n\t\t\t\t\t|| !session.getConnectionId().equals(packet.getPacketFrom()))) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tPacket result;\n\n\t\t\t\t// This is where and how we set the address of the component\n\t\t\t\t// which should rceive the result packet for the final delivery\n\t\t\t\t// to the end-user. In most cases this is a c2s or Bosh component\n\t\t\t\t// which keep the user connection.\n\t\t\t\tString resource = packet.getStanzaTo().getResource();\n\n\t\t\t\tif (resource == null) {\n\n\t\t\t\t\t// In default packet handler we deliver packets to a specific resource only\n\t\t\t\t\tresult = Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"The feature is not supported yet.\", true);\n\t\t\t\t\tresult.setPacketFrom(null);\n\t\t\t\t\tresult.setPacketTo(null);\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise only to the given resource or sent back as error.\n\t\t\t\t\tXMPPResourceConnection con = session.getParentSession().getResourceForResource(\n\t\t\t\t\t\t\tresource);\n\n\t\t\t\t\tif (con != null) {\n\t\t\t\t\t\tresult = packet.copyElementOnly();\n\t\t\t\t\t\tresult.setPacketTo(con.getConnectionId());\n\n\t\t\t\t\t\t// In most cases this might be skept, however if there is a\n\t\t\t\t\t\t// problem during packet delivery an error might be sent back\n\t\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Delivering message, packet: {0}, to session: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\t\t\t\tcon });\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"The recipient is no longer available.\", true);\n\t\t\t\t\t\tresult.setPacketFrom(null);\n\t\t\t\t\t\tresult.setPacketTo(null);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Don't forget to add the packet to the results queue or it\n\t\t\t\t// will be lost.\n\t\t\t\tresults.offer(result);\n\n\t\t\t\treturn;\n\t\t\t}    // end of else\n\t\t\tif (from != null) {\n\t\t\t\tif (session.isUserId(from.getBareJID())) {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (NotAuthorizedException e) {\n\t\t\ttry {\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t\t\tlog.log(Level.FINE, \"NotAuthorizedException for packet: {0}\", packet.toString());\n\t\t\t} catch (PacketErrorTypeException e2) {\n\t\t\t\tlog.log(Level.FINE, \"Packet processing exception: {0}\", e2);\n\t\t\t}\n\t\t}    // end of try-catch\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/05/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppsession/SMResourceConnection.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.server.xmppsession;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthRepository;\nimport tigase.db.UserRepository;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.vhosts.VHostItem;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Feb 27, 2010 8:02:11 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SMResourceConnection extends XMPPResourceConnection {\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param connectionId\n\t * @param rep\n\t * @param authRepo\n\t * @param loginHandler\n\t */\n\tpublic SMResourceConnection(JID connectionId, UserRepository rep,\n\t\t\tAuthRepository authRepo, SessionManagerHandler loginHandler) {\n\t\tsuper(connectionId, rep, authRepo, loginHandler);\n\n\t\ttry {\n\t\t\tsetDomain(new VHostItem(loginHandler.getComponentId().getDomain()).getUnmodifiableVHostItem());\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(SMResourceConnection.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isServerSession() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isUserId(BareJID bareJID) {\n\t\treturn isLocalDomain(bareJID.toString(), false);\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppsession/SessionManager.java",
    "content": "/*\n * SessionManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppsession;\n\nimport tigase.annotations.TigaseDeprecatedComponent;\nimport tigase.auth.mechanisms.AbstractSaslSCRAM;\nimport tigase.auth.mechanisms.SaslEXTERNAL;\nimport tigase.conf.Configurable;\nimport tigase.conf.ConfigurationException;\nimport tigase.db.*;\nimport tigase.disco.XMPPService;\nimport tigase.server.*;\nimport tigase.server.script.CommandIfc;\nimport tigase.stats.StatisticsList;\nimport tigase.sys.OnlineJidsReporter;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.Base64;\nimport tigase.util.*;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.C2SDeliveryErrorProcessor;\nimport tigase.xmpp.impl.JabberIqRegister;\nimport tigase.xmpp.impl.PresenceCapabilitiesManager;\n\nimport javax.script.Bindings;\nimport java.io.ByteArrayInputStream;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateFactory;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.server.xmppsession.SessionManagerConfig.*;\n\n/**\n * Class SessionManager\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SessionManager\n\t\t\t\textends AbstractMessageReceiver\n\t\t\t\timplements Configurable, SessionManagerHandler, OnlineJidsReporter {\n\t/** Field description */\n\tprotected static final String ADMIN_COMMAND_NODE = \"http://jabber.org/protocol/admin\";\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(SessionManager.class.getName());\n\n\tprivate static final String SESSION_CLOSE_TIMER_KEY = \"session-close-timer\";\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate AuthRepository                   auth_repository                 = null;\n\tprivate long                             authTimeouts                    = 0;\n\tprivate long                             closedConnections               = 0;\n\tprivate DefaultHandlerProc               defHandlerProc                  = null;\n\tprivate PacketDefaultHandler             defPacketHandler                = null;\n\tprivate String                           defPluginsThreadsPool = \"default-threads-pool\";\n\tprivate boolean                          forceDetailStaleConnectionCheck = true;\n\tprivate int                              maxIdx                          = 100;\n\tprivate int                              maxUserConnections              = 0;\n\tprivate int                              maxUserSessions                 = 0;\n\tprivate int                              maxUserSessionsDaily            = 0;\n\tprivate int                              maxUserSessionsYesterday        = 0;\n\tprivate NonAuthUserRepository            naUserRepository                = null;\n\tprivate SessionCloseProc                 sessionCloseProc                = null;\n\tprivate SessionOpenProc                  sessionOpenProc                 = null;\n\tprivate SMResourceConnection             smResourceConnection            = null;\n\tprivate int                              tIdx                            = 0;\n\tprivate long                             totalUserConnections            = 0;\n\tprivate long                             totalUserSessions               = 0;\n\tprivate UserRepository                   user_repository                 = null;\n\tprivate Map<String, XMPPStopListenerIfc> stopListeners = new ConcurrentHashMap<String,\n\t\t\tXMPPStopListenerIfc>(10);\n\tprivate boolean          skipPrivacy = false;\n\tprivate int          pluginsThreadFactor = 1;\n\tprivate Set<XMPPImplIfc> allPlugins  = new ConcurrentSkipListSet<XMPPImplIfc>();\n\tprivate long authTimeout = 120;\n\n\t/**\n\t * A Map with bare user JID as a key and a user session object as a value.\n\t */\n\tprotected ConcurrentHashMap<BareJID, XMPPSession> sessionsByNodeId =\n\t\t\tnew ConcurrentHashMap<BareJID, XMPPSession>(100000);\n\tprivate Map<String, ProcessingThreads<ProcessorWorkerThread>> workerThreads =\n\t\t\tnew ConcurrentHashMap<String, ProcessingThreads<ProcessorWorkerThread>>(32);\n\tprivate StaleConnectionCloser         staleConnectionCloser =\n\t\t\tnew StaleConnectionCloser();\n\tprivate Map<String, XMPPProcessorIfc> processors = new ConcurrentHashMap<String,\n\t\t\tXMPPProcessorIfc>(32);\n\tprivate Map<String, XMPPPresenceUpdateProcessorIfc> presenceProcessors =\n\t\t\tnew ConcurrentHashMap<String, XMPPPresenceUpdateProcessorIfc>();\n\tprivate Map<String, XMPPPreprocessorIfc> preProcessors = new ConcurrentHashMap<String,\n\t\t\tXMPPPreprocessorIfc>(10);\n\n\t// private long[] defPrepTime = new long[maxIdx];\n\t// private long[] prepTime = new long[maxIdx];\n\t// private long[] defForwTime = new long[maxIdx];\n\t// private long[] walkTime = new long[maxIdx];\n\t// private long[] postTime = new long[maxIdx];\n\tprivate Map<String, long[]>               postTimes = new ConcurrentSkipListMap<String,\n\t\t\tlong[]>();\n\tprivate Map<String, XMPPPostprocessorIfc> postProcessors =\n\t\t\tnew ConcurrentHashMap<String, XMPPPostprocessorIfc>(10);\n\tprivate Map<String, Map<String, Object>> plugin_config = new ConcurrentHashMap<String,\n\t\t\tMap<String, Object>>(20);\n\tprivate Map<String, XMPPPacketFilterIfc> outFilters = new ConcurrentHashMap<String,\n\t\t\tXMPPPacketFilterIfc>(10);\n\tprivate ConnectionCheckCommandHandler connectionCheckCommandHandler =\n\t\t\tnew ConnectionCheckCommandHandler();\n\n\t/** Field description */\n\tprotected Queue<Packet> packetWriterQueue = new WriterQueue<Packet>();\n\n\t/**\n\t * A Map with connectionID as a key and an object with all the user connection\n\t * data as a value\n\t */\n\tprotected ConcurrentHashMap<JID, XMPPResourceConnection> connectionsByFrom =\n\t\t\tnew ConcurrentHashMap<JID, XMPPResourceConnection>(100000);\n\tprivate int activeUserNumber = 0;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean addOutPacket(Packet packet) {\n\n\t\t// We actually have to set packetFrom address to the session manager ID\n\t\t// to make sure the connection manager for instance can report problems back\n\t\t// This cause other problems with packets processing which have to be\n\t\t// resolved anyway\n\t\tif (packet.getPacketFrom() == null) {\n\t\t\tpacket.setPacketFrom(getComponentId());\n\t\t}\n\n\t\treturn super.addOutPacket(packet);\n\t}\n\n\tpublic XMPPImplIfc addPlugin(String plug_id, String conc)\n\t\t\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException {\n\t\tXMPPImplIfc      result = null;\n\t\tXMPPProcessorIfc proc   = null;\n\t\tString           version;\n\n\t\tif (plug_id.equals(sessionOpenProcId)) {\n\t\t\tsessionOpenProc = new SessionOpenProc();\n\t\t\tproc            = sessionOpenProc;\n\t\t}\n\t\tif (plug_id.equals(sessionCloseProcId)) {\n\t\t\tsessionCloseProc = new SessionCloseProc();\n\t\t\tproc             = sessionCloseProc;\n\t\t}\n\t\tif (plug_id.equals(defaultHandlerProcId)) {\n\t\t\tdefHandlerProc = new DefaultHandlerProc();\n\t\t\tproc           = defHandlerProc;\n\t\t}\n\t\tif (proc == null) {\n\t\t\tproc = SessionManagerConfig.getProcessor(plug_id);\n\t\t}\n\n\t\tboolean loaded = false;\n\t\tif (proc != null) {\n\t\t\tint threadsNo = proc.concurrentQueuesNo();\n\t\t\tint queueSize = maxQueueSize / threadsNo;\n\t\t\tif (conc != null && !conc.trim().isEmpty()) {\n\t\t\t\t\tString[] plug_conc = conc.split(\":\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthreadsNo = Integer.parseInt(plug_conc[0]);\n\t\t\t\t\t\tqueueSize = maxQueueSize / threadsNo;\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Concurrency for plugin: {0} set to: {1}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { plug_id,\n\t\t\t\t\t\t\t\t\t\t\tthreadsNo });\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Plugin \" + plug_id + \" concurrency parsing error for: \" + conc, e);\n\t\t\t\t\t\tthreadsNo = proc.concurrentQueuesNo();\n\t\t\t\t\t}\n\t\t\t\t\tif (plug_conc.length > 1) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tqueueSize = Integer.parseInt(plug_conc[1]);\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Queue for plugin: {0} set to: {1} per thread\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { plug_id,\n\t\t\t\t\t\t\t\t\t\t\tqueueSize });\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Plugin \" + plug_id + \" queueSize parsing error for: \" + conc, e);\n\t\t\t\t\t\tqueueSize = maxQueueSize / threadsNo;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n\n\t\t\tthreadsNo = threadsNo * pluginsThreadFactor;\n\n\t\t\t// If there is not default processors thread pool or the processor does\n\t\t\t// have thread pool specific settings create a separate thread pool\n\t\t\t// for the processor\n\t\t\tif ((workerThreads.get(defPluginsThreadsPool) == null) || (conc != null)) {\n\n\t\t\t\t// Added to make sure that there will be only one thread pool for plugin\n\t\t\t\t// so if one exits we will keep it and not create another one\n\t\t\t\tif (!workerThreads.containsKey(proc.id())) {\n\t\t\t\t\tProcessorWorkerThread                    worker = new ProcessorWorkerThread();\n\t\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt =\n\t\t\t\t\t\t\tnew ProcessingThreads<ProcessorWorkerThread>(worker, threadsNo,\n\t\t\t\t\t\t\tqueueSize, proc.id());\n\n\t\t\t\t\tworkerThreads.put(proc.id(), pt);\n\t\t\t\t\tlog.log(Level.CONFIG,\n\t\t\t\t\t\t\t\"Created thread pool: {0}, queue per thread: {1} for plugin id: {2}\", new Object[] {\n\t\t\t\t\t\t\tthreadsNo,\n\t\t\t\t\t\t\tqueueSize, proc.id() });\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessors.put(proc.id(), proc);\n\t\t\tlog.log(Level.CONFIG, \"Added processor: {0} for plugin id: {1}\", new Object[] { proc\n\t\t\t\t\t.getClass().getSimpleName(),\n\t\t\t\t\tproc.id() });\n\t\t\tloaded  = true;\n\t\t\tresult  = proc;\n\t\t\tversion = result.getComponentInfo().getComponentVersion();\n\t\t\tSystem.out.println(\"Loading plugin: \" + plug_id + \"=\" + threadsNo + \":\" + queueSize +\n\t\t\t\t\t\t\t\" ... \" +\t(version.isEmpty()\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: \"\\t, version: \" + version));\n\t\t}\n\n\t\tXMPPPreprocessorIfc preproc = SessionManagerConfig.getPreprocessor(plug_id);\n\n\t\tif (preproc != null) {\n\t\t\tpreProcessors.put(plug_id, preproc);\n\t\t\tlog.log(Level.CONFIG, \"Added preprocessor: {0} for plugin id: {1}\", new Object[] {\n\t\t\t\t\tpreproc.getClass().getSimpleName(),\n\t\t\t\t\tplug_id });\n\t\t\tloaded = true;\n\t\t\tresult = preproc;\n\t\t}\n\n\t\tXMPPPostprocessorIfc postproc = SessionManagerConfig.getPostprocessor(plug_id);\n\n\t\tif (postproc != null) {\n\t\t\tpostProcessors.put(plug_id, postproc);\n\t\t\tlog.log(Level.CONFIG, \"Added postprocessor: {0} for plugin id: {1}\", new Object[] {\n\t\t\t\t\tpostproc.getClass().getSimpleName(),\n\t\t\t\t\tplug_id });\n\t\t\tloaded = true;\n\t\t\tresult = postproc;\n\t\t}\n\n\t\tXMPPStopListenerIfc stoplist = SessionManagerConfig.getStopListener(plug_id);\n\n\t\tif (stoplist != null) {\n\t\t\tstopListeners.put(plug_id, stoplist);\n\t\t\tlog.log(Level.CONFIG, \"Added stopped processor: {0} for plugin id: {1}\",\n\t\t\t\t\tnew Object[] { stoplist.getClass().getSimpleName(),\n\t\t\t\t\tplug_id });\n\t\t\tloaded = true;\n\t\t\tresult = stoplist;\n\t\t}\n\n\t\tXMPPPacketFilterIfc filterproc = SessionManagerConfig.getPacketFilter(plug_id);\n\n\t\tif (filterproc != null) {\n\t\t\toutFilters.put(plug_id, filterproc);\n\t\t\tlog.log(Level.CONFIG, \"Added packet filter: {0} for plugin id: {1}\", new Object[] {\n\t\t\t\t\tfilterproc.getClass().getSimpleName(),\n\t\t\t\t\tplug_id });\n\t\t\tloaded = true;\n\t\t\tresult = filterproc;\n\t\t}\n\t\tif (!loaded) {\n\t\t\tlog.log(Level.WARNING, \"No implementation found for plugin id: {0}\", plug_id);\n\t\t}    // end of if (!loaded)\n\t\tif (result != null) {\n\t\t\tallPlugins.add(result);\n\t\t\tif (result instanceof PresenceCapabilitiesManager.PresenceCapabilitiesListener) {\n\t\t\t\tPresenceCapabilitiesManager.registerPresenceHandler((PresenceCapabilitiesManager\n\t\t\t\t\t\t.PresenceCapabilitiesListener) result);\n\t\t\t}\n\t\t\tif (result instanceof XMPPPresenceUpdateProcessorIfc) {\n\t\t\t\tpresenceProcessors.put(result.id(), (XMPPPresenceUpdateProcessorIfc) result);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean containsJid(BareJID jid) {\n\t\treturn sessionsByNodeId.containsKey(jid);\n\t}\n\t\n\t@Override\n\tpublic boolean containsJidLocally(BareJID jid) {\n\t\treturn sessionsByNodeId.containsKey(jid);\n\t}\n\n\t@Override\n\tpublic boolean containsJidLocally(JID jid) {\n\t\tXMPPSession session = sessionsByNodeId.get(jid.getBareJID());\n\t\treturn session != null && session.getResourceForJID(jid) != null;\n\t}\t\n\t\n\tpublic void handleLocalPacket(Packet packet, XMPPResourceConnection conn) {\n\n\t\t// Do nothing here. Maybe we will attach some handlers later\n\t}\n\n\t@Override\n\tpublic void handleLogin(BareJID userId, XMPPResourceConnection conn) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"handleLogin called for: {0}, conn_id: {1}\", new Object[] {\n\t\t\t\t\tuserId,\n\t\t\t\t\tconn });\n\t\t}\n\t\tregisterNewSession(userId, conn);\n\t}\n\n\t@Override\n\tpublic void handleLogout(BareJID userId, XMPPResourceConnection conn) {\n\t\tXMPPSession session = sessionsByNodeId.get(userId);\n\n\t\t// we need to make sure that session has no other connections as it might\n\t\t// have one connection but not this one, so condition\n\t\t// session.getActiveResourcesSize() <= 1\n\t\t// was not enough\n\t\t//if ((session != null) && (session.getActiveResourcesSize() <= 1)) {\n\t\tboolean onlyConnectionForSession = session != null && (session.getActiveResourcesSize() == 0\n\t\t\t\t|| (session.getActiveResourcesSize() == 1 && session.getActiveResources().contains(conn)));\n\n\t\tif (onlyConnectionForSession) {\n\t\t\tsessionsByNodeId.remove(userId);\n\t\t}    // end of if (session.getActiveResourcesSize() == 0)\n\t\ttry {\n\t\t\tconnectionsByFrom.remove(conn.getConnectionId());\n\n\t\t\tPacket cmd = Command.CLOSE.getPacket(getComponentId(), conn.getConnectionId(),\n\t\t\t\t\tStanzaType.set, conn.nextStanzaId());\n\t\t\tString error = (String) conn.getSessionData(XMPPResourceConnection.ERROR_KEY);\n\n\t\t\tif (error != null) {\n\t\t\t\tElement err_el = new Element(error);\n\n\t\t\t\terr_el.setXMLNS(\"urn:ietf:params:xml:ns:xmpp-streams\");\n\t\t\t\tcmd.getElement().getChild(\"command\").addChild(err_el);\n\t\t\t}\n\t\t\tfastAddOutPacket(cmd);\n\t\t} catch (NoConnectionIdException ex) {\n\t\t\tlog.log(Level.WARNING, \"Connection ID not set for session: {0}\", conn);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handlePresenceSet(XMPPResourceConnection conn) {\n\t\tXMPPSession parentSession = conn.getParentSession();\n\n\t\tif (parentSession == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tElement presence = conn.getPresence();\n\n\t\tthis.processPresenceUpdate(parentSession, presence);\n\t}\n\n\t@Override\n\tpublic void handleResourceBind(XMPPResourceConnection conn) {\n\t\tif (!conn.isServerSession() && (!\"USER_STATUS\".equals(conn.getSessionId())) &&!conn\n\t\t\t\t.isTmpSession()) {\n\t\t\ttry {\n\t\t\t\tPacket user_login_cmd = Command.USER_LOGIN.getPacket(getComponentId(), conn\n\t\t\t\t\t\t.getConnectionId(), StanzaType.set, conn.nextStanzaId(), Command.DataType\n\t\t\t\t\t\t.submit);\n\n\t\t\t\tCommand.addFieldValue(user_login_cmd, \"user-jid\", conn.getjid().toString());\n\t\t\t\taddOutPacket(user_login_cmd);\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// This actually should not happen... might be a bug:\n\t\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean handlesLocalDomains() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int hashCodeForPacket(Packet packet) {\n\t\t// moved this check from AbstractMessageReceiver as it is related only to SM\n\t\t// and in other components it causes issues as SM sending packet send packetFrom\n\t\t// to SM address which in fact forced other components to process all packets\n\t\t// from SM on single thread !!\n\t\tif ((packet.getPacketFrom() != null) &&!getComponentId().equals(packet\n\t\t\t\t.getPacketFrom())) {\n\n\t\t\t// This comes from connection manager so the best way is to get hashcode\n\t\t\t// by the connectionId, which is in the getFrom()\n\t\t\treturn packet.getPacketFrom().hashCode();\n\t\t}\n\t\t\n\t\treturn super.hashCodeForPacket(packet);\n\t}\n\t\n\t@Override\n\tpublic void initBindings( Bindings binds ) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(CommandIfc.AUTH_REPO, auth_repository);\n\t\tbinds.put(CommandIfc.USER_CONN, connectionsByFrom);\n\t\tbinds.put(CommandIfc.USER_REPO, user_repository);\n\t\tbinds.put(CommandIfc.USER_SESS, sessionsByNodeId);\n\t\tXMPPProcessorIfc registerModule = getProcessor(JabberIqRegister.ID);\n\t\tif (registerModule != null)\n\t\t\tbinds.put(\"JabberIqRegister\", registerModule);\n\n\t}\n\n\t@Override\n\tpublic int processingInThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors() * 16;\n\t}\n\n\t@Override\n\tpublic int processingOutThreads() {\n\t\treturn Runtime.getRuntime().availableProcessors() * 16;\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Received packet: {0}\", packet.toStringSecure());\n\t\t}\n\t\tif (packet.isCommand() && processCommand(packet)) {\n\t\t\tpacket.processedBy(\"SessionManager\");\n\n\t\t\t// No more processing is needed for command packet\n\t\t\treturn;\n\t\t}    // end of if (pc.isCommand())\n\n\t\tXMPPResourceConnection conn = getXMPPResourceConnection(packet);\n\n\t\tif ((conn == null) && (isBrokenPacket(packet)) || processAdminsOrDomains(packet)) {\n\t\t\treturn;\n\t\t}\n\t\tprocessPacket(packet, conn);\n\t}\n\n\tpublic void removePlugin(String plug_id) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Removing plugin {0}\", plug_id);\n\t\t}\n\n\t\tXMPPImplIfc                              p  = null;\n\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.remove(plug_id);\n\n\t\tif (pt != null) {\n\t\t\tp = processors.remove(plug_id);\n\t\t\tpt.shutdown();\n\t\t\tif (p != null) {\n\t\t\t\tallPlugins.remove(p);\n\t\t\t}\n\t\t}\n\t\tif (preProcessors.get(plug_id) != null) {\n\t\t\tp = preProcessors.remove(plug_id);\n\t\t\tallPlugins.remove(p);\n\t\t}\n\t\tif (postProcessors.get(plug_id) != null) {\n\t\t\tp = postProcessors.remove(plug_id);\n\t\t\tallPlugins.remove(p);\n\t\t}\n\t\tif (stopListeners.get(plug_id) != null) {\n\t\t\tp = stopListeners.remove(plug_id);\n\t\t\tallPlugins.remove(p);\n\t\t}\n\t\tif (p != null) {\n\t\t\tif (p instanceof PresenceCapabilitiesManager.PresenceCapabilitiesListener) {\n\t\t\t\tPresenceCapabilitiesManager.unregisterPresenceHandler((PresenceCapabilitiesManager\n\t\t\t\t\t\t.PresenceCapabilitiesListener) p);\n\t\t\t}\n\t\t\tif (p instanceof XMPPPresenceUpdateProcessorIfc) {\n\t\t\t\tpresenceProcessors.remove(plug_id);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic boolean skipPrivacy() {\n\t\treturn skipPrivacy;\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tsuper.stop();\n\t\tList<String> pluginsToStop = new ArrayList<String>(workerThreads.keySet());\n\t\tfor (String plugin_id : pluginsToStop) {\n\t\t\ttry {\n\t\t\t\tremovePlugin(plugin_id);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Exception while stopping plugin\", ex);\n\t\t\t}\n\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic JID[] getConnectionIdsForJid(BareJID jid) {\n\t\tif (skipPrivacy()) {\n\t\t\tXMPPSession session = sessionsByNodeId.get(jid);\n\n\t\t\tif (session != null) {\n\t\t\t\treturn session.getConnectionIds();\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> props = super.getDefaults(params);\n\n\t\tSessionManagerConfig.getDefaults(props, params);\n\t\tprops.put(FORCE_DETAIL_STALE_CONNECTION_CHECK, true);\n\t\tprops.put(STALE_CONNECTION_CLOSER_QUEUE_SIZE_KEY, StaleConnectionCloser\n\t\t\t\t.DEF_QUEUE_SIZE);\n\t\tprops.put(AUTH_TIMEOUT_PROP_KEY, AUTH_TIMEOUT_PROP_VAL);\n\t\tprops.put(SM_THREADS_FACTOR_PROP_KEY, SM_THREADS_FACTOR_PROP_VAL);\n\n\t\treturn props;\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn \"sm\";\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"Session manager\";\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\tList<Element> features = new LinkedList<Element>();\n\t\tList<Element> tmp      = super.getDiscoFeatures(from);\n\n\t\tif (tmp != null) {\n\t\t\tfeatures.addAll(tmp);\n\t\t}\n\t\tfor (XMPPProcessorIfc proc_t : processors.values()) {\n\t\t\tElement[] discoFeatures = proc_t.supDiscoFeatures(null);\n\n\t\t\tif (discoFeatures != null) {\n\t\t\t\tfeatures.addAll(Arrays.asList(discoFeatures));\n\t\t\t}    // end of if (discoFeatures != null)\n\t\t}\n\n\t\treturn features;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tif ((jid != null) && (getName().equals(jid.getLocalpart()) || isLocalDomain(jid\n\t\t\t\t.toString()))) {\n\t\t\tElement query = super.getDiscoInfo(node, jid, from);\n\n\t\t\tif (query == null) {\n\t\t\t\tquery = new Element(\"query\");\n\t\t\t\tquery.setXMLNS(XMPPService.INFO_XMLNS);\n\t\t\t}\n\t\t\tif (node == null) {\n\t\t\t\tfor (XMPPProcessorIfc proc_t : processors.values()) {\n\t\t\t\t\tElement[] discoFeatures = proc_t.supDiscoFeatures(null);\n\n\t\t\t\t\tif (discoFeatures != null) {\n\t\t\t\t\t\tquery.addChildren(Arrays.asList(discoFeatures));\n\t\t\t\t\t}    // end of if (discoFeatures != null)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Found disco info: {0}\", ((query != null)\n\t\t\t\t\t\t? query.toString()\n\t\t\t\t\t\t: null));\n\t\t\t}\n\n\t\t\treturn query;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Not found disco info for node: {0}, jid: {1}\",\n\t\t\t\t\tnew Object[] { node,\n\t\t\t\t\tjid });\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic XMPPResourceConnection getResourceConnection(JID jid) {\n\t\tXMPPSession session = getSession(jid.getBareJID());\n\n\t\tif (session != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Session not null, searching session for jid: {0}\", jid);\n\t\t\t}\n\n\t\t\tXMPPResourceConnection res = session.getResourceConnection(jid);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Found session: {0}, for jid: {1}\", new Object[] { res,\n\t\t\t\t\t\tjid });\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}    // end of if (session != null)\n\n\t\t// Maybe this is a call for the server session?\n\t\tif (isLocalDomain(jid.toString(), false)) {\n\t\t\treturn smResourceConnection;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic int getOpenUsersConnectionsAmount(){\n\t\treturn connectionsByFrom.size();\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tif (list.checkLevel(Level.FINEST)) {\n\t\t\tlist.add(getName(), \"Registered accounts\", user_repository.getUsersCount(), Level\n\t\t\t\t\t.FINEST);\n\t\t}\n\t\tlist.add(getName(), \"Open user connections\", connectionsByFrom.size(), Level.INFO);\n\t\tlist.add(getName(), \"Maximum user connections\", maxUserConnections, Level.INFO);\n\t\tlist.add(getName(), \"Total user connections\", totalUserConnections, Level.FINER);\n\t\tlist.add(getName(), \"Closed user connections\", closedConnections, Level.FINER);\n\t\tlist.add(getName(), \"Open user sessions\", sessionsByNodeId.size(), Level.INFO);\n\t\tlist.add(getName(), \"Maximum user sessions\", maxUserSessions, Level.FINE);\n\t\tlist.add(getName(), \"Total user sessions\", totalUserSessions, Level.FINER);\n\t\tlist.add(getName(), \"Active user connections\", activeUserNumber, Level.FINER);\n\t\tlist.add(getName(), \"Authentication timouts\", authTimeouts, Level.INFO);\n\t\tif (list.checkLevel(Level.INFO)) {\n\t\t\tint  totalQueuesWait     = list.getValue(getName(), \"Total queues wait\", 0);\n\t\t\tlong totalQueuesOverflow = list.getValue(getName(), \"Total queues overflow\", 0l);\n\n\t\t\tfor (Map.Entry<String, ProcessingThreads<ProcessorWorkerThread>> procent :\n\t\t\t\t\tworkerThreads.entrySet()) {\n\t\t\t\tProcessingThreads<ProcessorWorkerThread> proc = procent.getValue();\n\n\t\t\t\ttotalQueuesWait     += proc.getTotalQueueSize();\n\t\t\t\ttotalQueuesOverflow += proc.getDroppedPackets();\n\t\t\t\tif (list.checkLevel(Level.INFO, proc.getTotalQueueSize() + proc\n\t\t\t\t\t\t.getDroppedPackets())) {\n\t\t\t\t\tlist.add(getName(), \"Processor: \" + procent.getKey(), \", Queue: \" + proc\n\t\t\t\t\t\t\t.getTotalQueueSize() + \", AvTime: \" + proc.getAverageProcessingTime() +\n\t\t\t\t\t\t\t\", Runs: \" + proc.getTotalRuns() + \", Lost: \" + proc.getDroppedPackets(),\n\t\t\t\t\t\t\tLevel.INFO);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlist.add(getName(), \"Total queues wait\", totalQueuesWait, Level.INFO);\n\t\t\tlist.add(getName(), \"Total queues overflow\", totalQueuesOverflow, Level.INFO);\n\t\t}\n\t\tif (list.checkLevel(Level.FINE)) {\n\t\t\tfor (Map.Entry tmEntry : postTimes.entrySet()) {\n\n\t\t\t\t// This line is only temporary because JIndent cannot parse it inside the above\n\t\t\t\t// for statement\n\t\t\t\tMap.Entry<String, long[]> entry = tmEntry;\n\n\t\t\t\tlist.add(getName(), \"Average \" + tmEntry.getKey() + \" on last \" + entry.getValue()\n\t\t\t\t\t\t.length + \" runs [ms]\", calcAverage(entry.getValue()), Level.FINE);\n\t\t\t}\n\t\t}\n\t\tlist.add(getName(), \"Maximum user sessions today\", maxUserSessionsDaily, Level.INFO);\n\t\tlist.add(getName(), \"Maximum user sessions yesterday\", maxUserSessionsYesterday, Level.INFO);\n\n\t\tfor (XMPPImplIfc plugin : allPlugins) {\n\t\t\tplugin.getStatistics(list);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasCompleteJidsInfo() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isLocalDomain(String domain, boolean includeComponents) {\n\t\tif (includeComponents) {\n\t\t\treturn isLocalDomainOrComponent(domain);\n\t\t} else {\n\t\t\treturn isLocalDomain(domain);\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t\tTigaseRuntime.getTigaseRuntime().addOnlineJidsReporter(this);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\t\tif (props.get(SKIP_PRIVACY_PROP_KEY) != null) {\n\t\t\tskipPrivacy = (Boolean) props.get(SKIP_PRIVACY_PROP_KEY);\n\t\t}\n\t\tif (props.get(FORCE_DETAIL_STALE_CONNECTION_CHECK) != null) {\n\t\t\tforceDetailStaleConnectionCheck = (Boolean) props.get(\n\t\t\t\t\tFORCE_DETAIL_STALE_CONNECTION_CHECK);\n\t\t\tlog.log(Level.CONFIG, \"forced detailed stale connection checking is set to = {0}\",\n\t\t\t\t\tforceDetailStaleConnectionCheck);\n\t\t}\n\t\tif (props.get(SM_THREADS_FACTOR_PROP_KEY) != null) {\n\t\t\tpluginsThreadFactor = (Integer) props.get(SM_THREADS_FACTOR_PROP_KEY);\n\t\t\tlog.log(Level.CONFIG, \"plugins thread pool multiplication factor set to = {0}\", pluginsThreadFactor);\n\t\t}\n\t\tif (props.get(STALE_CONNECTION_CLOSER_QUEUE_SIZE_KEY) != null) {\n\t\t\tstaleConnectionCloser.setMaxQueueSize((Integer) props.get(\n\t\t\t\t\tSTALE_CONNECTION_CLOSER_QUEUE_SIZE_KEY));\n\t\t\tlog.log(Level.CONFIG, \"stale connection closer queue is set to = {0}\",\n\t\t\t\t\tstaleConnectionCloser.getMaxQueueSize());\n\t\t}\n\t\tif (!staleConnectionCloser.isScheduled()) {\n\t\t\taddTimerTask(staleConnectionCloser, staleConnectionCloser.getTimeout());\n\t\t}\n\n\t\tif (props.get(AUTH_TIMEOUT_PROP_KEY) != null) {\n\t\t\tauthTimeout = (Long)props.get(AUTH_TIMEOUT_PROP_KEY);\n\t\t}\n\n\t\tif (props.size() == 1) {\n\n\t\t\t// If props.size() == 1, it means this is a single property update\n\t\t\t// and this component does not support single property change for the rest\n\t\t\t// of it's settings\n\t\t\treturn;\n\t\t}\n\t\tdefPacketHandler = new PacketDefaultHandler();\n\n\t\t// Is there shared user repository instance? If so I want to use it:\n\t\tuser_repository = (UserRepository) props.get(RepositoryFactory\n\t\t\t\t.SHARED_USER_REPO_PROP_KEY);\n\t\tif (user_repository != null) {\n\t\t\tlog.log(Level.CONFIG, \"Using shared repository instance: {0}\", user_repository\n\t\t\t\t\t.getClass().getName());\n\t\t} else {\n\t\t\tMap<String, String> user_repo_params = new LinkedHashMap<String, String>(10);\n\n\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\tif (entry.getKey().startsWith(RepositoryFactory.USER_REPO_PARAMS_NODE)) {\n\n\t\t\t\t\t// Split the key to configuration nodes separated with '/'\n\t\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t\t// The plugin ID part may contain many IDs separated with comma ','\n\t\t\t\t\tif (nodes.length > 1) {\n\t\t\t\t\t\tuser_repo_params.put(nodes[1], entry.getValue().toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\n\t\t\t\t// String cls_name = (String) props.get(USER_REPO_CLASS_PROP_KEY);\n\t\t\t\tString res_uri = (String) props.get(RepositoryFactory.USER_REPO_URL_PROP_KEY);\n\n\t\t\t\tuser_repository = RepositoryFactory.getUserRepository(null, res_uri,\n\t\t\t\t\t\tuser_repo_params);\n\t\t\t\tlog.log(Level.CONFIG, \"Initialized {0} as user repository: {1}\", new Object[] {\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tres_uri });\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize user repository: \", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t\tauth_repository = (AuthRepository) props.get(RepositoryFactory\n\t\t\t\t.SHARED_AUTH_REPO_PROP_KEY);\n\t\tif (auth_repository != null) {\n\t\t\tlog.log(Level.CONFIG, \"Using shared auth repository instance: {0}\", auth_repository\n\t\t\t\t\t.getClass().getName());\n\t\t} else {\n\t\t\tMap<String, String> auth_repo_params = new LinkedHashMap<String, String>(10);\n\n\t\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\t\tif (entry.getKey().startsWith(RepositoryFactory.AUTH_REPO_PARAMS_NODE)) {\n\n\t\t\t\t\t// Split the key to configuration nodes separated with '/'\n\t\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t\t// The plugin ID part may contain many IDs separated with comma ','\n\t\t\t\t\tif (nodes.length > 1) {\n\t\t\t\t\t\tauth_repo_params.put(nodes[1], entry.getValue().toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tString res_uri = (String) props.get(RepositoryFactory.AUTH_REPO_URL_PROP_KEY);\n\n\t\t\t\tauth_repository = RepositoryFactory.getAuthRepository(null, res_uri,\n\t\t\t\t\t\tauth_repo_params);\n\t\t\t\tlog.log(Level.CONFIG, \"Initialized {0} as auth repository: {1}\", new Object[] {\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tres_uri });\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize auth repository: \", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t\tnaUserRepository = new NonAuthUserRepositoryImpl(user_repository, getDefHostName(),\n\t\t\t\tBoolean.parseBoolean((String) props.get(AUTO_CREATE_OFFLINE_USER_PROP_KEY)));\n\t\tsynchronized (this) {\n\t\t\tLinkedHashMap<String, String> plugins_concurrency = new LinkedHashMap<String,\n\t\t\t\t\tString>(20);\n\t\t\tString[] plugins_conc = ((String) props.get(PLUGINS_CONCURRENCY_PROP_KEY)).split(\n\t\t\t\t\t\",\");\n\n\t\t\tlog.log(Level.CONFIG, \"Loading concurrency plugins list: {0}\", Arrays.toString(\n\t\t\t\t\tplugins_conc));\n\t\t\tif ((plugins_conc != null) && (plugins_conc.length > 0)) {\n\t\t\t\tfor (String plugc : plugins_conc) {\n\t\t\t\t\tlog.log(Level.CONFIG, \"Loading: {0}\", plugc);\n\t\t\t\t\tif (!plugc.trim().isEmpty()) {\n\t\t\t\t\t\tString[] pc = plugc.split(\"=\");\n\t\t\t\t\t\tplugins_concurrency.put(pc[0], pc[1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSet<String> keys = new HashSet<String>(processors.keySet());\n\n\t\t\ttry {\n\t\t\t\tif (!isInitializationComplete()) {\n\t\t\t\t\tString sm_threads_pool = (String) props.get(SM_THREADS_POOL_PROP_KEY);\n\n\t\t\t\t\tif (!sm_threads_pool.equals(SM_THREADS_POOL_PROP_VAL)) {\n\t\t\t\t\t\tString[] threads_pool_params = sm_threads_pool.split(\":\");\n\t\t\t\t\t\tint      def_pool_size       = 100;\n\n\t\t\t\t\t\tif (threads_pool_params.length > 1) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tdef_pool_size = Integer.parseInt(threads_pool_params[1]);\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\t\t\"Incorrect threads pool size: {0}, setting default to 100\",\n\t\t\t\t\t\t\t\t\t\tthreads_pool_params[1]);\n\t\t\t\t\t\t\t\tdef_pool_size = 100;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tProcessorWorkerThread                    worker = new ProcessorWorkerThread();\n\t\t\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt =\n\t\t\t\t\t\t\t\tnew ProcessingThreads<ProcessorWorkerThread>(worker, def_pool_size,\n\t\t\t\t\t\t\t\tmaxQueueSize, defPluginsThreadsPool);\n\n\t\t\t\t\t\tworkerThreads.put(defPluginsThreadsPool, pt);\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Created a default thread pool: {0}\", def_pool_size);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tString[] plugins = SessionManagerConfig.getActivePlugins(props);\n\n\t\t\t\tlog.log(Level.CONFIG, \"Loaded plugins list: {0}\", Arrays.toString(plugins));\n\n\t\t\t\t// maxPluginsNo = plugins.length;\n\t\t\t\t// processors.clear();\n\t\t\t\tfor (String plug_id : plugins) {\n\t\t\t\t\tkeys.remove(plug_id);\n\t\t\t\t\tlog.log(Level.CONFIG, \"Loading and configuring plugin: {0}\", plug_id);\n\n\t\t\t\t\tXMPPImplIfc plugin = addPlugin(plug_id, plugins_concurrency.get(plug_id));\n\n\t\t\t\t\tif (plugin != null) {\n\t\t\t\t\t\tif (plugin.getClass().isAnnotationPresent(TigaseDeprecatedComponent.class)) {\n\t\t\t\t\t\t\tTigaseDeprecatedComponent annotation = plugin.getClass().getAnnotation( TigaseDeprecatedComponent.class );\n\t\t\t\t\t\t\tlog.log( Level.WARNING, \"Deprecated Plugin: \" + plugin.id() + \", INFO: \" + annotation.note() + \"\\n\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tMap<String, Object> plugin_settings = getPluginSettings(plug_id, props);\n\n\t\t\t\t\t\tif (plugin_settings.size() > 0) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.CONFIG)) {\n\t\t\t\t\t\t\t\tlog.log(Level.CONFIG, \"Plugin configuration: {0}\", plugin_settings);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tplugin_config.put(plug_id, plugin_settings);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tplugin.init(plugin_settings);\n\t\t\t\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\t\t\t\tlog.log(Level.SEVERE, \"Problem initializing plugin: \" + plugin.id(), ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}    // end of for (String comp_id: plugins)\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Problem with component initialization: \" + getName(), e);\n\t\t\t}\n\t\t\tfor (String key : keys) {\n\t\t\t\tremovePlugin(key);\n\t\t\t}\n\t\t}\n\t\tif (!isInitializationComplete()) {\n\t\t\tsmResourceConnection = new SMResourceConnection(null, user_repository,\n\t\t\t\t\tauth_repository, this);\n\t\t\tregisterNewSession(getComponentId().getBareJID(), smResourceConnection);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected void addOutPackets(Packet packet, XMPPResourceConnection conn,\n\t\t\tQueue<Packet> results) {\n\t\tfor (XMPPPacketFilterIfc outfilter : outFilters.values()) {\n\t\t\toutfilter.filter(packet, conn, naUserRepository, results);\n\t\t}    // end of for (XMPPPostprocessorIfc postproc: postProcessors)\n\t\taddOutPackets(results);\n\t}\n\n\tprotected boolean addTrusted(JID jid) {\n\t\treturn trusted.add(jid.getBareJID().toString());\n\t}\n\n\tprotected void closeConnection(XMPPResourceConnection connection, JID connectionId, \n\t\t\tString userId, boolean closeOnly) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"Stream closed from: {0}\", connectionId);\n\t\t}\n\n\t\t// for test let's assume connection is not found\n\t\tif (connection == null) {\n\t\t\tconnection = connectionsByFrom.remove(connectionId);\n\t\t}\n\n\t\tif (connection != null) {\n\n\t\t\t// Make sure no other stuff happen on the connection while it is being\n\t\t\t// closed. The best example is handleLogin, it happens they are called\n\t\t\t// concurrently and this is where things go wrong....\n\t\t\tsynchronized (connection) {\n\t\t\t\tconnection.putSessionData(XMPPResourceConnection.CLOSING_KEY,\n\t\t\t\t\t\tXMPPResourceConnection.CLOSING_KEY);\n\t\t\t\tcloseSession(connection, closeOnly);\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Can not find resource connection for connectionId: {0}\",\n\t\t\t\t\t\tconnectionId);\n\t\t\t}\n\t\t\tif (userId != null) {\n\n\t\t\t\t// check using userId if we can find stale XMPPResourceConnection\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Found trying to find stale XMPPResourceConnection by userId {0}...\",\n\t\t\t\t\t\t\tuserId);\n\t\t\t\t}\n\n\t\t\t\tJID         userJid         = JID.jidInstanceNS(userId);\n\t\t\t\tXMPPSession sessionByUserId = getSession(userJid.getBareJID());\n\n\t\t\t\tif (sessionByUserId != null) {\n\t\t\t\t\tconnection = sessionByUserId.getResourceForConnectionId(connectionId);\n\t\t\t\t\tif (connection != null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\"Found stale XMPPResourceConnection {0} by userId {1}, removing...\",\n\t\t\t\t\t\t\t\t\tnew Object[] { connection,\n\t\t\t\t\t\t\t\t\tuserId });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsessionByUserId.removeResourceConnection(connection);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Maybe we should move this loop based check to separe thread for performance reason\n\t\t\t// Check if our Set<JID> of not found sessions contains each of available connections from each session\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"queuing connection {0} for user {1} for detail stale connection check - should not happen!!\", \n\t\t\t\t\t\tnew Object[] { connectionId, userId });\n\t\t\t}\n\t\t\tif (!forceDetailStaleConnectionCheck) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Let's make sure there is no stale XMPPResourceConnection in some\n\t\t\t// XMPPSession\n\t\t\t// object which may cause problems and packets sent to nowhere.\n\t\t\t// This might an expensive operation though.... add item to queue\n\t\t\t// executed in other thread\n\t\t\tstaleConnectionCloser.queueForClose(connectionId);\n\n\t\t\t// code below is original loop for finding stale XMPPResourceConnections\n//    log.log(Level.INFO, \"Trying to find and remove stale XMPPResourceConnection: {0}\",\n//        connectionId);\n//\n//    for (XMPPSession session : sessionsByNodeId.values()) {\n//      connection = session.getResourceForConnectionId(connectionId);\n//      if (connection != null) {\n//        log.log(Level.WARNING, \"Found stale XMPPResourceConnection: {0}, removing...\",\n//            connection);\n//        session.removeResourceConnection(connection);\n//\n//        break;\n//      }\n//    }\n\t\t}    // end of if (conn != null) else\n\t}\n\n\tprotected void closeSession(XMPPResourceConnection conn, boolean closeOnly) {\n\t\tif (!closeOnly) {\n\t\t\tQueue<Packet> results = new ArrayDeque<Packet>(50);\n\n\t\t\tfor (XMPPStopListenerIfc stopProc : stopListeners.values()) {\n\t\t\t\tstopProc.stopped(conn, results, plugin_config.get(stopProc.id()));\n\t\t\t}    // end of for ()\n\t\t\taddOutPackets(null, conn, results);\n\t\t}\n\t\ttry {\n\t\t\tif (conn.isAuthorized()) {\n\t\t\t\tJID userJid = conn.getJID();\n\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE, \"Closing connection for: {0}, conn: {1}\", new Object[] {userJid, conn});\n\t\t\t\t}\n\n\t\t\t\tXMPPSession sessionParent = conn.getParentSession();\n\n\t\t\t\tif (sessionParent != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"Found parent session for: {0}\", userJid);\n\t\t\t\t\t}\n\t\t\t\t\t// as we are closing this connection we should ensure that it is removed\n\t\t\t\t\t// from list of active resources before going any further\n\t\t\t\t\tsessionParent.removeResourceConnection(conn);\n\t\t\t\t\tif (sessionParent.getActiveResourcesSize() <= 1) {\n\n\t\t\t\t\t\t// we should check if other this is the only connection on session\n\t\t\t\t\t\t// as in some cases connection can be already removed from active\n\t\t\t\t\t\t// resources but there might be other connection which is active\n\t\t\t\t\t\tif ((sessionParent.getActiveResourcesSize() > 0) &&!sessionParent.getActiveResources()\n\t\t\t\t\t\t\t\t.contains(conn)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"Session contains connection for other \" +\n\t\t\t\t\t\t\t\t\t\"resource than: {0}, not removing session\", userJid);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tStringBuilder sb = new StringBuilder(100);\n\n\t\t\t\t\t\t\t\tfor (XMPPResourceConnection res_con : sessionParent.getActiveResources()) {\n\t\t\t\t\t\t\t\t\tsb.append(\", res=\").append(res_con.getResource());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tlog.log(Level.FINER, \"Number of connections is {0} for the user: {1}{2}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { sessionParent.getActiveResourcesSize(),\n\t\t\t\t\t\t\t\t\t\tuserJid, sb.toString() });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tXMPPSession sessionFromMap = getSession( userJid.getBareJID());\n\n\t\t\t\t\t\tif (sessionParent.equals( sessionFromMap ) && sessionFromMap.getActiveResources().isEmpty() ) {\n\t\t\t\t\t\t\tsessionParent = sessionsByNodeId.remove(userJid.getBareJID());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (sessionParent == null) {\n\t\t\t\t\t\t\tlog.log(Level.INFO, \"UPS can't remove, session not found in map: {0}\",\n\t\t\t\t\t\t\t\t\tuserJid);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINER, \"Number of user sessions: {0}\", sessionsByNodeId\n\t\t\t\t\t\t\t\t\t\t.size());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}    // end of else\n\t\t\t\t\t\tauth_repository.logout(userJid.getBareJID());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\tStringBuilder sb = new StringBuilder(100);\n\n\t\t\t\t\t\t\tfor (XMPPResourceConnection res_con : sessionParent.getActiveResources()) {\n\t\t\t\t\t\t\t\tsb.append(\", res=\").append(res_con.getResource());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlog.log(Level.FINER, \"Number of connections is {0} for the user: {1}{2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { sessionParent.getActiveResourcesSize(),\n\t\t\t\t\t\t\t\t\tuserJid, sb.toString() });\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of if (session.getActiveResourcesSize() == 0)\n\t\t\t}\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.log(Level.INFO, \"Closed not authorized session: {0}\", e);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Exception closing session... \", e);\n\t\t}\n\t\t++closedConnections;\n\t\tconn.streamClosed();\n\t}\n\n\tprotected XMPPResourceConnection createUserSession(JID conn_id, String domain)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tXMPPResourceConnection connection = new XMPPResourceConnection(conn_id,\n\t\t\t\tuser_repository, auth_repository, this);\n\t\tVHostItem vitem = null;\n\n\t\tif (domain != null) {\n\t\t\tvitem = getVHostItem(domain);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Setting hostname {0} for connection: {1}, VHostItem: {2}\",\n\t\t\t\t\t\tnew Object[] { domain,\n\t\t\t\t\t\tconn_id, vitem });\n\t\t\t}\n\t\t}\n\t\tif (vitem == null) {\n\n\t\t\t// This shouldn't generally happen. Must mean misconfiguration.\n\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\"Can't get VHostItem for domain: {0}, using default one instead: {1}\",\n\t\t\t\t\t\tnew Object[] { domain,\n\t\t\t\t\t\tgetDefHostName() });\n\t\t\t}\n\t\t\tvitem = new VHostItem(getDefHostName().getDomain());\n\t\t}\n\t\tconnection.setDomain(vitem.getUnmodifiableVHostItem());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Domain set for connectionId {0}\", conn_id);\n\t\t}\n\t\tconnectionsByFrom.put(conn_id, connection);\n\n\t\tint currSize = connectionsByFrom.size();\n\n\t\tif (currSize > maxUserConnections) {\n\t\t\tmaxUserConnections = currSize;\n\t\t}\n\t\t++totalUserConnections;\n\n\t\treturn connection;\n\t}\n\n\tprotected boolean delTrusted(JID jid) {\n\t\treturn trusted.remove(jid.getBareJID().toString());\n\t}\n\n\tprotected boolean fastAddOutPacket(Packet packet) {\n\t\treturn addOutPacket(packet);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tprotected XMPPResourceConnection loginUserSession(JID conn_id, String domain,\n\t\t\tBareJID user_id, String resource, String xmpp_sessionId, boolean tmpSession) {\n\t\ttry {\n\t\t\tXMPPResourceConnection conn = createUserSession(conn_id, domain);\n\n\t\t\tconn.setTmpSession(tmpSession);\n\t\t\tconn.setSessionId(xmpp_sessionId);\n\n\t\t\t// user_repository.setData(user_id, \"tokens\", xmpp_sessionId, conn_id.toString());\n\t\t\t// Authorization auth = conn.loginToken(user_id, xmpp_sessionId, conn_id.toString());\n\t\t\tconn.authorizeJID(user_id, false);\n\t\t\tif (conn.isAuthorized()) {\n\t\t\t\thandleLogin(user_id, conn);\n\t\t\t\tif ( resource == null ){\n\t\t\t\t\tresource = UUID.randomUUID().toString();\n\t\t\t\t}\n\t\t\t\tconn.setResource( resource );\n\t\t\t} else {\n\t\t\t\tconnectionsByFrom.remove(conn_id);\n\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn conn;\n\t\t} catch (TigaseStringprepException | NotAuthorizedException ex) {\n\t\t\tlog.log(Level.WARNING, \"Problem logging user: \" + user_id + \"/\" + resource, ex);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprotected boolean processAdminsOrDomains(Packet packet) {\n\t\tif ((packet.getStanzaFrom() == null) && (packet.getPacketFrom() != null)) {\n\n\t\t\t// The packet, probably did not went through the first state of processing\n\t\t\t// yet.\n\t\t\treturn false;\n\t\t}\n\n\t\tJID to = packet.getStanzaTo();\n\n\t\tif ((to != null) && isLocalDomain(to.toString())) {\n\t\t\tif (packet.getElemName() == \"message\") {\n\n\t\t\t\t// Yes this packet is for admin....\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Packet for admin: {0}\", packet);\n\t\t\t\t}\n\t\t\t\tsendToAdmins(packet);\n\t\t\t\tpacket.processedBy(\"admins-or-domains\");\n\n\t\t\t\treturn true;\n\t\t\t} else if (packet.getElemName() == \"iq\"\n\t\t\t\t\t\t\t\t && packet.getType() == StanzaType.result) {\n\t\t\t\tif ( log.isLoggable( Level.FINER ) ){\n\t\t\t\t\tlog.log( Level.FINER, \"IQ result packet addressed directly to server and not handle by any plugin: {0}\",\n\t\t\t\t\t\t\t\t\t packet );\n\t\t\t\t}\n\t\t\t\tpacket.processedBy( \"iq-result-to-server\" );\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Packet for hostname, should be handled elsewhere: {0}\",\n\t\t\t\t\t\t\tpacket);\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of if (isInRoutings(to))\n\n\t\treturn false;\n\t}\n\n\tprotected boolean processCommand(Packet pc) {\n\t\tif ((pc.getStanzaTo() == null) ||!(getComponentId().equals(pc.getStanzaTo()) ||\n\t\t\t\tisLocalDomain(pc.getStanzaTo().toString()))) {\n\t\t\treturn false;\n\t\t}\n\n\t\tIq      iqc               = (Iq) pc;\n\t\tboolean processing_result = false;\n\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"{0} command from: {1}\", new Object[] { iqc.getCommand()\n\t\t\t\t\t.toString(),\n\t\t\t\t\tiqc.getFrom() });\n\t\t}\n\n\t\tXMPPResourceConnection connection = connectionsByFrom.get(iqc.getFrom());\n\n\t\tswitch (iqc.getCommand()) {\n\t\tcase CLOSE : {\n\t\t\tlog.log(Level.WARNING, \"Unexpected packet: {0}\", pc);\n\t\t\tprocessing_result = true;\n\t\t}\n\n\t\tbreak;\n\n\t\tcase STREAM_OPENED : {\n\n\t\t\t// Response is sent from the thread when opening user session is\n\t\t\t// completed.\n\t\t\t// fastAddOutPacket(pc.okResult((String) null, 0));\n\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(sessionOpenProc\n\t\t\t\t\t.id());\n\n\t\t\tif (pt == null) {\n\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t}\n\t\t\tpt.addItem(sessionOpenProc, iqc, connection);\n\t\t\tprocessing_result = true;\n\t\t}\n\n\t\tbreak;\n\n\t\tcase GETFEATURES : {\n\t\t\tif (iqc.getType() == StanzaType.get) {\n\n\t\t\t\tboolean ssl = iqc.getStanzaId().startsWith( \"ssl_\" );\n\n\t\t\t\tconnection = connectionsByFrom.get( iqc.getStanzaFrom() );\n\t\t\t\tif ( connection != null && ssl ){\n\t\t\t\t\tconnection.putSessionData( \"SSL\", ssl );\n\t\t\t\t}\n\n\t\t\t\tList<Element> features = getFeatures( connection );\n\t\t\t\tPacket result = iqc.commandResult( null );\n\n\t\t\t\tCommand.setData(result, features);\n\t\t\t\taddOutPacket(result);\n\t\t\t}    // end of if (pc.getType() == StanzaType.get)\n\t\t\tprocessing_result = true;\n\t\t}\n\n\t\tbreak;\n\t\t\t\n\t\tcase STREAM_CLOSED : {\n\t\t\tfastAddOutPacket(iqc.okResult((String) null, 0));\n\n\t\t\t//try {\n//\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(sessionCloseProc\n//\t\t\t\t\t.id());\n//\n//\t\t\tif (pt == null) {\n//\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n//\t\t\t}\n//\t\t\tpt.addItem(sessionCloseProc, iqc, connection);\n\t\t\t// Replaced code above with new code below to execute STREAM_CLOSE in same\n\t\t\t// thread as other packets from connection so next packets will know there\n\t\t\t// is no session available after STREAM_CLOSE\n\t\t\t// This should not have bigger impact on performance as SessionCloseProc was\n\t\t\t// reimplemented to speed up process of closing connections (using maps instead\n\t\t\t// of list, etc.)\n\t\t\t// Updated by Artur: It does have a big impact. In most cases a DB is accessed during the\n\t\t\t// session close processing. If this is done in the main SM thread everything is slowed down.\n\t\t\t// If we work under load of 100 logins/logouts per second this bring down the whole system.\n\t\t\t// see below!!\n\t\t\t//sessionCloseProc.process(iqc, connection, naUserRepository, packetWriterQueue, plugin_config.get(sessionCloseProc.id()));\n\t\t\t//\t\t\t} catch (XMPPException ex) {\n\t\t\t//\t\t\t\tlog.log(Level.WARNING, \"Exception while processing STREAM_CLOSE command\", ex);\n\t\t\t//\t\t\t}\n\t\t\t// closeConnection(pc.getFrom(), false);\n\t\t\t//\n\t\t\t// we need to use other aproach then, as we need to remove session ASAP,\n\t\t\t// so let's at first remove XMPPResourceConnection in this thread and later add packet to \n\t\t\t// queue to close it later on\n\t\t\tif (connection != null) {\n\t\t\t\tif (!connection.isAuthorized()) {\n\t\t\t\t\t// first remove connection from connections map\n\t\t\t\t\t// only if connection is not authorized as in other case\n\t\t\t\t\t// it will be removed on end of stream in STREAM_FINISHED\n\t\t\t\t\tconnectionsByFrom.remove(iqc.getFrom(), connection);\n\t\t\t\t}\n\n\t\t\t\t// ok, now remove connection from session\n\t\t\t\tXMPPSession session = connection.getParentSession();\n\t\t\t\tif (session != null) {\n\t\t\t\t\tsession.removeResourceConnection(connection);\n\t\t\t\t\t// now set parent session to let processors properly close XMPPResourceConnection\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconnection.setParentSession(session);\n\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"this should not happen as JID was already created once\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (connection == null || !connection.isAuthorized()) {\n\t\t\t\t// now we add packet to processing thread to let it close properly in separate thread\n\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(sessionCloseProc\n\t\t\t\t\t\t.id());\n\n\t\t\t\tif (pt == null) {\n\t\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t\t}\n\t\t\t\tpt.addItem(sessionCloseProc, iqc, connection);\n\t\t\t} else {\n\t\t\t\ttigase.util.TimerTask task = new SessionCloseTimer(iqc.getFrom(), connection.getSessionId());\n\t\t\t\taddTimerTask(task, 10, TimeUnit.SECONDS);\n\t\t\t\tconnection.putSessionData(SESSION_CLOSE_TIMER_KEY, task);\n\t\t\t}\n\t\t\tprocessing_result = true;\n\t\t}\n\n\t\tbreak;\n\n\t\tcase STREAM_CLOSED_UPDATE : {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} processing comment, connection: {1}\", new Object[] {\n\t\t\t\t\t\tiqc.getCommand(), ((connection != null)\n\t\t\t\t\t\t? connection\n\t\t\t\t\t\t: \" is null\") });\n\t\t\t}\n\n\t\t\t// Note! We don't send response to this packet....\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} adding to the processor: {1}\", new Object[] { iqc\n\t\t\t\t\t\t.getCommand(), ((connection != null)\n\t\t\t\t\t\t? connection\n\t\t\t\t\t\t: \" is null\") });\n\t\t\t}\n\t\t\tif (connection == null) {\n\n\t\t\t\t// Hm, the user connection does not exist here but\n\t\t\t\t// the XMPPSession thinks it still does, a quick fix should\n\t\t\t\t// be enough.\n\t\t\t\t// TODO: investigate why this happens at all, an exception\n\t\t\t\t// during connection close processing????\n\t\t\t\tJID stanzaFrom = iqc.getStanzaFrom();\n\n\t\t\t\tif (stanzaFrom == null) {\n\n\t\t\t\t\t// This is wrong\n\t\t\t\t\tlog.log(Level.WARNING, \"Stream close update without an user JID: {0}\", iqc);\n\t\t\t\t} else {\n\t\t\t\t\tXMPPSession xs = sessionsByNodeId.get(stanzaFrom.getBareJID());\n\n\t\t\t\t\tif (xs == null) {\n\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\"Stream close for the user session which does not exist: {0}\", iqc);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tXMPPResourceConnection xcr = xs.getResourceForConnectionId(iqc\n\t\t\t\t\t\t\t\t.getPacketFrom());\n\n\t\t\t\t\t\tif (xcr == null) {\n\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\"Stream close for the resource connection which does not exist\", iqc);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\txs.removeResourceConnection(xcr);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0} removed resource connection: {1}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { iqc.getCommand(),\n\t\t\t\t\t\t\t\t\t\txcr });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(sessionCloseProc\n\t\t\t\t\t\t.id());\n\n\t\t\t\tif (pt == null) {\n\t\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t\t}\n\t\t\t\tpt.addItem(sessionCloseProc, iqc, connection);\n\t\t\t}\n\n\t\t\t// closeConnection(pc.getFrom(), false);\n\t\t\tprocessing_result = true;\n\t\t}\n\n\t\tbreak;\n\n\t\tcase STREAM_FINISHED:\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0} processing command, connection: {1}\", new Object[] {\n\t\t\t\t\t\tiqc.getCommand(), ((connection != null)\n\t\t\t\t\t\t? connection\n\t\t\t\t\t\t: \" is null\") });\n\t\t\t}\n\t\t\tif (connection != null) {\n\t\t\t\ttigase.util.TimerTask task = (tigase.util.TimerTask) connection.getSessionData(SESSION_CLOSE_TIMER_KEY);\n\t\t\t\tif (task != null) {\n\t\t\t\t\t// cancel existing timer task as it will not be needed\n\t\t\t\t\ttask.cancel();\n\t\t\t\t}\n\t\t\t\t// first remove connection from connections map\n\t\t\t\tconnectionsByFrom.remove(iqc.getFrom(), connection);\n\t\t\t}\n\t\t\t\n\t\t\t// now we add packet to processing thread to let it close properly in separate thread\n\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(sessionCloseProc\n\t\t\t\t\t.id());\n\n\t\t\tif (pt == null) {\n\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t}\n\t\t\tpt.addItem(sessionCloseProc, iqc, connection);\n\t\t\t\n\t\t\tprocessing_result = true;\n\t\t\t\n\t\tbreak;\n\t\t\t\n\t\tcase USER_STATUS :\n\t\t\ttry {\n\t\t\tfinal boolean isTrusted = isTrusted(iqc.getStanzaFrom())\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t|| isTrusted(iqc.getStanzaFrom().getDomain());\n\t\t\t\tString pb = Command.getFieldValue( pc, \"prebind\" );\n\t\t\t\tboolean prebind = ( ( pb != null ) && pb.equalsIgnoreCase( \"true\" ) );\n\n\t\t\t\tif (prebind || isTrusted) {\n\t\t\t\t\tString  av        = Command.getFieldValue(pc, \"available\");\n\t\t\t\t\tboolean available = !((av != null) && av.equalsIgnoreCase(\"false\"));\n\n\t\t\t\t\tJID user_jid = JID.jidInstance( Command.getFieldValue( iqc, \"jid\" ) );\n\n\t\t\t\t\tif ( prebind ){\n\t\t\t\t\t\tString id = Command.getFieldValue( pc, \"session-id\" );\n\t\t\t\t\t\tif ( id == null ){\n\t\t\t\t\t\t\tid = UUID.randomUUID().toString();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tloginUserSession( iqc.getStanzaFrom(), user_jid.getDomain(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuser_jid.getBareJID(), user_jid.getResource(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tid, false );\n\t\t\t\t\t\tfastAddOutPacket( iqc.okResult( (String) null, 0 ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif (available) {\n\t\t\t\t\t\tPacket  presence = null;\n\t\t\t\t\t\tElement p        = iqc.getElement().getChild(\"command\").getChild(\"presence\");\n\n\t\t\t\t\t\tif (p != null) {\n\n\t\t\t\t\t\t\t// + // use this hack to break XMLNS\n\t\t\t\t\t\t\t// + Element el = new Element(\"presence\");\n\t\t\t\t\t\t\t// + el.setChildren(p.getChildren());\n\t\t\t\t\t\t\tElement elem = p.clone();\n\n\t\t\t\t\t\t\telem.setXMLNS(\"jabber:client\");\n\t\t\t\t\t\t\tpresence = Packet.packetInstance(elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconnection = connectionsByFrom.get(iqc.getStanzaFrom());\n\t\t\t\t\t\tif (!prebind && connection == null) {\n\t\t\t\t\t\t\tconnection = loginUserSession(iqc.getStanzaFrom(), user_jid.getDomain(),\n\t\t\t\t\t\t\t\t\tuser_jid.getBareJID(), user_jid.getResource(), \"USER_STATUS\", false);\n\t\t\t\t\t\t\tconnection.putSessionData(\"jingle\", \"active\");\n\t\t\t\t\t\t\tfastAddOutPacket(iqc.okResult((String) null, 0));\n\t\t\t\t\t\t\tif (presence == null) {\n\t\t\t\t\t\t\t\tpresence = Packet.packetInstance(new Element(\"presence\", new Element[] {\n\t\t\t\t\t\t\t\t\t\tnew Element(\"priority\", \"-1\"),\n\t\t\t\t\t\t\t\t\t\tnew Element(\"c\", new String[] { \"node\", \"ver\", \"ext\", \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"http://www.google.com/xmpp/client/caps\",\n\t\t\t\t\t\t\t\t\t\tXMPPServer.getImplementationVersion(), \"voice-v1\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/caps\" }) }, null, null));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// addOutPacket(Authorization.CONFLICT.getResponseMessage(pc,\n\t\t\t\t\t\t\t// \"The user resource already exists.\", true));\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\t\t\t\"USER_STATUS set to true for user who is already available: \" + iqc\n\t\t\t\t\t\t\t\t\t\t.toStringSecure());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (presence != null) {\n\t\t\t\t\t\t\tpresence.setPacketFrom(iqc.getStanzaFrom());\n\t\t\t\t\t\t\tpresence.setPacketTo(getComponentId());\n\t\t\t\t\t\t\taddOutPacket(presence);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconnection = connectionsByFrom.remove(iqc.getStanzaFrom());\n\t\t\t\t\t\tif (connection != null) {\n\t\t\t\t\t\t\tcloseSession(connection, false);\n\t\t\t\t\t\t\taddOutPacket(iqc.okResult((String) null, 0));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\taddOutPacket(Authorization.ITEM_NOT_FOUND.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\t\t\"The user resource you want to remove does not exist.\", true));\n\t\t\t\t\t\t\tlog.info(\"Can not find resource connection for packet: \" + iqc\n\t\t\t\t\t\t\t\t\t.toStringSecure());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddOutPacket(Authorization.FORBIDDEN.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\t\"Only trusted entity can do it.\", true));\n\t\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\t\tlog.warning(\"Packet error type when not expected: \" + iqc.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(Authorization.UNDEFINED_CONDITION.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\"Unexpected error occured during the request: \" + e, true));\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tex.printStackTrace();\n\t\t\t\t}\n\t\t\t\tlog.log(Level.WARNING, \"USER_STATUS session creation error: \", e);\n\t\t\t}\n\t\t\tprocessing_result = true;\n\n\t\t\tbreak;\n\n\t\tcase OTHER :\n\t\t\t//#2682: Commands addressed to domain should be processed by sess-man\n\t\t\tif ( iqc.isCommand() && isLocalDomain( iqc.getStanzaTo().getDomain() ) ){\n\t\t\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\t\t\tprocessing_result = processScriptCommand( iqc, results );\n\t\t\t\taddOutPackets( results );\n\t\t\t}\n\n\t\t\tif (getComponentId().equals(iqc.getStanzaTo()) && getComponentId().equals(iqc\n\t\t\t\t\t.getPacketFrom())) {\n\n\t\t\t\t// No such command available. This prevents from an infinite loop in\n\t\t\t\t// case there is no implementation to hadle such a command\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\"There is no implementation for such command on the server.\", true));\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tex.printStackTrace();\n\t\t\t\t}\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"There is no implementation for such command on the server: \" + iqc);\n\t\t\t\tprocessing_result = true;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\t\tcase TLS_HANDSHAKE_COMPLETE:\n\t\t\t\tif (connection != null) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Handshake details received. connection: {0}\", connection);\n\t\t\t\t\tString tlsUniqueId = Command.getFieldValue(pc, \"tls-unique-id\");\n\t\t\t\t\tif (tlsUniqueId != null) {\n\t\t\t\t\t\tbyte[] bytes = Base64.decode(tlsUniqueId);\n\t\t\t\t\t\tconnection.putSessionData(AbstractSaslSCRAM.TLS_UNIQUE_ID_KEY, bytes);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"tls-unique-id {0} stored in session-data. connection: {1}\", new Object[]{tlsUniqueId, connection});\n\t\t\t\t\t}\n\t\t\t\t\tString encodedCertificate = Command.getFieldValue(pc, \"peer-certificate\");\n\t\t\t\t\tif (encodedCertificate != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tbyte[] bytes = Base64.decode(encodedCertificate);\n\n\t\t\t\t\t\t\tByteArrayInputStream bais = new ByteArrayInputStream(bytes);\n\t\t\t\t\t\t\tCertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n\t\t\t\t\t\t\tCertificate certificate = cf.generateCertificate(bais);\n\n\t\t\t\t\t\t\tconnection.putSessionData(SaslEXTERNAL.PEER_CERTIFICATE_KEY, certificate);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"peer-certificate {0} stored in session-data. connection: {1}\", new Object[]{certificate, connection});\n\n\t\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"could not decode peer certificate\", ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tencodedCertificate = Command.getFieldValue(pc, \"local-certificate\");\n\t\t\t\t\tif (encodedCertificate != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tbyte[] bytes = Base64.decode(encodedCertificate);\n\n\t\t\t\t\t\t\tByteArrayInputStream bais = new ByteArrayInputStream(bytes);\n\t\t\t\t\t\t\tCertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n\t\t\t\t\t\t\tCertificate certificate = cf.generateCertificate(bais);\n\n\t\t\t\t\t\t\tconnection.putSessionData(AbstractSaslSCRAM.LOCAL_CERTIFICATE_KEY, certificate);\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"local-certificate {0} stored in session-data. connection: {1}\", new Object[]{certificate, connection});\n\t\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"could not decode local certificate\", ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Handshake details received, but no connection is related.\");\n\t\t\t\t}\n\t\t\t\tprocessing_result = true;\n\t\t\t\tbreak;\n\n\t\t\tcase STREAM_MOVED :\n\t\t\tif (connection != null) {\n\t\t\t\tString oldConnectionJidStr = Command.getFieldValue(pc, \"old-conn-jid\");\n\t\t\t\tJID    oldConnJid          = JID.jidInstanceNS(oldConnectionJidStr);\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// get old session and replace it's connection id to redirect packets\n\t\t\t\t\t// to new connection\n\t\t\t\t\tXMPPResourceConnection oldConn = connectionsByFrom.remove(oldConnJid);\n\n\t\t\t\t\toldConn.setConnectionId(connection.getConnectionId());\n\t\t\t\t\tconnectionsByFrom.remove(connection.getConnectionId());\n\t\t\t\t\tconnectionsByFrom.put(oldConn.getConnectionId(), oldConn);\n\n\t\t\t\t\t// remove current connection from list of active connections as\n\t\t\t\t\t// this connection will be used with other already authenticated connection\n\t\t\t\t\tsessionsByNodeId.get(oldConn.getBareJID()).removeResourceConnection(connection);\n\n\t\t\t\t\txmppStreamMoved(oldConn, oldConnJid, oldConn.getConnectionId());\n\t\t\t\t} catch (XMPPException ex) {\n\t\t\t\t\tlog.log(Level.SEVERE, \"exception while replacing old connection id = \" +\n\t\t\t\t\t\t\toldConnJid + \" with new connection id = \" + pc.getPacketFrom().toString(),\n\t\t\t\t\t\t\tex);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessing_result = true;\n\n\t\t\tbreak;\n\n\t\tcase BROADCAST_TO_ONLINE: {\n\t\t\tElement packetToBroadcast = null;\n\t\t\tfor (Element elem : pc.getElement().getChildren()) {\n\t\t\t\tif (elem.getXMLNS() == \"http://tigase.org/protocol/broadcast\") {\n\t\t\t\t\tpacketToBroadcast = elem;\n\t\t\t\t\tpacketToBroadcast.setAttribute(\"xmlns\", Packet.CLIENT_XMLNS);\n\t\t\t\t}\n\t\t\t}\n\t\t\tString to = Command.getFieldValue(pc, \"to\");\n\t\t\tif (to == null) {\n\t\t\tfor (XMPPSession session : sessionsByNodeId.values()) {\n\t\t\t\t\tJID[] jids = session.getJIDs();\n\n\t\t\t\t\tif (jids == null) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (JID jid : jids) {\n\t\t\t\t\t\tElement msg = packetToBroadcast.clone();\n\t\t\t\t\t\tmsg.setAttribute(\"to\", jid.toString());\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tPacket toSend = Packet.packetInstance(msg);\n\t\t\t\t\t\t// it is better to send by addOutPacket as in other case results\n\t\t\t\t\t\t\t// collection could be very large!!\n\t\t\t\t\t\t\taddOutPacket(toSend);\n\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"could not create packet for message to broadcast\", ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tBareJID userJid = BareJID.bareJIDInstanceNS(to);\n\t\t\t\tXMPPSession session = sessionsByNodeId.get(userJid);\n\t\t\t\tif (session != null) {\n\t\t\t\t\tJID[] jids = session.getJIDs();\n\n\t\t\t\t\tif (jids != null) {\n\t\t\t\t\t\tfor (JID jid : jids) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"broadcasting packet to {0}\", jid);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tElement msg = packetToBroadcast.clone();\n\t\t\t\t\t\t\tmsg.setAttribute(\"to\", jid.toString());\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tPacket toSend = Packet.packetInstance(msg);\n\t\t\t\t\t\t\t\t// it is better to send by addOutPacket as in other case results\n\t\t\t\t\t\t\t\t// collection could be very large!!\n\t\t\t\t\t\t\t\taddOutPacket(toSend);\n\t\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"could not create packet for message to broadcast\", ex);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t}\n\t\t\tprocessing_result = true;\n\t\t\tbreak;\n\t\t\t\n\t\tdefault :\n\t\t\tif (getComponentId().equals(iqc.getStanzaTo()) && getComponentId().equals(iqc\n\t\t\t\t\t.getPacketFrom())) {\n\n\t\t\t\t// No such command available. This prevents from an infinite loop in\n\t\t\t\t// case there is no implementation to hadle such a command\n\t\t\t\ttry {\n\t\t\t\t\taddOutPacket(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(iqc,\n\t\t\t\t\t\t\t\"There is no implementation for such command on the server.\", true));\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tex.printStackTrace();\n\t\t\t\t}\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"There is no implementation for such command on the server: \" + iqc);\n\t\t\t\tprocessing_result = true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}    // end of switch (pc.getCommand())\n\n\t\treturn processing_result;\n\t}\n\n\tprotected void processPacket(Packet packet, XMPPResourceConnection conn) {\n\t\tlong startTime = System.currentTimeMillis();\n\t\tint  idx       = tIdx;\n\n\t\ttIdx = (tIdx + 1) % maxIdx;\n\n\t\t// long defPrepTm = 0;\n\t\t// long prepTm = 0;\n\t\t// long defForwTm = 0;\n\t\t// long walkTm = 0;\n\t\t// long postTm = 0;\n\t\t// TODO: check if this is really necessary, seems to be even harmful in some\n\t\t// cases like when the error is generated as a response to a bad packet.\n\t\tpacket.setPacketTo(getComponentId());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"processing packet: {0}, connection: {1}\", new Object[] {\n\t\t\t\t\tpacket.toStringSecure(),\n\t\t\t\t\tconn });\n\t\t}\n\n\t\tQueue<Packet> results = new ArrayDeque<Packet>(2);\n\t\tboolean       stop    = false;\n\n\t\tif (!stop) {\n\t\t\tif (defPacketHandler.preprocess(packet, conn, naUserRepository, results)) {\n\t\t\t\tpacket.processedBy(\"filter-foward\");\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Packet preprocessed: {0}\", packet.toStringSecure());\n\t\t\t\t\tif (results.size() > 0) {\n\t\t\t\t\t\tfor (Packet p : results) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Preprocess result: {0}\", p.toStringSecure());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taddOutPackets(packet, conn, results);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// defPrepTm = System.currentTimeMillis() - startTime;\n\t\t// Preprocess..., all preprocessors get all messages to look at.\n\t\t// I am not sure if this is correct for now, let's try to do it this\n\t\t// way and maybe change it later.\n\t\t// If any of them returns true - it means processing should stop now.\n\t\t// That is needed for preprocessors like privacy lists which should\n\t\t// block certain packets.\n\t\tif (!stop) {\n\t\t\tfor (XMPPPreprocessorIfc preproc : preProcessors.values()) {\n\t\t\t\tstop |= preproc.preProcess(packet, conn, naUserRepository, results, plugin_config\n\t\t\t\t\t\t.get(preproc.id()));\n\t\t\t\tif (stop && log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Packet blocked by: {0}, packet{1}\", new Object[] {\n\t\t\t\t\t\t\tpreproc.id(),\n\t\t\t\t\t\t\tpacket });\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}    // end of for (XMPPPreprocessorIfc preproc: preProcessors)\n\t\t}\n\n\t\tsetPermissions( conn, packet );\n\n\t\t// prepTm = System.currentTimeMillis() - startTime;\n\t\tif (!stop) {\n\t\t\tif (defPacketHandler.forward(packet, conn, naUserRepository, results)) {\n\t\t\t\tpacket.processedBy(\"filter-foward\");\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Packet forwarded: {0}\", packet);\n\t\t\t\t}\n\t\t\t\taddOutPackets(packet, conn, results);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// defForwTm = System.currentTimeMillis() - startTime;\n\t\tif (!stop) {\n\t\t\twalk(packet, conn);\n\t\t\ttry {\n\t\t\t\tif ((conn != null) && conn.getConnectionId().equals(packet.getPacketFrom())) {\n\t\t\t\t\thandleLocalPacket(packet, conn);\n\t\t\t\t}\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// Ignore, this should not happen at this point, or even at all.\n\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\"Impossible happened, please report to developer packet: {0}, connection: {1}.\",\n\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\tconn });\n\t\t\t}\n\t\t}\n\n\t\t// walkTm = System.currentTimeMillis() - startTime;\n\t\tif (!stop) {\n\t\t\tfor (XMPPPostprocessorIfc postproc : postProcessors.values()) {\n\t\t\t\tString plug_id      = postproc.id();\n\t\t\t\tlong[] postProcTime = null;\n\n\t\t\t\tsynchronized (postTimes) {\n\t\t\t\t\tpostProcTime = postTimes.get(plug_id);\n\t\t\t\t\tif (postProcTime == null) {\n\t\t\t\t\t\tpostProcTime = new long[maxIdx];\n\t\t\t\t\t\tpostTimes.put(plug_id, postProcTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlong stTime = System.currentTimeMillis();\n\n\t\t\t\tpostproc.postProcess(packet, conn, naUserRepository, results, plugin_config.get(\n\t\t\t\t\t\tpostproc.id()));\n\t\t\t\tpostProcTime[idx] = System.currentTimeMillis() - stTime;\n\t\t\t}    // end of for (XMPPPostprocessorIfc postproc: postProcessors)\n\t\t}      // end of if (!stop)\n\n\t\t// postTm = System.currentTimeMillis() - startTime;\n\t\tif (!stop &&!packet.wasProcessed() && ((packet.getStanzaTo() == null) ||\n\t\t\t\t(!isLocalDomain(packet.getStanzaTo().toString())))) {\n\t\t\tif (defPacketHandler.canHandle(packet, conn)) {\n\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(defHandlerProc\n\t\t\t\t\t\t.id());\n\n\t\t\t\tif (pt == null) {\n\t\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t\t}\n\t\t\t\tpt.addItem(defHandlerProc, packet, conn);\n\t\t\t\tpacket.processedBy(defHandlerProc.id());\n\t\t\t}\n\t\t}\n\t\tsetPermissions(conn, results);\n\t\taddOutPackets(packet, conn, results);\n\t\tif (packet.wasProcessed() || processAdminsOrDomains(packet)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet processed by: {0}\", packet.getProcessorsIds()\n\t\t\t\t\t\t.toString());\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet not processed: {0}\", packet.toStringSecure());\n\t\t\t}\n\n\t\t\tPacket error = null;\n\n\t\t\tif (stop || ((conn == null) && (packet.getStanzaFrom() != null) && (packet\n\t\t\t\t\t.getStanzaTo() != null) &&!packet.getStanzaTo().equals(getComponentId()) &&\n\t\t\t\t\t((packet.getElemName() == Iq.ELEM_NAME) || (packet.getElemName() == Message\n\t\t\t\t\t.ELEM_NAME)))) {\n\t\t\t\ttry {\n\t\t\t\t\terror = Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Service not available.\", true);\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.log(Level.FINE, \"Service not available. Packet is error type already: {0}\",\n\t\t\t\t\t\t\tpacket.toStringSecure());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (((packet.getStanzaFrom() != null) || (conn != null)) && packet.wasSkipped()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\terror = Authorization.RESOURCE_CONSTRAINT.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Server subsystem overloaded, service temporarily unavailable.\", true);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"Server subsystem overloaded. Packet {0} not processed by processors {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { packet.toStringSecure(), packet.getSkippedProcessorsIds() });\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"Internal queues full. Packet is error type already: {0}\", packet.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t} else if ((packet.getStanzaFrom() != null) || (conn != null)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\terror = Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Feature not supported yet.\", true);\n\t\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Feature not supported yet. Packet is error type already: {0}\", packet\n\t\t\t\t\t\t\t\t.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (error != null) {\n\t\t\t\tif (error.getStanzaTo() != null) {\n\t\t\t\t\tconn = getResourceConnection(error.getStanzaTo());\n\t\t\t\t}      // end of if (error.getElemTo() != null)\n\t\t\t\ttry {\n\t\t\t\t\tif (conn != null) {\n\t\t\t\t\t\terror.setPacketTo(conn.getConnectionId());\n\t\t\t\t\t}    // end of if (conn != null)\n\t\t\t\t\taddOutPacket(error);\n\t\t\t\t} catch (NoConnectionIdException e) {\n\n\t\t\t\t\t// Hm, strange, SM own session?\n\t\t\t\t\tlog.log(Level.WARNING, \"Error packet to the SM''s own session: {0}\", error);\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of else\n\n\t\t// defPrepTime[idx] = defPrepTm;\n\t\t// prepTime[idx] = prepTm;\n\t\t// defForwTime[idx] = defForwTm;\n\t\t// walkTime[idx] = walkTm;\n\t\t// postTime[idx] = postTm;\n\t}\n\n\tprotected void processPresenceUpdate(XMPPSession session, Element packet) {\n\t\ttry {\n\t\t\tif (presenceProcessors.isEmpty()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPacket presence = Packet.packetInstance(packet);\n\n\t\t\tfor (XMPPResourceConnection conn : session.getActiveResources()) {\n\t\t\t\tfor (XMPPPresenceUpdateProcessorIfc proc : presenceProcessors.values()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tproc.presenceUpdate(conn, presence, packetWriterQueue);\n\t\t\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"exception processing presence update for \" +\n\t\t\t\t\t\t\t\t\"session = {0} and packet = {1}\", new Object[] { session,\n\t\t\t\t\t\t\t\tpacket });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\n\t\t\t// should not happen\n\t\t\tlog.log(Level.SEVERE, \"exception processing presence update for session = {0}\" +\n\t\t\t\t\t\" and packet = {1}\", new Object[] { session,\n\t\t\t\t\tpacket });\n\t\t}\n\t}\n\n\tprotected void registerNewSession(BareJID userId, XMPPResourceConnection conn) {\n\t\tsynchronized (conn) {\n\t\t\tif (conn.getSessionData(XMPPResourceConnection.CLOSING_KEY) != null) {\n\n\t\t\t\t// The user just closed the connection, ignore....\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tXMPPSession session = getSession(userId);\n\n\t\t\tif (session == null) {\n\t\t\t\tsession = new XMPPSession(userId.getLocalpart());\n\t\t\t\tsessionsByNodeId.put(userId, session);\n\n\t\t\t\tint currSize = sessionsByNodeId.size();\n\n\t\t\t\tif (currSize > maxUserSessions) {\n\t\t\t\t\tmaxUserSessions = currSize;\n\t\t\t\t}\n\t\t\t\tif (currSize > maxUserSessionsDaily) {\n\t\t\t\t\tmaxUserSessionsDaily = currSize;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t++totalUserSessions;\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Created new XMPPSession for: {0}\", userId);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Check all other connections whether they are still alive....\n\t\t\t\tList<XMPPResourceConnection> connections = session.getActiveResources();\n\n\t\t\t\tif (connections != null) {\n\t\t\t\t\tfor (XMPPResourceConnection connection : connections) {\n\t\t\t\t\t\tif (connection != conn) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Checking connection: {0}\", connection);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tPacket command = Command.CHECK_USER_CONNECTION.getPacket(\n\t\t\t\t\t\t\t\t\t\tgetComponentId(), connection.getConnectionId(), StanzaType.get, UUID\n\t\t\t\t\t\t\t\t\t\t.randomUUID().toString());\n\n\t\t\t\t\t\t\t\tCommand.addFieldValue(command, \"user-jid\", userId.toString());\n\t\t\t\t\t\t\t\taddOutPacketWithTimeout(command, connectionCheckCommandHandler, 30l,\n\t\t\t\t\t\t\t\t\t\tTimeUnit.SECONDS);\n\t\t\t\t\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t\t\t\t\t// This actually should not happen... might be a bug:\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsession.addResourceConnection(conn);\n\t\t\t\tif ((!\"USER_STATUS\".equals(conn.getSessionId())) &&!conn.isServerSession() &&!conn\n\t\t\t\t\t\t.isTmpSession()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPacket user_login_cmd = Command.USER_LOGIN.getPacket(getComponentId(), conn\n\t\t\t\t\t\t\t\t.getConnectionId(), StanzaType.set, conn.nextStanzaId(), Command.DataType\n\t\t\t\t\t\t\t\t.submit);\n\n\t\t\t\t\t\tCommand.addFieldValue(user_login_cmd, \"user-jid\", userId.toString());\n\t\t\t\t\t\taddOutPacket(user_login_cmd);\n\t\t\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t\t\t// This actually should not happen... might be a bug:\n\t\t\t\t\t\tlog.log(Level.WARNING, \"This should not happen, check it out!, \", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tlog.log(Level.INFO, \"Stringprep problem for resource connection: {0}\", conn);\n\t\t\t\thandleLogout(userId, conn);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void sendToAdmins(Packet packet) {\n\t\tfor (BareJID admin : admins) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"Sending packet to admin: {0}\", admin);\n\t\t\t}\n\n\t\t\tPacket admin_pac = packet.copyElementOnly();\n\n\t\t\tadmin_pac.initVars(packet.getStanzaFrom(), JID.jidInstance(admin));\n\t\t\tprocessPacket(admin_pac);\n\t\t}\n\t}\n\n\tprotected void xmppStreamMoved(XMPPResourceConnection conn, JID oldConnId, JID newConnId) {\n\t\tPacket cmd = Command.STREAM_MOVED.getPacket(getComponentId(), oldConnId,\n\t\t\t\tStanzaType.set, \"moved\");\n\n\t\tCommand.addFieldValue(cmd, \"cmd\", \"stream-moved\");\n\t\tCommand.addFieldValue(cmd, \"new-conn-jid\", newConnId.toString());\n\t\tcmd.setPacketFrom(getComponentId());\n\t\tcmd.setPacketTo(oldConnId);\n\t\taddOutPacket(cmd);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic Map<String, XMPPProcessorIfc> getProcessors() {\n\t\treturn Collections.unmodifiableMap(processors);\n\t}\n\n\tpublic Map<String, XMPPPreprocessorIfc> getPreProcessors() {\n\t\treturn Collections.unmodifiableMap(preProcessors);\n\t}\n\n\tpublic Map<String, XMPPPostprocessorIfc> getPostProcessors() {\n\t\treturn Collections.unmodifiableMap(postProcessors);\n\t}\n\n\tpublic Map<String, XMPPPacketFilterIfc> getOutFilters() {\n\t\treturn Collections.unmodifiableMap(outFilters);\n\t}\n\n\t\n\t\n\t@Override\n\tprotected Integer getMaxQueueSize(int def) {\n\t\treturn def * 10;\n\t}\n\n\tprotected XMPPSession getSession(BareJID jid) {\n\t\treturn sessionsByNodeId.get(jid);\n\t}\n\n\tprotected XMPPResourceConnection getXMPPResourceConnection(JID connId) {\n\t\treturn connectionsByFrom.get(connId);\n\t}\n\n\tprotected XMPPResourceConnection getXMPPResourceConnection(Packet p) {\n\t\tXMPPResourceConnection conn = null;\n\t\tJID                    from = p.getPacketFrom();\n\n\t\tif (from != null) {\n\t\t\tconn = connectionsByFrom.get(from);\n\t\t\tif (conn != null) {\n\t\t\t\treturn conn;\n\t\t\t}\n\t\t}\n\n\t\t// It might be a message _to_ some user on this server\n\t\t// so let's look for established session for this user...\n\t\tJID to = p.getStanzaTo();\n\n\t\tif (to != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Searching for resource connection for: \" + to);\n\t\t\t}\n\t\t\tconn = getResourceConnection(to);\n\t\t} else {\n\n\t\t\t// Hm, not sure what should I do now....\n\t\t\t// Maybe I should treat it as message to admin....\n\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\"Message without TO attribute set, don''t know what to do wih this: {0}\", p);\n\t\t}    // end of else\n\n\t\treturn conn;\n\t}\n\n\tprotected boolean isBrokenPacket(Packet p) {\n\n\t\t// TODO: check this out to make sure it does not lead to an infinite\n\t\t// processing loop These are most likely packets generated inside the SM to\n\t\t// other users who are offline, like presence updates.\n\t\tif (getComponentId().equals(p.getPacketFrom()) && (p.getPacketTo() == null)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (p.getFrom() == null) {\n\n\t\t\t// This is actually a broken packet and we can't even return an error\n\t\t\t// for it, so just log it and drop it.\n\t\t\tlog.log(Level.FINE, \"Broken packet: {0}\", p.toStringSecure());\n\n\t\t\treturn true;\n\t\t}\n\t\tif (!p.getFrom().equals(p.getStanzaFrom()) && (!p.isCommand() || (p.isCommand() && (p\n\t\t\t\t.getCommand() == Command.OTHER)))) {\n\n\t\t\t// Sometimes (Bosh) connection is gone and this is an error packet\n\t\t\t// sent back to the original sender. This original sender might be\n\t\t\t// not local....\n\t\t\tif ((p.getStanzaFrom() != null) &&!isLocalDomain(p.getStanzaFrom().getDomain())) {\n\n\t\t\t\t// ok just forward it there....\n\t\t\t\tp.setPacketFrom(null);\n\t\t\t\tp.setPacketTo(null);\n\t\t\t\tfastAddOutPacket(p);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// this is special case in which we know and expect that there will be\n\t\t\t// no session for this packet but we still need to process it\n\t\t\tif (C2SDeliveryErrorProcessor.isDeliveryError(p))\n\t\t\t\treturn false;\n\n\t\t\t// if this is packet to bare jid then we need to process it on behalf of a user\n\t\t\t// even if there is no session for this user\n\t\t\tif (p.getStanzaTo() != null && p.getStanzaTo().getResource() == null)\n\t\t\t\treturn false;\n\t\t\t\n\t\t\t// It doesn't look good, there should really be a connection for\n\t\t\t// this packet....\n\t\t\t// returning error back...\n\t\t\tlog.log(Level.FINE, \"Broken packet: {0}\", p.toStringSecure());\n\n\t\t\t// we do not want to send presence error packets here...\n\t\t\tif ((p.getElemName() == Iq.ELEM_NAME) || (p.getElemName() == Message.ELEM_NAME)) {\n\t\t\t\ttry {\n\t\t\t\t\tPacket error = Authorization.SERVICE_UNAVAILABLE.getResponseMessage(p,\n\t\t\t\t\t\t\t\"Service not available.\", true);\n\n\t\t\t\t\terror.setPacketTo(p.getFrom());\n\t\t\t\t\tfastAddOutPacket(error);\n\t\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\t\tlog.log(Level.FINE, \"Packet is error type already: {0}\", p.toStringSecure());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate long calcAverage(long[] timings) {\n\t\tlong res = 0;\n\n\t\tfor (long ppt : timings) {\n\t\t\tres += ppt;\n\t\t}\n\n\t\tlong processingTime = res / timings.length;\n\n\t\treturn processingTime;\n\t}\n\n\tprivate void walk(final Packet packet, final XMPPResourceConnection connection) {\n\n\t\t// final Element elem, final Queue<Packet> results) {\n\t\tfor (XMPPProcessorIfc proc_t : processors.values()) {\n\t\t\tXMPPProcessorIfc processor = proc_t;\n\t\t\tAuthorization    result    = processor.canHandle(packet, connection);\n\n\t\t\tif (result == Authorization.AUTHORIZED) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"XMPPProcessorIfc: {0} ({1}\" + \")\" + \"Request: \" +\n\t\t\t\t\t\t\t\"{2}, conn: {3}\", new Object[] { processor.getClass().getSimpleName(),\n\t\t\t\t\t\t\tprocessor.id(), packet, connection });\n\t\t\t\t}\n\n\t\t\t\tProcessingThreads<ProcessorWorkerThread> pt = workerThreads.get(processor.id());\n\n\t\t\t\tif (pt == null) {\n\t\t\t\t\tpt = workerThreads.get(defPluginsThreadsPool);\n\t\t\t\t}\n\t\t\t\tif (pt.addItem(processor, packet, connection)) {\n\t\t\t\t\tpacket.processedBy(processor.id());\n\t\t\t\t} else {\n\t\t\t\t\tpacket.notProcessedBy(processor.id());\n\t\t\t\t\t// proc_t.debugQueue();\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Can not add packet: {0} to processor: {1} internal queue full.\",\n\t\t\t\t\t\t\t\tnew Object[] { packet.toStringSecure(),\n\t\t\t\t\t\t\t\tpt.getName() });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (result != null) {\n\n\t\t\t\t\t// TODO: A plugin returned an error, the packet should be bounced back\n\t\t\t\t\t// with an appropriate error\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of for ()\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic synchronized void everyMinute() {\n\t\tsuper.everyMinute();\n\t\tint count = 0;\n\n\t\tfor (BareJID bareJID : sessionsByNodeId.keySet()) {\n\t\t\tif (!bareJID.toString().startsWith(\"sess-man\")) {\n\t\t\t\tXMPPSession session = sessionsByNodeId.get(bareJID);\n\t\t\t\t// check if session is still there as it could be closed \n\t\t\t\t// if sessionsByNodeId is big collection\n\t\t\t\tif (session != null) {\n\t\t\t\t\tfor (XMPPResourceConnection xMPPResourceConnection : session\n\t\t\t\t\t\t\t.getActiveResources()) {\n\t\t\t\t\t\tif (System.currentTimeMillis() - xMPPResourceConnection.getLastAccessed() < 5\n\t\t\t\t\t\t\t\t* 60 * 1000) {\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tactiveUserNumber = count;\n\n\t\tfinal Calendar now = Calendar.getInstance();\n\t\tif (now.get(Calendar.YEAR) != lastDailyStatsReset.get(Calendar.YEAR)\n\t\t\t\t|| now.get(Calendar.DAY_OF_YEAR) != lastDailyStatsReset.get(Calendar.DAY_OF_YEAR)) {\n\t\t\tlastDailyStatsReset = Calendar.getInstance();\n\t\t\t\n\t\t\tmaxUserSessionsYesterday = maxUserSessionsDaily;\n\t\t\tmaxUserSessionsDaily = sessionsByNodeId.size();\n\t\t}\n\t}\n\n\t/*\n\t * Date of moment where daily stats was resetted.\n\t */\n\tprivate Calendar lastDailyStatsReset = Calendar.getInstance();\n\t\n\tprivate List<Element> getFeatures(XMPPResourceConnection session) {\n\t\tList<Element> results = new LinkedList<Element>();\n\n\t\tfor (XMPPProcessorIfc proc_t : processors.values()) {\n\t\t\tElement[] features = proc_t.supStreamFeatures(session);\n\n\t\t\tif (features != null) {\n\t\t\t\tresults.addAll(Arrays.asList(features));\n\t\t\t}    // end of if (features != null)\n\t\t}      // end of for ()\n\n\t\treturn results;\n\t}\n\n\tprivate Map<String, Object> getPluginSettings(String plug_id, Map<String,\n\t\t\tObject> props) {\n\t\tMap<String, Object> plugin_settings = new ConcurrentHashMap<String, Object>(10);\n\n\t\t// First set all options common for all plugins and then set all options\n\t\t// specific to the\n\t\t// plugin to make sure specific options can overwrite common options\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(PLUGINS_CONF_PROP_KEY)) {\n\n\t\t\t\t// Split the key to configuration nodes separated with '/'\n\t\t\t\tString[] nodes = entry.getKey().split(\"/\");\n\n\t\t\t\t// Settings option for all plugins\n\t\t\t\tif (nodes.length == 2) {\n\t\t\t\t\tplugin_settings.put(nodes[1], entry.getValue());\n\t\t\t\t\tlog.log(Level.CONFIG, \"Adding a common plugins option: {0} = {1}\",\n\t\t\t\t\t\t\tnew Object[] { nodes[1],\n\t\t\t\t\t\t\tentry.getValue() });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now set plugin specific options\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(PLUGINS_CONF_PROP_KEY)) {\n\n\t\t\t\t// Workaround for plugin id containing \"/\" in id\n\t\t\t\tString key = entry.getKey();\n\t\t\t\tif (plug_id.contains(\"/\")) {\n\t\t\t\t\tif (!key.contains(plug_id))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tkey = key.replace(plug_id, \"plugin-id\");\n\t\t\t\t}\n\t\t\t\t// Split the key to configuration nodes separated with '/'\n\t\t\t\tString[] nodes = key.split(\"/\");\n\n\t\t\t\t// The plugin ID part may contain many IDs separated with comma ','\n\t\t\t\tif (nodes.length > 2) {\n\t\t\t\t\tString[] ids = nodes[1].split(\",\");\n\n\t\t\t\t\tArrays.sort(ids);\n\t\t\t\t\tif (Arrays.binarySearch(ids, plug_id) >= 0 || Arrays.binarySearch(ids, \"plugin-id\") >= 0) {\n\t\t\t\t\t\tplugin_settings.put(nodes[2], entry.getValue());\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Adding a specific plugins option [{0}]: {1} = {2}\",\n\t\t\t\t\t\t\t\tnew Object[] { plug_id,\n\t\t\t\t\t\t\t\tnodes[2], entry.getValue() });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tplugin_settings.put(\"sm-jid\", getComponentId());\n\n\t\treturn plugin_settings;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprivate void setPermissions( XMPPResourceConnection conn, Packet packet ) {\n\t\tPermissions perms = getPermissionForConnection( conn );\n\t\tpacket.setPermissions( perms );\n\t}\n\n\tprivate void setPermissions(XMPPResourceConnection conn, Queue<Packet> results) {\n\t\tPermissions perms = getPermissionForConnection( conn );\n\t\tfor (Packet res : results) {\n\t\t\tres.setPermissions(perms);\n\t\t}\n\t}\n\n\tprivate Permissions getPermissionForConnection( XMPPResourceConnection conn ) {\n\t\tPermissions perms = Permissions.NONE;\n\t\tif (conn != null) {\n\t\t\tperms = Permissions.LOCAL;\n\t\t\tif (conn.isAuthorized()) {\n\t\t\t\tperms = Permissions.AUTH;\n\t\t\t\tif (conn.isAnonymous()) {\n\t\t\t\t\tperms = Permissions.ANONYM;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tJID id = conn.getJID();\n\n\t\t\t\t\t\tif (isTrusted(id)) {\n\t\t\t\t\t\t\tperms = Permissions.TRUSTED;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isAdmin(id)) {\n\t\t\t\t\t\t\tperms = Permissions.ADMIN;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\t\t\tperms = Permissions.NONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn perms;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class AuthenticationTimer\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\tprivate JID connId = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate AuthenticationTimer(JID connId) {\n\t\t\tthis.connId = connId;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tXMPPResourceConnection conn = connectionsByFrom.get(connId);\n\n\t\t\tif (conn != null) {\n\t\t\t\tsynchronized (conn) {\n\t\t\t\t\tif (!conn.isAuthorized()) {\n\t\t\t\t\t\tconn.putSessionData(XMPPResourceConnection.AUTHENTICATION_TIMEOUT_KEY,\n\t\t\t\t\t\t\t\tXMPPResourceConnection.AUTHENTICATION_TIMEOUT_KEY);\n\t\t\t\t\t\tconnectionsByFrom.remove(connId);\n\t\t\t\t\t\t++authTimeouts;\n\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\"Authentication timeout expired, closing connection: {0}\", connId);\n\t\t\t\t\t\tfastAddOutPacket(Command.CLOSE.getPacket(getComponentId(), connId, StanzaType\n\t\t\t\t\t\t\t\t.set, conn.nextStanzaId()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tprivate class ConnectionCheckCommandHandler\n\t\t\t\t\timplements ReceiverTimeoutHandler {\n\t\t@Override\n\t\tpublic void responseReceived(Packet packet, Packet response) {\n\t\t\tif (response.getType() == StanzaType.error) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER,\n\t\t\t\t\t\t\t\"Connection checker error received, closing connection: {0}\", packet\n\t\t\t\t\t\t\t.getTo());\n\t\t\t\t}\n\n\t\t\t\t// The connection is not longer active, closing the user session here.\n\t\t\t\tString userJid = Command.getFieldValue(packet, \"user-jid\");\n\n\t\t\t\tcloseConnection(null, packet.getTo(), userJid, false);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void timeOutExpired(Packet packet) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER,\n\t\t\t\t\t\t\"Connection checker timeout expired, closing connection: {0}\", packet\n\t\t\t\t\t\t.getTo());\n\t\t\t}\n\n\t\t\tString userJid = Command.getFieldValue(packet, \"user-jid\");\n\n\t\t\tcloseConnection(null, packet.getTo(), userJid, false);\n\t\t}\n\t}\n\n\n\tprivate class DefaultHandlerProc\n\t\t\t\t\textends XMPPProcessor\n\t\t\t\t\timplements XMPPProcessorIfc {\n\t\t@Override\n\t\tpublic int concurrentQueuesNo() {\n\t\t\treturn Runtime.getRuntime().availableProcessors() * 4;\n\t\t}\n\n\t\t@Override\n\t\tpublic String id() {\n\t\t\treturn defaultHandlerProcId;\n\t\t}\n\n\t\t@Override\n\t\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\tthrows XMPPException {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Executing default packet handler for: {0}\", packet);\n\t\t\t}\n\t\t\tdefPacketHandler.process(packet, session, repo, results);\n\t\t}\n\t}\n\n\n\tprivate class ProcessorWorkerThread\n\t\t\t\t\textends WorkerThread {\n\t\tprivate ArrayDeque<Packet> local_results = new ArrayDeque<Packet>(100);\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void process(QueueItem item) {\n\t\t\tXMPPProcessorIfc processor = item.getProcessor();\n\n\t\t\ttry {\n\t\t\t\tprocessor.process(item.getPacket(), item.getConn(), naUserRepository,\n\t\t\t\t\t\tlocal_results, plugin_config.get(processor.id()));\n\t\t\t\tif (item.getConn() != null) {\n\t\t\t\t\tsetPermissions(item.getConn(), local_results);\n\t\t\t\t}\n\t\t\t\taddOutPackets(item.getPacket(), item.getConn(), local_results);\n\t\t\t} catch (PacketErrorTypeException e) {\n\t\t\t\tlog.log(Level.INFO, \"Already error packet, ignoring: {0}\", item.getPacket()\n\t\t\t\t\t\t.toStringSecure());\n\t\t\t} catch (XMPPException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Exception during packet processing: \" + item.getPacket()\n\t\t\t\t\t\t.toStringSecure(), e);\n\t\t\t}\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic WorkerThread getNewInstance() {\n\t\t\tProcessorWorkerThread worker = new ProcessorWorkerThread();\n\n\t\t\treturn worker;\n\t\t}\n\t}\n\n\n\tprivate class SessionCloseProc\n\t\t\t\t\textends XMPPProcessor\n\t\t\t\t\timplements XMPPProcessorIfc {\n\t\t@Override\n\t\tpublic int concurrentQueuesNo() {\n\t\t\treturn super.concurrentQueuesNo() * 4;\n\t\t}\n\n\t\t@Override\n\t\tpublic String id() {\n\t\t\treturn sessionCloseProcId;\n\t\t}\n\n\t\t@Override\n\t\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\tthrows XMPPException {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Executing connection close for: {0}\", packet);\n\t\t\t}\n\n\t\t\tString userJid = Command.getFieldValue(packet, \"user-jid\");\n\n\t\t\tcloseConnection(session, packet.getFrom(), userJid, false);\n\t\t}\n\t}\n\n\n\tprivate class SessionOpenProc\n\t\t\t\t\textends XMPPProcessor\n\t\t\t\t\timplements XMPPProcessorIfc {\n\t\t@Override\n\t\tpublic int concurrentQueuesNo() {\n\t\t\treturn super.concurrentQueuesNo() * 2;\n\t\t}\n\n\t\t@Override\n\t\tpublic String id() {\n\t\t\treturn sessionOpenProcId;\n\t\t}\n\n\t\t@Override\n\t\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\tthrows XMPPException {\n\t\t\tXMPPResourceConnection conn = session;\n\n\t\t\t// It might be existing opened stream after TLS/SASL authorization\n\t\t\t// If not, it means this is new stream\n\t\t\tif (conn == null) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Adding resource connection for: {0}\", packet.getFrom());\n\t\t\t\t}\n\n\t\t\t\tfinal String hostname = Command.getFieldValue(packet, \"hostname\");\n\n\t\t\t\ttry {\n\t\t\t\t\tconn = createUserSession(packet.getFrom(), hostname);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Incrrect hostname, did not pass stringprep processing: {0}\", hostname);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\taddTimerTask(new AuthenticationTimer(packet.getFrom()), authTimeout, TimeUnit.SECONDS);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Stream opened for existing session, authorized: {0}\",\n\t\t\t\t\t\t\tconn.isAuthorized());\n\t\t\t\t}\n\t\t\t}    // end of else\n\t\t\tconn.setSessionId(Command.getFieldValue(packet, \"session-id\"));\n\t\t\tconn.setDefLang(Command.getFieldValue(packet, \"xml:lang\"));\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Setting session-id {0} for connection: {1}\",\n\t\t\t\t\t\tnew Object[] { conn.getSessionId(),\n\t\t\t\t\t\tconn });\n\t\t\t}\n\t\t\tfastAddOutPacket(packet.okResult((String) null, 0));\n\t\t}\n\t}\n\n\t/**\n\t * Class implements timer which will be scheduled on STREAM_CLOSED to ensure\n\t * that session is properly closed, even if STREAM_FINISHED would not be received\n\t */\n\tprivate class SessionCloseTimer extends tigase.util.TimerTask {\n\t\tprivate JID connId = null;\n\t\tprivate String sessId = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate SessionCloseTimer(JID connId, String sessId) {\n\t\t\tthis.connId = connId;\n\t\t\tthis.sessId = sessId;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tXMPPResourceConnection conn = connectionsByFrom.get(connId);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"session closed timer executed for connId = {0}, \"\n\t\t\t\t\t\t+ \"sessionId = {1}, conn = {2}\", new Object[] { connId, sessId, conn });\n\t\t\t}\n\t\t\t// if connection still exists then close it\n\t\t\tif (conn != null && (sessId == null || sessId.equals(conn.getSessionId()))) {\n\t\t\t\tconnectionsByFrom.remove(connId, conn);\n\t\t\t\n\t\t\t\tcloseConnection(conn, connId, null, false);\n\t\t\t}\n\t\t}\t\t\n\t}\n\n\tprivate class StaleConnectionCloser\n\t\t\t\t\textends tigase.util.TimerTask {\n\t\t/** Field description */\n\t\tpublic static final int DEF_QUEUE_SIZE = 1000;\n\n\t\t/** Field description */\n\t\tpublic static final long DEF_TIMEOUT = 30 * 1000;\n\n\t\t//~--- fields -------------------------------------------------------------\n\n\t\tprivate int      maxQueueSize;\n\t\tprivate Set<JID> queueSet;\n\t\tprivate Thread   thread;\n\t\tprivate long     timeout;\n\t\tprivate Set<JID> workingSet;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tpublic StaleConnectionCloser() {\n\t\t\tthis(DEF_QUEUE_SIZE, DEF_TIMEOUT);\n\t\t}\n\n\t\tpublic StaleConnectionCloser(int queueSize, long timeout) {\n\t\t\tthis.timeout      = timeout;\n\t\t\tthis.maxQueueSize = queueSize;\n\t\t\tworkingSet        = new HashSet<JID>(queueSize);\n\t\t\tqueueSet          = new HashSet<JID>(queueSize);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\tpublic void closeConnections() {\n\n\t\t\t// nothing waiting to remove\n\t\t\tif (workingSet.isEmpty()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlog.log(Level.INFO, \"Trying to find and remove stale XMPPResourceConnections\");\n\n\t\t\tLinkedList<XMPPResourceConnection> staleConnections =\n\t\t\t\t\tnew LinkedList<XMPPResourceConnection>();\n\n\t\t\tfor (XMPPSession session : sessionsByNodeId.values()) {\n\t\t\t\tList<XMPPResourceConnection> connections = session.getActiveResources();\n\n\t\t\t\tfor (XMPPResourceConnection connection : connections) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tJID connectionId = connection.getConnectionId();\n\n\t\t\t\t\t\tif (workingSet.contains(connectionId)) {\n\n\t\t\t\t\t\t\t// queue connection for removal\n\t\t\t\t\t\t\tstaleConnections.offer(connection);\n\n\t\t\t\t\t\t\t// remove from working set\n\t\t\t\t\t\t\tworkingSet.remove(connectionId);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"found connection without proper connection id = {0}\",\n\t\t\t\t\t\t\t\tconnection.toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// remove queued connections\n\t\t\t\tXMPPResourceConnection connection;\n\n\t\t\t\twhile ((connection = staleConnections.poll()) != null) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Found stale XMPPResourceConnection: {0}, removing...\",\n\t\t\t\t\t\t\tconnection);\n\t\t\t\t\tsession.removeResourceConnection(connection);\n\t\t\t\t}\n\n\t\t\t\t// working set is empty so break iteration now\n\t\t\t\tif (workingSet.isEmpty()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean queueForClose(JID connectionId) {\n\t\t\tboolean result;\n\n\t\t\tsynchronized (this) {\n\t\t\t\tif (queueSet.size() > maxQueueSize) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tresult = queueSet.add(connectionId);\n\t\t\t}\n\t\t\tif (!result && log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"connection with id {0} already queued for removing as stale\" +\n\t\t\t\t\t\t\" XMPPResourceConnection\", connectionId);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tif ((thread != null) && thread.isAlive()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthread = new Thread() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tprocess();\n\t\t\t\t\tthread = null;\n\t\t\t\t}\n\t\t\t};\n\t\t\tthread.start();\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\tpublic int getMaxQueueSize() {\n\t\t\treturn maxQueueSize;\n\t\t}\n\n\t\tpublic long getTimeout() {\n\t\t\treturn timeout;\n\t\t}\n\n\t\t//~--- set methods --------------------------------------------------------\n\n\t\tpublic void setMaxQueueSize(int queueSize) {\n\t\t\tthis.maxQueueSize = queueSize;\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\tprivate void process() {\n\t\t\ttry {\n\t\t\t\twhile (swapSets()) {\n\t\t\t\t\tcloseConnections();\n\t\t\t\t}\n\t\t\t} catch (Throwable th) {\n\t\t\t\tlog.log(Level.SEVERE, \"exception closing stale connections\", th);\n\t\t\t}\n\t\t\taddTimerTask(this, timeout);\n\t\t}\n\n\t\tprivate boolean swapSets() {\n\t\t\tsynchronized (this) {\n\t\t\t\tSet<JID> tmp = workingSet;\n\n\t\t\t\tworkingSet = queueSet;\n\t\t\t\tqueueSet   = tmp;\n\t\t\t\tqueueSet.clear();\n\n\t\t\t\treturn !workingSet.isEmpty();\n\t\t\t}\n\t\t}\n\t}\n\n\n\tprotected class WriterQueue<E extends Packet>\n\t\t\t\t\textends AbstractQueue<E> {\n\t\t@Override\n\t\tpublic Iterator<E> iterator() {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean offer(E packet) {\n\t\t\treturn SessionManager.this.addOutPacket(packet);\n\t\t}\n\n\t\t@Override\n\t\tpublic E peek() {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t\t}\n\n\t\t@Override\n\t\tpublic E poll() {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t\t}\n\n\t\t@Override\n\t\tpublic int size() {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t\t}\n\t}\n\n\n\t@Override\n\tpublic void handleDomainChange(final String domain, final XMPPResourceConnection conn) {\n\t\ttry {\n\t\t\tVHostItem vHostItem = getVHostItem(domain);\n\t\t\tif (vHostItem == null) {\n\t\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\t\tlog.log(Level.INFO, \"Can't get VHostItem for domain: {0}, using default one instead: {1}\", new Object[] {\n\t\t\t\t\t\t\tdomain, getDefHostName() });\n\t\t\t\t}\n\t\t\t\tvHostItem = new VHostItem(getDefHostName().getDomain());\n\t\t\t}\n\t\t\tconn.setDomain(vHostItem.getUnmodifiableVHostItem());\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.log(Level.INFO, \"Stringprep problem for resource connection: {0}\", conn);\n\t\t\t// handleLogout(userId, conn);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppsession/SessionManagerConfig.java",
    "content": "/*\n * SessionManagerConfig.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.server.xmppsession;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\n\nimport tigase.xmpp.*;\n\nimport tigase.osgi.ModulesManagerImpl;\n\nimport java.util.*;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.conf.Configurable.GEN_SM_PLUGINS;\nimport static tigase.conf.Configurable.GEN_TEST;\n\n/**\n * Describe class SessionManagerConfig here.\n *\n *\n * Created: Tue Oct 24 23:07:57 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class SessionManagerConfig {\n\t/** Field description */\n\tpublic static final String defaultHandlerProcId = \"default-handler\";\n\n\t/** Field description */\n\tpublic static final String PLUGINS_CONCURRENCY_PROP_KEY = \"plugins-concurrency\";\n\n\t/** Field description */\n\tpublic static final String PLUGINS_CONF_PROP_KEY = \"plugins-conf\";\n\n\t/** Field description */\n\tpublic static final String PLUGINS_PROP_KEY = \"plugins\";\n\n\t/** Field description */\n\tpublic static final String sessionCloseProcId = \"session-close\";\n\n\t/** Field description */\n\tpublic static final String sessionOpenProcId = \"session-open\";\n\n\t/** Field description */\n\tprotected static final String ADMIN_SCRIPTS_PROP_KEY = \"admin-scripts-dir\";\n\n\t/** Field description */\n\tprotected static final String ADMIN_SCRIPTS_PROP_VAL = \"scripts/admin/\";\n\n\t/** Field description */\n\tprotected static final String AUTO_CREATE_OFFLINE_USER_PROP_KEY =\n\t\t\t\"offline-user-autocreate\";\n\n\t/** Field description */\n\tprotected static final String AUTO_CREATE_OFFLINE_USER_PROP_VAL = \"false\";\n\n\t/** Field description */\n\tprotected static final String FORCE_DETAIL_STALE_CONNECTION_CHECK =\n\t\t\t\"force-detail-stale-connection-check\";\n\n\t/** Field description */\n\tprotected static final String SKIP_PRIVACY_PROP_KEY = \"skip-privacy\";\n\n\t/** Field description */\n\tprotected static final String SM_THREADS_POOL_CUSTOM_PROP_VAL = \"custom\";\n\n\t/** Field description */\n\tprotected static final String SM_THREADS_POOL_PROP_KEY = \"sm-threads-pool\";\n\n\t/** Field description */\n\tprotected static final String SM_THREADS_POOL_PROP_VAL = \"default\";\n\t\n\tprotected static final String SM_THREADS_FACTOR_PROP_KEY = \"sm-threads-factor\";\n\tprotected static final int SM_THREADS_FACTOR_PROP_VAL = 1;\n\n\tprotected static final String AUTH_TIMEOUT_PROP_KEY = \"auth-timeout\";\n\tprotected static final long AUTH_TIMEOUT_PROP_VAL = 120;\n\n\t/** Field description */\n\tprotected static final String STALE_CONNECTION_CLOSER_QUEUE_SIZE_KEY =\n\t\t\t\"stale-connection-closer-queue-size\";\n\n\t// public static final String ANONYMOUS_PEERS_PROP_KEY = \"anonymous-peers\";\n\n\t/**\n\t * List of default plugins loaded by the server. It can be changed later\n\t * in config file or at runtime.\n\t */\n\tprivate static final String[] PLUGINS_NO_REG_PROP_VAL = {\n\t\tsessionCloseProcId, sessionOpenProcId, defaultHandlerProcId, \"jabber:iq:auth\",\n\t\t\"urn:ietf:params:xml:ns:xmpp-sasl\", \"urn:ietf:params:xml:ns:xmpp-bind\",\n\t\t\"urn:ietf:params:xml:ns:xmpp-session\", \"jabber:iq:roster\", \"jabber:iq:privacy\",\n\t\t\"jabber:iq:version\", \"http://jabber.org/protocol/stats\", \"starttls\", \"vcard-temp\",\n\t\t\"http://jabber.org/protocol/commands\", \"jabber:iq:private\", \"urn:xmpp:ping\",\n\t\t\"presence-state\", \"presence-subscription\",\n\n\t\t// \"basic-filter\",\n\t\t\"disco\", \"domain-filter\", \"zlib\", \"amp\", \"message-carbons\", \"vcard-xep-0292\", \"urn:xmpp:time\",\n\t\t\"urn:xmpp:csi:0\"\n\t};\n\n\t/**\n\t * List of plugins loaded when the server is loaded in test mode.\n\t * Some plugins like off-line message storage is disabled during tests.\n\t */\n\tprivate static final String[] PLUGINS_TEST_PROP_VAL = {\n\t\tsessionCloseProcId, sessionOpenProcId, defaultHandlerProcId, \"jabber:iq:register\",\n\t\t\"jabber:iq:auth\", \"urn:ietf:params:xml:ns:xmpp-sasl\",\n\t\t\"urn:ietf:params:xml:ns:xmpp-bind\", \"urn:ietf:params:xml:ns:xmpp-session\",\n\t\t\"jabber:iq:roster\", \"jabber:iq:privacy\", \"jabber:iq:version\",\n\t\t\"http://jabber.org/protocol/stats\", \"starttls\", \"vcard-temp\",\n\t\t\"http://jabber.org/protocol/commands\", \"jabber:iq:private\", \"urn:xmpp:ping\",\n\t\t\"presence-state\", \"presence-subscription\",\n\n\t\t// \"basic-filter\",\n\t\t\"disco\", \"domain-filter\", \"zlib\", \"amp\", \"message-carbons\", \"vcard-xep-0292\", \"urn:xmpp:time\",\n\t\t\"urn:xmpp:csi:0\"\n\t};\n\tprivate static final String[] PLUGINS_FULL_PROP_VAL = {\n\t\tsessionCloseProcId, sessionOpenProcId, defaultHandlerProcId, \"jabber:iq:register\",\n\t\t\"jabber:iq:auth\", \"urn:ietf:params:xml:ns:xmpp-sasl\",\n\t\t\"urn:ietf:params:xml:ns:xmpp-bind\", \"urn:ietf:params:xml:ns:xmpp-session\",\n\t\t\"jabber:iq:roster\", \"jabber:iq:privacy\", \"jabber:iq:version\",\n\t\t\"http://jabber.org/protocol/stats\", \"starttls\", \"vcard-temp\",\n\t\t\"http://jabber.org/protocol/commands\", \"jabber:iq:private\", \"urn:xmpp:ping\",\n\t\t\"presence-state\", \"presence-subscription\",\n\n\t\t// \"basic-filter\",\n\t\t\"disco\", \"domain-filter\", \"zlib\", \"amp\", \"message-carbons\", \"vcard-xep-0292\", \"urn:xmpp:time\",\n\t\t\"urn:xmpp:csi:0\"\n\t};\n\tprivate static String[]      TRUSTED_PROP_VAL = { \"admin@localhost\", \"admin@hostname\" };\n\tprivate static final boolean SKIP_PRIVACY_PROP_VAL = false;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns list of active plugins with implementation available\n\t *\n\t * @param props\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t */\n\tpublic static String[] getActivePlugins(Map<String, Object> props) {\n\t\tString[]     allPlugins = (String[]) props.get(PLUGINS_PROP_KEY);\n\t\tList<String> plugins    = new ArrayList<String>();\n\n\t\tfor (String plugin_id : allPlugins) {\n\n\t\t\t// this plugins are not in ModulesManager and not in ProcessorFactory\n\t\t\tif (sessionCloseProcId.equals(plugin_id) || sessionOpenProcId.equals(plugin_id) ||\n\t\t\t\t\tdefaultHandlerProcId.equals(plugin_id)) {\n\t\t\t\tplugins.add(plugin_id);\n\t\t\t} else if (ModulesManagerImpl.getInstance().hasPluginForId(plugin_id) ||\n\t\t\t\t\tProcessorFactory.hasImplementation(plugin_id)) {\n\t\t\t\tplugins.add(plugin_id);\n\t\t\t}\n\t\t}\n\n\t\treturn plugins.toArray(new String[plugins.size()]);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param props\n\t * @param params\n\t */\n\tpublic static void getDefaults(Map<String, Object> props, Map<String, Object> params) {\n\t\tprops.put(ADMIN_SCRIPTS_PROP_KEY, ADMIN_SCRIPTS_PROP_VAL);\n\n\t\tboolean full_comps = (params.get(RepositoryFactory.GEN_AUTH_DB) == null)\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"mysql\")\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"pgsql\")\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"derby\")\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"sqlserver\")\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"tigase.mongodb.MongoRepository\")\n\t\t\t\t\t\t\t\t\t\t\t\t || params.get(RepositoryFactory.GEN_AUTH_DB).toString().equals(\"tigase-auth\");\n\t\tLinkedHashSet<String> plugins = new LinkedHashSet<String>(32);\n\n\t\tif ((Boolean) params.get(GEN_TEST)) {\n\t\t\tCollections.addAll(plugins, PLUGINS_TEST_PROP_VAL);\n\t\t} else {\n\t\t\tif (full_comps) {\n\n\t\t\t\t// Some plugins are not loaded during tests at least until proper\n\t\t\t\t// test cases are created for them. Sample case is off-line message\n\t\t\t\t// storage which may impact some test cases.\n\t\t\t\tCollections.addAll(plugins, PLUGINS_FULL_PROP_VAL);\n\t\t\t} else {\n\t\t\t\tCollections.addAll(plugins, PLUGINS_NO_REG_PROP_VAL);\n\t\t\t}\n\t\t}\n\n\t\tString str_plugins        = (String) params.get(GEN_SM_PLUGINS);\n\t\tString plugin_concurrency = \"\";\n\n\t\tif (str_plugins != null) {\n\t\t\tstr_plugins = str_plugins.replaceAll(\"\\\\s+\",\"\");\n\t\t\tString[] conf_plugins = str_plugins.split(\",\");\n\n\t\t\tfor (String plugin : conf_plugins) {\n\t\t\t\tswitch (plugin.charAt(0)) {\n\t\t\t\tcase '+' :\n\t\t\t\t\tif (addPlugin(plugins, plugin.substring(1))) {\n\t\t\t\t\t\tplugin_concurrency += plugin.substring(1) + \",\";\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase '-' :\n\t\t\t\t\tplugins.remove(plugin.substring(1));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tif (addPlugin(plugins, plugin)) {\n\t\t\t\t\t\tplugin_concurrency += plugin + \",\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprops.put(PLUGINS_PROP_KEY, plugins.toArray(new String[plugins.size()]));\n\t\tprops.put(PLUGINS_CONCURRENCY_PROP_KEY, plugin_concurrency);\n\n\t\tString skip_privacy = (String) params.get(\"--\" + SKIP_PRIVACY_PROP_KEY);\n\n\t\tprops.put(SKIP_PRIVACY_PROP_KEY, (skip_privacy != null) && skip_privacy.equals(\n\t\t\t\t\"true\"));\n\t\tprops.put(AUTO_CREATE_OFFLINE_USER_PROP_KEY, AUTO_CREATE_OFFLINE_USER_PROP_VAL);\n\n\t\tString sm_threads_pool = SM_THREADS_POOL_PROP_VAL;\n\n\t\tif (params.get(\"--\" + SM_THREADS_POOL_PROP_KEY) != null) {\n\t\t\tsm_threads_pool = (String) params.get(\"--\" + SM_THREADS_POOL_PROP_KEY);\n\t\t}\n\t\tprops.put(SM_THREADS_POOL_PROP_KEY, sm_threads_pool);\n\t}\n\n\t/**\n\t * Get packetfilter instance\n\t *\n\t * @param plug_id\n\t *\n\t *\n\t * @return a value of <code>XMPPPacketFilterIfc</code>\n\t */\n\tpublic static XMPPPacketFilterIfc getPacketFilter(String plug_id) {\n\t\tXMPPImplIfc proc = getXMPPImplIfc(plug_id);\n\n\t\tif (proc == null) {\n\t\t\treturn ProcessorFactory.getPacketFilter(plug_id);\n\t\t}\n\t\tif (proc instanceof XMPPPacketFilterIfc) {\n\t\t\treturn (XMPPPacketFilterIfc) proc;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get postprocessor instance\n\t *\n\t * @param plug_id\n\t *\n\t *\n\t * @return a value of <code>XMPPPostprocessorIfc</code>\n\t */\n\tpublic static XMPPPostprocessorIfc getPostprocessor(String plug_id) {\n\t\tXMPPImplIfc proc = getXMPPImplIfc(plug_id);\n\n\t\tif (proc == null) {\n\t\t\treturn ProcessorFactory.getPostprocessor(plug_id);\n\t\t}\n\t\tif (proc instanceof XMPPPostprocessorIfc) {\n\t\t\treturn (XMPPPostprocessorIfc) proc;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get preprocessor instance\n\t *\n\t * @param plug_id\n\t *\n\t *\n\t * @return a value of <code>XMPPPreprocessorIfc</code>\n\t */\n\tpublic static XMPPPreprocessorIfc getPreprocessor(String plug_id) {\n\t\tXMPPImplIfc proc = getXMPPImplIfc(plug_id);\n\n\t\tif (proc == null) {\n\t\t\treturn ProcessorFactory.getPreprocessor(plug_id);\n\t\t}\n\t\tif (proc instanceof XMPPPreprocessorIfc) {\n\t\t\treturn (XMPPPreprocessorIfc) proc;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get processor instance\n\t *\n\t * @param plug_id\n\t *\n\t *\n\t * @return a value of <code>XMPPProcessorIfc</code>\n\t */\n\tpublic static XMPPProcessorIfc getProcessor(String plug_id) {\n\t\tXMPPImplIfc proc = getXMPPImplIfc(plug_id);\n\n\t\tif (proc == null) {\n\t\t\treturn ProcessorFactory.getProcessor(plug_id);\n\t\t}\n\t\tif (proc instanceof XMPPProcessorIfc) {\n\t\t\treturn (XMPPProcessorIfc) proc;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get stoplistener instance\n\t *\n\t * @param plug_id\n\t *\n\t *\n\t * @return a value of <code>XMPPStopListenerIfc</code>\n\t */\n\tpublic static XMPPStopListenerIfc getStopListener(String plug_id) {\n\t\tXMPPImplIfc proc = getXMPPImplIfc(plug_id);\n\n\t\tif (proc == null) {\n\t\t\treturn ProcessorFactory.getStopListener(plug_id);\n\t\t}\n\t\tif (proc instanceof XMPPStopListenerIfc) {\n\t\t\treturn (XMPPStopListenerIfc) proc;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate static boolean addPlugin(LinkedHashSet<String> plugins, String plugin) {\n\t\tString[] pla = plugin.split(\"=\");\n\n\t\tplugins.add(pla[0]);\n\n\t\treturn pla.length > 1;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate static XMPPImplIfc getXMPPImplIfc(String plug_id) {\n\t\tXMPPImplIfc proc = null;\n\n\t\ttry {\n\t\t\tproc = ModulesManagerImpl.getInstance().getPlugin(plug_id);\n\t\t} catch (InstantiationException ex) {\n\t\t\tLogger.getLogger(SessionManagerConfig.class.getName()).log(Level.SEVERE, null, ex);\n\t\t} catch (IllegalAccessException ex) {\n\t\t\tLogger.getLogger(SessionManagerConfig.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\n\t\treturn proc;\n\t}\n}    // SessionManagerConfig\n\n\n//~ Formatted in Tigase Code Convention on 13/10/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/server/xmppsession/SessionManagerHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.server.xmppsession;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Describe interface SessionManagerHandler here.\n *\n *\n * Created: Sat Feb 18 13:27:58 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface SessionManagerHandler {\n\n\t/** Field description */\n\tpublic static final String COMMIT_HANDLER_KEY = \"LoginHandlerKey\";\n\n\tJID getComponentId();\n\n\tvoid handleLogin(BareJID userId, XMPPResourceConnection conn);\n\t\n\tvoid handleDomainChange(String domain,XMPPResourceConnection conn);\n\n\tvoid handleLogout(BareJID userId, XMPPResourceConnection conn);\n\n\tvoid handlePresenceSet(XMPPResourceConnection conn);\n\n\tvoid handleResourceBind(XMPPResourceConnection conn);\n\n\tboolean isLocalDomain(String domain, boolean includeComponents);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/Counter.java",
    "content": "/*\n * Counter.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\nimport java.util.logging.Level;\n\n/**\n *\n * @author andrzej\n */\npublic class Counter extends CounterValue {\n\t\t\n\tprivate long last_hour_counter = 0;\n\tprivate long last_minute_counter = 0;\n\tprivate long last_second_counter = 0;\n\t\n\tprivate long per_hour = 0;\n\tprivate long per_minute = 0;\n\tprivate long per_second = 0;\n\n\tpublic Counter(String name, Level level) {\n\t\tsuper(name, level);\n\t}\n\t\n\tpublic synchronized void everyHour() {\n\t\tper_hour = counter - last_hour_counter;\n\t\tlast_hour_counter = counter;\n\t}\n\t\n\tpublic synchronized void everyMinute() {\n\t\tper_minute = counter - last_minute_counter;\n\t\tlast_minute_counter = counter;\n\t}\n\t\n\tpublic synchronized void everySecond() {\n\t\tper_second = counter - last_second_counter;\n\t\tlast_second_counter = counter;\n\t}\t\t\n\t\n\tpublic long getPerHour() {\n\t\treturn per_hour;\n\t}\n\t\n\tpublic long getPerMinute() {\n\t\treturn per_minute;\n\t}\n\t\n\tpublic long getPerSecond() {\n\t\treturn per_second;\n\t}\n\t\n\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\tif (list.checkLevel(level)) {\n\t\t\tlist.add(compName, name + \" last hour\", per_hour, level);\n\t\t\tlist.add(compName, name + \" last minute\", per_minute, level);\n\t\t\tlist.add(compName, name + \" last second\", per_second, level);\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/CounterDataArchivizer.java",
    "content": "/*\n * CounterDataArchivizer.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.DataRepository;\nimport tigase.db.DBInitException;\nimport tigase.db.RepositoryFactory;\n\nimport tigase.server.XMPPServer;\n\nimport tigase.sys.TigaseRuntime;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport java.text.NumberFormat;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Created: Mar 25, 2010 8:55:11 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class CounterDataArchivizer\n\t\t\t\timplements StatisticsArchivizerIfc {\n\tpublic static final String DB_URL_PROP_KEY = \"db-url\";\n\tpublic static final String KEY_FIELD_PROP_KEY = \"key-field\";\n\tpublic static final String TABLE_NAME_PROP_KEY = \"table-name\";\n\tpublic static final String  VAL_FIELD_PROP_KEY   = \"val-field\";\n\tprivate static final String CPU_USAGE_TEXT       = \"Usage CPU [%]: \";\n\tprivate static final String DEF_KEY_FIELD_NAME   = \"counter_name\";\n\tprivate static final String DEF_TABLE_NAME       = \"counter_data\";\n\tprivate static final String DEF_VALUE_FIELD_NAME = \"counter_value\";\n\tprivate static final String MEM_USAGE_TEXT       = \"Usage RAM [%]: \";\n\tprivate static final Logger log = Logger.getLogger(CounterDataArchivizer.class\n\t\t\t.getName());\n\tprivate static final String SERVER_CONNECTIONS_TEXT = \"Connections s2s: \";\n\tprivate static final String UPTIME_TEXT             = \"Uptime: \";\n\tprivate static final String USER_CONNECTIONS_TEXT   = \"Connections c2s: \";\n\tprivate static final String USER_REGISTERED_TEXT    = \"Registered user: \";\n\tprivate static final String VERSION_TEXT            = \"Version: \";\n\tprivate static final String VHOSTS_TEXT             = \"VHosts: \";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String         create_table_query = null;\n\tprivate DataRepository data_repo          = null;\n\tprivate String         init_entry_query   = null;\n\n\t// private PreparedStatement initEntry = null;\n\tprivate String tableName          = DEF_TABLE_NAME;\n\tprivate String keyField           = DEF_KEY_FIELD_NAME;\n\tprivate String update_entry_query = null;\n\n\t// private PreparedStatement updateEntry = null;\n\tprivate String valueField = DEF_VALUE_FIELD_NAME;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void execute(StatisticsProvider sp) {\n\t\tNumberFormat format = NumberFormat.getNumberInstance();\n\n\t\tformat.setMaximumFractionDigits(2);\n\t\tinitData(CPU_USAGE_TEXT, format.format(sp.getCPUUsage()));\n\t\tinitData(MEM_USAGE_TEXT, format.format(sp.getHeapMemUsage()));\n\t\tformat = NumberFormat.getIntegerInstance();\n\t\tinitData(USER_REGISTERED_TEXT, format.format(sp.getRegistered()));\n\t\tinitData(USER_CONNECTIONS_TEXT, format.format(sp.getConnectionsNumber()));\n\t\tinitData(SERVER_CONNECTIONS_TEXT, format.format(sp.getServerConnections()));\n\t\tinitData(UPTIME_TEXT, TigaseRuntime.getTigaseRuntime().getUptimeString());\n\t\tinitData(VHOSTS_TEXT, format.format(sp.getStats(\"vhost-man\", \"Number of VHosts\", 0)));\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> conf) {\n\t\tString prop = (String) conf.get(TABLE_NAME_PROP_KEY);\n\n\t\tif (prop != null) {\n\t\t\ttableName = prop;\n\t\t}\n\t\tprop = (String) conf.get(KEY_FIELD_PROP_KEY);\n\t\tif (prop != null) {\n\t\t\tkeyField = prop;\n\t\t}\n\t\tprop = (String) conf.get(VAL_FIELD_PROP_KEY);\n\t\tif (prop != null) {\n\t\t\tvalueField = prop;\n\t\t}\n\t\tlog.log(Level.SEVERE, \"Initialize stats archive, table: {0} \", tableName);\n\t\tinit_entry_query = \"insert into \" + tableName + \" (\" + keyField + \", \" + valueField +\n\t\t\t\t\") \" + \" (select ?, ? from \" + tableName + \" where \" + keyField +\n\t\t\t\t\" = ? HAVING count(*)=0)\";\n\t\tupdate_entry_query = \"update \" + tableName + \" set \" + valueField + \" = ? where \" +\n\t\t\t\tkeyField + \" = ?\";\n\t\tcreate_table_query = \"CREATE TABLE \" + tableName + \" ( \" + keyField +\n\t\t\t\t\" varchar(255) NOT NULL DEFAULT '0', \" + valueField +\n\t\t\t\t\" varchar(255) NOT NULL DEFAULT '0',\" + \"  PRIMARY KEY ( \" + keyField + \" ));\";\n\t\ttry {\n\t\t\tinitRepository((String) conf.get(DB_URL_PROP_KEY), null);\n\t\t\tinitData(VERSION_TEXT, XMPPServer.getImplementationVersion());\n\t\t\tinitData(CPU_USAGE_TEXT, \"0\");\n\t\t\tinitData(MEM_USAGE_TEXT, \"0\");\n\t\t\tinitData(USER_CONNECTIONS_TEXT, \"0\");\n\t\t\tinitData(SERVER_CONNECTIONS_TEXT, \"0\");\n\t\t\tinitData(VHOSTS_TEXT, \"0\");\n\t\t\tinitData(UPTIME_TEXT, TigaseRuntime.getTigaseRuntime().getUptimeString());\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"Cannot initialize connection to database: \", ex);\n\t\t}\n\t}\n\n\tpublic void initData(String key, String value) {\n\t\ttry {\n\t\t\tPreparedStatement updateEntry = data_repo.getPreparedStatement(null,\n\t\t\t\t\tupdate_entry_query);\n\t\t\tPreparedStatement initEntry = data_repo.getPreparedStatement(null,\n\t\t\t\t\tinit_entry_query);\n\n\t\t\tsynchronized (updateEntry) {\n\t\t\t\tupdateEntry.setString(1, value);\n\t\t\t\tupdateEntry.setString(2, key);\n\t\t\t\tupdateEntry.executeUpdate();\n\t\t\t}\n\t\t\tsynchronized (initEntry) {\n\t\t\t\tinitEntry.setString(1, key);\n\t\t\t\tinitEntry.setString(2, value);\n\t\t\t\tinitEntry.setString(3, key);\n\t\t\t\tinitEntry.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem adding new entry to DB: \", e);\n\t\t}\n\t}\n\n\tpublic void initRepository(String conn_str, Map<String, String> params)\n\t\t\t\t\tthrows SQLException, ClassNotFoundException, InstantiationException,\n\t\t\t\t\t\t\tIllegalAccessException, DBInitException {\n\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, params);\n\t\tcheckDB();\n\t\tdata_repo.initPreparedStatement(init_entry_query, init_entry_query);\n\t\tdata_repo.initPreparedStatement(update_entry_query, update_entry_query);\n\t}\n\n\t@Override\n\tpublic void release() {\n\n\t\t// Do nothing for now....\n\t}\n\n\tpublic void updateData(String key, String value) {\n\t\ttry {\n\t\t\tPreparedStatement updateEntry = data_repo.getPreparedStatement(null,\n\t\t\t\t\tupdate_entry_query);\n\n\t\t\tsynchronized (updateEntry) {\n\t\t\t\tupdateEntry.setString(1, value);\n\t\t\t\tupdateEntry.setString(2, key);\n\t\t\t\tupdateEntry.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem adding new entry to DB: \", e);\n\t\t}\n\t}\n\n\tprivate void checkDB() throws SQLException {\n\t\tdata_repo.checkTable(tableName, create_table_query);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/02\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/CounterDataFileLogger.java",
    "content": "/*\n * CounterDataLogger.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class responsible for dumping server statistics to a file\n *\n * @author wojtek\n */\npublic class CounterDataFileLogger\n\t\timplements StatisticsArchivizerIfc {\n\n\t/* logger instance */\n\tprivate static final Logger log = Logger.getLogger( CounterDataFileLogger.class.getName() );\n\n\t/* Field denoting directory configuration */\n\tprivate static final String DIRECTORY_KEY = \"stats-directory\";\n\t/* Field denoting file prefix configuration */\n\tprivate static final String FILENAME_KEY = \"stats-filename\";\n\t/* Field denoting whether include or not unixtime into filename configuration */\n\tprivate static final String UNIXTIME_KEY = \"stats-unixtime\";\n\t/* Field denoting whether include or not datetime timestamp into filename configuration */\n\tprivate static final String DATETIME_KEY = \"stats-datetime\";\n\t/* Field denoting datetime format configuration */\n\tprivate static final String DATETIME_FORMAT_KEY = \"stats-datetime-format\";\n\t/* Field denoting level of the statistics configuration */\n\tprivate static final String STATISTICS_LEVE_KEY = \"stats-level\";\n\n\t/* Field holding directory path configuration */\n\tprivate static String directory = \"logs/stats\";\n\t/* Field holding file prefix configuration */\n\tprivate static String filename = \"stats\";\n\t/* Field holding configuration whether include or not unixtime into filename */\n\tprivate static boolean includeUnixTime = true;\n\t/* Field holding configuration whether include or not datetime timestamp into filename */\n\tprivate static boolean includeDateTime = true;\n\n\t/* Field holding datetime format configuration */\n\tprivate static String dateTimeFormat = \"yyyy-MM-dd_HH:mm:ss\";\n\n\t/* Field holding level of the statistics configuration */\n\tprivate static Level statsLevel = Level.ALL;\n\n\t/* Variable for SimpleDateFormat */\n\tprivate static SimpleDateFormat sdf;\n\n\t@Override\n\tpublic void execute( StatisticsProvider sp ) {\n\n\t\tDate currTime = new Date();\n\t\tString path = directory + \"/\"\n\t\t\t\t\t\t\t\t\t+ filename\n\t\t\t\t\t\t\t\t\t+ ( includeUnixTime ? \"_\" + currTime.getTime() : \"\" )\n\t\t\t\t\t\t\t\t\t+ ( includeDateTime ? \"_\" + sdf.format( currTime ) : \"\" )\n\t\t\t\t\t\t\t\t\t+ \".txt\";\n\n\t\tlog.log( Level.FINEST, \"Dumping server statistics to: {0}\", path );\n\t\tPath p = Paths.get( path);\n\t\t\n\t\tMap<String, String> stats = sp.getAllStats( statsLevel.intValue() );\n\n\t\ttry (BufferedWriter writer = Files.newBufferedWriter(p, StandardCharsets.UTF_8)) {\n\t\t\tfor ( Map.Entry<String,String> entry : stats.entrySet() ) {\n\t\t\t\twriter.write( entry.getKey() );\n\t\t\t\twriter.write( \"\\t\" );\n\t\t\t\twriter.write( entry.getValue() );\n\t\t\t\twriter.newLine();\n\t\t\t}\n\t\t\twriter.write( \"Statistics time: \" + sdf.format( currTime ) );\n\t\t\twriter.newLine();\n\t\t\twriter.write( \"Statistics time (linux): \" + currTime.getTime() );\n\t\t\twriter.newLine();\n\t\t} catch ( IOException ex ) {\n\t\t\tlog.log( Level.SEVERE, \"Error dumping server statistics to file\", ex );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void init( Map<String, Object> archivizerConf ) {\n\t\tif ( null != archivizerConf.get( DIRECTORY_KEY ) ){\n\t\t\tdirectory = String.valueOf( archivizerConf.get( DIRECTORY_KEY ) );\n\t\t}\n\t\tnew File( directory ).mkdirs();\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger directory to: {0}\", directory );\n\n\t\tif ( null != archivizerConf.get( FILENAME_KEY ) ){\n\t\t\tfilename = (String) archivizerConf.get( FILENAME_KEY );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger filename to: {0}\", filename );\n\n\t\tif ( null != archivizerConf.get( UNIXTIME_KEY ) ){\n\t\t\tincludeUnixTime = Boolean.valueOf( (String) archivizerConf.get( UNIXTIME_KEY ) );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger includeUnixTime to: {0}\", includeUnixTime );\n\n\t\tif ( null != archivizerConf.get( DATETIME_KEY ) ){\n\t\t\tincludeDateTime = Boolean.valueOf( (String) archivizerConf.get( DATETIME_KEY ) );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger includeDateTime to: {0}\", includeDateTime );\n\n\t\tif ( null != archivizerConf.get( DATETIME_FORMAT_KEY ) ){\n\t\t\tdateTimeFormat = (String) archivizerConf.get( DATETIME_FORMAT_KEY );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger dateTimeFormat to: {0}\", dateTimeFormat );\n\t\tsdf = new SimpleDateFormat( dateTimeFormat );\n\n\t\tif ( null != archivizerConf.get( STATISTICS_LEVE_KEY ) ){\n\t\t\tstatsLevel = Level.parse( (String) archivizerConf.get( STATISTICS_LEVE_KEY ) );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting CounterDataFileLogger statsLevel to: {0}\", statsLevel );\n\n\t}\n\n\t@Override\n\tpublic void release() {\n\t\t// pass\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/CounterDataLogger.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\npackage tigase.stats;\n\nimport tigase.db.DBInitException;\nimport tigase.db.DataRepository;\nimport tigase.db.RepositoryFactory;\n\nimport tigase.util.DNSResolverFactory;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.db.RepositoryFactory.GEN_USER_DB_URI_PROP_KEY;\n\n/**\n * Created: Apr 20, 2010 6:39:05 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class CounterDataLogger\n\t\t\t\timplements StatisticsArchivizerIfc {\n\t/**\n\t * SQL INT UNSIGNED\n\t */\n\tpublic static final String BOSH_CONNS_COL = \"bosh_conns\";\n\n\t/**\n\t * SQL INT UNSIGNED\n\t */\n\tpublic static final String C2S_CONNS_COL = \"c2s_conns\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String C2S_PACKETS_COL = \"c2s_packets\";\n\n\t/**\n\t * SQL float UNSIGNED\n\t */\n\tpublic static final String CPU_USAGE_COL = \"cpu_usage\";\n\n\t/** Field description */\n\tpublic static final String DB_URL_PROP_KEY = \"db-url\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String EXT_PACKETS_COL = \"ext_packets\";\n\n\t/**\n\t * SQL VARCHAR(2049)\n\t */\n\tpublic static final String HOSTNAME_COL = \"hostname\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String IQS_COL = \"iqs\";\n\n\t/**\n\t * SQL float UNSIGNED\n\t */\n\tpublic static final String MEM_USAGE_COL = \"mem_usage\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String MESSAGES_COL = \"messages\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String MUC_PACKETS_COL = \"muc_packets\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String PRESENCES_COL = \"presences\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String PUBSUB_PACKETS_COL = \"pubsub_packets\";\n\n\t/**\n\t * SQL INT UNSIGNED\n\t */\n\tpublic static final String S2S_CONNS_COL = \"s2s_conns\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String S2S_PACKETS_COL = \"s2s_packets\";\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String SM_PACKETS_COL = \"sm_packets\";\n\n\t/** Field description */\n\tpublic static final String STATS_TABLE = \"tig_stats_log\";\n\n\t/**\n\t * SQL BIGINT\n\t */\n\tpublic static final String UPTIME_COL = \"uptime\";\n\n\t/**\n\t * SQL INT UNSIGNED\n\t */\n\tpublic static final String  VHOSTS_COL = \"vhosts\";\n\tprivate static final Logger log = Logger.getLogger(CounterDataLogger.class.getName());\n\n\tprotected static String defaultHostname;\n\n\t/**\n\t * SQL BIGINT UNSIGNED\n\t */\n\tpublic static final String REGISTERED_COL = \"registered\";\n\tprivate static final String CREATE_STATS_TABLE = \"create table \" + STATS_TABLE + \" ( \"\n\t\t+ \" lid serial,\"\n\t\t+ \" ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\"\n\t\t+ \" \" + HOSTNAME_COL + \" varchar(2049) NOT NULL,\"\n\t\t+ \" \" + CPU_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + MEM_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + UPTIME_COL + \" bigint not null default 0,\"\n\t\t+ \" \" + VHOSTS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + SM_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MUC_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PUBSUB_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + S2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + EXT_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PRESENCES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MESSAGES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + IQS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + REGISTERED_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + S2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + BOSH_CONNS_COL + \" int  not null default 0,\"\n+ \" primary key(ts,\"+HOSTNAME_COL+\"(255)))\";\n\n\tprivate static final String DERBY_CREATE_STATS_TABLE = \"create table \" + STATS_TABLE + \" ( \"\n\t\t+ \" lid bigint generated by default as identity not null,\"\n\t\t+ \" ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\"\n\t\t+ \" \" + HOSTNAME_COL + \" varchar(2049) NOT NULL,\"\n\t\t+ \" \" + CPU_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + MEM_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + UPTIME_COL + \" bigint not null default 0,\"\n\t\t+ \" \" + VHOSTS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + SM_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MUC_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PUBSUB_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + S2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + EXT_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PRESENCES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MESSAGES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + IQS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + REGISTERED_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + S2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + BOSH_CONNS_COL + \" int  not null default 0,\"\n+ \" primary key(ts,\"+HOSTNAME_COL+\"))\";\n\n\tprivate static final String SQLSERVER_CREATE_STATS_TABLE = \"create table \" + STATS_TABLE + \" ( \"\n\t\t+ \" lid [bigint] IDENTITY(1,1),\"\n\t\t+ \" ts [datetime] DEFAULT  getdate(),\"\n\t\t+ \" \" + HOSTNAME_COL + \" [nvarchar](2049) NOT NULL,\"\n\t\t+ \" \" + CPU_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + MEM_USAGE_COL + \" double precision not null default 0,\"\n\t\t+ \" \" + UPTIME_COL + \" bigint not null default 0,\"\n\t\t+ \" \" + VHOSTS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + SM_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MUC_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PUBSUB_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + S2S_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + EXT_PACKETS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + PRESENCES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + MESSAGES_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + IQS_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + REGISTERED_COL + \" bigint  not null default 0,\"\n\t\t+ \" \" + C2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + S2S_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" \" + BOSH_CONNS_COL + \" int  not null default 0,\"\n\t\t+ \" primary key(ts,\"+HOSTNAME_COL+\"))\";\n\n\n\tprivate static final String STATS_INSERT_QUERY = \"insert into \" + STATS_TABLE + \"(\"\n\t\t+ CPU_USAGE_COL + \", \" + MEM_USAGE_COL + \", \" + UPTIME_COL + \", \" + VHOSTS_COL + \", \"\n\t\t+ SM_PACKETS_COL + \", \" + MUC_PACKETS_COL + \", \" + PUBSUB_PACKETS_COL + \", \" + C2S_PACKETS_COL\n\t\t+ \", \" + S2S_PACKETS_COL + \", \" + EXT_PACKETS_COL + \", \" + PRESENCES_COL + \", \" + MESSAGES_COL\n\t\t+ \", \" + IQS_COL + \", \" + REGISTERED_COL + \", \" + C2S_CONNS_COL + \", \" + S2S_CONNS_COL + \", \"\n\t\t+ BOSH_CONNS_COL + \", \" + HOSTNAME_COL  + \") values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate DataRepository data_repo           = null;\n\tprivate long           last_c2s_packets    = 0;\n\tprivate long           last_ext_packets    = 0;\n\tprivate long           last_iqs            = 0;\n\tprivate long           last_messages       = 0;\n\tprivate long           last_muc_packets    = 0;\n\tprivate long           last_presences      = 0;\n\tprivate long           last_pubsub_packets = 0;\n\tprivate long           last_s2s_packets    = 0;\n\tprivate long           last_sm_packets     = 0;\n\n\tpublic void addStatsLogEntry(float cpu_usage, float mem_usage, long uptime, int vhosts,\n\t\t\tlong sm_packets, long muc_packets, long pubsub_packets, long c2s_packets,\n\t\t\tlong s2s_packets, long ext_packets, long presences, long messages, long iqs,\n\t\t\tlong registered, int c2s_conns, int s2s_conns, int bosh_conns) {\n\t\ttry {\n\t\t\tPreparedStatement insert_stats = data_repo.getPreparedStatement(null,\n\t\t\t\t\tSTATS_INSERT_QUERY);\n\n\t\t\tsynchronized (insert_stats) {\n\t\t\t\tinsert_stats.setFloat(1, ((cpu_usage >= 0f)\n\t\t\t\t\t\t? cpu_usage\n\t\t\t\t\t\t: 0f));\n\t\t\t\tinsert_stats.setFloat(2, mem_usage);\n\t\t\t\tinsert_stats.setLong(3, uptime);\n\t\t\t\tinsert_stats.setInt(4, vhosts);\n\t\t\t\tinsert_stats.setLong(5, sm_packets);\n\t\t\t\tinsert_stats.setLong(6, muc_packets);\n\t\t\t\tinsert_stats.setLong(7, pubsub_packets);\n\t\t\t\tinsert_stats.setLong(8, c2s_packets);\n\t\t\t\tinsert_stats.setLong(9, s2s_packets);\n\t\t\t\tinsert_stats.setLong(10, ext_packets);\n\t\t\t\tinsert_stats.setLong(11, presences);\n\t\t\t\tinsert_stats.setLong(12, messages);\n\t\t\t\tinsert_stats.setLong(13, iqs);\n\t\t\t\tinsert_stats.setLong(14, registered);\n\t\t\t\tinsert_stats.setInt(15, c2s_conns);\n\t\t\t\tinsert_stats.setInt(16, s2s_conns);\n\t\t\t\tinsert_stats.setInt(17, bosh_conns);\n\t\t\t\tinsert_stats.setString(18, defaultHostname);\n\t\t\t\tinsert_stats.executeUpdate();\n\t\t\t}\n\t\t} catch (SQLException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem adding new entry to DB: \", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void execute(StatisticsProvider sp) {\n\t\tlong c2s_packets    = sp.getCompPackets(\"c2s\");\n\t\tlong ext_packets    = sp.getCompPackets(\"ext\");\n\t\tlong iqs            = sp.getCompIqs(\"sess-man\");\n\t\tlong messages       = sp.getCompMessages(\"sess-man\");\n\t\tlong muc_packets    = sp.getCompPackets(\"muc\");\n\t\tlong presences      = sp.getCompPresences(\"sess-man\");\n\t\tlong pubsub_packets = sp.getCompPackets(\"pubsub\");\n\t\tlong s2s_packets    = sp.getCompPackets(\"s2s\");\n\t\tlong sm_packets     = sp.getSMPacketsNumber();\n\n\t\taddStatsLogEntry(sp.getCPUUsage(), sp.getHeapMemUsage(), sp.getUptime(), sp.getStats(\n\t\t\t\t\"vhost-man\", \"Number of VHosts\", 0), sm_packets - last_sm_packets, muc_packets -\n\t\t\t\tlast_muc_packets, pubsub_packets - last_pubsub_packets, c2s_packets -\n\t\t\t\tlast_c2s_packets, s2s_packets - last_s2s_packets, ext_packets - last_ext_packets,\n\t\t\t\tpresences - last_presences, messages - last_messages, iqs - last_iqs, sp\n\t\t\t\t.getRegistered(), sp.getCompConnections(\"c2s\"), sp.getCompConnections(\"s2s\"), sp\n\t\t\t\t.getCompConnections(\"bosh\"));\n\t\tlast_c2s_packets    = c2s_packets;\n\t\tlast_ext_packets    = ext_packets;\n\t\tlast_iqs            = iqs;\n\t\tlast_messages       = messages;\n\t\tlast_muc_packets    = muc_packets;\n\t\tlast_presences      = presences;\n\t\tlast_pubsub_packets = pubsub_packets;\n\t\tlast_s2s_packets    = s2s_packets;\n\t\tlast_sm_packets     = sm_packets;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> archivizerConf) {\n\t\tdefaultHostname = DNSResolverFactory.getInstance().getDefaultHost();\n\t\ttry {\n\t\t\tString resource = (String) archivizerConf.get(DB_URL_PROP_KEY);\n\t\t\tif (resource == null ) {\n\t\t\t\tresource = System.getProperty(GEN_USER_DB_URI_PROP_KEY);\n\t\t\t}\n\t\t\tinitRepository(resource, null);\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"Cannot initialize connection to database: \", ex);\n\t\t}\n\t}\n\n\t/**\n\t * Method initialize repository\n\t *\n\t * @param conn_str database connection URI\n\t * @param map map of the additional parameters\n\t *\n\t * @throws SQLException\n\t * @throws ClassNotFoundException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t * @throws DBInitException\n\t */\n\tpublic void initRepository(String conn_str, Map<String, String> map)\n\t\t\t\t\tthrows SQLException, ClassNotFoundException, IllegalAccessException,\n\t\t\t\t\t\t\tInstantiationException, DBInitException {\n\t\tlog.log(Level.INFO, \"Initializing dbAccess for db connection url: {0}\", conn_str);\n\t\tdata_repo = RepositoryFactory.getDataRepository(null, conn_str, map);\n\n\t\t// Check if DB is correctly setup and contains all required tables.\n\t\tcheckDB();\n\t\tdata_repo.initPreparedStatement(STATS_INSERT_QUERY, STATS_INSERT_QUERY);\n\t}\n\n\t@Override\n\tpublic void release() {}\n\n\tprivate void checkDB() throws SQLException {\n\t\tDataRepository.dbTypes databaseType = data_repo.getDatabaseType();\n\n\t\tswitch (databaseType) {\n\t\tcase derby :\n\t\t\tdata_repo.checkTable(STATS_TABLE, DERBY_CREATE_STATS_TABLE);\n\n\t\t\tbreak;\n\n\t\tcase jtds :\n\t\tcase sqlserver :\n\t\t\tdata_repo.checkTable(STATS_TABLE, SQLSERVER_CREATE_STATS_TABLE);\n\n\t\t\tbreak;\n\n\t\tcase postgresql :\n\t\tcase mysql :\n\t\tdefault :\n\t\t\tdata_repo.checkTable(STATS_TABLE, CREATE_STATS_TABLE);\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/CounterPerSecond.java",
    "content": "/*\n * CounterPerSecond.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\nimport java.util.logging.Level;\nimport tigase.util.EverySecond;\n\n/**\n *\n * @author andrzej\n */\npublic class CounterPerSecond extends CounterValue implements EverySecond {\n\t\t\n\tprivate long last_second_counter = 0;\n\t\n\tprivate long per_second = 0;\n\n\tpublic CounterPerSecond(String name, Level level) {\n\t\tsuper(name, level);\n\t}\n\t\t\n\t@Override\n\tpublic synchronized void everySecond() {\n\t\tper_second = counter - last_second_counter;\n\t\tlast_second_counter = counter;\n\t}\t\t\n\t\t\n\tpublic long getPerSecond() {\n\t\treturn per_second;\n\t}\n\t\n\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\tif (list.checkLevel(level)) {\n\t\t\tlist.add(compName, name + \" last second\", per_second, level);\n\t\t}\n\t}\n\t\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/CounterValue.java",
    "content": "/*\n * CounterValue.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */package tigase.stats;\n\nimport java.util.logging.Level;\n \n/**\n *\n * @author andrzej\n */\npublic class CounterValue {\n\n\tprotected String name;\n\tprotected final Level level;\n\t\n\tprotected long counter = 0;\n\n\tpublic CounterValue(String name, Level level) {\n\t\tthis.name = name;\n\t\tthis.level = level;\n\t}\n\t\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\t\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\t\n\tpublic void inc() {\n\t\t++counter;\n\t}\n\t\n\tpublic Level getLevel() {\n\t\treturn level;\n\t}\n\t\n\tpublic long getValue() {\n\t\treturn counter;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/ErrorsStatisticsProvider.java",
    "content": "/*\n * ErrorsStatisticsProvider.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\nimport java.lang.reflect.Constructor;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.management.Attribute;\nimport javax.management.AttributeList;\nimport javax.management.AttributeNotFoundException;\nimport javax.management.DynamicMBean;\nimport javax.management.InvalidAttributeValueException;\nimport javax.management.MBeanAttributeInfo;\nimport javax.management.MBeanConstructorInfo;\nimport javax.management.MBeanException;\nimport javax.management.MBeanInfo;\nimport javax.management.MBeanNotificationInfo;\nimport javax.management.MBeanOperationInfo;\nimport javax.management.MBeanParameterInfo;\nimport javax.management.ReflectionException;\nimport javax.management.RuntimeOperationsException;\nimport tigase.server.xmppclient.StreamErrorCounterIOProcessor;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.StreamError;\nimport tigase.xmpp.impl.ErrorCounter;\n\n/**\n *\n * @author andrzej\n */\npublic class ErrorsStatisticsProvider\n\t\timplements DynamicMBean {\n\n\tprivate static final String ERRORS_NUMBER = \"ErrorsNumber\";\n\tprivate static final String PER_SECOND = \"PerSecond\";\n\tprivate static final String TOTAL = \"Total\";\n\t\n\tprivate static final String TYPE_FLOAT = \"java.lang.Float\";\n\tprivate static final String TYPE_LONG = \"java.lang.Long\";\n\t\n\t// internal variables describing the MBean\n\tprivate final String dClassName = this.getClass().getName();\n\tprivate final String dDescription = \"Error statistics MBean\";\n\tprivate MBeanAttributeInfo[] dAttributes;\n\tprivate final MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[0];\n\tprivate final MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];\n\tprivate MBeanInfo dMBeanInfo = null;\n\n\tprivate String[] statsKeys;\n\tprivate final Map<String,Holder> stats = new ConcurrentHashMap<>();\n\t\n\tprivate final Map<String,String> statsKeyToKey = new HashMap<>();\n\tprivate final Map<String,String> attrToKey = new HashMap<>();\n\n\tpublic ErrorsStatisticsProvider() {\n\t\tbuildDynamicMBeanInfo();\n\t}\n\n\tpublic void update(StatisticsProvider sp) {\n\t\t// retrieval of statistics data for keys listed in statsKeys\n\t\tMap<String,Object> data = sp.getCurStats(statsKeys);\n\t\t\n\t\t// refreshing totals and per second values using retrieved data\n\t\tfor (String statKey : statsKeys) {\n\t\t\tString key = statsKeyToKey.get(statKey);\n\t\t\tlong value = (long) data.getOrDefault(statKey, 0);\n\t\t\t\n\t\t\tHolder holder = stats.get(key);\n\t\t\tif (holder == null) {\n\t\t\t\tholder = new Holder();\n\t\t\t\tstats.put(key, holder);\n\t\t\t}\n\t\t\t\n\t\t\tholder.updateTotal(value);\n\t\t}\n\t\t\n\t\tfor (String errorName : StreamErrorCounterIOProcessor.ErrorStatisticsHolder.getErrorNames()) {\n\t\t\tlong total = 0;\n\t\t\tfor (String compName : sp.getCompNames()) {\n\t\t\t\tString key = \"StreamErrorStats/\" + errorName  + \"ErrorsNumber\";\n\t\t\t\ttotal += sp.getStats(compName, key, 0L);\n\t\t\t}\n\t\t\t\n\t\t\tHolder holder = stats.get(errorName);\n\t\t\tif (holder == null) {\n\t\t\t\tholder = new Holder();\n\t\t\t\tstats.put(errorName, holder);\n\t\t\t}\n\t\t\t\n\t\t\tholder.updateTotal(total);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {\n\t\tboolean total = attribute.endsWith(TOTAL);\n\t\tboolean perSec = attribute.endsWith(PER_SECOND);\n\t\t\n\t\tattribute = attrToKey.get(attribute);\n\t\tHolder holder = stats.get(attribute);\n\t\t\n\t\tif (holder != null) { \n\t\t\tif (total)\n\t\t\t\treturn holder.getTotal();\n\t\t\telse if (perSec)\n\t\t\t\treturn holder.getPerSecond();\n\t\t}\n\t\t\n\t\tthrow new RuntimeOperationsException(\n\t\t\t\tnew IllegalArgumentException(\n\t\t\t\t\t\"Unknown attribute name \" + attribute),\n\t\t\t\t\"Cannot invoke a getter of \" + dClassName);\n\t}\n\n\t@Override\n\tpublic void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic AttributeList getAttributes(String[] attributeNames) {\n\t\tif (attributeNames == null) {\n\t\t\tthrow new RuntimeOperationsException(\n\t\t\t\t\tnew IllegalArgumentException(\n\t\t\t\t\t\t\t\"attributeNames[] cannot be null\"),\n\t\t\t\t\t\"Cannot invoke a getter of \" + dClassName);\n\t\t}\n\t\tAttributeList resultList = new AttributeList();\n\n\t\tif (attributeNames.length == 0) {\n\t\t\treturn resultList;\n\t\t}\n\n\t\tfor (String attributeName : attributeNames) {\n\t\t\ttry {\n\t\t\t\tObject value = getAttribute((String) attributeName);\n\t\t\t\tresultList.add(new Attribute(attributeName, value));\n\t\t\t}catch (Exception e) {\n\t\t\t\t// ignoring this exception\n\t\t\t}\n\t\t}\n\t\treturn resultList;\n\t}\n\n\t@Override\n\tpublic AttributeList setAttributes(AttributeList attributes) {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\"); //To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t@Override\n\tpublic Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {\n\t\tswitch (actionName) {\n\t\t\tcase \"getAllStats\":\n\t\t\t\treturn getAllStats();\n\t\t\tdefault:\n\t\t\t\tthrow new RuntimeOperationsException(\n\t\t\t\t\tnew IllegalArgumentException(\n\t\t\t\t\t\t\t\"Unknown method \" + actionName),\n\t\t\t\t\t\"Cannot invoke a method \" + actionName);\n\t\t}\n\t}\n\n\tpublic Map<String,String> getAllStats() throws MBeanException, ReflectionException {\n\t\tLinkedHashMap<String,String> result = new LinkedHashMap<>();\n\t\tfor (String attr : attrToKey.keySet()) {\n\t\t\ttry {\n\t\t\t\tObject value = getAttribute(attr);\n\t\t\t\tif (value != null)\n\t\t\t\t\tresult.put(attr, String.valueOf(value));\n\t\t\t} catch (AttributeNotFoundException ex) {\n\t\t\t\t// should not happens\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\t\n\t@Override\n\tpublic MBeanInfo getMBeanInfo() {\n\t\treturn dMBeanInfo;\n\t}\n\t\n\tprivate void buildDynamicMBeanInfo() {\n\t\tList<MBeanAttributeInfo> attrs = new ArrayList<MBeanAttributeInfo>();\n\t\t\n\t\tfor (String errorName : ErrorCounter.ErrorStatisticsHolder.getErrorNames()) {\n\t\t\tString attrName = errorName + ERRORS_NUMBER + PER_SECOND;\n\t\t\tattrs.add(new MBeanAttributeInfo(attrName, TYPE_FLOAT, \"Number of errors \" + errorName + \" per second\", true, false, false));\n\t\t\tattrToKey.put(attrName, errorName);\n\t\t\tattrName = errorName + ERRORS_NUMBER + TOTAL;\n\t\t\tattrs.add(new MBeanAttributeInfo(attrName, TYPE_LONG, \"Total number of errors \" + errorName, true, false, false));\n\t\t\tattrToKey.put(attrName, errorName);\n\t\t}\n\t\t\n\t\tfor (String errorName : StreamErrorCounterIOProcessor.ErrorStatisticsHolder.getErrorNames()) {\n\t\t\tString attrName = errorName + ERRORS_NUMBER + PER_SECOND;\n\t\t\tattrs.add(new MBeanAttributeInfo(attrName, TYPE_FLOAT, \"Number of errors \" + errorName + \" per second\", true, false, false));\n\t\t\tattrToKey.put(attrName, errorName);\n\t\t\tattrName = errorName + ERRORS_NUMBER + TOTAL;\n\t\t\tattrs.add(new MBeanAttributeInfo(attrName, TYPE_LONG, \"Total number of errors \" + errorName, true, false, false));\n\t\t\tattrToKey.put(attrName, errorName);\n\t\t}\n\t\t\n\t\tdAttributes = attrs.toArray(new MBeanAttributeInfo[attrs.size()]);\n\t\t\n\t\tdOperations[0] = new MBeanOperationInfo(\"getAllStats\", \"Provides errors statistics\", new MBeanParameterInfo[0], \"java.util.Map\", MBeanOperationInfo.INFO);\n\t\t\n\t\tdMBeanInfo = new MBeanInfo(dClassName,\n                               dDescription,\n                               dAttributes,\n                               dConstructors,\n                               dOperations,\n                               new MBeanNotificationInfo[0]);\n\t\n\t\tString[] errorNames = ErrorCounter.ErrorStatisticsHolder.getErrorNames();\n\t\tstatsKeys = new String[errorNames.length];\n\t\tfor (int i=0; i<errorNames.length; i++) {\n\t\t\tString key = \"sess-man/ErrorStats/\" + errorNames[i]  + \"ErrorsNumber[L]\";\n\t\t\tstatsKeys[i] = key;\n\t\t\tstatsKeyToKey.put(key, errorNames[i]);\n\t\t}\n\t}\n\t\n\tprivate static class Holder {\n\t\tprivate long total = 0;\n\t\tprivate float perSec = 0;\n\t\tprivate float prevPerSec = 0;\n\t\t\n\t\tpublic void updateTotal(long newValue) {\n\t\t\tfloat temp = perSec;\n\t\t\tlong prevTotal = total;\n\t\t\ttotal = newValue;\n\t\t\tperSec = (prevPerSec + (temp * 2f) + (total - prevTotal)) / 4f;\n\t\t\tprevPerSec = temp;\t\t\t\n\t\t}\n\t\t\n\t\tpublic long getTotal() {\n\t\t\treturn total;\n\t\t}\n\t\t\n\t\tpublic float getPerSecond() {\n\t\t\treturn perSec;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/JMXProxyListener.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.stats;\n\n/**\n * Created: Aug 24, 2009 1:02:08 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface JMXProxyListener {\n\n\tvoid connected(String id, StatisticsProviderMBean bean);\n\n\tvoid disconnected(String id);\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/JMXProxyListenerOpt.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.stats;\n\n/**\n * @author Artur Hefczyc Created Jun 3, 2011\n */\npublic interface JMXProxyListenerOpt {\n\tvoid connected(String id, JavaJMXProxyOpt bean);\n\n\tvoid disconnected(String id);\n\n\tString[] getDataIds();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/JavaJMXProxy.java",
    "content": "/*\n * JavaJMXProxy.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport javax.management.MBeanServerConnection;\nimport javax.management.MBeanServerInvocationHandler;\nimport javax.management.Notification;\nimport javax.management.NotificationListener;\nimport javax.management.ObjectName;\nimport javax.management.remote.JMXConnectionNotification;\nimport javax.management.remote.JMXConnector;\nimport javax.management.remote.JMXConnectorFactory;\nimport javax.management.remote.JMXServiceURL;\n\n/**\n * Created: Aug 24, 2009 12:35:28 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JavaJMXProxy\n\t\t\t\timplements StatisticsProviderMBean, NotificationListener {\n\tprivate static final Logger log = Logger.getLogger(JavaJMXProxy.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate float   clCompressionRatio   = 0;\n\tprivate int     clIOQueueSize        = 0;\n\tprivate long    clNetworkBytes       = 0;\n\tprivate float   clNetworkBytesPerSec = 0;\n\tprivate float   clPacketsPerSec      = 0;\n\tprivate float[] clpacks_history      = null;\n\tprivate int     clQueueSize          = 0;\n\tprivate int     clusterCacheSize     = 0;\n\tprivate long    clusterPacketsNumber = 0;\n\tprivate int     connectionsNumber    = 0;\n\tprivate int[]   conns_history        = null;\n\tprivate float[] cpu_history          = null;\n\n\t// Cache section...\n\tprivate int                     cpuNo                    = 0;\n\tprivate float                   cpuUsage                 = 0;\n\tprivate long                    delay                    = -1;\n\tprivate long[]                  direct_history           = null;\n\tprivate long                    directUsed               = 0;\n\tprivate float[]                 heap_history             = null;\n\tprivate float                   heapUsage                = 0;\n\tprivate String                  hostname                 = null;\n\tprivate String                  id                       = null;\n\tprivate long                    interval                 = -1;\n\tprivate long                    iqAuthNumber             = 0;\n\tprivate long                    iqOtherNumber            = 0;\n\tprivate float                   iqOtherPerSec            = 0;\n\tprivate JMXConnector            jmxc                     = null;\n\tprivate JMXServiceURL           jmxUrl                   = null;\n\tprivate long                    lastCacheUpdate          = 0;\n\tprivate long                    messagesNumber           = 0;\n\tprivate float                   messagesPerSec           = 0;\n\tprivate float                   nonHeapUsage             = 0;\n\tprivate String                  password                 = null;\n\tprivate int                     port                     = -1;\n\tprivate long                    presencesNumber          = 0;\n\tprivate float                   presencesPerSec          = 0;\n\tprivate long                    processCPUTime           = 0;\n\tprivate long                    queueOverflow            = 0;\n\tprivate int                     queueSize                = 0;\n\tprivate MBeanServerConnection   server                   = null;\n\tprivate int                     serverConnections        = 0;\n\tprivate int[]                   serverConnectionsHistory = null;\n\tprivate List<JMXProxyListener>  listeners = new LinkedList<JMXProxyListener>();\n\tprivate long                    smPacketsNumber          = 0;\n\tprivate float                   smPacketsPerSec          = 0;\n\tprivate float[]                 smpacks_history          = null;\n\tprivate int                     smQueueSize              = 0;\n\tprivate String                  sysDetails               = \"No details loaded yet\";\n\tprivate StatisticsProviderMBean tigBean                  = null;\n\tprivate StatisticsUpdater       updater                  = null;\n\tprivate long                    uptime                   = 0;\n\tprivate String                  urlPath                  = null;\n\tprivate String                  userName                 = null;\n\tprivate boolean                 loadHistory              = false;\n\tprivate boolean                 initialized              = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tpublic JavaJMXProxy(String id, String hostname, int port, String userName,\n\t\t\tString password, long delay, long interval, boolean loadHistory) {\n\t\tthis.id          = id;\n\t\tthis.hostname    = hostname;\n\t\tthis.port        = port;\n\t\tthis.userName    = userName;\n\t\tthis.password    = password;\n\t\tthis.delay       = delay;\n\t\tthis.interval    = interval;\n\t\tthis.urlPath     = \"/jndi/rmi://\" + this.hostname + \":\" + this.port + \"/jmxrmi\";\n\t\tthis.loadHistory = loadHistory;\n\t\tSystem.out.println(\"Created: \" + hostname);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic void addJMXProxyListener(JMXProxyListener listener) {\n\t\tlisteners.add(listener);\n\t}\n\n\tpublic void connect() throws Exception {\n\t\tthis.jmxUrl = new JMXServiceURL(\"rmi\", \"\", 0, this.urlPath);\n\n\t\tString[]                userCred = new String[] { userName, password };\n\t\tHashMap<String, Object> env      = new HashMap<String, Object>();\n\n\t\tenv.put(JMXConnector.CREDENTIALS, userCred);\n\t\tjmxc = JMXConnectorFactory.newJMXConnector(jmxUrl, env);\n\t\tjmxc.addConnectionNotificationListener(this, null, null);\n\t\tjmxc.connect();\n\t}\n\n\t@Override\n\tpublic void handleNotification(Notification notification, Object handback) {\n\t\tif (notification.getType().equals(JMXConnectionNotification.OPENED)) {\n\t\t\tSystem.out.println(\"Connected: \" + hostname);\n\t\t\ttry {\n\t\t\t\tserver = jmxc.getMBeanServerConnection();\n\n\t\t\t\tObjectName obn = new ObjectName(StatisticsCollector.STATISTICS_MBEAN_NAME);\n\n\t\t\t\ttigBean = MBeanServerInvocationHandler.newProxyInstance(server, obn,\n\t\t\t\t\t\tStatisticsProviderMBean.class, false);\n\t\t\t\tif (loadHistory) {\n\t\t\t\t\tcpu_history = tigBean.getCPUUsageHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded cpu_history, size: \" + cpu_history\n\t\t\t\t\t\t\t.length);\n\t\t\t\t\theap_history = tigBean.getHeapUsageHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded heap_history, size: \" + heap_history\n\t\t\t\t\t\t\t.length);\n\t\t\t\t\tsmpacks_history = tigBean.getSMPacketsPerSecHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded smpacks_history, size: \" +\n\t\t\t\t\t\t\tsmpacks_history.length);\n\t\t\t\t\tclpacks_history = tigBean.getCLPacketsPerSecHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded clpacks_history, size: \" +\n\t\t\t\t\t\t\tclpacks_history.length);\n\t\t\t\t\tconns_history = tigBean.getConnectionsNumberHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded conns_history, size: \" + conns_history\n\t\t\t\t\t\t\t.length);\n\t\t\t\t\tserverConnectionsHistory = tigBean.getServerConnectionsHistory();\n\t\t\t\t\tSystem.out.println(hostname + \" loaded server_conns_history, size: \" +\n\t\t\t\t\t\t\tserverConnectionsHistory.length);\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(hostname + \" loading history switched off.\");\n\t\t\t\t}\n\t\t\t\tfor (JMXProxyListener jMXProxyListener : listeners) {\n\t\t\t\t\tjMXProxyListener.connected(id, this);\n\t\t\t\t}\n\t\t\t\tstart();\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (notification.getType().equals(JMXConnectionNotification.CLOSED)) {\n\t\t\tserver  = null;\n\t\t\ttigBean = null;\n\t\t\tfor (JMXProxyListener jMXProxyListener : listeners) {\n\t\t\t\tjMXProxyListener.disconnected(id);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (notification.getType().equals(JMXConnectionNotification.FAILED)) {\n\t\t\tSystem.out.println(\"Reconnection to {hostName} failed...\");\n\n\t\t\treturn;\n\t\t}\n\t\tSystem.out.println(\"Unsupported JMX notification: {notification.getType()}\");\n\t}\n\n\tpublic void start() {\n\t\tif (updater == null) {\n\t\t\tupdater = new StatisticsUpdater();\n\t\t\tSystem.out.println(\"Started: \" + hostname);\n\t\t}\n\t}\n\n\tpublic void update() {\n\t\tif (tigBean != null) {\n\n\t\t\t// This doesn't ever change so it is enough to query it once\n\t\t\tif (cpuNo == 0) {\n\t\t\t\tcpuNo = tigBean.getCPUsNumber();\n\t\t\t}\n\t\t\tuptime               = tigBean.getUptime();\n\t\t\tprocessCPUTime       = tigBean.getProcesCPUTime();\n\t\t\tconnectionsNumber    = tigBean.getConnectionsNumber();\n\t\t\tserverConnections    = tigBean.getServerConnections();\n\t\t\tclusterCacheSize     = tigBean.getClusterCacheSize();\n\t\t\tqueueSize            = tigBean.getQueueSize();\n\t\t\tsmQueueSize          = tigBean.getSMQueueSize();\n\t\t\tclQueueSize          = tigBean.getCLQueueSize();\n\t\t\tclIOQueueSize        = tigBean.getCLIOQueueSize();\n\t\t\tqueueOverflow        = tigBean.getQueueOverflow();\n\t\t\tsmPacketsNumber      = tigBean.getSMPacketsNumber();\n\t\t\tclusterPacketsNumber = tigBean.getClusterPackets();\n\t\t\tmessagesNumber       = tigBean.getMessagesNumber();\n\t\t\tpresencesNumber      = tigBean.getPresencesNumber();\n\t\t\tsmPacketsPerSec      = tigBean.getSMPacketsNumberPerSec();\n\t\t\tclPacketsPerSec      = tigBean.getClusterPacketsPerSec();\n\t\t\tmessagesPerSec       = tigBean.getMessagesNumberPerSec();\n\t\t\tpresencesPerSec      = tigBean.getPresencesNumberPerSec();\n\n\t\t\t// iqOtherNumber = tigBean.getIQOtherNumber();\n\t\t\t// iqOtherPerSec = tigBean.getIQOtherNumberPerSec();\n\t\t\t// iqAuthNumber = tigBean.getIQAuthNumber();\n\t\t\tcpuUsage             = tigBean.getCPUUsage();\n\t\t\theapUsage            = tigBean.getHeapMemUsage();\n\t\t\tnonHeapUsage         = tigBean.getNonHeapMemUsage();\n\t\t\tdirect_history       = tigBean.getDirectMemUsedHistory();\n\t\t\tdirectUsed           = tigBean.getDirectMemUsed();\n\t\t\tsysDetails           = tigBean.getSystemDetails();\n\t\t\tclCompressionRatio   = tigBean.getClusterCompressionRatio();\n\t\t\tclNetworkBytes       = tigBean.getClusterNetworkBytes();\n\t\t\tclNetworkBytesPerSec = tigBean.getClusterNetworkBytesPerSecond();\n\t\t\tlastCacheUpdate      = System.currentTimeMillis();\n\t\t\tinitialized          = true;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic Map<String, String> getAllStats(int level) {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getAllStats(level);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getCLIOQueueSize() {\n\t\treturn clIOQueueSize;\n\t}\n\n\t@Override\n\tpublic float[] getCLPacketsPerSecHistory() {\n\t\treturn clpacks_history;\n\t}\n\n\t@Override\n\tpublic int getCLQueueSize() {\n\t\treturn clQueueSize;\n\t}\n\n\t@Override\n\tpublic int getClusterCacheSize() {\n\t\treturn clusterCacheSize;\n\t}\n\n\t@Override\n\tpublic float getClusterCompressionRatio() {\n\t\treturn clCompressionRatio;\n\t}\n\n\t@Override\n\tpublic long getClusterNetworkBytes() {\n\t\treturn clNetworkBytes;\n\t}\n\n\t@Override\n\tpublic float getClusterNetworkBytesPerSecond() {\n\t\treturn clNetworkBytesPerSec;\n\t}\n\n\t@Override\n\tpublic long getClusterPackets() {\n\t\treturn clusterPacketsNumber;\n\t}\n\n\t@Override\n\tpublic float getClusterPacketsPerSec() {\n\t\treturn clPacketsPerSec;\n\t}\n\n\t@Override\n\tpublic List<String> getComponentsNames() {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getComponentsNames();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Map<String, String> getComponentStats(String compName, int level) {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getComponentStats(compName, level);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getConnectionsNumber() {\n\t\treturn connectionsNumber;\n\t}\n\n\t@Override\n\tpublic int[] getConnectionsNumberHistory() {\n\t\treturn conns_history;\n\t}\n\n\t@Override\n\tpublic int getCPUsNumber() {\n\t\treturn cpuNo;\n\t}\n\n\t@Override\n\tpublic float getCPUUsage() {\n\t\treturn cpuUsage;\n\t}\n\n\t@Override\n\tpublic float[] getCPUUsageHistory() {\n\t\treturn cpu_history;\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getCurStats(String[] statsKeys) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic long getDirectMemUsed() {\n\t\treturn directUsed;\n\t}\n\n\t@Override\n\tpublic long[] getDirectMemUsedHistory() {\n\t\treturn direct_history;\n\t}\n\n\t@Override\n\tpublic float getHeapMemUsage() {\n\t\treturn heapUsage;\n\t}\n\n\t@Override\n\tpublic float[] getHeapUsageHistory() {\n\t\treturn heap_history;\n\t}\n\n\tpublic String getId() {\n\t\treturn id;\n\t}\n\n\t@Override\n\tpublic long getIQAuthNumber() {\n\t\treturn iqAuthNumber;\n\t}\n\n\t@Override\n\tpublic long getIQOtherNumber() {\n\t\treturn iqOtherNumber;\n\t}\n\n\t@Override\n\tpublic float getIQOtherNumberPerSec() {\n\t\treturn iqOtherPerSec;\n\t}\n\n\tpublic long getLastCacheUpdate() {\n\t\treturn lastCacheUpdate;\n\t}\n\n\t@Override\n\tpublic long getMessagesNumber() {\n\t\treturn messagesNumber;\n\t}\n\n\t@Override\n\tpublic float getMessagesNumberPerSec() {\n\t\treturn messagesPerSec;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getName();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic float getNonHeapMemUsage() {\n\t\treturn nonHeapUsage;\n\t}\n\n\t@Override\n\tpublic long getPresencesNumber() {\n\t\treturn presencesNumber;\n\t}\n\n\t@Override\n\tpublic float getPresencesNumberPerSec() {\n\t\treturn presencesPerSec;\n\t}\n\n\t@Override\n\tpublic long getProcesCPUTime() {\n\t\treturn processCPUTime;\n\t}\n\n\t@Override\n\tpublic long getQueueOverflow() {\n\t\treturn queueOverflow;\n\t}\n\n\t@Override\n\tpublic int getQueueSize() {\n\t\treturn queueSize;\n\t}\n\n\t@Override\n\tpublic int getServerConnections() {\n\t\treturn serverConnections;\n\t}\n\n\t@Override\n\tpublic int[] getServerConnectionsHistory() {\n\t\treturn serverConnectionsHistory;\n\t}\n\n\t@Override\n\tpublic long getSMPacketsNumber() {\n\t\treturn smPacketsNumber;\n\t}\n\n\t@Override\n\tpublic float getSMPacketsNumberPerSec() {\n\t\treturn smPacketsPerSec;\n\t}\n\n\t@Override\n\tpublic float[] getSMPacketsPerSecHistory() {\n\t\treturn smpacks_history;\n\t}\n\n\t@Override\n\tpublic int getSMQueueSize() {\n\t\treturn smQueueSize;\n\t}\n\n\t@Override\n\tpublic Map<String, LinkedList<Object>> getStatsHistory(String[] statsKeys) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getSystemDetails() {\n\t\treturn sysDetails;\n\t}\n\n\t@Override\n\tpublic long getUptime() {\n\t\treturn uptime;\n\t}\n\n\tpublic boolean isConnected() {\n\t\treturn tigBean != null;\n\t}\n\n\tpublic boolean isInitialized() {\n\t\treturn isConnected() && initialized;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class StatisticsUpdater {\n\t\tprivate Timer updateTimer = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate StatisticsUpdater() {\n\t\t\tupdateTimer = new Timer(\"stats-updater\", true);\n\t\t\tupdateTimer.scheduleAtFixedRate(new TimerTask() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (server == null) {\n\t\t\t\t\t\t\tconnect();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (server != null) {\n\t\t\t\t\t\t\tupdate();\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\tThrowable cause = e;\n\n\t\t\t\t\t\twhile (cause.getCause() != null) {\n\t\t\t\t\t\t\tcause = cause.getCause();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlog.log(Level.WARNING, \"{0}, retrying in {1} seconds.\", new Object[] { cause\n\t\t\t\t\t\t\t\t.getMessage(),\n\t\t\t\t\t\t\t\tinterval / 1000 });\n\t\t\t\t\t\tlog.log(Level.FINEST, e.getMessage(), e);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem retrieving statistics: \", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, delay, interval);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/JavaJMXProxyOpt.java",
    "content": "/*\n * JavaJMXProxyOpt.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.DataTypes;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.IOException;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport javax.management.MBeanServerConnection;\nimport javax.management.MBeanServerInvocationHandler;\nimport javax.management.Notification;\nimport javax.management.NotificationListener;\nimport javax.management.ObjectName;\nimport javax.management.remote.JMXConnectionNotification;\nimport javax.management.remote.JMXConnector;\nimport javax.management.remote.JMXConnectorFactory;\nimport javax.management.remote.JMXServiceURL;\n\n/**\n * @author Artur Hefczyc Created Jun 3, 2011\n */\npublic class JavaJMXProxyOpt\n\t\t\t\timplements NotificationListener {\n\tprivate static final Logger log = Logger.getLogger(JavaJMXProxyOpt.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int                             cpuNo              = 0;\n\tprivate long                            delay              = -1;\n\tprivate Map<String, LinkedList<Object>> history            = null;\n\tprivate String                          hostname           = null;\n\tprivate String                          id                 = null;\n\tprivate long                            interval           = -1;\n\tprivate JMXConnector                    jmxc               = null;\n\tprivate JMXServiceURL                   jmxUrl             = null;\n\tprivate Date                            lastDisconnectTime = null;\n\tprivate String                          password           = null;\n\tprivate int                             port               = -1;\n\tprivate MBeanServerConnection           server             = null;\n\tprivate String                          sysDetails         = \"No data yet...\";\n\tprivate StatisticsProviderMBean         tigBean            = null;\n\tprivate StatisticsUpdater               updater            = null;\n\tprivate String                          urlPath            = null;\n\tprivate String                          userName           = null;\n\tprivate Set<String>                     metrics            =\n\t\t\tnew LinkedHashSet<String>();\n\tprivate boolean                         loadHistory        = false;\n\tprivate List<JMXProxyListenerOpt>       listeners =\n\t\t\tnew LinkedList<JMXProxyListenerOpt>();\n\tprivate boolean                         initialized        = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tpublic JavaJMXProxyOpt(String id, String hostname, int port, String userName,\n\t\t\tString password, long delay, long interval, boolean loadHistory) {\n\t\tthis.id          = id;\n\t\tthis.hostname    = hostname;\n\t\tthis.port        = port;\n\t\tthis.userName    = userName;\n\t\tthis.password    = password;\n\t\tthis.delay       = delay;\n\t\tthis.interval    = interval;\n\t\tthis.urlPath     = \"/jndi/rmi://\" + this.hostname + \":\" + this.port + \"/jmxrmi\";\n\t\tthis.loadHistory = loadHistory;\n\t\tSystem.out.println(\"Created: \" + id + \":\" + hostname + \":\" + port);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic void addJMXProxyListener(JMXProxyListenerOpt listener) {\n\t\tlisteners.add(listener);\n\n\t\tString[] dataIds = listener.getDataIds();\n\n\t\tif ((dataIds != null) && (dataIds.length > 0)) {\n\t\t\tfor (String did : dataIds) {\n\t\t\t\tmetrics.add(did);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void connect() throws Exception {\n\t\tthis.jmxUrl = new JMXServiceURL(\"rmi\", \"\", 0, this.urlPath);\n\n\t\tString[]                userCred = new String[] { userName, password };\n\t\tHashMap<String, Object> env      = new HashMap<String, Object>();\n\n\t\tenv.put(JMXConnector.CREDENTIALS, userCred);\n\t\tjmxc = JMXConnectorFactory.newJMXConnector(jmxUrl, env);\n\t\tjmxc.addConnectionNotificationListener(this, null, null);\n\t\tjmxc.connect();\n\t}\n\n\t@Override\n\tpublic void handleNotification(Notification notification, Object handback) {\n\t\tif (notification.getType().equals(JMXConnectionNotification.OPENED)) {\n\t\t\tSystem.out.println(\"Connected: \" + id + \":\" + hostname + \":\" + port);\n\t\t\ttry {\n\t\t\t\tserver = jmxc.getMBeanServerConnection();\n\n\t\t\t\tObjectName obn = new ObjectName(StatisticsCollector.STATISTICS_MBEAN_NAME);\n\n\t\t\t\ttigBean = MBeanServerInvocationHandler.newProxyInstance(server, obn,\n\t\t\t\t\t\tStatisticsProviderMBean.class, false);\n\t\t\t\tif (history == null) {\n\t\t\t\t\tif (loadHistory) {\n\t\t\t\t\t\tString[] metrics_arr = metrics.toArray(new String[metrics.size()]);\n\n\t\t\t\t\t\thistory = tigBean.getStatsHistory(metrics_arr);\n\t\t\t\t\t\tSystem.out.println(hostname + \" loaded history, size: \" + (((history !=\n\t\t\t\t\t\t\t\tnull) && (history.get(metrics_arr[0]) != null))\n\t\t\t\t\t\t\t\t? history.get(metrics_arr[0]).size()\n\t\t\t\t\t\t\t\t: \"null\"));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSystem.out.println(hostname + \" loading history switched off.\");\n\t\t\t\t\t}\n\t\t\t\t\tif (history == null) {\n\t\t\t\t\t\thistory = new LinkedHashMap<String, LinkedList<Object>>();\n\t\t\t\t\t\tfor (String m : metrics) {\n\t\t\t\t\t\t\tLinkedList<Object> list = new LinkedList<Object>();\n\n\t\t\t\t\t\t\thistory.put(m, list);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(hostname + \" history already loaded, skipping.\");\n\t\t\t\t}\n\t\t\t\tfor (JMXProxyListenerOpt jMXProxyListener : listeners) {\n\t\t\t\t\tjMXProxyListener.connected(id, this);\n\t\t\t\t}\n\t\t\t\tstart();\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (notification.getType().equals(JMXConnectionNotification.CLOSED)) {\n\t\t\tserver             = null;\n\t\t\ttigBean            = null;\n\t\t\tlastDisconnectTime = new Date();\n\t\t\tfor (JMXProxyListenerOpt jMXProxyListener : listeners) {\n\t\t\t\tjMXProxyListener.disconnected(id);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (notification.getType().equals(JMXConnectionNotification.FAILED)) {\n\t\t\tSystem.out.println(\"Reconnection to {hostName} failed...\");\n\n\t\t\treturn;\n\t\t}\n\t\tSystem.out.println(\"Unsupported JMX notification: {notification.getType()}\");\n\t}\n\n\tpublic void start() {\n\t\tif (updater == null) {\n\t\t\tupdater = new StatisticsUpdater();\n\t\t\tSystem.out.println(\"Started: \" + id + \":\" + hostname + \":\" + port);\n\t\t}\n\t}\n\n\tpublic void update() {\n\t\tif (tigBean != null) {\n\n\t\t\t// This doesn't ever change so it is enough to query it once\n\t\t\tif (cpuNo == 0) {\n\t\t\t\tcpuNo = tigBean.getCPUsNumber();\n\t\t\t}\n\n\t\t\tMap<String, Object> curMetrics = tigBean.getCurStats(metrics.toArray(\n\t\t\t\t\tnew String[metrics.size()]));\n\n\t\t\tfor (Map.Entry<String, Object> e : curMetrics.entrySet()) {\n\t\t\t\tLinkedList<Object> list = history.get(e.getKey());\n\n\t\t\t\tif (list != null) {\n\t\t\t\t\tlist.add(e.getValue());\n\t\t\t\t\tif (list.size() > 1) {\n\t\t\t\t\t\tlist.removeFirst();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsysDetails  = tigBean.getSystemDetails();\n\t\t\tinitialized = true;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic Map<String, String> getAllStats(int level) {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getAllStats(level);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic List<String> getComponentsNames() {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getComponentsNames();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic Map<String, String> getComponentStats(String compName, int level) {\n\t\tif (tigBean != null) {\n\t\t\treturn tigBean.getComponentStats(compName, level);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic String getHostname() {\n\t\treturn hostname;\n\t}\n\n\tpublic String getId() {\n\t\treturn id;\n\t}\n\n\tpublic Object getMetricData(String key) {\n\t\tLinkedList<Object> h = history.get(key);\n\n\t\tif (h != null) {\n\t\t\treturn h.getLast();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic Object[] getMetricHistory(String key) {\n\t\tList<Object> result = history.get(key);\n\n\t\tif (result != null) {\n\t\t\tswitch (DataTypes.decodeTypeIdFromName(key)) {\n\t\t\tcase 'I' :\n\t\t\t\treturn result.toArray(new Integer[result.size()]);\n\n\t\t\tcase 'L' :\n\t\t\t\treturn result.toArray(new Long[result.size()]);\n\n\t\t\tcase 'F' :\n\t\t\t\treturn result.toArray(new Float[result.size()]);\n\n\t\t\tcase 'D' :\n\t\t\t\treturn result.toArray(new Double[result.size()]);\n\n\t\t\tdefault :\n\t\t\t\treturn result.toArray(new String[result.size()]);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic String getSystemDetails() {\n\t\treturn sysDetails;\n\t}\n\n\tpublic boolean isConnected() {\n\t\treturn tigBean != null;\n\t}\n\n\tpublic boolean isInitialized() {\n\t\treturn isConnected() && initialized;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class StatisticsUpdater {\n\t\tprivate Timer updateTimer = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate StatisticsUpdater() {\n\t\t\tupdateTimer = new Timer(\"stats-updater\", true);\n\n\t\t\t// updateTimer.scheduleAtFixedRate(new TimerTask() {\n\t\t\tupdateTimer.schedule(new TimerTask() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (server == null) {\n\t\t\t\t\t\t\tconnect();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (server != null) {\n\t\t\t\t\t\t\tupdate();\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\tThrowable cause = e;\n\n\t\t\t\t\t\twhile (cause.getCause() != null) {\n\t\t\t\t\t\t\tcause = cause.getCause();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString disconnected = \"\";\n\n\t\t\t\t\t\tif (lastDisconnectTime != null) {\n\t\t\t\t\t\t\tlong disconnectedInterval = (System.currentTimeMillis() - lastDisconnectTime\n\t\t\t\t\t\t\t\t\t.getTime()) / (1000 * 60);\n\n\t\t\t\t\t\t\tdisconnected = \", disconnected: \" + lastDisconnectTime + \", \" +\n\t\t\t\t\t\t\t\t\tdisconnectedInterval + \" minutes ago.\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlog.log(Level.WARNING, \"{0}, {1}, retrying in {2} seconds{3}\", new Object[] {\n\t\t\t\t\t\t\t\tcause.getMessage(),\n\t\t\t\t\t\t\t\thostname, interval / 1000, disconnected });\n\n\t\t\t\t\t\t// log.log(Level.FINEST, e.getMessage(), e);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem retrieving statistics: \", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, delay, interval);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatRecord.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.stats;\n\nimport java.util.logging.Level;\n\n/**\n * Describe class StatRecord here.\n *\n *\n * Created: Wed Nov 23 21:28:53 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StatRecord {\n\n\tprivate StatisticType type = StatisticType.OTHER;\n\tprivate Level level = Level.INFO;\n\tprivate long longValue = -1;\n \tprivate int intValue = -1;\n\tprivate float floatValue = -1f;\n\n\tprivate String description = null;\n\tprivate String value = null;\n\tprivate String component = null;\n\n\tpublic StatRecord(String comp, String description,\tString value,\n\t\tLevel level) {\n\t\tthis.description = description.intern();\n\t\tthis.value = value.intern();\n\t\tthis.level = level;\n\t\tthis.component = comp.intern();\n\t}\n\n\tpublic StatRecord(String comp, String description, int value,\n\t\tLevel level) {\n\t\tthis(comp, description, \"\" + value, level);\n\t\tthis.intValue = value;\n\t}\n\n\tpublic StatRecord(String comp, StatisticType type, long value, Level level) {\n\t\tthis(comp, type.getDescription(), \"\" + value, level);\n\t\tthis.type = type;\n\t\tthis.longValue = value;\n\t}\n\n\tpublic StatRecord(String comp, StatisticType type, int value, Level level) {\n\t\tthis(comp, type.getDescription(), \"\" + value, level);\n\t\tthis.type = type;\n\t\tthis.intValue = value;\n\t}\n\n\tpublic StatRecord(String comp, String description, long value,\n\t\tLevel level) {\n\t\tthis(comp, description, \"\" + value, level);\n\t\tthis.longValue = value;\n\t}\n\n\tStatRecord(String comp, String description, float value, Level level) {\n\t\tthis(comp, description, \"\" + value, level);\n\t\tthis.floatValue = value;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn description;\n\t}\n\n\tpublic String getValue() {\n\t\treturn value;\n\t}\n\n\tpublic StatisticType getType() {\n\t\treturn type;\n\t}\n\n\tpublic Level getLevel() {\n\t\treturn level;\n\t}\n\n\tpublic String getComponent() {\n\t\treturn component;\n\t}\n\n\tpublic long getLongValue() {\n\t\treturn this.longValue;\n\t}\n\n\tpublic int getIntValue() {\n\t\treturn this.intValue;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(component).append('/').append(description);\n\n\t\tsb.append('[');\n\t\tif (longValue > -1) { sb.append('L');\n\t\t} else if (intValue > -1) { sb.append('I');\n\t\t} else if (floatValue > -1f) { sb.append('F');\n\t\t} else { sb.append('S'); }\n\t\tsb.append(']');\n\n\t\tsb.append(\" = \").append(value);\n\t\treturn sb.toString();\n\t}\n\n\tfloat getFloatValue() {\n\t\treturn this.floatValue;\n\t}\n\n} // StatRecord\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticHolder.java",
    "content": "/*\n * StatisticHolder.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\n/**\n *\n * @author andrzej\n */\npublic interface StatisticHolder {\n\t\n\tvoid statisticExecutedIn(long executionTime);\n\t\n\tvoid everyHour();\t\n\tvoid everyMinute();\n\tvoid everySecond();\t\n\t\n\tvoid getStatistics(String compName, StatisticsList list);\t\n\n\tvoid setStatisticsPrefix(String prefix);\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticHolderImpl.java",
    "content": "/*\n * StatisticHolderImpl.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.stats;\n\nimport java.util.logging.Level;\n\n/**\n *\n * @author andrzej\n */\npublic class StatisticHolderImpl extends Counter implements StatisticHolder {\n\t\n//\tprivate String prefix = null;\n//\t\n//\tprivate long last_hour_packets = 0;\n//\tprivate long last_minute_packets = 0;\n//\tprivate long last_second_packets = 0;\n//\tprivate long packets_per_hour = 0;\n//\tprivate long packets_per_minute = 0;\n//\tprivate long packets_per_second = 0;\n//\tprivate long requestsOk = 0;\n\tprivate long avgProcessingTime = 0;\t\t\n\t\n\tpublic StatisticHolderImpl() {\n\t\tsuper(\"NULL\", Level.FINEST);\n\t}\n\t\n\tpublic StatisticHolderImpl(String name) {\n\t\tsuper(name, Level.FINEST);\n\t}\t\n\n\t@Override\n\tpublic void statisticExecutedIn(long executionTime) {\n\t\tavgProcessingTime = (avgProcessingTime + executionTime) / 2;\n\t\tinc();\n\t}\n\t\n\t@Override\n\tpublic void getStatistics(String compName, StatisticsList list) {\n\t\tsuper.getStatistics(compName, list);\n\t\tlist.add(compName, getName() +\"/Average processing time\", avgProcessingTime, Level.FINE);\n\t}\t\n\t\n\t@Override\n\tpublic void setStatisticsPrefix(String prefix) {\n\t\tsetName(prefix);\n\t}\n\t\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.stats;\n\n/**\n * Describe class StatisticType here.\n *\n *\n * Created: Wed Nov 23 21:20:20 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum StatisticType {\n\n\tQUEUE_WAITING(\"Total waiting packets\"),\n\tMAX_QUEUE_SIZE(\"Max queue size\"),\n\tMSG_RECEIVED_OK(\"Packets received\"),\n\tMSG_SENT_OK(\"Packets sent\"),\n\tIN_QUEUE_OVERFLOW(\"IN Queue overflow\"),\n\tOUT_QUEUE_OVERFLOW(\"OUT Queue overflow\"),\n\tOTHER(null);\n\n\n\tprivate String description = null;\n\n\tprivate StatisticType(String description) {\n\t\tthis.description = description;\n\t}\n\n\tpublic String getDescription() { return description; }\n\n} // StatisticType\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsArchivizerIfc.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.stats;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Mar 25, 2010 5:10:28 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface StatisticsArchivizerIfc {\n\tvoid execute(StatisticsProvider sp);\n\n\tvoid init(Map<String, Object> archivizerConf);\n\n\tvoid release();\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsCollector.java",
    "content": "/*\n * StatisticsCollector.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractComponentRegistrator;\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.ServerComponent;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport tigase.conf.ConfigurationException;\nimport tigase.conf.ConfiguratorAbstract;\nimport tigase.disco.ServiceEntity;\nimport tigase.disco.ServiceIdentity;\nimport tigase.sys.ShutdownHook;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.ElementUtils;\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport javax.management.ObjectName;\n\n/**\n * Class StatisticsCollector\n *\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StatisticsCollector\n\t\t\t\textends AbstractComponentRegistrator<StatisticsContainer>\n\t\t\t\timplements ShutdownHook {\n\tpublic static final String ERRORS_STATISTICS_MBEAN_NAME =\n\t\t\t\"tigase.stats:type=ErrorStatistics\";\n\tpublic static final String STATISTICS_MBEAN_NAME =\n\t\t\t\"tigase.stats:type=StatisticsProvider\";\n\n\tpublic static final String STATS_ARCHIVIZERS = \"--stats-archiv\";\n\n\tpublic static final String STATS_ARCHIVIZERS_PROP_KEY = \"stats-archiv\";\n\n\tpublic static final String STATS_HISTORY = \"--stats-history\";\n\n\tpublic static final String STATS_HISTORY_SIZE_PROP_KEY = \"stats-history-size\";\n\n\tpublic static final int STATS_HISTORY_SIZE_PROP_VAL = 8640;\n\n\tpublic static final String STATS_UPDATE_INTERVAL_PROP_KEY = \"stats-update-interval\";\n\n\tpublic static final long    STATS_UPDATE_INTERVAL_PROP_VAL = 10l;\n\tprivate static final String STATS_XMLNS = \"http://jabber.org/protocol/stats\";\n\tprivate static final Logger log = Logger.getLogger(StatisticsCollector.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int                                  historySize                 = 0;\n\tprivate TimerTask                            initializationCompletedTask = null;\n\tprivate ServiceEntity                        serviceEntity               = null;\n\tprivate StatisticsProvider                   sp                          = null;\n\tprivate ErrorsStatisticsProvider\t\t\t esp\t\t\t\t\t\t = null;\n\tprivate final Map<String, StatisticsArchivizerIfc> archivizers =\n\t\t\tnew ConcurrentSkipListMap<>();\n\tprivate final ArchivizerRunner arch_runner = new ArchivizerRunner();\n\n\t// private ServiceEntity stats_modules = null;\n\tprivate Level statsLevel       = Level.INFO;\n\tprivate final Timer statsArchivTasks = new Timer(\"stats-archivizer-tasks\", true);\n\tprivate long  updateInterval   = 10;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void componentAdded(StatisticsContainer component) {\n\t\tServiceEntity item = serviceEntity.findNode(component.getName());\n\n\t\tif (item == null) {\n\t\t\titem = new ServiceEntity(getName(), component.getName(), \"Component: \" + component\n\t\t\t\t\t.getName());\n\t\t\titem.addFeatures(CMD_FEATURES);\n\t\t\titem.addIdentities(new ServiceIdentity(\"automation\", \"command-node\",\n\t\t\t\t\t\"Component: \" + component.getName()));\n\t\t\tserviceEntity.addItems(item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void componentRemoved(StatisticsContainer component) {}\n\n\t@Override\n\tpublic void initializationCompleted() {\n\t\tif (isInitializationComplete()) {\n\n\t\t\t// Do we really need to do this again?\n\t\t\treturn;\n\t\t}\n\t\tsuper.initializationCompleted();\n\t\ttry {\n\t\t\tsp = new StatisticsProvider(this, historySize, updateInterval);\n\n\t\t\tString     objName = STATISTICS_MBEAN_NAME;\n\t\t\tObjectName on      = new ObjectName(objName);\n\n\t\t\tManagementFactory.getPlatformMBeanServer().registerMBean(sp, on);\n\t\t\tConfiguratorAbstract.putMXBean(objName, sp);\n\t\t\t\n\t\t\tesp = new ErrorsStatisticsProvider();\n\t\t\t\n\t\t\tobjName = ERRORS_STATISTICS_MBEAN_NAME;\n\t\t\ton      = new ObjectName(objName);\n\n\t\t\tManagementFactory.getPlatformMBeanServer().registerMBean(esp, on);\n\t\t\tConfiguratorAbstract.putMXBean(objName, esp);\t\t\t\n\t\t} catch (Exception ex) {\n\t\t\tlog.log(Level.SEVERE, \"Can not install Statistics MXBean: \", ex);\n\t\t}\n\t\tTigaseRuntime.getTigaseRuntime().addShutdownHook(this);\n\t\tif (initializationCompletedTask != null) {\n\t\t\tinitializationCompletedTask.run();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(final Packet packet, final Queue<Packet> results) {\n\t\tif (!packet.isCommand() || (packet.getType() == StanzaType.result)) {\n\t\t\treturn;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0} command received: {1}\", new Object[] { packet\n\t\t\t\t\t.getCommand().name(),\n\t\t\t\t\tpacket });\n\t\t}\n\n\t\tIq      iqc            = (Iq) packet;\n\t\tBareJID stanzaFromBare = iqc.getStanzaFrom().getBareJID();\n\t\tJID     stanzaFrom     = JID.jidInstance(stanzaFromBare);\n\n\t\tif (!isAdmin(stanzaFrom)) {\n\t\t\tPacket result = iqc.commandResult(Command.DataType.result);\n\n\t\t\tCommand.addTextField(result, \"Error\",\n\t\t\t\t\t\"You do not have enough permissions to manage this domain\");\n\t\t\tresults.offer(result);\n\n\t\t\treturn;\n\t\t}\n\t\tswitch (iqc.getCommand()) {\n\t\tcase GETSTATS : {\n\n\t\t\t// Element statistics = new Element(\"statistics\");\n\t\t\tElement iq = ElementUtils.createIqQuery(iqc.getStanzaTo(), iqc.getStanzaFrom(),\n\t\t\t\t\tStanzaType.result, iqc.getStanzaId(), STATS_XMLNS);\n\t\t\tElement        query = iq.getChild(\"query\");\n\t\t\tStatisticsList stats = getAllStats();\n\n\t\t\tif (stats != null) {\n\t\t\t\tfor (StatRecord record : stats) {\n\t\t\t\t\tElement item = new Element(\"stat\");\n\n\t\t\t\t\titem.addAttribute(\"name\", record.getComponent() + \"/\" + record\n\t\t\t\t\t\t\t.getDescription());\n\t\t\t\t\titem.addAttribute(\"value\", record.getValue());\n\t\t\t\t\tquery.addChild(item);\n\t\t\t\t}    // end of for ()\n\t\t\t}      // end of if (stats != null && stats.count() > 0)\n\n\t\t\tPacket result = Packet.packetInstance(iq, iqc.getStanzaTo(), iqc.getStanzaFrom());\n\n\t\t\t// Command.setData(result, statistics);\n\t\t\tresults.offer(result);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase OTHER : {\n\t\t\tif (iqc.getStrCommand() == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString nick = iqc.getTo().getLocalpart();\n\n\t\t\tif (!getName().equals(nick)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tCommand.Action action = Command.getAction(iqc);\n\n\t\t\tif (action == Command.Action.cancel) {\n\t\t\t\tPacket result = iqc.commandResult(null);\n\n\t\t\t\tresults.offer(result);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString tmp_val = Command.getFieldValue(iqc, \"Stats level\");\n\n\t\t\t// copying default value of stats level to local variable to not override default value\n\t\t\tLevel statsLevel = this.statsLevel;\n\t\t\tif (tmp_val != null) {\n\t\t\t\tstatsLevel = Level.parse(tmp_val);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"statsLevel parsed to: {0}\", statsLevel.getName());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tStatisticsList list = new StatisticsList(statsLevel);\n\n\t\t\tif (iqc.getStrCommand().equals(\"stats\")) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Getting all stats for level: {0}\", statsLevel.getName());\n\t\t\t\t}\n\t\t\t\tgetAllStats(list);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"All stats for level loaded: {0}\", statsLevel.getName());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tString[] spl = iqc.getStrCommand().split(\"/\");\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Getting stats for component: {0}, level: {1}\",\n\t\t\t\t\t\t\tnew Object[] { spl[1],\n\t\t\t\t\t\t\tstatsLevel.getName() });\n\t\t\t\t}\n\t\t\t\tgetComponentStats(spl[1], list);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Stats loaded for component: {0}, level: {1}\",\n\t\t\t\t\t\t\tnew Object[] { spl[1],\n\t\t\t\t\t\t\tstatsLevel.getName() });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPacket result = iqc.commandResult(Command.DataType.form);\n\n\t\t\tfor (StatRecord rec : list) {\n\t\t\t\tCommand.addFieldValue(result, XMLUtils.escape(rec.getComponent() + \"/\" + rec\n\t\t\t\t\t\t.getDescription()), XMLUtils.escape(rec.getValue()));\n\t\t\t}\n\n\t\t\tCommand.addFieldValue(result, \"Stats level\", statsLevel.getName(), \"Stats level\",\n\t\t\t\t\tnew String[] { Level.INFO.getName(),\n\t\t\t\t\tLevel.FINE.getName(), Level.FINER.getName(), Level.FINEST.getName() },\n\t\t\t\t\t\t\tnew String[] { Level.INFO.getName(),\n\t\t\t\t\tLevel.FINE.getName(), Level.FINER.getName(), Level.FINEST.getName() });\n\t\t\tresults.offer(result);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Returning stats result: {0}\", result);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault :\n\t\t\tbreak;\n\t\t}    // end of switch (packet.getCommand())\n\t}\n\n\t@Override\n\tpublic void release() {\n\t\tsuper.release();\n\t\tsp.stop();\n\t\tstatsArchivTasks.cancel();\n\n\t\tfor (String stat_arch_key : archivizers.keySet()) {\n\t\t\tStatisticsArchivizerIfc stat_arch = archivizers.remove(stat_arch_key);\n\n\t\t\tif (stat_arch != null) {\n\t\t\t\tstat_arch.release();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic String shutdown() {\n\t\tStatisticsList allStats = getAllStats();\n\t\tStringBuilder  sb       = new StringBuilder(4096);\n\n\t\tfor (StatRecord statRecord : allStats) {\n\t\t\tsb.append(statRecord.toString()).append('\\n');\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic StatisticsList getAllStats() {\n\t\tStatisticsList list = new StatisticsList(Level.ALL);\n\n\t\tgetAllStats(list);\n\n\t\treturn list;\n\t}\n\n\tpublic void getAllStats(StatisticsList list) {\n\t\tfor (StatisticsContainer comp : components.values()) {\n\t\t\tgetComponentStats(comp.getName(), list);\n\t\t}\n\n\t\tint  totalQueuesWait     = 0;\n\t\tlong totalQueuesOverflow = 0;\n\n\t\tfor (StatisticsContainer comp : components.values()) {\n\t\t\ttotalQueuesWait     += list.getValue(comp.getName(), \"Total queues wait\", 0);\n\t\t\ttotalQueuesOverflow += list.getValue(comp.getName(), \"Total queues overflow\", 0L);\n\t\t}\n\t\tlist.add(\"total\", \"Total queues wait\", totalQueuesWait, Level.INFO);\n\t\tlist.add(\"total\", \"Total queues overflow\", totalQueuesOverflow, Level.INFO);\n\t}\n\n\tpublic List<String> getComponentsNames() {\n\t\treturn new ArrayList<String>(components.keySet());\n\t}\n\n\tpublic void getComponentStats(String name, StatisticsList list) {\n\t\tStatisticsContainer stats = components.get(name);\n\n\t\tif (stats != null) {\n\t\t\tstats.getStatistics(list);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs             = super.getDefaults(params);\n\t\tString              statsArchivizers = (String) params.get(STATS_ARCHIVIZERS);\n\n\t\tif ((statsArchivizers != null) &&!statsArchivizers.isEmpty()) {\n\t\t\tString[] archivs = statsArchivizers.split(\",\");\n\n\t\t\tdefs.put(STATS_ARCHIVIZERS_PROP_KEY, archivs);\n\t\t}\n\n\t\tint    hSize         = historySize;\n\t\tlong   updateInt     = updateInterval;\n\t\tString stats_history = (String) params.get(STATS_HISTORY);\n\n\t\tif (stats_history != null) {\n\t\t\tString[] st_pars = stats_history.split(\",\");\n\n\t\t\ttry {\n\t\t\t\thSize = Integer.parseInt(st_pars[0]);\n\t\t\t} catch (NumberFormatException ex) {\n\t\t\t\tlog.log(Level.CONFIG, \"Invalid statistics history size settings: {0}\",\n\t\t\t\t\t\tst_pars[0]);\n\t\t\t}\n\t\t\tif (st_pars.length > 1) {\n\t\t\t\ttry {\n\t\t\t\t\tupdateInt = Long.parseLong(st_pars[1]);\n\t\t\t\t} catch (NumberFormatException ex) {\n\t\t\t\t\tlog.log(Level.CONFIG, \"Invalid statistics update interval: {0}\", st_pars[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdefs.put(STATS_HISTORY_SIZE_PROP_KEY, hSize);\n\t\tdefs.put(STATS_UPDATE_INTERVAL_PROP_KEY, updateInt);\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoFeatures(JID from) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getDiscoInfo(String node, JID jid, JID from) {\n\t\tif ((jid != null) && getName().equals(jid.getLocalpart()) && isAdmin(from)) {\n\t\t\treturn serviceEntity.getDiscoInfo(node);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getDiscoItems(String node, JID jid, JID from) {\n\t\tif (isAdmin(from)) {\n\t\t\tif (getName().equals(jid.getLocalpart()) || getComponentId().equals(jid)) {\n\t\t\t\tList<Element> items = serviceEntity.getDiscoItems(node, jid.toString());\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Processing discoItems for node: {0}, result: {1}\",\n\t\t\t\t\t\t\tnew Object[] { node, (items == null)\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: items.toString() });\n\t\t\t\t}\n\n\t\t\t\treturn items;\n\t\t\t} else {\n\t\t\t\tif (node == null) {\n\t\t\t\t\tElement item = serviceEntity.getDiscoItem(null, BareJID.toString(getName(), jid\n\t\t\t\t\t\t\t.toString()));\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Processing discoItems, result: {0}\", ((item == null)\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: item.toString()));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Arrays.asList(item);\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn super.getName();\n\t}\n\n\t@Override\n\tpublic boolean isCorrectType(ServerComponent component) {\n\t\treturn component instanceof StatisticsContainer;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t\tserviceEntity = new ServiceEntity(name, \"stats\", \"Server statistics\");\n\t\tserviceEntity.addIdentities(new ServiceIdentity(\"component\", \"stats\",\n\t\t\t\t\"Server statistics\"), new ServiceIdentity(\"automation\", \"command-node\",\n\t\t\t\t\"All statistics\"), new ServiceIdentity(\"automation\", \"command-list\",\n\t\t\t\t\"Statistics retrieving commands\"));\n\t\tserviceEntity.addFeatures(DEF_FEATURES);\n\t\tserviceEntity.addFeatures(CMD_FEATURES);\n\t}\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> props) throws ConfigurationException {\n\t\tsuper.setProperties(props);\n\n\t\tString[] archivs = (String[]) props.get(STATS_ARCHIVIZERS_PROP_KEY);\n\n\t\tif (archivs != null) {\n\t\t\tinitStatsArchivizers(archivs, props);\n\t\t}\n\t\tif (props.get(STATS_HISTORY_SIZE_PROP_KEY) != null) {\n\t\t\thistorySize = (Integer) props.get(STATS_HISTORY_SIZE_PROP_KEY);\n\t\t}\n\t\tif (props.get(STATS_UPDATE_INTERVAL_PROP_KEY) != null) {\n\t\t\tupdateInterval = (Long) props.get(STATS_UPDATE_INTERVAL_PROP_KEY);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected void statsUpdated() {\n\t\tsynchronized (arch_runner) {\n\t\t\tarch_runner.notifyAll();\n\t\t}\n\t\tesp.update(sp);\n\t}\n\n\tprivate void initStatsArchivizers(final String[] archivs, final Map<String,\n\t\t\tObject> props) {\n\t\tfor (String stat_arch_key : archivizers.keySet()) {\n\t\t\tStatisticsArchivizerIfc stat_arch = archivizers.remove(stat_arch_key);\n\n\t\t\tif (stat_arch != null) {\n\t\t\t\tstat_arch.release();\n\t\t\t}\n\t\t}\n\t\tinitializationCompletedTask = new TimerTask() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tfor (String arch_prop : archivs) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString[]                      arch_prop_a = arch_prop.split(\":\");\n\t\t\t\t\t\tString                        arch_class  = arch_prop_a[0];\n\t\t\t\t\t\tString                        arch_name   = arch_prop_a[1];\n\t\t\t\t\t\tfinal StatisticsArchivizerIfc stat_arch = (StatisticsArchivizerIfc) Class\n\t\t\t\t\t\t\t\t.forName(arch_class).newInstance();\n\n\t\t\t\t\t\tstat_arch.init(getArchivizerConf(arch_name, props));\n\n\t\t\t\t\t\tlong freq = -1;\n\n\t\t\t\t\t\tif (arch_prop_a.length > 2) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tfreq = Long.parseLong(arch_prop_a[2]);\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\tfreq = -1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Some archivizers run in regular intervals of time\n\t\t\t\t\t\t// some others run each time statistics collection has completed.\n\t\t\t\t\t\tif (freq > 0) {\n\t\t\t\t\t\t\tstatsArchivTasks.schedule(new TimerTask() {\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\t\t\tstat_arch.execute(sp);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, freq * 1000, freq * 1000);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tarchivizers.put(arch_name, stat_arch);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlog.log(Level.CONFIG, \"Loaded statistics archivizer: {0} for class: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { arch_name,\n\t\t\t\t\t\t\t\tarch_class });\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"Can't initialize statistics archivizer: \" + arch_prop,\n\t\t\t\t\t\t\t\te);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate Map<String, Object> getArchivizerConf(String name, Map<String, Object> props) {\n\t\tMap<String, Object> result    = new LinkedHashMap<String, Object>(4);\n\t\tString              key_start = STATS_ARCHIVIZERS_PROP_KEY + \"/\" + name + \"/\";\n\n\t\tfor (Map.Entry<String, Object> entry : props.entrySet()) {\n\t\t\tif (entry.getKey().startsWith(key_start)) {\n\t\t\t\tString key = entry.getKey().substring(key_start.length());\n\n\t\t\t\tlog.log(Level.CONFIG, \"Found {0} property: {1} = {2}\", new Object[] { name, key,\n\t\t\t\t\t\tentry.getValue() });\n\t\t\t\tresult.put(key, entry.getValue());\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class ArchivizerRunner\n\t\t\t\t\textends Thread {\n\t\tprivate boolean stopped = false;\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\tprivate ArchivizerRunner() {\n\t\t\tsuper(\"stats-archivizer\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (!stopped) {\n\t\t\t\ttry {\n\t\t\t\t\tsynchronized (this) {\n\t\t\t\t\t\tthis.wait();\n\t\t\t\t\t}\n\t\t\t\t\tfor (Map.Entry<String, StatisticsArchivizerIfc> archiv_entry : archivizers\n\t\t\t\t\t\t\t.entrySet()) {\n\t\t\t\t\t\tarchiv_entry.getValue().execute(sp);\n\t\t\t\t\t}\n\t\t\t\t} catch (InterruptedException ex) {\n\n\t\t\t\t\t// Ignore...\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsContainer.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */package tigase.stats;\n\nimport tigase.server.ServerComponent;\n\npublic interface StatisticsContainer extends StatisticsContainerIfc, ServerComponent {\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsContainerIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.stats;\n\n/**\n * Interface StatisticsContainerIfc\n *\n * Objects which inherits this type can return runtime statistics. Any object\n * can collect job statistics and implementing this interface guarantees that\n * statistics will be presented in configured way to user who wants to see them.\n *\n * Created: Tue Nov 22 07:07:11 2005\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface StatisticsContainerIfc {\n\n  public String getName();\n\n  public void getStatistics(StatisticsList list);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsList.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.QueueType;\nimport tigase.util.DataTypes;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.NoSuchElementException;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jul 10, 2009 3:23:23 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StatisticsList implements Iterable<StatRecord> {\n\tprivate static final Logger log = Logger.getLogger(StatisticsList.class.getName());\n\tprivate Level statLevel = Level.ALL;\n\tprivate final LinkedHashMap<String, LinkedHashMap<String, StatRecord>> stats =\n\t\t\tnew LinkedHashMap<String, LinkedHashMap<String, StatRecord>>();\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\tpublic StatisticsList(Level level) {\n\t\tthis.statLevel = level;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\tpublic boolean add(String comp, String description, long value, Level recordLevel) {\n\t\treturn addEntry(comp, description, recordLevel, new StatRecord(comp, description, value, recordLevel));\n\t}\n\n\tpublic boolean add(String comp, String description, int value, Level recordLevel) {\n\t\treturn addEntry(comp, description, recordLevel, new StatRecord(comp, description, value, recordLevel));\n\t}\n\n\tpublic boolean add(String comp, String description, String value, Level recordLevel) {\n\t\treturn addEntry(comp, description, recordLevel, new StatRecord(comp, description, value, recordLevel));\n\t}\n\n\tpublic boolean add(String comp, String description, float value, Level recordLevel) {\n\t\treturn addEntry(comp, description, recordLevel, new StatRecord(comp, description, value, recordLevel));\n\t}\n\n\tprivate boolean addEntry(String comp, String description, Level recordLevel, StatRecord statRecord) {\n\t\tdescription = description.intern();\n\t\tif (checkLevel(recordLevel)) {\n\t\t\tLinkedHashMap<String, StatRecord> compStats = stats.get(comp);\n\n\t\t\tif (compStats == null) {\n\t\t\t\tcompStats = addCompStats(comp);\n\t\t\t}\n\n\t\t\tcompStats.put(description, statRecord);\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic LinkedHashMap<String, StatRecord> addCompStats(String comp) {\n\t\tLinkedHashMap<String, StatRecord> compStats = new LinkedHashMap<String, StatRecord>();\n\n\t\tstats.put(comp, compStats);\n\n\t\treturn compStats;\n\t}\n\n\tpublic boolean checkLevel(Level recordLevel) {\n\t\treturn recordLevel.intValue() >= statLevel.intValue();\n\t}\n\n\tpublic boolean checkLevel(Level recordLevel, long value) {\n\t\tif (checkLevel(recordLevel)) {\n\t\t\tif (value == 0) {\n\t\t\t\treturn checkLevel(Level.FINEST);\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic boolean checkLevel(Level recordLevel, int value) {\n\t\tif (checkLevel(recordLevel)) {\n\t\t\tif (value == 0) {\n\t\t\t\treturn checkLevel(Level.FINEST);\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\tpublic int getCompConnections(String comp) {\n\t\treturn getValue(comp, \"Open connections\", 0);\n\t}\n\n\tpublic long getCompIq(String comp) {\n\t\treturn getCompIqSent(comp) + getCompIqReceived(comp);\n\t}\n\n\tpublic long getCompIqReceived(String comp) {\n\t\treturn getValue(comp, QueueType.IN_QUEUE.name() + \" processed IQ\", 0L);\n\t}\n\n\tpublic long getCompIqSent(String comp) {\n\t\treturn getValue(comp, QueueType.OUT_QUEUE.name() + \" processed IQ\", 0L);\n\t}\n\n\t/**\n\t * Returns names of every component for which statistics are stored in <code>stats</code> variable\n\t * \n\t * @return \n\t */\n\tpublic Set<String> getCompNames() {\n\t\treturn stats.keySet();\n\t}\n\t\n\tpublic long getCompMsg(String comp) {\n\t\treturn getCompMsgSent(comp) + getCompMsgReceived(comp);\n\t}\n\n\tpublic long getCompMsgReceived(String comp) {\n\t\treturn getValue(comp, QueueType.IN_QUEUE.name() + \" processed messages\", 0L);\n\t}\n\n\tpublic long getCompMsgSent(String comp) {\n\t\treturn getValue(comp, QueueType.OUT_QUEUE.name() + \" processed messages\", 0L);\n\t}\n\n\tpublic long getCompPackets(String comp) {\n\t\treturn getCompSentPackets(comp) + getCompReceivedPackets(comp);\n\t}\n\n\tpublic long getCompPres(String comp) {\n\t\treturn getCompPresSent(comp) + getCompPresReceived(comp);\n\t}\n\n\tpublic long getCompPresReceived(String comp) {\n\t\treturn getValue(comp, QueueType.IN_QUEUE.name() + \" processed presences\", 0L);\n\t}\n\n\tpublic long getCompPresSent(String comp) {\n\t\treturn getValue(comp, QueueType.OUT_QUEUE.name() + \" processed presences\", 0L);\n\t}\n\n\tpublic long getCompReceivedPackets(String comp) {\n\t\treturn getValue(comp, StatisticType.MSG_RECEIVED_OK.getDescription(), 0L);\n\t}\n\n\tpublic long getCompSentPackets(String comp) {\n\t\treturn getValue(comp, StatisticType.MSG_SENT_OK.getDescription(), 0L);\n\t}\n\n\tpublic LinkedHashMap<String, StatRecord> getCompStats(String comp) {\n\t\treturn stats.get(comp);\n\t}\n\n\tpublic long getValue(String comp, String description, long def) {\n\t\tlong result = def;\n\t\tLinkedHashMap<String, StatRecord> compStats = stats.get(comp);\n\n\t\tif (compStats != null) {\n\t\t\tStatRecord rec = compStats.get(description);\n\n\t\t\tif (rec != null) {\n\t\t\t\tresult = rec.getLongValue();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic float getValue(String comp, String description, float def) {\n\t\tfloat result = def;\n\t\tLinkedHashMap<String, StatRecord> compStats = stats.get(comp);\n\n\t\tif (compStats != null) {\n\t\t\tStatRecord rec = compStats.get(description);\n\n\t\t\tif (rec != null) {\n\t\t\t\tresult = rec.getFloatValue();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic int getValue(String comp, String description, int def) {\n\t\tint result = def;\n\t\tLinkedHashMap<String, StatRecord> compStats = stats.get(comp);\n\n\t\tif (compStats != null) {\n\t\t\tStatRecord rec = compStats.get(description);\n\n\t\t\tif (rec != null) {\n\t\t\t\tresult = rec.getIntValue();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic String getValue(String comp, String description, String def) {\n\t\tString result = def;\n\t\tLinkedHashMap<String, StatRecord> compStats = stats.get(comp);\n\n\t\tif (compStats != null) {\n\t\t\tStatRecord rec = compStats.get(description);\n\n\t\t\tif (rec != null) {\n\t\t\t\tresult = rec.getValue();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic Object getValue(String dataId) {\n\t\tchar dataType = DataTypes.decodeTypeIdFromName(dataId);\n\t\tString dataName = DataTypes.stripNameFromTypeId(dataId);\n\t\tint idx = dataName.indexOf('/');\n\t\tString comp = dataName.substring(0, idx);\n\t\tString descr = dataName.substring(idx + 1);\n//\t\tlog.log(Level.FINEST,\n//\t\t\t\t\"Returning metrics for component: {0}, description: {1} and type: {2}\",\n//\t\t\t\tnew Object[] { comp, descr, dataType });\n\t\tswitch (dataType) {\n\t\t\tcase 'L':\n\t\t\t\treturn getValue(comp, descr, 0l);\n\t\t\tcase 'I':\n\t\t\t\treturn getValue(comp, descr, 0);\n\t\t\tcase 'F':\n\t\t\t\treturn getValue(comp, descr, 0f);\n\t\t\tdefault:\n\t\t\t\treturn getValue(comp, descr, \" \");\n\t\t}\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Iterator<StatRecord> iterator() {\n\t\treturn new StatsIterator();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn stats.toString();\n\t}\n\n\t// ~--- inner classes --------------------------------------------------------\n\n\tprivate class StatsIterator implements Iterator<StatRecord> {\n\t\tIterator<LinkedHashMap<String, StatRecord>> compsIt = stats.values().iterator();\n\t\tIterator<StatRecord> recIt = null;\n\n\t\t// ~--- get methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic boolean hasNext() {\n\t\t\tif ((recIt == null) || !recIt.hasNext()) {\n\t\t\t\tif (compsIt.hasNext()) {\n\t\t\t\t\trecIt = compsIt.next().values().iterator();\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn recIt.hasNext();\n\t\t}\n\n\t\t// ~--- methods ------------------------------------------------------------\n\n\t\t@Override\n\t\tpublic StatRecord next() throws NoSuchElementException {\n\t\t\tif ((recIt == null) || !recIt.hasNext()) {\n\t\t\t\tif (compsIt.hasNext()) {\n\t\t\t\t\trecIt = compsIt.next().values().iterator();\n\t\t\t\t} else {\n\t\t\t\t\tthrow new NoSuchElementException(\"No more statistics.\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn recIt.next();\n\t\t}\n\n\t\t@Override\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsProvider.java",
    "content": "/*\n * StatisticsProvider.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.sys.TigaseRuntime;\n\nimport tigase.util.AllHistoryCache;\nimport tigase.util.FloatHistoryCache;\nimport tigase.util.IntHistoryCache;\nimport tigase.util.LongHistoryCache;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport javax.management.MBeanAttributeInfo;\nimport javax.management.MBeanInfo;\nimport javax.management.MBeanNotificationInfo;\nimport javax.management.MBeanOperationInfo;\nimport javax.management.MBeanParameterInfo;\nimport javax.management.NotCompliantMBeanException;\nimport javax.management.StandardMBean;\n\n/**\n * Class StatisticsProvider\n *\n * @author kobit\n */\npublic class StatisticsProvider\n\t\t\t\textends StandardMBean\n\t\t\t\timplements StatisticsProviderMBean {\n\tprivate static final Logger log = Logger.getLogger(StatisticsProvider.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\tprivate StatisticsCache     cache = null;\n\tprivate StatisticsCollector theRef;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\tpublic StatisticsProvider(StatisticsCollector theRef, int historySize,\n\t\t\tlong updateInterval)\n\t\t\t\t\tthrows NotCompliantMBeanException {\n\n\t\t// WARNING Uncomment the following call to super() to make this class\n\t\t// compile (see BUG ID 122377)\n\t\tsuper(StatisticsProviderMBean.class, false);\n\t\tthis.theRef = theRef;\n\t\tcache       = new StatisticsCache(historySize, updateInterval);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic void stop() {\n\t\tif (cache != null) {\n\t\t\tcache.stop();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\n\t@Override\n\tpublic Map<String, String> getAllStats(int level) {\n//\t\tif (log.isLoggable(Level.FINEST)) {\n//\t\t\tlog.log(Level.FINEST, \"Get all stats called for level: {0}\", level);\n//\t\t}\n\n\n\t\tStatisticsList list = new StatisticsList(Level.parse(\"\" + level));\n\n\t\ttheRef.getAllStats(list);\n\n\t\treturn getMapFromList(list);\n\t}\n\n\t@Override\n\tpublic int getCLIOQueueSize() {\n\t\treturn cache.clIOQueue;\n\t}\n\n\t@Override\n\tpublic float[] getCLPacketsPerSecHistory() {\n\t\treturn (cache.clpacks_history != null)\n\t\t\t\t? cache.clpacks_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\t@Override\n\tpublic int getCLQueueSize() {\n\t\treturn cache.clQueue;\n\t}\n\n\t@Override\n\tpublic int getClusterCacheSize() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.clusterCache;\n\t}\n\n\t@Override\n\tpublic float getClusterCompressionRatio() {\n\t\treturn cache.clusterCompressionRatio;\n\t}\n\n\t@Override\n\tpublic long getClusterNetworkBytes() {\n\t\treturn cache.clusterNetworkBytes;\n\t}\n\n\t@Override\n\tpublic float getClusterNetworkBytesPerSecond() {\n\t\treturn cache.clusterNetworkBytesPerSecond;\n\t}\n\n\t@Override\n\tpublic long getClusterPackets() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.clusterPackets;\n\t}\n\n\t@Override\n\tpublic float getClusterPacketsPerSec() {\n\t\treturn cache.clusterPacketsPerSec;\n\t}\n\n\tpublic int getCompConnections(String comp) {\n\t\treturn cache.allStats.getCompConnections(comp);\n\t}\n\n\tpublic long getCompIqs(String comp) {\n\t\treturn cache.allStats.getCompIq(comp);\n\t}\n\n\tpublic long getCompMessages(String comp) {\n\t\treturn cache.allStats.getCompMsg(comp);\n\t}\n\n\t@Override\n\tpublic List<String> getComponentsNames() {\n\t\treturn theRef.getComponentsNames();\n\t}\n\n\t@Override\n\tpublic Map<String, String> getComponentStats(String compName, int level) {\n\t\tStatisticsList list = new StatisticsList(Level.parse(\"\" + level));\n\n\t\ttheRef.getComponentStats(compName, list);\n\n\t\treturn getMapFromList(list);\n\t}\n\n\tpublic long getCompPackets(String comp) {\n\t\treturn cache.allStats.getCompPackets(comp);\n\t}\n\n\tpublic long getCompPresences(String comp) {\n\t\treturn cache.allStats.getCompPres(comp);\n\t}\n\n\t@Override\n\tpublic int getConnectionsNumber() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.clientConnections;\n\t}\n\n\t@Override\n\tpublic int[] getConnectionsNumberHistory() {\n\t\treturn (cache.conns_history != null)\n\t\t\t\t? cache.conns_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\t@Override\n\tpublic int getCPUsNumber() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getCPUsNumber();\n\t}\n\n\t@Override\n\tpublic float getCPUUsage() {\n\t\treturn cache.cpuUsage;\n\t}\n\n\t@Override\n\tpublic float[] getCPUUsageHistory() {\n\t\treturn (cache.cpu_usage_history != null)\n\t\t\t\t? cache.cpu_usage_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\tpublic Map<String, Object> getCurStats(String[] statsKeys) {\n\t\tMap<String, Object> result = new LinkedHashMap<String, Object>();\n\n\t\tfor (String key : statsKeys) {\n\t\t\tresult.put(key, cache.allStats.getValue(key));\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic long getDirectMemUsed() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getDirectMemUsed();\n\t}\n\n\t@Override\n\tpublic long[] getDirectMemUsedHistory() {\n\t\treturn (cache.direct_used_history != null)\n\t\t\t\t? cache.direct_used_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\t\n\t@Override\n\tpublic float getHeapMemUsage() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getHeapMemUsage();\n\t}\n\n\t@Override\n\tpublic float[] getHeapUsageHistory() {\n\t\treturn (cache.heap_usage_history != null)\n\t\t\t\t? cache.heap_usage_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\t@Override\n\tpublic long getIQAuthNumber() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.iqAuthNumber;\n\t}\n\n\t@Override\n\tpublic long getIQOtherNumber() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.iqOtherNumber;\n\t}\n\n\t@Override\n\tpublic float getIQOtherNumberPerSec() {\n\t\treturn cache.iqOtherNumberPerSec;\n\t}\n\n\t@Override\n\tpublic MBeanInfo getMBeanInfo() {\n\t\tMBeanInfo mbinfo = super.getMBeanInfo();\n\n\t\treturn new MBeanInfo(mbinfo.getClassName(), mbinfo.getDescription(), mbinfo\n\t\t\t\t.getAttributes(), mbinfo.getConstructors(), mbinfo.getOperations(),\n\t\t\t\tgetNotificationInfo());\n\t}\n\n\t@Override\n\tpublic long getMessagesNumber() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.messagesNumber;\n\t}\n\n\t@Override\n\tpublic float getMessagesNumberPerSec() {\n\t\treturn cache.messagesPerSec;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn theRef.getName();\n\t}\n\n\t@Override\n\tpublic float getNonHeapMemUsage() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getNonHeapMemUsage();\n\t}\n\n\tpublic MBeanNotificationInfo[] getNotificationInfo() {\n\t\treturn new MBeanNotificationInfo[] {};\n\t}\n\n\t@Override\n\tpublic long getPresencesNumber() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.presencesNumber;\n\t}\n\n\t@Override\n\tpublic float getPresencesNumberPerSec() {\n\t\treturn cache.presencesPerSec;\n\t}\n\n\t@Override\n\tpublic long getProcesCPUTime() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getProcessCPUTime();\n\t}\n\n\t@Override\n\tpublic long getQueueOverflow() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.queueOverflow;\n\t}\n\n\t@Override\n\tpublic int getQueueSize() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.queueSize;\n\t}\n\n\tpublic long getRegistered() {\n\t\treturn cache.registered;\n\t}\n\n\t@Override\n\tpublic int getServerConnections() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.serverConnections;\n\t}\n\n\t@Override\n\tpublic int[] getServerConnectionsHistory() {\n\t\treturn (cache.server_conns_history != null)\n\t\t\t\t? cache.server_conns_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\t@Override\n\tpublic long getSMPacketsNumber() {\n\t\treturn cache.smPackets;\n\t}\n\n\t@Override\n\tpublic float getSMPacketsNumberPerSec() {\n\t\treturn cache.smPacketsPerSec;\n\t}\n\n\t@Override\n\tpublic float[] getSMPacketsPerSecHistory() {\n\t\treturn (cache.smpacks_history != null)\n\t\t\t\t? cache.smpacks_history.getCurrentHistory()\n\t\t\t\t: null;\n\t}\n\n\t@Override\n\tpublic int getSMQueueSize() {\n\t\treturn cache.smQueue;\n\t}\n\n\tpublic long getStats(String cmp_name, String stat, long def) {\n\t\treturn cache.allStats.getValue(cmp_name, stat, def);\n\t}\n\n\tpublic float getStats(String cmp_name, String stat, float def) {\n\t\treturn cache.allStats.getValue(cmp_name, stat, def);\n\t}\n\n\tpublic String getStats(String cmp_name, String stat, String def) {\n\t\treturn cache.allStats.getValue(cmp_name, stat, def);\n\t}\n\n\tpublic int getStats(String cmp_name, String stat, int def) {\n\t\treturn cache.allStats.getValue(cmp_name, stat, def);\n\t}\n\n\tpublic Map<String, LinkedList<Object>> getStatsHistory(String[] statsKeys) {\n\t\tlog.log(Level.INFO, \"Generating history for metrics: {0}\", Arrays.toString(\n\t\t\t\tstatsKeys));\n\n\t\tMap<String, LinkedList<Object>> result = null;\n\n\t\tif (cache.allHistory != null) {\n\t\t\tresult = new LinkedHashMap<String, LinkedList<Object>>();\n\t\t\tfor (StatisticsList stHist : cache.allHistory.getCurrentHistory()) {\n\t\t\t\tfor (String key : statsKeys) {\n\t\t\t\t\tLinkedList<Object> statsForKey = result.get(key);\n\n\t\t\t\t\tif (statsForKey == null) {\n\t\t\t\t\t\tstatsForKey = new LinkedList<Object>();\n\t\t\t\t\t\tresult.put(key, statsForKey);\n\t\t\t\t\t}\n\t\t\t\t\tstatsForKey.add(stHist.getValue(key));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log(Level.INFO, \"The server does not keep metrics history.\");\n\t\t}\n\n\t\t// log.log(Level.INFO, \"History generated: {0}\", result);\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic String getSystemDetails() {\n\n\t\t// cache.updateIfOlder(1000);\n\t\treturn cache.systemDetails;\n\t}\n\n\t@Override\n\tpublic long getUptime() {\n\t\treturn TigaseRuntime.getTigaseRuntime().getUptime();\n\t}\n\n\t@Override\n\tprotected String getDescription(MBeanInfo info) {\n\t\treturn \"Provides the Tigase server statistics\";\n\t}\n\n\t@Override\n\tprotected String getDescription(MBeanAttributeInfo info) {\n\t\tString description = null;\n\n\t\tif (info.getName().equals(\"AllStats\")) {\n\t\t\tdescription = \"Collection of statistics from all components.\";\n\t\t} else {\n\t\t\tif (info.getName().equals(\"ComponentsNames\")) {\n\t\t\t\tdescription = \"List of components names for which statistics are available\";\n\t\t\t} else {\n\t\t\t\tif (info.getName().equals(\"Name\")) {\n\t\t\t\t\tdescription =\n\t\t\t\t\t\t\t\"This is a component name - name of the statistics collector component,\";\n\t\t\t\t} else {\n\t\t\t\t\tif (info.getName().equals(\"getUptime\")) {\n\t\t\t\t\t\tdescription = \"Returns JVM uptime.\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (info.getName().equals(\"getProcesCPUTime\")) {\n\t\t\t\t\t\t\tdescription = \"Returns JMV process CPU time.\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn description;\n\t}\n\n\t@Override\n\tprotected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param,\n\t\t\tint sequence) {\n\t\tif (op.getName().equals(\"getAllStats\")) {\n\t\t\tswitch (sequence) {\n\t\t\tcase 0 :\n\t\t\t\treturn \"Statistics level, 0 - All, 500 - Medium, 800 - Minimal\";\n\n\t\t\tdefault :\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\tif (op.getName().equals(\"getComponentStats\")) {\n\t\t\t\tswitch (sequence) {\n\t\t\t\tcase 0 :\n\t\t\t\t\treturn \"The component name to provide statistics for\";\n\n\t\t\t\tcase 1 :\n\t\t\t\t\treturn \"Statistics level, 0 - All, 500 - Medium, 800 - Minimal\";\n\n\t\t\t\tdefault :\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected String getDescription(MBeanOperationInfo info) {\n\t\tString               description = null;\n\t\tMBeanParameterInfo[] params      = info.getSignature();\n\t\tString[]             signature   = new String[params.length];\n\n\t\tfor (int i = 0; i < params.length; i++) {\n\t\t\tsignature[i] = params[i].getType();\n\t\t}\n\n\t\tString[] methodSignature;\n\n\t\tmethodSignature = new String[] { java.lang.Integer.TYPE.getName() };\n\t\tif (info.getName().equals(\"getAllStats\") && Arrays.equals(signature,\n\t\t\t\tmethodSignature)) {\n\t\t\tdescription = \"Provides statistics for all components for a given level.\";\n\t\t}\n\t\tmethodSignature = new String[] { java.lang.String.class.getName(),\n\t\t\t\tjava.lang.Integer.TYPE.getName() };\n\t\tif (info.getName().equals(\"getComponentStats\") && Arrays.equals(signature,\n\t\t\t\tmethodSignature)) {\n\t\t\tdescription =\n\t\t\t\t\t\"Provides statistics for a given component name and statistics level.\";\n\t\t}\n\n\t\treturn description;\n\t}\n\n\t@Override\n\tprotected String getParameterName(MBeanOperationInfo op, MBeanParameterInfo param,\n\t\t\tint sequence) {\n\t\tif (op.getName().equals(\"getAllStats\")) {\n\t\t\tswitch (sequence) {\n\t\t\tcase 0 :\n\t\t\t\treturn \"level\";\n\n\t\t\tdefault :\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\tif (op.getName().equals(\"getComponentStats\")) {\n\t\t\t\tswitch (sequence) {\n\t\t\t\tcase 0 :\n\t\t\t\t\treturn \"compName\";\n\n\t\t\t\tcase 1 :\n\t\t\t\t\treturn \"level\";\n\n\t\t\t\tdefault :\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprotected Set<String> getCompNames() {\n\t\treturn cache.allStats.getCompNames();\n\t}\n\t\n\tprivate Map<String, String> getMapFromList(StatisticsList list) {\n\t\tif (list != null) {\n\t\t\tMap<String, String> result = new LinkedHashMap<String, String>(300);\n\n\t\t\tfor (StatRecord rec : list) {\n\t\t\t\tString key   = rec.getComponent() + \"/\" + rec.getDescription();\n\t\t\t\tString value = rec.getValue();\n\n\t\t\t\tresult.put(key, value);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\t// ~--- inner classes --------------------------------------------------------\n\tprivate class StatisticsCache {\n\t\tprivate static final String WS2S_COMP = \"ws2s\";\n\t\tprivate static final String BOSH_COMP = \"bosh\";\n\t\tprivate static final String C2S_COMP  = \"c2s\";\n\t\tprivate static final String CL_COMP   = \"cl-comp\";\n\n\t\t// private static final int HISTORY_SIZE = 8640;\n\t\tprivate static final int    HISTORY_SIZE = 30;\n\t\tprivate static final String S2S_COMP     = \"s2s\";\n\t\tprivate static final long   SECOND       = 1000;\n\t\tprivate static final String SM_COMP      = \"sess-man\";\n\t\tprivate static final long   MINUTE       = 60 * SECOND;\n\t\tprivate static final long   HOUR         = 60 * MINUTE;\n\n\t\t//~--- fields -------------------------------------------------------------\n\n\t\tprivate AllHistoryCache allHistory        = null;\n\t\tprivate int             clientConnections = 0;\n\n\t\t// ~--- fields -------------------------------------------------------------\n\t\tprivate int               clIOQueue                        = 0;\n\t\tprivate FloatHistoryCache clpacks_history                  = null;\n\t\tprivate int               clQueue                          = 0;\n\t\tprivate int               clusterCache                     = 0;\n\t\tprivate float             clusterCompressionRatio          = 0f;\n\t\tprivate long              clusterNetworkBytes              = 0L;\n\t\tprivate float             clusterNetworkBytesPerSecond     = 0L;\n\t\tprivate long              clusterNetworkBytesReceived      = 0L;\n\t\tprivate long              clusterNetworkBytesSent          = 0L;\n\t\tprivate long              clusterPackets                   = 0L;\n\t\tprivate float             clusterPacketsPerSec             = 0;\n\t\tprivate long              clusterPacketsReceived           = 0L;\n\t\tprivate long              clusterPacketsSent               = 0L;\n\t\tprivate int               cnt                              = 0;\n\t\tprivate IntHistoryCache   conns_history                    = null;\n\t\tprivate FloatHistoryCache cpu_usage_history                = null;\n\t\tprivate float             cpuUsage                         = 0f;\n\t\tprivate LongHistoryCache  direct_used_history              = null;\n\t\tprivate FloatHistoryCache heap_usage_history               = null;\n\t\tprivate int               inter                            = 10;\n\t\tprivate long              iqAuthNumber                     = 0;\n\t\tprivate long              iqOtherNumber                    = 0;\n\t\tprivate float             iqOtherNumberPerSec              = 0;\n\t\tprivate String            largeQueues                      = \"\";\n\t\tprivate long              lastPresencesReceived            = 0;\n\t\tprivate long              lastPresencesSent                = 0;\n\t\tprivate long              messagesNumber                   = 0;\n\t\tprivate float             messagesPerSec                   = 0;\n\t\tprivate long              presences_received_per_update    = 0;\n\t\tprivate long              presences_sent_per_update        = 0;\n\t\tprivate long              presencesNumber                  = 0;\n\t\tprivate float             presencesPerSec                  = 0;\n\t\tprivate long              prevClusterNetworkBytes          = 0L;\n\t\tprivate float             prevClusterNetworkBytesPerSecond = 0L;\n\t\tprivate long              prevClusterPackets               = 0L;\n\t\tprivate float             prevClusterPacketsPerSec         = 0;\n\t\tprivate float             prevCpuUsage                     = 0f;\n\t\tprivate float             prevIqOtherNumberPerSec          = 0;\n\t\tprivate long              prevMessagesNumber               = 0;\n\t\tprivate float             prevMessagesPerSec               = 0;\n\t\tprivate long              prevPresencesNumber              = 0;\n\t\tprivate float             prevPresencesPerSec              = 0;\n\t\tprivate long              prevSmPackets                    = 0;\n\t\tprivate float             prevSmPacketsPerSec              = 0;\n\t\tprivate long              queueOverflow                    = 0;\n\t\tprivate int               queueSize                        = 0;\n\t\tprivate long              registered                       = 0;\n\t\tprivate int               runs_counter                     = 100;\n\t\tprivate IntHistoryCache   server_conns_history             = null;\n\t\tprivate int               serverConnections                = 0;\n\t\tprivate long              smPackets                        = 0;\n\t\tprivate float             smPacketsPerSec                  = 0;\n\t\tprivate FloatHistoryCache smpacks_history                  = null;\n\t\tprivate int               smQueue                          = 0;\n\t\tprivate String            systemDetails                    = \"\";\n\t\tprivate Timer             updateTimer                      = null;\n\n\t\t// private long lastUpdate = 0;\n\t\tprivate StatisticsList allStats = new StatisticsList(Level.FINER);\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\t// ~--- constructors -------------------------------------------------------\n\t\tprivate StatisticsCache(int historySize, long cacheUpdate) {\n\t\t\tif (historySize > 0) {\n\t\t\t\tsmpacks_history      = new FloatHistoryCache(historySize);\n\t\t\t\tserver_conns_history = new IntHistoryCache(historySize);\n\t\t\t\theap_usage_history   = new FloatHistoryCache(historySize);\n\t\t\t\tcpu_usage_history    = new FloatHistoryCache(historySize);\n\t\t\t\tconns_history        = new IntHistoryCache(historySize);\n\t\t\t\tclpacks_history      = new FloatHistoryCache(historySize);\n\t\t\t\tdirect_used_history  = new LongHistoryCache(historySize);\n\t\t\t\tallHistory           = new AllHistoryCache(historySize);\n\t\t\t}\n\t\t\tupdateTimer = new Timer(\"stats-cache\", true);\n\t\t\tupdateTimer.scheduleAtFixedRate(new TimerTask() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdate();\n\t\t\t\t\t\tupdateSystemDetails();\n\t\t\t\t\t\ttheRef.statsUpdated();\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem retrieving statistics: \", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 10 * 1000, cacheUpdate * 1000);\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\n\t\tpublic void stop() {\n\t\t\tupdateTimer.cancel();\n\t\t}\n\n\t\tprivate void update() {\n//\t\t\tif (log.isLoggable(Level.FINEST)) {\n//\t\t\t\tlog.log(Level.FINEST, \"Update started\");\n//\t\t\t}\n\n\t\t\tfloat temp = cpuUsage;\n\n\t\t\tcpuUsage = (prevCpuUsage + (temp * 2) + TigaseRuntime.getTigaseRuntime()\n\t\t\t\t\t.getCPUUsage()) / 4;\n\t\t\tif (cpu_usage_history != null) {\n\t\t\t\tcpu_usage_history.addItem(cpuUsage);\n\t\t\t}\n\t\t\tprevCpuUsage = temp;\n\t\t\tif (heap_usage_history != null) {\n\t\t\t\theap_usage_history.addItem(getHeapMemUsage());\n\t\t\t}\n\t\t\tif (direct_used_history != null) {\n\t\t\t\tdirect_used_history.addItem(getDirectMemUsed());\n\t\t\t}\n\t\t\tif (++runs_counter >= 100) {\n\t\t\t\tallStats     = new StatisticsList(Level.FINEST);\n\t\t\t\truns_counter = 0;\n\t\t\t} else {\n\t\t\t\tallStats = new StatisticsList(Level.FINER);\n\t\t\t}\n\t\t\ttheRef.getAllStats(allStats);\n\t\t\tif (allHistory != null) {\n\t\t\t\tallHistory.addItem(allStats);\n\t\t\t}\n\n\t\t\tlong tmp_reg = allStats.getValue(SM_COMP, \"Registered accounts\", -1L);\n\n\t\t\tif (tmp_reg > 0) {\n\t\t\t\tregistered = tmp_reg;\n\t\t\t}\n\n\t\t\t// System.out.println(allStats.toString());\n\t\t\tclusterCompressionRatio = (allStats.getValue(CL_COMP, \"Average compression ratio\",\n\t\t\t\t\t-1f) + allStats.getValue(CL_COMP, \"Average decompression ratio\", -1f)) / 2f;\n\t\t\tclusterPacketsReceived = allStats.getCompReceivedPackets(CL_COMP);\n\t\t\tclusterPacketsSent     = allStats.getCompSentPackets(CL_COMP);\n\t\t\tclusterPackets         = clusterPacketsSent + clusterPacketsReceived;\n\t\t\ttemp                   = clusterPacketsPerSec;\n\t\t\tclusterPacketsPerSec = (prevClusterPacketsPerSec + (temp * 2f) + (clusterPackets -\n\t\t\t\t\tprevClusterPackets)) / 4f;\n\t\t\tif (clpacks_history != null) {\n\t\t\t\tclpacks_history.addItem(clusterPacketsPerSec);\n\t\t\t}\n\t\t\tprevClusterPacketsPerSec = temp;\n\t\t\tprevClusterPackets       = clusterPackets;\n\t\t\tsmPackets                = allStats.getCompPackets(SM_COMP);\n\t\t\ttemp                     = smPacketsPerSec;\n\t\t\tsmPacketsPerSec = (prevSmPacketsPerSec + (temp * 2f) + (smPackets -\n\t\t\t\t\tprevSmPackets)) / 4f;\n\t\t\tif (smpacks_history != null) {\n\t\t\t\tsmpacks_history.addItem(smPacketsPerSec);\n\t\t\t}\n\t\t\tprevSmPacketsPerSec = temp;\n\t\t\tprevSmPackets       = smPackets;\n\t\t\tclientConnections = allStats.getCompConnections(C2S_COMP)\n\t\t\t\t\t\t\t\t\t\t\t\t\t+ allStats.getCompConnections( BOSH_COMP )\n\t\t\t\t\t\t\t\t\t\t\t\t\t+ allStats.getCompConnections( WS2S_COMP );\n\t\t\tif (conns_history != null) {\n\t\t\t\tconns_history.addItem(clientConnections);\n\t\t\t}\n\t\t\tserverConnections = allStats.getCompConnections(S2S_COMP);\n\t\t\tif (server_conns_history != null) {\n\t\t\t\tserver_conns_history.addItem(serverConnections);\n\t\t\t}\n\t\t\tclIOQueue      = allStats.getValue(CL_COMP, \"Waiting to send\", 0);\n\t\t\tclusterCache   = allStats.getValue(\"cl-caching-strat\", \"Cached JIDs\", 0);\n\t\t\tmessagesNumber = allStats.getCompMsg(SM_COMP);\n\t\t\ttemp           = messagesPerSec;\n\t\t\tmessagesPerSec = (prevMessagesPerSec + (temp * 2f) + (messagesNumber -\n\t\t\t\t\tprevMessagesNumber)) / 4f;\n\t\t\tprevMessagesPerSec          = temp;\n\t\t\tprevMessagesNumber          = messagesNumber;\n\t\t\tclusterNetworkBytesSent     = allStats.getValue(CL_COMP, \"Bytes sent\", 0L);\n\t\t\tclusterNetworkBytesReceived = allStats.getValue(CL_COMP, \"Bytes received\", 0L);\n\t\t\tclusterNetworkBytes         = clusterNetworkBytesSent + clusterNetworkBytesReceived;\n\t\t\ttemp                        = clusterNetworkBytesPerSecond;\n\t\t\tclusterNetworkBytesPerSecond = (prevClusterNetworkBytesPerSecond + (temp * 2f) +\n\t\t\t\t\t(clusterNetworkBytes - prevClusterNetworkBytes)) / 4f;\n\t\t\tprevClusterNetworkBytesPerSecond = temp;\n\t\t\tprevClusterNetworkBytes          = clusterNetworkBytes;\n\n\t\t\tlong currPresencesReceived = allStats.getCompPresReceived(SM_COMP);\n\t\t\tlong currPresencesSent     = allStats.getCompPresSent(SM_COMP);\n\n\t\t\tpresencesNumber = currPresencesReceived + currPresencesSent;\n\t\t\ttemp            = presencesPerSec;\n\t\t\tpresencesPerSec = (prevPresencesPerSec + (temp * 2f) + (presencesNumber -\n\t\t\t\t\tprevPresencesNumber)) / 4f;\n\t\t\tprevPresencesPerSec = temp;\n\t\t\tprevPresencesNumber = presencesNumber;\n\t\t\tif (++cnt >= inter) {\n\t\t\t\tpresences_sent_per_update = (currPresencesSent - lastPresencesSent) / 10;\n\t\t\t\tpresences_received_per_update = (currPresencesReceived - lastPresencesReceived) /\n\t\t\t\t\t\t10;\n\t\t\t\tlastPresencesSent     = currPresencesSent;\n\t\t\t\tlastPresencesReceived = currPresencesReceived;\n\t\t\t\tcnt                   = 0;\n\t\t\t}\n\t\t\tqueueSize     = 0;\n\t\t\tqueueOverflow = 0;\n\t\t\tsmQueue       = 0;\n\t\t\tclQueue       = 0;\n\t\t\tlargeQueues   = \"\";\n\t\t\tfor (StatRecord rec : allStats) {\n\t\t\t\tif ((rec.getDescription() == StatisticType.IN_QUEUE_OVERFLOW.getDescription()) ||\n\t\t\t\t\t\t(rec.getDescription() == StatisticType.OUT_QUEUE_OVERFLOW.getDescription())) {\n\t\t\t\t\tqueueOverflow += rec.getLongValue();\n\t\t\t\t}\n\t\t\t\tif ((rec.getDescription() == \"Total In queues wait\") || (rec.getDescription() ==\n\t\t\t\t\t\t\"Total Out queues wait\")) {\n\t\t\t\t\tqueueSize += rec.getIntValue();\n\t\t\t\t\tif (rec.getComponent().equals(SM_COMP)) {\n\t\t\t\t\t\tsmQueue += rec.getIntValue();\n\t\t\t\t\t}\n\t\t\t\t\tif (rec.getComponent().equals(CL_COMP)) {\n\t\t\t\t\t\tclQueue += rec.getIntValue();\n\t\t\t\t\t}\n\t\t\t\t\tif (rec.getIntValue() > 10000) {\n\t\t\t\t\t\tlargeQueues += rec.getComponent() + \" - queue size: \" + rec.getIntValue() +\n\t\t\t\t\t\t\t\t\"\\n\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// System.out.println(\"clusterPackets: \" + clusterPackets +\n\t\t\t// \", smPackets: \" + smPackets +\n\t\t\t// \", clientConnections: \" + clientConnections);\n//\t\t\tif (log.isLoggable(Level.FINEST)) {\n//\t\t\t\tlog.log(Level.FINEST, \"Update finished\");\n//\t\t\t}\n\t\t}\n\n\t\tprivate void updateSystemDetails() {\n\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\tsb.append(\"Uptime: \").append(TigaseRuntime.getTigaseRuntime().getUptimeString());\n\n\t\t\tint cpu_temp = allStats.getValue(\"cpu-mon\", \"CPU temp\", 0);\n\n\t\t\tif (cpu_temp > 0) {\n\t\t\t\tsb.append(\",      Temp: \").append(cpu_temp).append(\" C\");\n\t\t\t}\n\n\t\t\tString cpu_freq = allStats.getValue(\"cpu-mon\", \"CPU freq\", null);\n\n\t\t\tif (cpu_freq != null) {\n\t\t\t\tsb.append(\"\\nFreq: \").append(cpu_freq);\n\t\t\t}\n\n\t\t\tString cpu_throt = allStats.getValue(\"cpu-mon\", \"CPU throt\", null);\n\n\t\t\tif (cpu_throt != null) {\n\t\t\t\tsb.append(\"\\nThrott: \").append(cpu_throt);\n\t\t\t}\n\t\t\tsb.append(\"\\nTop threads:\");\n\n\t\t\tString cpu_thread = allStats.getValue(\"cpu-mon\", \"1st max CPU thread\", null);\n\n\t\t\tif (cpu_thread != null) {\n\t\t\t\tsb.append(\"\\n   \").append(cpu_thread);\n\t\t\t}\n\t\t\tcpu_thread = allStats.getValue(\"cpu-mon\", \"2nd max CPU thread\", null);\n\t\t\tif (cpu_thread != null) {\n\t\t\t\tsb.append(\"\\n   \").append(cpu_thread);\n\t\t\t}\n\t\t\tcpu_thread = allStats.getValue(\"cpu-mon\", \"3rd max CPU thread\", null);\n\t\t\tif (cpu_thread != null) {\n\t\t\t\tsb.append(\"\\n   \").append(cpu_thread);\n\t\t\t}\n\t\t\tcpu_thread = allStats.getValue(\"cpu-mon\", \"4th max CPU thread\", null);\n\t\t\tif (cpu_thread != null) {\n\t\t\t\tsb.append(\"\\n   \").append(cpu_thread);\n\t\t\t}\n\t\t\tcpu_thread = allStats.getValue(\"cpu-mon\", \"5th max CPU thread\", null);\n\t\t\tif (cpu_thread != null) {\n\t\t\t\tsb.append(\"\\n   \").append(cpu_thread);\n\t\t\t}\n\n\t\t\tLinkedHashMap<String, StatRecord> compStats = allStats.getCompStats(SM_COMP);\n\n\t\t\tif (compStats != null) {\n\t\t\t\tfor (StatRecord rec : compStats.values()) {\n\t\t\t\t\tif (rec.getDescription().startsWith(\"Processor:\")) {\n\t\t\t\t\t\tsb.append(\"\\n\").append(rec.getDescription()).append(rec.getValue());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.append(\"\\nSM presences rec Tot: \").append(lastPresencesReceived);\n\t\t\tsb.append(\" / \").append(presences_received_per_update).append(\" last sec\");\n\t\t\tsb.append(\"\\nSM presences sent Tot: \").append(lastPresencesSent);\n\t\t\tsb.append(\" / \").append(presences_sent_per_update).append(\" last sec\");\n\t\t\tsb.append(\"\\nCluster bytes/sec: \").append(clusterNetworkBytesPerSecond);\n\t\t\tsb.append(\", compress: \").append(clusterCompressionRatio);\n\t\t\tsb.append(\"\\nCluster bytes: [S] \").append(clusterNetworkBytesSent);\n\t\t\tsb.append(\" / [R] \").append(clusterNetworkBytesReceived);\n\t\t\tsb.append(\"\\nCluster packets: [S] \").append(clusterPacketsSent);\n\t\t\tsb.append(\" / [R] \").append(clusterPacketsReceived);\n\t\t\tif (!largeQueues.isEmpty()) {\n\t\t\t\tsb.append(\"\\n\").append(largeQueues);\n\t\t\t}\n\t\t\tsystemDetails = sb.toString();\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsProviderIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.stats;\n\n/**\n * Created by andrzej on 28.04.2016.\n */\npublic interface StatisticsProviderIfc {\n\n\tvoid getStatistics(String compName, StatisticsList list);\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/stats/StatisticsProviderMBean.java",
    "content": "/*\n * StatisticsProviderMBean.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.stats;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Interface StatisticsProviderMBean\n *\n * @author kobit\n */\npublic interface StatisticsProviderMBean {\n\t/**\n\t * Operation exposed for management\n\t * @param level Statistics level, 0 - All, 500 - Medium, 800 - Minimal\n\t * @return {@code java.util.Map<String, String>}\n\t */\n\tpublic Map<String, String> getAllStats(int level);\n\n\tpublic int getCLIOQueueSize();\n\n\tpublic float[] getCLPacketsPerSecHistory();\n\n\tpublic int getCLQueueSize();\n\n\tpublic int getClusterCacheSize();\n\n\tpublic float getClusterCompressionRatio();\n\n\tpublic long getClusterNetworkBytes();\n\n\tpublic float getClusterNetworkBytesPerSecond();\n\n\tpublic long getClusterPackets();\n\n\tpublic float getClusterPacketsPerSec();\n\n\n\t/**\n\t * Get Attribute exposed for management\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<String>}\n\t */\n\tpublic List<String> getComponentsNames();\n\n\t/**\n\t * Operation exposed for management\n\t * @param compName The component name to provide statistics for\n\t * @param level Statistics level, 0 - All, 500 - Medium, 800 - Minimal\n\t * @return {@code java.util.Map<String, String>}\n\t */\n\tpublic Map<String, String> getComponentStats(String compName, int level);\n\n\tpublic int getConnectionsNumber();\n\n\tpublic int[] getConnectionsNumberHistory();\n\n\tpublic int getCPUsNumber();\n\n\tpublic float getCPUUsage();\n\n\tpublic float[] getCPUUsageHistory();\n\n\tpublic Map<String, Object> getCurStats(String[] statsKeys);\n\n\tpublic long getDirectMemUsed();\n\n\tpublic long[] getDirectMemUsedHistory();\n\n\tpublic float getHeapMemUsage();\n\n\tpublic float[] getHeapUsageHistory();\n\n\tpublic long getIQAuthNumber();\n\n\tpublic long getIQOtherNumber();\n\n\tpublic float getIQOtherNumberPerSec();\n\n\tpublic long getMessagesNumber();\n\n\tpublic float getMessagesNumberPerSec();\n\n\tpublic String getName();\n\n\tpublic float getNonHeapMemUsage();\n\n\tpublic long getPresencesNumber();\n\n\tpublic float getPresencesNumberPerSec();\n\n\tpublic long getProcesCPUTime();\n\n\tpublic long getQueueOverflow();\n\n\tpublic int getQueueSize();\n\n\tpublic int getServerConnections();\n\n\tpublic int[] getServerConnectionsHistory();\n\n\tpublic long getSMPacketsNumber();\n\n\tpublic float getSMPacketsNumberPerSec();\n\n\tpublic float[] getSMPacketsPerSecHistory();\n\n\tpublic int getSMQueueSize();\n\n\tpublic Map<String, LinkedList<Object>> getStatsHistory(String[] statsKeys);\n\n\tpublic String getSystemDetails();\n\n\tpublic long getUptime();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/CPULoadListener.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.sys;\n\n/**\n * Created: Feb 19, 2009 12:21:15 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface CPULoadListener {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/MemoryChangeListener.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.sys;\n\n/**\n * Created: Feb 19, 2009 12:19:57 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface MemoryChangeListener {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/OnlineJidsReporter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.sys;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\n/**\n * Created: Apr 19, 2009 12:15:07 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface OnlineJidsReporter {\n\n\t/**\n\t * Method checks whether the clustering strategy has a complete JIDs info.\n\t * That is whether the strategy knows about all users connected to all nodes.\n\t * Some strategies may choose not to share this information among nodes, hence\n\t * the methods returns false. Other may synchronize this information and can\n\t * provide it to further optimize cluster traffic.\n\t *\n\t * @return a true boolean value if the strategy has a complete information\n\t *         about all users connected to all cluster nodes.\n\t */\n\tboolean hasCompleteJidsInfo();\n\n\t/**\n\t * The method checks whether the given JID is known to the installation,\n\t * either user connected to local machine or any of the cluster nodes. False\n\t * result does not mean the user is not connected. It means the method does\n\t * not know anything about the JID. Some clustering strategies may not cache\n\t * online users information.\n\t *\n\t * @param jid\n\t *          a user's JID for whom we query information.\n\t *\n\t * @return true if the user is known as online to the installation, false if\n\t *         the method does not know.\n\t */\n\tboolean containsJid( BareJID jid );\n\n\t/**\n\t * The method checks whether the given JID is known to local cluster node\n\t * as connected user. False result means that given JID is not connected\n\t * to local cluster node but it may be connected to other cluster node.\n\t * Result of this method should be independent of used clustering strategy.\n\t * \n\t * @param jid\n\t *\t\t\ta user's JID for whom we query information\n\t * \n\t * @return true if user is known as connected to local cluster node, false if\n\t *\t\t\tit is not connected to local node\n\t */\n\tboolean containsJidLocally( BareJID jid);\n\n\t/**\n\t * The method checks whether the given JID is known to local cluster node\n\t * as connected user. False result means that given JID is not connected\n\t * to local cluster node but it may be connected to other cluster node.\n\t * Result of this method should be independent of used clustering strategy.\n\t * \n\t * @param jid\n\t *\t\t\ta user's JID for whom we query information\n\t * \n\t * @return true if user is known as connected to local cluster node, false if\n\t *\t\t\tit is not connected to local node\n\t */\n\tboolean containsJidLocally( JID jid);\t\n\t\n\t/**\n\t * Retrieve all connection IDs (CIDs) for the given user.\n\t *\n\t * @param jid id of the user for which we want to retrieve the list.\n\t *\n\t * @return an array of {@link JID} containing all Connection IDs (CIDs) for\n\t *         the given user.\n\t */\n\tJID[] getConnectionIdsForJid( BareJID jid );\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/ResourceState.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.sys;\n\n/**\n * Created: Feb 19, 2009 12:22:55 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum ResourceState {\n\tGREEN,\n\tYELLOW,\n\tRED;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/ShutdownHook.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.sys;\n\n/**\n * Created: Feb 19, 2009 12:17:03 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface ShutdownHook {\n\n\tString getName();\n\n\tString shutdown();\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/sys/TigaseRuntime.java",
    "content": "/*\n * TigaseRuntime.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.sys;\n\nimport tigase.server.XMPPServer;\nimport tigase.server.monitor.MonitorRuntime;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport java.lang.management.GarbageCollectorMXBean;\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.MemoryPoolMXBean;\nimport java.lang.management.MemoryUsage;\nimport java.lang.management.OperatingSystemMXBean;\nimport java.lang.management.ThreadMXBean;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Feb 19, 2009 12:15:02 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic abstract class TigaseRuntime {\n\tprotected static final long SECOND = 1000;\n\tprivate static final Logger log    = Logger.getLogger(TigaseRuntime.class.getName());\n\tprotected static final long MINUTE = 60 * SECOND;\n\tprotected static final long HOUR = 60 * MINUTE;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int              cpus        = Runtime.getRuntime().availableProcessors();\n\tprivate float            cpuUsage    = 0F;\n\tprivate MemoryPoolMXBean oldMemPool  = null;\n\tprivate long             prevCputime = 0;\n\tprivate long             prevUptime  = 0;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tprotected TigaseRuntime() {\n\t\tList<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();\n\n\t\tfor (MemoryPoolMXBean memoryPoolMXBean : memPools) {\n\t\t\tif (memoryPoolMXBean.getName().toLowerCase().contains(\"old\")) {\n\t\t\t\toldMemPool = memoryPoolMXBean;\n\t\t\t\tlog.log(Level.INFO, \"Using {0} memory pool for reporting memory usage.\", memoryPoolMXBean.getName());\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tList<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();\n\t\tfor ( GarbageCollectorMXBean gcBean : gcBeans ) {\n\t\t\tlog.log( Level.INFO, \"Using GC: {0} for pools: {1}\",\n\t\t\t\t\t\t\t new Object[] { gcBean.getName(), Arrays.asList( gcBean.getMemoryPoolNames() ) } );\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic abstract void addCPULoadListener(CPULoadListener cpuListener);\n\n\tpublic abstract void addMemoryChangeListener(MemoryChangeListener memListener);\n\n\tpublic abstract void addOnlineJidsReporter(OnlineJidsReporter onlineReporter);\n\n\tpublic abstract void addShutdownHook(ShutdownHook hook);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic abstract JID[] getConnectionIdsForJid(JID jid);\n\n\tpublic int getCPUsNumber() {\n\t\treturn cpus;\n\t}\n\n\tpublic ResourceState getCPUState() {\n\t\treturn ResourceState.GREEN;\n\t}\n\n\tpublic float getCPUUsage() {\n\t\tlong currCputime = -1;\n\t\tlong elapsedCpu  = -1;\n\t\tlong currUptime  = getUptime();\n\t\tlong elapsedTime = currUptime - prevUptime;\n\n\t\tif ((prevUptime > 0L) && (elapsedTime > 500L)) {\n\t\t\tcurrCputime = getProcessCPUTime();\n\t\t\telapsedCpu  = currCputime - prevCputime;\n\t\t\tcpuUsage    = Math.min(99.99F, elapsedCpu / (elapsedTime * 10000F * cpus));\n\t\t}\n\t\tif (elapsedTime > 500L) {\n\t\t\tprevUptime  = currUptime;\n\t\t\tprevCputime = currCputime;\n\t\t}\n\n\t\treturn cpuUsage;\n\t}\n\n\tpublic long getDirectMemUsed() {\n\t\tlong                   result   = -1;\n\t\tList<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();\n\n\t\tfor (MemoryPoolMXBean memoryPoolMXBean : memPools) {\n\t\t\tif (memoryPoolMXBean.getName().toLowerCase().contains(\"direct\")) {\n\t\t\t\tresult = memoryPoolMXBean.getUsage().getUsed();\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * We try to return OLD memory pool size as this is what is the most interesting\n\t * to us. If this is not possible then we return total Heap size.\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getHeapMemMax() {\n\t\tif (oldMemPool != null) {\n\t\t\tMemoryUsage memUsage = oldMemPool.getUsage();\n\n\t\t\treturn memUsage.getMax();\n\t\t}\n\n\t\treturn ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax();\n\t}\n\n\tpublic float getHeapMemUsage() {\n\t\treturn  getHeapMemMax() == -1 ? -1.0F : (getHeapMemUsed() * 100F) / getHeapMemMax();\n\t}\n\n\t/**\n\t * We try to return OLD memory pool size as this is what is the most interesting\n\t * to us. If this is not possible then we return total Heap used.\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getHeapMemUsed() {\n\t\tif (oldMemPool != null) {\n\t\t\tMemoryUsage memUsage = oldMemPool.getUsage();\n\n\t\t\treturn memUsage.getUsed();\n\t\t}\n\n\t\treturn ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();\n\t}\n\n\tpublic double getLoadAverage() {\n\t\treturn ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();\n\t}\n\n\tpublic ResourceState getMemoryState() {\n\t\treturn ResourceState.GREEN;\n\t}\n\n\tpublic long getNonHeapMemMax() {\n\t\treturn ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax();\n\t}\n\n\tpublic float getNonHeapMemUsage() {\n\t\treturn getNonHeapMemMax() == -1 ? -1.0F : (getNonHeapMemUsed() * 100F) / getNonHeapMemMax();\n\t}\n\n\tpublic long getNonHeapMemUsed() {\n\t\treturn ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed();\n\t}\n\n\tpublic long getProcessCPUTime() {\n\t\tlong                  result   = 0;\n\t\tOperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();\n\n\t\tif (osMXBean instanceof com.sun.management.OperatingSystemMXBean) {\n\n\t\t\t// The easy way if possible\n\t\t\tcom.sun.management.OperatingSystemMXBean sunOSMXBean = (com.sun.management\n\t\t\t\t\t.OperatingSystemMXBean) osMXBean;\n\n\t\t\tresult = sunOSMXBean.getProcessCpuTime();\n\t\t} else {\n\n\t\t\t// The hard way...\n\t\t\tThreadMXBean thBean = ManagementFactory.getThreadMXBean();\n\n\t\t\tfor (long thid : thBean.getAllThreadIds()) {\n\t\t\t\tresult += thBean.getThreadCpuTime(thid);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic int getThreadsNumber() {\n\t\treturn ManagementFactory.getThreadMXBean().getThreadCount();\n\t}\n\n\tpublic static TigaseRuntime getTigaseRuntime() {\n\t\treturn MonitorRuntime.getMonitorRuntime();\n\t}\n\n\tpublic long getUptime() {\n\t\treturn ManagementFactory.getRuntimeMXBean().getUptime();\n\t}\n\n\tpublic String getUptimeString() {\n\t\tlong uptime  = ManagementFactory.getRuntimeMXBean().getUptime();\n\t\tlong days    = uptime / (24 * HOUR);\n\t\tlong hours   = (uptime - (days * 24 * HOUR)) / HOUR;\n\t\tlong minutes = (uptime - (days * 24 * HOUR + hours * HOUR)) / MINUTE;\n\t\tlong seconds = (uptime - (days * 24 * HOUR + hours * HOUR + minutes * MINUTE)) /\n\t\t\t\tSECOND;\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tsb.append((days > 0)\n\t\t\t\t? days + ((days == 1)\n\t\t\t\t? \" day\"\n\t\t\t\t: \" days\")\n\t\t\t\t: \"\");\n\t\tif (hours > 0) {\n\t\t\tif (sb.length() > 0) {\n\t\t\t\tsb.append(\", \");\n\t\t\t}\n\t\t\tsb.append(hours + ((hours == 1)\n\t\t\t\t\t? \" hour\"\n\t\t\t\t\t: \" hours\"));\n\t\t}\n\t\tif ((days == 0) && (minutes > 0)) {\n\t\t\tif (sb.length() > 0) {\n\t\t\t\tsb.append(\", \");\n\t\t\t}\n\t\t\tsb.append(minutes + ((minutes == 1)\n\t\t\t\t\t? \" min\"\n\t\t\t\t\t: \" mins\"));\n\t\t}\n\t\tif ((days == 0) && (hours == 0) && (seconds > 0)) {\n\t\t\tif (sb.length() > 0) {\n\t\t\t\tsb.append(\", \");\n\t\t\t}\n\t\t\tsb.append(seconds + \" sec\");\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\tpublic abstract boolean hasCompleteJidsInfo();\n\n\tpublic abstract boolean isJidOnline(JID jid);\n\t\n\tpublic abstract boolean isJidOnlineLocally(BareJID jid);\n\t\n\tpublic abstract boolean isJidOnlineLocally(JID jid);\n\n\tpublic void shutdownTigase(String[] msg) {\n\t\t\tif (XMPPServer.isOSGi()) {\n\t\t\t\t// for some reason System.out.println is not working in OSGi\n\t\t\t\tfor (String line : msg) {\n\t\t\t\t\tlog.log(Level.SEVERE, line);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor (String line : msg) {\n\t\t\t\t\tSystem.out.println(line);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSystem.exit(1);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/AllHistoryCache.java",
    "content": "/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev: 2411 $\n* Last modified by $Author: kobit $\n* $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.util;\n\nimport tigase.stats.StatisticsList;\n\n/**\n * @author Artur Hefczyc\n * Created May 28, 2011\n */\npublic class AllHistoryCache {\n\n\tprivate StatisticsList[] buffer = null;\n\tprivate int start = 0;\n\tprivate int count = 0;\n\n\tpublic AllHistoryCache(int limit) {\n\t\tbuffer = new StatisticsList[limit];\n\t}\n\n\tpublic synchronized void addItem(StatisticsList item) {\n\t\tint ix = (start + count) % buffer.length;\n\t\tbuffer[ix] = item;\n\t\tif (count < buffer.length) {\n\t\t\tcount++;\n\t\t} else {\n\t\t\tstart++;\n\t\t\tstart %= buffer.length;\n\t\t}\n\t}\n\n\tpublic synchronized StatisticsList[] getCurrentHistory() {\n\t\tStatisticsList[] result = new StatisticsList[count];\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tint ix = (start + i) % buffer.length;\n\t\t\tresult[i] = buffer[ix];\n\t\t}\n\t\treturn result;\n\t}\n\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/DBSchemaLoader.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013, \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.util;\n\nimport java.io.*;\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.LinkedHashSet;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.*;\nimport java.util.logging.*;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.AuthRepository;\nimport tigase.xmpp.BareJID;\n\n/**\n * Simple utility class allowing various Database operations, including\n * executing simple queries, loading specific schema files or performing\n * complete load of all Tigase schema required to run the server.\n *\n * Following set of {@link Properties} is accepted:\n * <ul>\n * <li>{@code dbType} - type of the database, possible values are:\n * {@code mysql}, {@code postgresql}, {@code derby}, {@code sqlserver};\n * <li>{@code schemaVersion} - schema version to be loaded, , possible values\n * are: {@code 5-1}, {@code 5}, {@code 4};\n * <li>{@code dbName} - name of the database to be created/used;\n * <li>{@code dbHostname} - hostname of the database;\n * <li>{@code dbUser} - username of the regular user;\n * <li>{@code dbPass} - password of the regular user;\n * <li>{@code rootUser} - username of the database administrator user;\n * <li>{@code rootPass} - password of the database administrator user;\n * <li>{@code query} - simple, single query to be executed;\n * <li>{@code file} - path to the single schema file to be loaded to the\n * database;\n * <li>{@code adminJID} - JID address of the XMPP administrator account;\n * <li>{@code adminJIDpass} - password of the XMPP administrator account.\n *\n * @author wojtek\n */\nclass DBSchemaLoader extends SchemaLoader {\n\n\t/** Denotes whether there wasn't any problem establishing connection to the\n\t * database */\n\tprivate boolean connection_ok = false;\n\t/** Denotes whether database exists */\n\tprivate boolean db_ok = false;\n\t/** Denotes whether schema has proper version */\n\tprivate boolean schema_ok = false;\n\t/** Denotes whether schema exists */\n\tprivate boolean schema_exists = false;\n\t/** Holds map of all replacement variables */\n\tprivate Map<String, String> replacementMap = new HashMap<String, String>();\n\tprivate static final Logger log = Logger.getLogger( DBSchemaLoader.class.getCanonicalName() );\n\t// drivers\n\tpublic static final String PGSQL_DRIVER = \"org.postgresql.Driver\";\n\tpublic static final String MYSQL_DRIVER = \"com.mysql.jdbc.Driver\";\n\tpublic static final String DERBY_DRIVER = \"org.apache.derby.jdbc.EmbeddedDriver\";\n\tpublic static final String SQLSERVER_DRIVER = \"net.sourceforge.jtds.jdbc.Driver\";\n\t// queries\n\tpublic static final String JDBC_CHECKUSERTABLE_QUERY = \"select count(*) from tig_users\";\n\tpublic static final String JDBC_GETSCHEMAVER_QUERY = \"select TigGetDBProperty('schema-version')\";\n\tpublic static final String DERBY_GETSCHEMAVER_QUERY = \"values TigGetDBProperty('schema-version')\";\n\tpublic static final String SQLSERVER_GETSCHEMAVER_QUERY = \"select dbo.TigGetDBProperty('schema-version')\";\n\tprivate String schema_ver_query = JDBC_GETSCHEMAVER_QUERY;\n\t// keys\n\tpublic static final String DATABASE_TYPE_KEY = \"dbType\";\n\tpublic static final String SCHEMA_VERSION_KEY = \"schemaVersion\";\n\tpublic static final String DATABASE_NAME_KEY = \"dbName\";\n\tpublic static final String DATABASE_HOSTNAME_KEY = \"dbHostname\";\n\tpublic static final String TIGASE_USERNAME_KEY = \"dbUser\";\n\tpublic static final String TIGASE_PASSWORD_KEY = \"dbPass\";\n\tpublic static final String ROOT_USERNAME_KEY = \"rootUser\";\n\tpublic static final String ROOT_PASSWORD_KEY = \"rootPass\";\n\tpublic static final String QUERY_KEY = \"query\";\n\tpublic static final String FILE_KEY = \"file\";\n\tpublic static final String ADMIN_JID_KEY = \"adminJID\";\n\tpublic static final String ADMIN_JID_PASS_KEY = \"adminJIDpass\";\n\tpublic static final String LOG_LEVEL_KEY = \"logLevel\";\n\tpublic static final String DASH = \"-\";\n\t// defaults\n\tpublic static final String DATABASE_TYPE_DEF = \"mysql\";\n\tpublic static final String SCHEMA_VERSION_DEF = \"7-1\";\n\tpublic static final String DATABASE_NAME_DEF = \"tigasedb\";\n\tpublic static final String DATABASE_HOSTNAME_DEF = \"localhost\";\n\tpublic static final String TIGASE_USERNAME_DEF = \"tigase_user\";\n\tpublic static final String TIGASE_PASSWORD_DEF = \"tigase_pass\";\n\tpublic static final String ROOT_USERNAME_DEF = \"root\";\n\tpublic static final String ROOT_PASSWORD_DEF = \"root\";\n\tpublic static final String LOG_LEVEL_DEF = \"CONFIG\";\n\n\tenum SQL_LOAD_STATE {\n\n\t\tINIT, IN_SQL;\n\t}\n\n\t/**\n\t * Constructs {@link DBSchemaLoader} and set default values for missing\n\t * properties - for the complete list see {@link DBSchemaLoader}\n\t * documentation.\n\t *\n\t * @param props user defined {@link Properties}\n\t */\n\tpublic DBSchemaLoader( Properties props ) {\n\n\t\t// set defaults\n\t\tif ( props.get( DATABASE_TYPE_KEY ) == null ){\n\t\t\tprops.setProperty( DATABASE_TYPE_KEY, DATABASE_TYPE_DEF );\n\t\t}\n\t\tif ( props.get( SCHEMA_VERSION_KEY ) == null ){\n\t\t\tprops.setProperty( SCHEMA_VERSION_KEY, SCHEMA_VERSION_DEF );\n\t\t}\n\t\tif ( props.get( DATABASE_NAME_KEY ) == null ){\n\t\t\tprops.setProperty( DATABASE_NAME_KEY, DATABASE_NAME_DEF );\n\t\t}\n\t\tif ( props.get( DATABASE_HOSTNAME_KEY ) == null ){\n\t\t\tprops.setProperty( DATABASE_HOSTNAME_KEY, DATABASE_HOSTNAME_DEF );\n\t\t}\n\t\tif ( props.get( TIGASE_USERNAME_KEY ) == null ){\n\t\t\tprops.setProperty( TIGASE_USERNAME_KEY, TIGASE_USERNAME_DEF );\n\t\t}\n\t\tif ( props.get( TIGASE_PASSWORD_KEY ) == null ){\n\t\t\tprops.setProperty( TIGASE_PASSWORD_KEY, TIGASE_PASSWORD_DEF );\n\t\t}\n\t\tif ( props.get( ROOT_USERNAME_KEY ) == null ){\n\t\t\tprops.setProperty( ROOT_USERNAME_KEY, ROOT_USERNAME_DEF );\n\t\t}\n\t\tif ( props.get( ROOT_PASSWORD_KEY ) == null ){\n\t\t\tprops.setProperty( ROOT_PASSWORD_KEY, ROOT_PASSWORD_DEF );\n\t\t}\n\t\tif ( props.get( LOG_LEVEL_KEY ) == null ){\n\t\t\tprops.setProperty( LOG_LEVEL_KEY, LOG_LEVEL_DEF );\n\t\t}\n\n\t\t// convert all properties to replacement map which allow usage\n\t\t// of variables in schema files\n\t\tfor ( String key : props.stringPropertyNames() ) {\n\t\t\treplacementMap.put( \"${\" + key + \"}\", props.get( key ).toString() );\n\t\t}\n\n\t\t// configure logger\n\t\tLevel lvl = Level.parse( String.valueOf( props.get( LOG_LEVEL_KEY ) ) );\n\n\t\tSystem.out.println( \"LogLevel: \" + lvl );\n\n\t\tHandler handler = new ConsoleHandler();\n\t\thandler.setLevel( lvl );\n\t\thandler.setFormatter( new myFormatter() );\n\t\tlog.setUseParentHandlers( false );\n\t\tlog.addHandler( handler );\n\t\tlog.setLevel( lvl );\n\n\t\tlog.log( Level.CONFIG, String.format( \"Properties: %1$s\", Arrays.asList( props ) ) );\n\t\t\n\t}\n\n\t/**\n\t * Main method allowing pass arguments to the class and setting all logging to\n\t * be printed to console.\n\t *\n\t * @param args key-value (in the form of {@code \"-<variable> value\"})\n\t *             parameters.\n\t */\n\tpublic static void main( String[] args ) {\n\n\t\tProperties otherArgs = parseArgs( args );\n\n\t\tDBSchemaLoader dbHelper = new DBSchemaLoader( otherArgs );\n\t\tDBSchemaLoader.execute( dbHelper, otherArgs );\n\t}\n\n\t/**\n\t * Executes set of {@link TigaseDBTask} tasks selected based on set on passed\n\t * properties\n\t *\n\t * @param helper {@link DBSchemaLoader} for which tasks will be executed.\n\t * @param props  set of configuration properties.\n\t */\n\tprivate static void execute( DBSchemaLoader helper, Properties props ) {\n\n\t\t// Get list of appropriate takst and execute them;\n\t\tTigaseDBTask[] tasks;\n\t\tif ( props.getProperty( QUERY_KEY ) != null ){\n\t\t\ttasks = Tasks.getQueryTasks();\n\t\t} else if ( props.getProperty( FILE_KEY ) != null ){\n\t\t\ttasks = Tasks.getSchemaTasks();\n\t\t} else {\n\t\t\ttasks = Tasks.getTasksInOrder();\n\t\t}\n\t\tfor ( TigaseDBTask task : tasks ) {\n\t\t\ttask.execute( helper, props );\n\t\t}\n\t}\n\n\t/**\n\t * Simple parser of command line arguments passed as parameter which converts\n\t * them into key-value {@code Properties}. If the argument list is empty then\n\t * a help outlining possible parameters is printed.\n\t *\n\t * @param args set of command line arguments.\n\t * @return {@link Properties} object created from provided set of arguments.\n\t */\n\tprivate static Properties parseArgs( String[] args ) {\n\t\tProperties props = new Properties();\n\t\tif ( args == null || args.length == 0 ){\n\t\t\tSystem.out.println( help() );\n\t\t\tSystem.exit( 0 );\n\t\t} else {\n\t\t\tfor ( int i = 0 ; i < args.length ; i++ ) {\n\t\t\t\tswitch ( args[i] ) {\n\t\t\t\t\tcase DASH + DATABASE_TYPE_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( DATABASE_TYPE_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + SCHEMA_VERSION_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( SCHEMA_VERSION_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + DATABASE_NAME_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( DATABASE_NAME_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + DATABASE_HOSTNAME_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( DATABASE_HOSTNAME_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + TIGASE_USERNAME_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( TIGASE_USERNAME_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + TIGASE_PASSWORD_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( TIGASE_PASSWORD_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + ROOT_USERNAME_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( ROOT_USERNAME_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + ROOT_PASSWORD_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( ROOT_PASSWORD_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + FILE_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( FILE_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + QUERY_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( QUERY_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + ADMIN_JID_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( ADMIN_JID_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + ADMIN_JID_PASS_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( ADMIN_JID_PASS_KEY, args[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DASH + LOG_LEVEL_KEY:\n\t\t\t\t\t\tif ( args.length > i + 1 ){\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\tprops.setProperty( LOG_LEVEL_KEY, args[i].toUpperCase() );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn props;\n\t}\n\n\t/**\n\t * Creates and returns list of possible parameters.\n\t *\n\t * @return {@code String} describing possible parameters.\n\t */\n\tprivate static String help() {\n\t\tString help = \"Usage:\"\n\t\t\t\t\t\t\t\t\t+ \"$ java -cp \\\"jars/*.jar\\\" tigase.util.DBSchemaLoader\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t -\" + DATABASE_TYPE_KEY + \" database_type {derby, mysql, postgresql, sqlserver} \"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + SCHEMA_VERSION_KEY + \" schema_version {4, 5, 5-1, 7-1} ]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + DATABASE_NAME_KEY + \" database_name]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + DATABASE_HOSTNAME_KEY + \" database hostname]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + TIGASE_USERNAME_KEY + \" tigase_username]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + TIGASE_PASSWORD_KEY + \" tigase_userpass]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + ROOT_USERNAME_KEY + \" database_root_username]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + ROOT_PASSWORD_KEY + \" database_root_password]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + FILE_KEY + \" path_to_sql_schema_file]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + QUERY_KEY + \" sql_query_to_execute]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + LOG_LEVEL_KEY + \" java logger Level]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + ADMIN_JID_KEY + \" comma separated list of admin JIDs]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t[-\" + ADMIN_JID_PASS_KEY + \" password (one for all entered JIDs]\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\targuments take following precedent: query, file, whole schema\"\n\t\t\t\t\t\t\t\t\t+ \"\\n\\t(i.e. file superseeds schema execution, query superseeds file execution).\";\n\t\treturn help;\n\t}\n\n\t/**\n\t * Performs actual read and parsing of queries from resource file. It skips\n\t * comments and require proper syntax of the file, i.e. each query enclosed in\n\t * {@code \"-- QUERY START:\"} and {@code \"-- QUERY END:\"}. If the file\n\t * references/sources/import another schema file then it will also be read and\n\t * parsed.\n\t *\n\t * @param resource   name of the resource for which an {@link InputStream}\n\t *                   should be created, either excerpt of the name or a\n\t *                   full/relative path to the schema {@code .sql} file.\n\t * @param res_prefix prefix of the resource denoting type of the database.\n\t * @param variables  set of {@code Properties} with all configuration options.\n\t * @return\n\t * @throws IOException\n\t */\n\tprivate ArrayList<String> loadSQLQueries( String resource, String res_prefix, Properties variables )\n\t\t\tthrows IOException {\n\t\tlog.log( Level.FINER,\n\t\t\t\t\t\t String.format( \"Loading queries, resource: %1$s, res_prefix: %2$s \", resource, res_prefix ) );\n\t\tArrayList<String> results = new ArrayList<>();\n\t\tboolean path = res_prefix == null ? true : false;\n\t\tBufferedReader br = new BufferedReader( new InputStreamReader( getResource( resource, path ) ) );\n\t\tString line;\n\t\tString sql_query = \"\";\n\t\tSQL_LOAD_STATE state = SQL_LOAD_STATE.INIT;\n\t\twhile ( ( line = br.readLine() ) != null ) {\n\t\t\tswitch ( state ) {\n\t\t\t\tcase INIT:\n\t\t\t\t\tif ( line.startsWith( \"-- QUERY START:\" ) ){\n\t\t\t\t\t\tsql_query = \"\";\n\t\t\t\t\t\tstate = SQL_LOAD_STATE.IN_SQL;\n\t\t\t\t\t}\n\t\t\t\t\tif ( line.startsWith( \"-- LOAD SCHEMA:\" ) ){\n\t\t\t\t\t\tresults.addAll( loadSchemaQueries( variables ) );\n\t\t\t\t\t}\n\t\t\t\t\tif (  line.startsWith( \"-- LOAD FILE:\" )  && line.trim().contains( \"sql\" ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tMatcher matcher = Pattern.compile( \"-- LOAD FILE:\\\\s*(.*\\\\.sql)\" ).matcher( line );\n\t\t\t\t\t\tif ( matcher.find() ){\n\t\t\t\t\t\t\tlog.log( Level.FINE,\n\t\t\t\t\t\t\t\t\t\t\t String.format( \"\\n\\n *** trying to load schema: %1$s \\n\", matcher.group( 1 ) ) );\n\t\t\t\t\t\t\tresults.addAll( loadSQLQueries(  matcher.group( 1 ), null, variables ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase IN_SQL:\n\t\t\t\t\tif ( line.startsWith( \"-- QUERY END:\" ) ){\n\t\t\t\t\t\tstate = SQL_LOAD_STATE.INIT;\n\t\t\t\t\t\tsql_query = sql_query.trim();\n\t\t\t\t\t\tif ( sql_query.endsWith( \";\" ) ){\n\t\t\t\t\t\t\tsql_query = sql_query.substring( 0, sql_query.length() - 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( sql_query.endsWith( \"//\" ) ){\n\t\t\t\t\t\t\tsql_query = sql_query.substring( 0, sql_query.length() - 2 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tString substitute = variableSubstitutor.substitute( sql_query, replacementMap );\n\t\t\t\t\t\tresults.add( substitute );\n\t\t\t\t\t}\n\t\t\t\t\tif ( line.isEmpty() || line.trim().startsWith( \"--\" ) ){\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsql_query += \" \" + line.trim();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbr.close();\n\t\treturn results;\n\t}\n\n\t/**\n\t * Load all queries from all schema files necessary to run Tigase XMPP Server\n\t * (which includes stored procedures and properties). Version and database\n\t * type is determined from properties.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t *\n\t * @return An {@code ArrayList} with all queries from all schema files.\n\t *\n\t * @throws IOException\n\t */\n\tprivate ArrayList<String> loadSchemaQueries( Properties variables )\n\t\t\tthrows IOException {\n\n\t\tString res_prefix = variables.get( DATABASE_TYPE_KEY ).toString();\n\t\tString version = variables.get( SCHEMA_VERSION_KEY ).toString();\n\t\tArrayList<String> queries = new ArrayList<>();\n\t\tqueries.addAll( loadSQLQueries( res_prefix + \"-schema-\" + version + \"-schema\", res_prefix, variables ) );\n\t\tqueries.addAll( loadSQLQueries( res_prefix + \"-schema-\" + version + \"-sp\", res_prefix, variables ) );\n\t\tqueries.addAll( loadSQLQueries( res_prefix + \"-schema-\" + version + \"-props\", res_prefix, variables ) );\n\t\tlog.log( Level.FINE,\n\t\t\t\t\t\t String.format( \"Loading schema queries: %1$s // %2$s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tArrays.asList( queries ),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tqueries.toArray() ) );\n\t\treturn queries;\n\t}\n\n\t/**\n\t * Created an {@code InputStream} for the desired resource.\n\t *\n\t * @param resource name of the resource for which an {@link InputStream}\n\t *                 should be created, either excerpt of the name or a\n\t *                 full/relative path to the schema {@code .sql} file.\n\t * @param path     denotes whether passed resource name is a full path to the\n\t *                 file ({@code true}) or a simple resource mapping\n\t *                 ({@code false}).\n\t * @return an {@code InputStream} for the desired resource.\n\t */\n\tprotected InputStream getResource( String resource, boolean path ) {\n\t\tFile f;\n\t\tif ( path ){\n\t\t\tf = new File( resource );\n\t\t} else {\n\t\t\tf = new File( \"database/\" + resource + \".sql\" );\n\t\t}\n\t\tInputStream is = null;\n\t\ttry {\n\t\t\tis = new FileInputStream( f );\n\t\t} catch ( FileNotFoundException ex ) {\n\t\t\tLogger.getLogger( DBSchemaLoader.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t String.format( \"Getting resource: %1$s @ filename: %2$s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tresource, f.getAbsolutePath() ) );\n\t\treturn is;\n\t}\n\n\t@Override\n\tpublic Result validateDBConnection( Properties variables ) {\n\t\tconnection_ok = false;\n\t\tString db_conn = getDBUri( variables, false, true );\n\t\tlog.log( Level.INFO, \"Validating DBConnection, URI: \" + db_conn );\n\t\tif ( db_conn == null ){\n\t\t\tlog.log( Level.WARNING, \"Missing DB connection URL\" );\n\t\t\treturn Result.ok;\n\t\t} else {\n\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ) {\n\t\t\t\tEnumeration<Driver> drivers = DriverManager.getDrivers();\n\t\t\t\tArrayList<String> availableDrivers = new ArrayList<>();\n\t\t\t\twhile ( drivers.hasMoreElements() ) {\n\t\t\t\t\tavailableDrivers.add( drivers.nextElement().toString() );\n\t\t\t\t}\n\t\t\t\tlog.log( Level.CONFIG, \"DriverManager (available drivers): \" + Arrays.asList( availableDrivers ) );\n\t\t\t\tconn.close();\n\t\t\t\tconnection_ok = true;\n\t\t\t\tlog.log( Level.INFO, \"Connection OK\" );\n\t\t\t\treturn Result.ok;\n\t\t\t} catch ( SQLException e ) {\n\t\t\t\t//e.printStackTrace();\n\t\t\t\tlog.log( Level.WARNING, e.getMessage() );\n\t\t\t\treturn Result.error;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Result shutdown( Properties variables ) {\n\t\treturn shutdownDerby(variables);\n\t}\n\t\n\tpublic Result shutdownDerby( Properties variables ) {\n\t\tString db_conn = getDBUri( variables, false, true );\n\t\tString database = variables.getProperty( DATABASE_TYPE_KEY );\n\t\tif ( \"derby\".equals( database ) ){\n\t\t\tlog.log( Level.INFO, \"Validating DBConnection, URI: \" + db_conn );\n\t\t\tif ( db_conn == null ){\n\t\t\t\tlog.log( Level.WARNING, \"Missing DB connection URL\" );\n\t\t\t} else {\n\t\t\t\tdb_conn += \";shutdown=true\";\n\t\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ) {\n\t\t\t\t\tEnumeration<Driver> drivers = DriverManager.getDrivers();\n\t\t\t\t\tArrayList<String> availableDrivers = new ArrayList<>();\n\t\t\t\t\twhile ( drivers.hasMoreElements() ) {\n\t\t\t\t\t\tavailableDrivers.add( drivers.nextElement().toString() );\n\t\t\t\t\t}\n\t\t\t\t\tlog.log( Level.CONFIG, \"DriverManager (available drivers): \" + Arrays.asList( availableDrivers ) );\n\t\t\t\t\tconn.close();\n\t\t\t\t\tconnection_ok = true;\n\t\t\t\t\tlog.log( Level.INFO, \"Connection OK\" );\n\t\t\t\t} catch ( SQLException e ) {\n\t\t\t\t\t//e.printStackTrace();\n\t\t\t\t\tlog.log( Level.WARNING, e.getMessage() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn Result.ok;\n\t}\n\n\t@Override\n\tpublic Result validateDBExists( Properties variables ) {\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.WARNING, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tString res_prefix = variables.get( DATABASE_TYPE_KEY ).toString();\n\t\tdb_ok = false;\n\t\tString db_conn = getDBUri( variables, true, false );\n\t\tlog.log( Level.INFO, \"Validating whether DB Exists, URI: \" + db_conn );\n\t\tif ( db_conn == null ){\n\t\t\tlog.log( Level.WARNING, \"Missing DB connection URL\" );\n\t\t\treturn Result.error;\n\t\t} else {\n\t\t\ttry\n\t\t\t\t( Connection conn = DriverManager.getConnection( db_conn ) ) {\n\t\t\t\tconn.close();\n\t\t\t\tdb_ok = true;\n\t\t\t\tlog.log( Level.INFO, \"Exists OK\" );\n\t\t\t\treturn Result.ok;\n\t\t\t} catch ( SQLException e ) {\n\t\t\t\tlog.log( Level.INFO, \"Doesn't exist, creating...\" );\n\n\t\t\t\tdb_conn = getDBUri( variables, false, true );\n\t\t\t\n\t\t\t\ttry\n\t\t\t\t\t(Connection conn = DriverManager.getConnection( db_conn ) ) {\n\t\t\t\t\tResult result = Result.ok;\n\t\t\t\t\tArrayList<String> queries = loadSQLQueries( res_prefix + \"-installer-create-db\", res_prefix, variables );\n\t\t\t\t\tfor ( String query : queries ) {\n\t\t\t\t\t\tlog.log( Level.FINE, \"Executing query: \" + query );\n\t\t\t\t\t\tif ( !query.isEmpty() ){\n\t\t\t\t\t\t\t// Some queries may fail and this is still fine\n\t\t\t\t\t\t\t// the user or the database may already exist\n\t\t\t\t\t\t\ttry ( Statement stmt = conn.createStatement() ) {\n\t\t\t\t\t\t\t\tstmt.execute( query );\n\t\t\t\t\t\t\t\tstmt.close();\n\t\t\t\t\t\t\t} catch ( SQLException ex ) {\n\t\t\t\t\t\t\t\tresult = Result.warning;\n\t\t\t\t\t\t\t\tlog.log( Level.WARNING, \"Query failed: \" + ex.getMessage() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconn.close();\n\t\t\t\t\tlog.log( Level.INFO, \" OK\" );\n\t\t\t\t\tdb_ok = true;\n\t\t\t\t\treturn result;\n\t\t\t\t} catch ( SQLException | IOException ex ) {\n\t\t\t\t\tlog.log( Level.WARNING, ex.getMessage() );\n\t\t\t\t\treturn Result.error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method, if the connection is validated by {@code validateDBConnection} and\n\t * database exists, checks if the schema exists and has correct version (one\n\t * which we want to load). If not - performs full schema load.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tpublic Result validateDBSchema( Properties variables ) {\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.WARNING, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tschema_exists = false;\n\t\tschema_ok = false;\n\t\tString db_conn = getDBUri( variables, true, false );\n\t\tlog.log( Level.INFO, \"Validating DBSchema, URI: \" + db_conn );\n\t\tlong users = 0;\n\t\ttry {\n\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ;\n\t\t\t\t\t\tStatement stmt = conn.createStatement() ) {\n\n\t\t\t\tString query = JDBC_CHECKUSERTABLE_QUERY;\n\n\t\t\t\tResultSet rs = stmt.executeQuery( query );\n\t\t\t\tif ( rs.next() ){\n\t\t\t\t\tusers = rs.getLong( 1 );\n\t\t\t\t\tschema_exists = true;\n\t\t\t\t\tlog.log( Level.INFO, \"Schema exists, users: \" + users );\n\t\t\t\t}\n\n\t\t\t\tschema_ver_query = JDBC_GETSCHEMAVER_QUERY;\n\t\t\t\tif ( db_conn.startsWith( \"jdbc:sqlserver\" ) || db_conn.startsWith( \"jdbc:jtds:sqlserver\" ) ){\n\t\t\t\t\tschema_ver_query = SQLSERVER_GETSCHEMAVER_QUERY;\n\t\t\t\t\tif ( db_conn.startsWith( \"jdbc:derby\" ) ){\n\t\t\t\t\t\tschema_ver_query = DERBY_GETSCHEMAVER_QUERY;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tquery = schema_ver_query;\n\t\t\t\tString loadedSchemaVersion = variables.get( SCHEMA_VERSION_KEY ).toString().replace( \"-\", \".\" );\n\t\t\t\trs = stmt.executeQuery( query );\n\t\t\t\tif ( rs.next() ){\n\t\t\t\t\tString schema_version = rs.getString( 1 );\n\t\t\t\t\tif ( loadedSchemaVersion.equals( schema_version ) ){\n\t\t\t\t\t\tschema_ok = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( SQLException e ) {\n\t\t\tlog.log( Level.WARNING, \"Exception, posibly schema hasn't been loaded yet.\");\n\t\t}\n\t\tif ( schema_ok ){\n\t\t\tlog.log( Level.INFO, \"Schema OK, accounts number: \" + users );\n\t\t\treturn Result.ok;\n\t\t}\n\t\tif ( !schema_exists ){\n\t\t\tdb_conn = getDBUri( variables, true, true );\n\t\t\tlog.log( Level.INFO, \"DB schema doesn't exists, creating one..., URI: \" + db_conn );\n\t\t\ttry {\n\t\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ;\n\t\t\t\t\t\t\tStatement stmt = conn.createStatement() ) {\n\t\t\t\t\tArrayList<String> queries = loadSchemaQueries( variables );\n\n\t\t\t\t\tfor ( String query : queries ) {\n\t\t\t\t\t\tif ( !query.isEmpty() ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Executing query: \" + query );\n\t\t\t\t\t\t\tstmt.execute( query );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tschema_ok = true;\n\t\t\t\tlog.log( Level.INFO, \"New schema loaded OK\" );\n\t\t\t\treturn Result.ok;\n\t\t\t} catch ( SQLException | IOException ex ) {\n\t\t\t\tlog.log( Level.WARNING, \"Can't load schema: \" + ex.getMessage() );\n\t\t\t\treturn Result.error;\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log( Level.INFO, \"Old schema, accounts number: \" + users );\n\t\t\treturn Result.warning;\n\t\t}\n\t}\n\n\t/**\n\t * Method performs post-installation action using using\n\t * {@code *-installer-post.sql} schema file substituting it's variables with\n\t * ones provided.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\t@Override\n\tpublic Result postInstallation( Properties variables ) {\n\t\t// part 1, check db preconditions\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.WARNING, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tif ( !schema_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database schema is invalid\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\t// part 2, acquire reqired fields and validate them\n\t\tString db_conn = getDBUri( variables, true, true );\n\t\tString res_prefix = variables.get( DATABASE_TYPE_KEY ).toString();\n\t\tlog.log( Level.INFO, \"Post Installation, URI: \" + db_conn );\n\t\ttry {\n\t\t\tlog.log( Level.INFO, \"Finalizing...\" );\n\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ;\n\t\t\t\t\t\tStatement stmt = conn.createStatement() ) {\n\n\t\t\t\tArrayList<String> queries = loadSQLQueries( res_prefix + \"-installer-post\", res_prefix, variables );\n\t\t\t\tfor ( String query : queries ) {\n\t\t\t\t\tif ( !query.isEmpty() ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"Executing query: \" + query );\n\t\t\t\t\t\tstmt.execute( query );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tschema_ok = true;\n\t\t\tlog.log( Level.INFO, \" completed OK\" );\n\t\t\treturn Result.ok;\n\t\t} catch ( SQLException | IOException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Can't finalize: \" + ex.getMessage() );\n\t\t\treturn Result.error;\n\t\t}\n\t}\n\n\t/**\n\t * Method performs post-installation action using using\n\t * {@code *-installer-post.sql} schema file substituting it's variables with\n\t * ones provided.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\t@Override\n\tpublic Result printInfo( Properties variables ) {\n\t\t// part 1, check db preconditions\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.WARNING, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tif ( !schema_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database schema is invalid\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tString db_conn = getDBUri( variables, true, false );\n\t\tString database = variables.getProperty( DATABASE_TYPE_KEY );\n\n\t\tswitch ( database ) {\n\t\t\tcase \"mysql\":\n\t\t\t\tdb_conn += \"&useUnicode=true&characterEncoding=UTF-8\";\n\t\t\t\tbreak;\n\t\t}\n\t\tlog.log( Level.INFO, \"\\n\\nDatabase init.properties configuration:\\n\"\n\t\t\t\t\t\t\t\t\t\t\t\t + \"\\n\" + \"--user-db=\" + database\n\t\t\t\t\t\t\t\t\t\t\t\t + \"\\n\" + \"--user-db-uri=\" + db_conn );\n\t\treturn Result.ok;\n\t}\n\n\t@Override\n\tpublic Result addXmppAdminAccount( Properties variables ) {\n\t\t// part 1, check db preconditions\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.WARNING, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tif ( !schema_ok ){\n\t\t\tlog.log( Level.WARNING, \"Database schema is invalid\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\t// part 2, acquire reqired fields and validate them\n\t\tObject admins = variables.get( ADMIN_JID_KEY );\n\t\tSet<BareJID> jids = new LinkedHashSet<>();\n\t\tif ( admins != null ){\n\t\t\tString[] adminsStr = admins.toString().split( \",\" );\n\t\t\tfor ( String adminStr : adminsStr ) {\n\t\t\t\tString jid = adminStr.trim();\n\t\t\t\tif ( jid != null && !jid.equals( \"\" ) ){\n\t\t\t\t\tjids.add( BareJID.bareJIDInstanceNS( jid ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ( jids.size() < 1 ){\n\t\t\tlog.log( Level.WARNING, \"Error: No admin users entered\" );\n\t\t\treturn Result.warning;\n\t\t}\n\n\t\tObject pwdObj = variables.get( ADMIN_JID_PASS_KEY );\n\t\tif ( pwdObj == null ){\n\t\t\tlog.log( Level.WARNING, \"Error: No admin password enetered\" );\n\t\t\treturn Result.warning;\n\t\t}\n\t\tString pwd = pwdObj.toString();\n\n\t\tString dbUri = getDBUri( variables, true, true );\n\t\tlog.log( Level.INFO, \"Adding XMPP Admin Account, URI: \" + dbUri );\n\n\t\ttry {\n\t\t\tMap<String, String> params = new HashMap<>();\n\t\t\tparams.put( RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, String.valueOf( 1 ) );\n\n\t\t\tlog.log( Level.CONFIG, \"RepositoryFactory.getAuthRepository(\" + null + \", \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t + dbUri + \",\" + Arrays.asList( params ) + \")\" );\n\t\t\tAuthRepository repo = RepositoryFactory.getAuthRepository( null, dbUri, params );\n\t\t\tfor ( BareJID jid : jids ) {\n\t\t\t\trepo.addUser( jid, pwd );\n\t\t\t}\n\n\t\t\tlog.log( Level.INFO, \"All users added\" );\n\t\t\treturn Result.ok;\n\t\t} catch ( TigaseDBException | ClassNotFoundException | InstantiationException | IllegalAccessException e ) {\n\t\t\tlog.log( Level.WARNING, \"Error initializing DB\" + e );\n\t\t\treturn Result.error;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Result loadSchemaFile( Properties variables ) {\n\n\t\t// part 1, check db preconditions\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.INFO, \"Connection not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.INFO, \"Database not validated\" );\n\t\t\treturn Result.error;\n\t\t}\n\n\t\tObject fileNameObj = variables.get( FILE_KEY );\n\t\tif ( fileNameObj == null ){\n\t\t\tlog.log( Level.WARNING, \"Error: empty query\" );\n\t\t\treturn Result.error;\n\t\t}\n\t\tString fileName = fileNameObj.toString();\n\n\t\tString db_conn = getDBUri( variables, true, true );\n\t\tlog.log( Level.INFO,\n\t\t\t\t\t\t String.format( \"Loading schema from file: %1$s, URI: %2$s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfileName, db_conn ) );\n\t\ttry {\n\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ;\n\t\t\t\t\t\tStatement stmt = conn.createStatement() ) {\n\n\t\t\t\tArrayList<String> queries = loadSQLQueries( fileName, null, variables );\n\t\t\t\tfor ( String query : queries ) {\n\t\t\t\t\tif ( !query.isEmpty() ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"Executing query: \" + query );\n\t\t\t\t\t\tstmt.execute( query );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tschema_ok = true;\n\t\t\tlog.log( Level.INFO, \" completed OK\" );\n\t\t\treturn Result.ok;\n\t\t} catch ( SQLException | IOException | NullPointerException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Can't finalize: \" + ex.getMessage() );\n\t\t\treturn Result.error;\n\t\t}\n\t}\n\n\t/**\n\t * Method checks whether the connection to the database is possible and that\n\t * database of specified name exists. If yes then a single query is executed.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tprotected void executeSingleQuery( Properties variables ) {\n\t\t// part 1, check db preconditions\n\t\tif ( !connection_ok ){\n\t\t\tlog.log( Level.INFO, \"Connection not validated\" );\n\t\t\treturn;\n\t\t}\n\t\tif ( !db_ok ){\n\t\t\tlog.log( Level.INFO, \"Database not validated\" );\n\t\t\treturn;\n\t\t}\n\n\t\tObject queryObj = variables.get( QUERY_KEY );\n\t\tif ( queryObj == null ){\n\t\t\tlog.log( Level.WARNING, \"Error: empty query\" );\n\t\t\treturn;\n\t\t}\n\t\tString simpleQuery = queryObj.toString();\n\n\t\tString db_conn = getDBUri( variables, true, false );\n\t\tlog.log( Level.INFO, \"Executing Simple Query, URI: \" + db_conn );\n\t\tif ( db_conn == null ){\n\t\t\tlog.log( Level.WARNING, \"Missing DB connection URL\" );\n\t\t} else {\n\t\t\tdb_conn = getDBUri( variables, false, true );\n\t\t\ttry {\n\t\t\t\ttry ( Connection conn = DriverManager.getConnection( db_conn ) ;\n\t\t\t\t\t\t\tStatement stmt = conn.createStatement() ) {\n\t\t\t\t\tArrayList<String> queries = new ArrayList<>();\n\t\t\t\t\tqueries.add( simpleQuery );\n\t\t\t\t\tfor ( String query : queries ) {\n\t\t\t\t\t\tlog.log( Level.FINEST, \"Executing query: \" + query );\n\t\t\t\t\t\tif ( !query.isEmpty() ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tstmt.execute( query );\n\t\t\t\t\t\t\t\tstmt.close();\n\t\t\t\t\t\t\t} catch ( SQLException ex ) {\n\t\t\t\t\t\t\t\tlog.log( Level.WARNING, \"Query failed: \" + query + \", \" + ex.getMessage() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlog.log( Level.INFO, \" OK\" );\n\t\t\t\tdb_ok = true;\n\t\t\t} catch ( Exception ex ) {\n\t\t\t\tlog.log( Level.WARNING, ex.getMessage() );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper method used to generate proper database URI depending on properties.\n\t *\n\t * @param props              set of {@code Properties} with all configuration\n\t *                           options\n\t * @param includeDbName      configure whether to include database name in the\n\t *                           URI\n\t * @param useRootCredentials whether to put in the URI credentials of database\n\t *                           administrator ({@code true}) or regular user.\n\t * @return\n\t */\n\tprivate static String getDBUri( Properties props, boolean includeDbName, boolean useRootCredentials ) {\n\t\tString db_uri = \"jdbc:\";\n\t\tString database = props.getProperty( DATABASE_TYPE_KEY );\n\t\tString USERNAME;\n\t\tString PASSWORD;\n\t\tif ( useRootCredentials ){\n\t\t\tUSERNAME = ROOT_USERNAME_KEY;\n\t\t\tPASSWORD = ROOT_PASSWORD_KEY;\n\t\t} else {\n\t\t\tUSERNAME = TIGASE_USERNAME_KEY;\n\t\t\tPASSWORD = TIGASE_PASSWORD_KEY;\n\t\t}\n\n\t\tswitch ( database ) {\n\t\t\tcase \"sqlserver\":\n\t\t\t\tdb_uri += \"jtds:sqlserver:\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdb_uri += database + \":\";\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch ( database ) {\n\t\t\tcase \"derby\":\n\t\t\t\tdb_uri += props.getProperty( DATABASE_NAME_KEY ) + \";create=true\";\n\t\t\t\tbreak;\n\t\t\tcase \"sqlserver\":\n\t\t\t\tdb_uri += \"//\" + props.getProperty( DATABASE_HOSTNAME_KEY );\n\t\t\t\tif ( includeDbName ){\n\t\t\t\t\tdb_uri += \";databaseName=\" + props.getProperty( DATABASE_NAME_KEY );\n\t\t\t\t}\n\t\t\t\tdb_uri += \";user=\" + props.getProperty( USERNAME );\n\t\t\t\tif ( props.getProperty( PASSWORD ) != null\n\t\t\t\t\t\t && !props.getProperty( PASSWORD ).isEmpty() ){\n\t\t\t\t\tdb_uri += \";password=\" + props.getProperty( PASSWORD );\n\t\t\t\t}\n\t\t\t\tdb_uri += \";schema=dbo\";\n\t\t\t\tdb_uri += \";lastUpdateCount=false\";\n\t\t\t\tdb_uri += \";cacheMetaData=false\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdb_uri += \"//\" + props.getProperty( DATABASE_HOSTNAME_KEY ) + \"/\";\n\t\t\t\tif ( includeDbName ){\n\t\t\t\t\tdb_uri += props.getProperty( DATABASE_NAME_KEY );\n\t\t\t\t} else if (database.equals( \"postgresql\")) {\n\t\t\t\t\tdb_uri +=  \"postgres\" ;\n\t\t\t\t}\n\t\t\t\tdb_uri += \"?user=\" + props.getProperty( USERNAME );\n\t\t\t\tif ( props.getProperty( PASSWORD ) != null\n\t\t\t\t\t\t && !props.getProperty( PASSWORD ).isEmpty() ){\n\t\t\t\t\tdb_uri += \"&password=\" + props.getProperty( PASSWORD );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\treturn db_uri;\n\t}\n\n\tenum Tasks implements TigaseDBTask {\n\n\t\tVALIDATE_CONNECTION( \"Checking connection to the database\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.validateDBConnection( variables );\n\t\t\t}\n\t\t},\n\t\tVALIDATE_DB_EXISTS( \"Checking if the database exists\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.validateDBExists( variables );\n\t\t\t}\n\t\t},\n\t\tVALIDATE_DB_SCHEMA( \"Checking the database schema\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.validateDBSchema( variables );\n\t\t\t}\n\t\t},\n\t\tADD_ADMIN_XMPP_ACCOUNT( \"Adding XMPP admin accounts\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.addXmppAdminAccount( variables );\n\t\t\t}\n\t\t},\n\t\tEXECUTE_SIMPLE_QUERY( \"Executing simple single query\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.executeSingleQuery( variables );\n\t\t\t}\n\t\t},\n\t\tLOAD_SCHEMA_FILE( \"Loading schema file from provided file\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.loadSchemaFile( variables );\n\t\t\t}\n\t\t},\n\t\tPOST_INSTALLATION( \"Post installation actions\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.postInstallation( variables );\n\t\t\t}\n\t\t},\n\t\tSHUTDOWN_DATABASE( \"Shutting Down Database\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.shutdownDerby( variables );\n\t\t\t}\n\t\t},\n\t\tPRINT_INFO_TASK( \"Database Configuration Details\" ) {\n\t\t\t@Override\n\t\t\tpublic void execute( DBSchemaLoader helper, Properties variables ) {\n\t\t\t\thelper.printInfo( variables );\n\t\t\t}\n\t\t};\n\t\tprivate final String description;\n\n\t\tprivate Tasks( String description ) {\n\t\t\tthis.description = description;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getDescription() {\n\t\t\treturn description;\n\t\t}\n\n\t\tpublic static TigaseDBTask[] getTasksInOrder() {\n\t\t\treturn new TigaseDBTask[] {\n\t\t\t\tVALIDATE_CONNECTION\n\t\t\t\t\t,VALIDATE_DB_EXISTS\n\t\t\t\t\t,VALIDATE_DB_SCHEMA\n\t\t\t\t\t,ADD_ADMIN_XMPP_ACCOUNT\n\t\t\t\t\t,POST_INSTALLATION\n\t\t\t\t\t,SHUTDOWN_DATABASE\n\t\t\t\t\t,PRINT_INFO_TASK\n\t\t\t};\n\t\t}\n\n\t\tpublic static TigaseDBTask[] getSchemaTasks() {\n\t\t\treturn new TigaseDBTask[] { VALIDATE_CONNECTION, VALIDATE_DB_EXISTS, LOAD_SCHEMA_FILE, SHUTDOWN_DATABASE, PRINT_INFO_TASK };\n\t\t}\n\n\t\tpublic static TigaseDBTask[] getQueryTasks() {\n\t\t\treturn new TigaseDBTask[] { VALIDATE_CONNECTION, VALIDATE_DB_EXISTS, EXECUTE_SIMPLE_QUERY, SHUTDOWN_DATABASE, PRINT_INFO_TASK };\n\t\t}\n\t}\n\n\tstatic interface TigaseDBTask {\n\n\t\tString getDescription();\n\n\t\tabstract void execute( DBSchemaLoader helper, Properties variables );\n\t}\n\n\t/**\n\t * Simple helper class allowing to substituting variables.\n\t */\n\tstatic class variableSubstitutor {\n\n\t\t/**\n\t\t * Method substitutes all occurrences of items in string based on the\n\t\t * substitution map.\n\t\t *\n\t\t * @param str            input string in which replacement should be made.\n\t\t * @param replacementMap replacement map listing all replacement patterns.\n\t\t *\n\t\t * @return string with replaced items.\n\t\t */\n\t\tstatic String substitute( String str, Map<String, String> replacementMap ) {\n\t\t\tString replaced = str;\n\t\t\tfor ( Map.Entry<String, String> entry : replacementMap.entrySet() ) {\n\t\t\t\treplaced = replaced.replace( entry.getKey(), entry.getValue() );\n\t\t\t}\n\t\t\treturn replaced;\n\t\t}\n\t}\n}\n\nclass myFormatter extends java.util.logging.Formatter {\n\n\t@Override\n\tpublic String format( LogRecord rec ) {\n\t\tStringBuilder buf = new StringBuilder( 1000 );\n\n\t\tbuf.append( String.format( \"%-30s \\t %-15s \\t %-10s %4$s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t rec.getSourceClassName(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t rec.getSourceMethodName(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t rec.getLevel(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t rec.getMessage() ) );\n\t\tbuf.append( \"\\n\" );\n\n\t\treturn buf.toString();\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/DBUtils.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class DBUtils here.\n *\n *\n * Created: Thu Nov  8 08:59:06 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class DBUtils {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param params\n\t * @param primaryKey\n\t * @param secondaryKey\n\t *\n\t * \n\t */\n\tpublic static String[] decodeDBParams(final Map<String, Object> params,\n\t\t\tfinal String primaryKey, final String secondaryKey) {\n\t\tString repo_class = null;\n\t\tString repo_url = null;\n\t\tString repo = (String) params.get(primaryKey);\n\n\t\tif ((repo == null) && (secondaryKey != null)) {\n\t\t\trepo = (String) params.get(secondaryKey);\n\t\t}\n\n\t\tif ( repo != null ){\n\t\t\tif ( repo.equals( \"mysql\" ) ){\n\t\t\t\trepo_class = RepositoryFactory.MYSQL_REPO_CLASS_PROP_VAL;\n\t\t\t\trepo_url = RepositoryFactory.MYSQL_REPO_URL_PROP_VAL;\n\t\t\t} else {\n\t\t\t\tif ( repo.equals( \"pgsql\" ) ){\n\t\t\t\t\trepo_class = RepositoryFactory.PGSQL_REPO_CLASS_PROP_VAL;\n\t\t\t\t\trepo_url = RepositoryFactory.PGSQL_REPO_URL_PROP_VAL;\n\t\t\t\t} else {\n\t\t\t\t\tif ( repo.equals( \"drupal\" ) ){\n\t\t\t\t\t\trepo_class = RepositoryFactory.DRUPALWP_REPO_CLASS_PROP_VAL;\n\t\t\t\t\t\trepo_url = RepositoryFactory.DRUPAL_REPO_URL_PROP_VAL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( repo.equals( \"sqlserver\" ) ){\n\t\t\t\t\t\t\trepo_class = RepositoryFactory.SQLSERVER_REPO_CLASS_PROP_VAL;\n\t\t\t\t\t\t\trepo_url = RepositoryFactory.SQLSERVER_REPO_URL_PROP_VAL;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ( repo.equals( \"libresource\" ) ){\n\t\t\t\t\t\t\t\trepo_class = RepositoryFactory.LIBRESOURCE_REPO_CLASS_PROP_VAL;\n\t\t\t\t\t\t\t\trepo_url = RepositoryFactory.LIBRESOURCE_REPO_URL_PROP_VAL;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trepo_class = repo;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new String[] { repo_class, repo_url };\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/DataTypes.java",
    "content": "/*\n * DataTypes.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.xmpp.JID;\n\nimport java.lang.reflect.Array;\n\n/**\n * Created: May 28, 2009 7:39:07 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DataTypes {\n\t/** Field description */\n\tpublic static final Map<String, Character> typesMap = new LinkedHashMap<String,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCharacter>();\n\n\tprivate static final Logger log = Logger.getLogger(DataTypes.class.getName());\n\t//~--- static initializers --------------------------------------------------\n\n\tstatic {\n\t\ttypesMap.put(String.class.getName(), 'S');\n\t\ttypesMap.put(Long.class.getName(), 'L');\n\t\ttypesMap.put(Integer.class.getName(), 'I');\n\t\ttypesMap.put(Boolean.class.getName(), 'B');\n\t\ttypesMap.put(Float.class.getName(), 'F');\n\t\ttypesMap.put(Double.class.getName(), 'D');\n\t\ttypesMap.put(JID.class.getName(), 'J');\n\t\ttypesMap.put(String[].class.getName(), 's');\n\t\ttypesMap.put(Long[].class.getName(), 'l');\n\t\ttypesMap.put(Integer[].class.getName(), 'i');\n\t\ttypesMap.put(Boolean[].class.getName(), 'b');\n\t\ttypesMap.put(Float[].class.getName(), 'f');\n\t\ttypesMap.put(Double[].class.getName(), 'd');\n\t\ttypesMap.put(long[].class.getName(), 'l');\n\t\ttypesMap.put(int[].class.getName(), 'i');\n\t\ttypesMap.put(boolean[].class.getName(), 'b');\n\t\ttypesMap.put(float[].class.getName(), 'f');\n\t\ttypesMap.put(double[].class.getName(), 'd');\n\t\ttypesMap.put(JID[].class.getName(), 'j');\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t// public static char[] sizeChars = {'k', 'K', 'm', 'M', 'g', 'G', 't', 'T'};\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param num\n\t * @param cls\n\t * @param def\n\t * @param <T>\n\t *\n\t * \n\t */\n\tpublic static <T extends Number> T parseNum(String num, Class<T> cls, T def) {\n\t\tif (num == null) {\n\t\t\treturn def;\n\t\t}\n\n\t\tT result        = def;\n\t\tString toParse  = num;\n\t\tLong multiplier = 1L;\n\n\t\ttry {\n\t\t\tswitch (num.charAt(num.length() - 1)) {\n\t\t\tcase 'k' :\n\t\t\tcase 'K' :\n\t\t\t\tmultiplier = 1024L;\n\t\t\t\ttoParse    = num.substring(0, num.length() - 1);\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'm' :\n\t\t\tcase 'M' :\n\t\t\t\tmultiplier = 1024L * 1024L;\n\t\t\t\ttoParse    = num.substring(0, num.length() - 1);\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'g' :\n\t\t\tcase 'G' :\n\t\t\t\tmultiplier = 1024L * 1024L * 1024L;\n\t\t\t\ttoParse    = num.substring(0, num.length() - 1);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(cls.equals(Integer.class)) {\n\t\t\t\tresult = cls.cast(Integer.valueOf(toParse) * multiplier.intValue());\n\t\t\t} else if(cls.equals(Long.class)) {\n\t\t\t\tresult = cls.cast(Long.valueOf(toParse) * multiplier);\n\t\t\t} else if(cls.equals(Double.class)) {\n\t\t\t\tresult = cls.cast(Double.valueOf(toParse) * multiplier.doubleValue());\n\t\t\t} else if(cls.equals(Float.class)) {\n\t\t\t\tresult = cls.cast(Float.valueOf(toParse) * multiplier.floatValue());\n\t\t\t} else if(cls.equals(Byte.class)) {\n\t\t\t\tInteger res = Byte.valueOf(toParse) * multiplier.byteValue();\n\t\t\t\tresult = cls.cast(res.byteValue());\n\t\t\t} else if(cls.equals(Short.class)) {\n\t\t\t\tInteger res = Short.valueOf(toParse) * multiplier.shortValue();\n\t\t\t\tresult = cls.cast(res.shortValue());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log( Level.WARNING, \"Error parsing value: {0} as {1}, using default: {2}\", new Object[] {num,cls,def});\n\t\t\treturn def;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param size\n\t * @param def\n\t *\n\t * \n\t */\n\tpublic static int parseSizeInt(String size, int def) {\n\t\treturn parseNum(size, Integer.class, def);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param val\n\t *\n\t * \n\t */\n\tpublic static boolean parseBool(final String val) {\n\t\treturn (val != null) &&\n\t\t\t\t\t (val.equalsIgnoreCase(\"yes\") || val.equalsIgnoreCase(\"true\") ||\n\t\t\t\t\t\tval.equalsIgnoreCase(\"on\") || val.equals(\"1\"));\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param typeId\n\t * @param value\n\t *\n\t * \n\t *\n\t * @throws IllegalArgumentException\n\t */\n\tpublic static Object decodeValueType(char typeId, String value)\n\t\t\t\t\tthrows IllegalArgumentException {\n\t\tObject result = value.trim();\n\n\t\ttry {\n\t\t\tswitch (typeId) {\n\t\t\tcase 'L' :\n\n\t\t\t\t// Long value\n\t\t\t\tresult = Long.decode(value.trim());\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'I' :\n\n\t\t\t\t// Integer value\n\t\t\t\tresult = Integer.decode(value.trim());\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'B' :\n\n\t\t\t\t// Boolean value\n\t\t\t\tresult = parseBool(value.trim());\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'F' :\n\n\t\t\t\t// Float value\n\t\t\t\tresult = Float.parseFloat(value.trim());\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'D' :\n\n\t\t\t\t// Double value\n\t\t\t\tresult = Double.parseDouble(value.trim());\n\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase 'J' :\n\t\t\t\tresult = JID.jidInstance(value);\n\t\t\t\t\n\t\t\t\tbreak;\n\n\t\t\tcase 's' :\n\n\t\t\t\t// Comma separated, Strings array\n\t\t\t\tString[] s_str      = value.split(\",\");\n\t\t\t\tString[] trimed_str = new String[s_str.length];\n\t\t\t\tint si              = 0;\n\n\t\t\t\tfor (String s : s_str) {\n\t\t\t\t\ttrimed_str[si++] = s.trim();\n\t\t\t\t}\n\t\t\t\tresult = trimed_str;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'l' :\n\n\t\t\t\t// Comma separated, long array\n\t\t\t\tString[] longs_str = value.split(\",\");\n\t\t\t\tlong[] longs       = new long[longs_str.length];\n\t\t\t\tint l              = 0;\n\n\t\t\t\tfor (String s : longs_str) {\n\t\t\t\t\tlongs[l++] = Long.parseLong(s.trim());\n\t\t\t\t}\n\t\t\t\tresult = longs;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'i' :\n\n\t\t\t\t// Comma separated, int array\n\t\t\t\tString[] ints_str = value.split(\",\");\n\t\t\t\tint[] ints        = new int[ints_str.length];\n\t\t\t\tint i             = 0;\n\n\t\t\t\tfor (String s : ints_str) {\n\t\t\t\t\tints[i++] = Integer.parseInt(s.trim());\n\t\t\t\t}\n\t\t\t\tresult = ints;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'b' :\n\n\t\t\t\t// Comma separated, boolean array\n\t\t\t\tString[] bools_str = value.split(\",\");\n\t\t\t\tboolean[] bools    = new boolean[bools_str.length];\n\t\t\t\tint b              = 0;\n\n\t\t\t\tfor (String s : bools_str) {\n\t\t\t\t\tbools[b++] = parseBool(s.trim());\n\t\t\t\t}\n\t\t\t\tresult = bools;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'f' :\n\n\t\t\t\t// Comma separated, float array\n\t\t\t\tString[] float_str = value.split(\",\");\n\t\t\t\tfloat[] floats     = new float[float_str.length];\n\t\t\t\tint f              = 0;\n\n\t\t\t\tfor (String s : float_str) {\n\t\t\t\t\tfloats[f++] = Float.parseFloat(s.trim());\n\t\t\t\t}\n\t\t\t\tresult = floats;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'd' :\n\n\t\t\t\t// Comma separated, double array\n\t\t\t\tString[] doubles_str = value.split(\",\");\n\t\t\t\tdouble[] doubles     = new double[doubles_str.length];\n\t\t\t\tint d                = 0;\n\n\t\t\t\tfor (String s : doubles_str) {\n\t\t\t\t\tdoubles[d++] = Double.parseDouble(s.trim());\n\t\t\t\t}\n\t\t\t\tresult = doubles;\n\n\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\tcase 'j' :\n\t\t\t\tString[] jids_str = value.split(\",\");\n\t\t\t\tJID[] jids = new JID[jids_str.length];\n\t\t\t\tint j = 0;\n\t\t\t\t\n\t\t\t\tfor (String s : jids_str) {\n\t\t\t\t\tjids[j++] = JID.jidInstance(s);\n\t\t\t\t}\n\t\t\t\tresult = jids;\n\t\t\t\t\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\n\t\t\t\t// Do nothing, default to String\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tthrow new IllegalArgumentException(e);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param value\n\t *\n\t * \n\t */\npublic static String valueToString(final Object value) {\n\n  if (value == null) {\n    return \"<null>\";\n  }\n\n  if(value.getClass().isArray()) {\n\n    if(Array.getLength(value) == 0) {\n      return \"\";\n    }\n\n    String varr = null;\n    char t = DataTypes.getTypeId(value);\n    switch (t) {\n    case 'l' :\n      varr = value instanceof long[] ? Arrays.toString((long[]) value) : Arrays.toString((Long[]) value);\n      break;\n\n    case 'i' :\n      varr = value instanceof int[] ? Arrays.toString((int[]) value) : Arrays.toString((Integer[]) value);\n      break;\n\n    case 'b' :\n      varr = value instanceof boolean[] ? Arrays.toString((boolean[]) value) : Arrays.toString((Boolean[]) value);\n      break;\n\n    case 'f' :\n      varr = value instanceof float[] ? Arrays.toString((float[]) value) : Arrays.toString((Float[]) value);\n      break;\n\n    case 'd' :\n      varr = value instanceof double[] ? Arrays.toString((double[]) value) : Arrays.toString((Double[]) value);\n      break;\n\n    default :\n      varr = Arrays.toString((Object[]) value);\n    }\n    return varr.substring(1, varr.length() - 1);\n  }\n\n  return value.toString();\n}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t *\n\t * \n\t */\n\tpublic static char decodeTypeIdFromName(String name) {\n\t\tchar result = 'S';\n\n\t\tif (name.endsWith(\"]\")) {\n\t\t\tresult = name.charAt(name.length() - 2);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t *\n\t * \n\t */\n\tpublic static String stripNameFromTypeId(String name) {\n\t\tif (name.endsWith(\"]\")) {\n\t\t\treturn name.substring(0, name.length() - 3);\n\t\t} else {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name\n\t * @param value\n\t *\n\t * \n\t */\n\tpublic static String encodeTypeIdInName(String name, Object value) {\n\t\tchar t = DataTypes.getTypeId(value);\n\n\t\treturn name + \"[\" + t + \"]\";\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param instance\n\t *\n\t * \n\t */\n\tpublic static char getTypeId(Object instance) {\n\t\tCharacter result;\n\n\t\tif (instance == null) {\n\t\t\tresult = 'S';\n\t\t} else {\n\t\t\tresult = typesMap.get(instance.getClass().getName());\n\t\t}\n\t\tif (result == null) {\n\t\t\tresult = 'S';\n\t\t}\n\n\t\treturn result.charValue();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t * @param def\n\t *\n\t * \n\t */\n\tpublic static boolean getProperty(String key, Boolean def) {\n\t\tString val = System.getProperty(key, (def != null)\n\t\t\t\t\t\t? def.toString()\n\t\t\t\t\t\t: null);\n\n\t\treturn parseBool(val);\n\t}\n\tpublic static void main( String[] args ) {\n\t\tSystem.out.println( parseSizeInt( \"256k\", 1 ) );\n\t\tSystem.out.println( parseNum(\"256k\", Integer.class, 1 ) );\n\t\tSystem.out.println( parseNum(\"655k\", Double.class, 1D ) );\n\t\tSystem.out.println( parseNum(\"256k\", Float.class, 1F ) );\n\t\tSystem.out.println( parseNum(\"256k\", Long.class, 1L ) );\n\t\tSystem.out.println( parseNum(\"25\", Short.class, Short.valueOf( \"1\") ) );\n\t\tSystem.out.println( parseNum(\"25\", Byte.class, (byte)1 ) );\n\t}\n}\n//~ Formatted in Tigase Code Convention on 13/03/04\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/ElementUtils.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.util;\n\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Describe class ElementUtils here.\n *\n *\n * Created: Sat Mar 25 20:08:17 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ElementUtils {\n\n\tpublic static Element createIqQuery(JID from, JID to, StanzaType type,\n\t\t\tString id, String xmlns) {\n\t\tElement iq = new Element(\"iq\",\n\t\t\tnew String[] {\"from\", \"to\", \"type\", \"id\"},\n\t\t\tnew String[] {from.toString(), to.toString(), type.toString(), id});\n\t\tElement query = new Element(\"query\");\n\t\tquery.setXMLNS(xmlns);\n\t\tiq.addChild(query);\n\t\treturn iq;\n\t}\n\n\tpublic static Element createIqQuery(JID from, JID to, StanzaType type,\n\t\t\tString id, Element query) {\n\t\tElement iq = new Element(\"iq\",\n\t\t\tnew String[] {\"from\", \"to\", \"type\", \"id\"},\n\t\t\tnew String[] {from.toString(), to.toString(), type.toString(), id});\n\t\tiq.addChild(query);\n\t\treturn iq;\n\t}\n\n} // ElementUtils\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/EverySecond.java",
    "content": "/*\n * EverySecond.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.util;\n\n/**\n *\n * @author andrzej\n */\npublic interface EverySecond {\n\n\tvoid everySecond();\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/FloatHistoryCache.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n/**\n * Created: Sep 8, 2009 7:32:09 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class FloatHistoryCache {\n\n\tprivate float[] buffer = null;\n\tprivate int start = 0;\n\tprivate int count = 0;\n\n\tpublic FloatHistoryCache(int limit) {\n\t\tbuffer = new float[limit];\n\t}\n\n\tpublic synchronized void addItem(float item) {\n\t\tint ix = (start + count) % buffer.length;\n\t\tbuffer[ix] = item;\n\t\tif (count < buffer.length) {\n\t\t\tcount++;\n\t\t} else {\n\t\t\tstart++;\n\t\t\tstart %= buffer.length;\n\t\t}\n\t}\n\n\tpublic synchronized float[] getCurrentHistory() {\n\t\tfloat[] result = new float[count];\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tint ix = (start + i) % buffer.length;\n\t\t\tresult[i] = buffer[ix];\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/IdentityComparator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\nimport java.util.Comparator;\n\n/**\n * Created: Jul 15, 2009 11:50:51 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class IdentityComparator implements Comparator<Object> {\n\n\t@Override\n\tpublic int compare(Object o1, Object o2) {\n\t\tif (o1 == o2) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (o1.hashCode() < o2.hashCode()) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn 1;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/IntHistoryCache.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n/**\n * Created: Sep 8, 2009 7:39:27 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class IntHistoryCache {\n\n\tprivate int[] buffer = null;\n\tprivate int start = 0;\n\tprivate int count = 0;\n\n\tpublic IntHistoryCache(int limit) {\n\t\tbuffer = new int[limit];\n\t}\n\n\tpublic synchronized void addItem(int item) {\n\t\tint ix = (start + count) % buffer.length;\n\t\tbuffer[ix] = item;\n\t\tif (count < buffer.length) {\n\t\t\tcount++;\n\t\t} else {\n\t\t\tstart++;\n\t\t\tstart %= buffer.length;\n\t\t}\n\t}\n\n\tpublic synchronized int[] getCurrentHistory() {\n\t\tint[] result = new int[count];\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tint ix = (start + i) % buffer.length;\n\t\t\tresult[i] = buffer[ix];\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/LogFilter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.util;\n\nimport java.util.logging.Filter;\nimport java.util.logging.LogRecord;\n\n/**\n * @author kobit Created Dec 20, 2011\n */\npublic class LogFilter implements Filter {\n\n\tprivate String[] trackers = null;\n\tprivate String id = null;\n\n\tpublic LogFilter(String id, String ... trackers) {\n\t\tthis.id = id;\n\t\tthis.trackers = trackers;\n\t}\n\t\n\tpublic String getId() {\n\t\treturn id;\n\t}\n\n\t@Override\n\tpublic boolean isLoggable(LogRecord record) {\n\t\tboolean matchTracker = false;\n\t\tString msg = record.getMessage();\n\t\tif (msg != null) {\n\t\t\tint i = 0;\n\t\t\twhile (!matchTracker && i < trackers.length) {\n\t\t\t\tmatchTracker = msg.contains(trackers[i++]);\n\t\t\t}\n\t\t}\n\t\treturn matchTracker;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/LogFormatter.java",
    "content": "/*\n * LogFormatter.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Calendar;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.logging.Formatter;\nimport java.util.logging.LogRecord;\nimport java.util.Map;\n\n/**\n * Describe class LogFormatter here.\n *\n *\n * Created: Thu Jan  5 22:58:02 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class LogFormatter\n\t\t\t\textends Formatter {\n\t/** Field description */\n\tpublic static final Map<Integer, LogWithStackTraceEntry> errors =\n\t\t\tnew ConcurrentSkipListMap<Integer, LogWithStackTraceEntry>();\n\tprivate static int DATE_TIME_LEN = 24;\n\tprivate static int LEVEL_OFFSET  = 12;\n\tprivate static int MED_LEN       = 35;\n\tprivate static int TH_NAME_LEN   = 17;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Calendar cal = Calendar.getInstance();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>LogFormatter</code> instance.\n\t *\n\t */\n\tpublic LogFormatter() {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic synchronized String format(LogRecord record) {\n\t\tStringBuilder sb = new StringBuilder(200);\n\n\t\tcal.setTimeInMillis(record.getMillis());\n\t\tsb.append(String.format(\"%1$tF %1$tT.%1$tL\", cal));\n\n\t\tString th_name = Thread.currentThread().getName();\n\n\t\tsb.append(\" [\").append(th_name).append(\"]\");\n\t\twhile (sb.length() < DATE_TIME_LEN + TH_NAME_LEN) {\n\t\t\tsb.append(' ');\n\t\t}    // end of while (sb.length() < MEDIUM_LEN)\n\t\tif (record.getSourceClassName() != null) {\n\t\t\tString clsName = record.getSourceClassName();\n\t\t\tint    idx     = clsName.lastIndexOf('.');\n\n\t\t\tif (idx >= 0) {\n\t\t\t\tclsName = clsName.substring(idx + 1);\n\t\t\t}    // end of if (idx >= 0)\n\t\t\tsb.append(\"  \").append(clsName);\n\t\t}      // end of if (record.getSourceClassName() != null)\n\t\tif (record.getSourceMethodName() != null) {\n\t\t\tsb.append(\".\").append(record.getSourceMethodName()).append(\"()\");\n\t\t}    // end of if (record.getSourceMethodName() != null)\n\t\twhile (sb.length() < DATE_TIME_LEN + TH_NAME_LEN + MED_LEN) {\n\t\t\tsb.append(' ');\n\t\t}    // end of while (sb.length() < MEDIUM_LEN)\n\t\tsb.append(\"  \").append(record.getLevel()).append(\": \");\n\t\twhile (sb.length() < DATE_TIME_LEN + TH_NAME_LEN + MED_LEN + LEVEL_OFFSET) {\n\t\t\tsb.append(' ');\n\t\t}    // end of while (sb.length() < MEDIUM_LEN)\n\t\tsb.append(formatMessage(record));\n\t\tif (record.getThrown() != null) {\n\t\t\tsb.append('\\n').append(record.getThrown().toString());\n\n\t\t\tStringBuilder st_sb = new StringBuilder(1024);\n\n\t\t\tgetStackTrace(st_sb, record.getThrown());\n\t\t\tsb.append(st_sb.toString());\n\t\t\taddError(record.getThrown(), st_sb.toString(), sb.toString());\n\t\t}\n\n\t\treturn sb.toString() + \"\\n\";\n\t}\n\n\tprivate void addError(Throwable thrown, String stack, String log_msg) {\n\t\tInteger                code  = stack.hashCode();\n\t\tLogWithStackTraceEntry entry = errors.get(code);\n\n\t\tif (entry == null) {\n\t\t\tString msg = thrown.getMessage();\n\n\t\t\tif (msg == null) {\n\t\t\t\tmsg = thrown.toString();\n\t\t\t}\n\t\t\tentry = new LogWithStackTraceEntry(msg, log_msg);\n\t\t\terrors.put(code, entry);\n\t\t}\n\t\tentry.increment();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate void getStackTrace(StringBuilder sb, Throwable th) {\n\t\tif (sb.length() > 0) {\n\t\t\tsb.append(\"\\nCaused by: \").append(th.toString());\n\t\t}\n\n\t\tStackTraceElement[] stackTrace = th.getStackTrace();\n\n\t\tif ((stackTrace != null) && (stackTrace.length > 0)) {\n\t\t\tfor (int i = 0; i < stackTrace.length; i++) {\n\t\t\t\tsb.append(\"\\n\\tat \").append(stackTrace[i].toString());\n\t\t\t}\n\t\t}\n\n\t\tThrowable cause = th.getCause();\n\n\t\tif (cause != null) {\n\t\t\tgetStackTrace(sb, cause);\n\t\t}\n\t}\n}    // LogFormatter\n\n\n//~ Formatted in Tigase Code Convention on 13/05/27\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/LogUserFilter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.util;\n\nimport java.util.Map;\nimport java.util.logging.Filter;\nimport java.util.logging.LogRecord;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPSession;\n\n/**\n * @author kobit Created Dec 20, 2011\n */\npublic class LogUserFilter implements Filter {\n\n\tprivate XMPPSession tracker = null;\n\tMap<BareJID, XMPPSession> sessionsByNodeId = null;\n\tprivate BareJID jid = null;\n\tprivate LogFormatter format = new LogFormatter();\n\n\tpublic LogUserFilter(BareJID jid, Map<BareJID, XMPPSession> sessionsByNodeId) {\n\t\tthis.jid = jid;\n\t\tthis.sessionsByNodeId = sessionsByNodeId;\n\t}\n\n\tpublic String getId() {\n\t\treturn jid.toString();\n\t}\n\n\t@Override\n\tpublic boolean isLoggable(LogRecord record) {\n\t\tboolean matchTracker = false;\n\t\tif (tracker == null || tracker.getActiveResourcesSize() == 0) {\n\t\t\ttracker = sessionsByNodeId.get(jid);\n\t\t}\n\t\tif (tracker != null) {\n\t\t\tString msg = format.format(record);\n\t\t\tif (msg != null) {\n\t\t\t\tif (!matchTracker) {\n\t\t\t\t\tJID[] trackers = tracker.getConnectionIds();\n\t\t\t\t\tif (trackers != null && trackers.length > 0) {\n\t\t\t\t\t\tint i = 0;\n\t\t\t\t\t\twhile (!matchTracker && i < trackers.length) {\n\t\t\t\t\t\t\tmatchTracker = msg.contains(trackers[i++].toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!matchTracker) {\n\t\t\t\t\tJID[] trackers = tracker.getJIDs();\n\t\t\t\t\tif (trackers != null && trackers.length > 0) {\n\t\t\t\t\t\tint i = 0;\n\t\t\t\t\t\twhile (!matchTracker && i < trackers.length) {\n\t\t\t\t\t\t\tmatchTracker = msg.contains(trackers[i++].toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matchTracker;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/LogWithStackTraceEntry.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.LogRecord;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n *\n */\npublic class LogWithStackTraceEntry {\n\tprivate long counter = 0;\n\tprivate String msg = null;\n\tprivate String record = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param record\n\t * @param msg\n\t */\n\tpublic LogWithStackTraceEntry(String msg, String record) {\n\t\tthis.msg = msg;\n\t\tthis.record = record;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getCounter() {\n\t\treturn counter;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getMessage() {\n\t\treturn msg;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic String getRecord() {\n\t\treturn record;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long increment() {\n\t\treturn ++counter;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/LongHistoryCache.java",
    "content": "/*\n * LongHistoryCache.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.util;\n\n/**\n * Created: Sep 8, 2009 7:39:27 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class LongHistoryCache {\n\tprivate long[] buffer = null;\n\tprivate int    count  = 0;\n\tprivate int    start  = 0;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param limit\n\t */\n\tpublic LongHistoryCache(int limit) {\n\t\tbuffer = new long[limit];\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param item is a <code>long</code>\n\t */\n\tpublic synchronized void addItem(long item) {\n\t\tint ix = (start + count) % buffer.length;\n\n\t\tbuffer[ix] = item;\n\t\tif (count < buffer.length) {\n\t\t\tcount++;\n\t\t} else {\n\t\t\tstart++;\n\t\t\tstart %= buffer.length;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return a value of <code>long[]</code>\n\t */\n\tpublic synchronized long[] getCurrentHistory() {\n\t\tlong[] result = new long[count];\n\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tint ix = (start + i) % buffer.length;\n\n\t\t\tresult[i] = buffer[ix];\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/NonpriorityQueue.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.LinkedBlockingQueue;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Feb 9, 2010 11:32:30 AM\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NonpriorityQueue<E> extends PriorityQueueAbstract<E> {\n\tprivate LinkedBlockingQueue<E> queue = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic NonpriorityQueue() {}\n\n\tprotected NonpriorityQueue(int maxSize) {\n\t\tinit(0, maxSize);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic final void init(int maxPriority, int maxSize) {\n\t\tqueue = new LinkedBlockingQueue<E>(maxSize);\n\t}\n\n\t@Override\n\tpublic boolean offer(E element, int priority) {\n\t\treturn queue.offer(element);\n\t}\n\n\t@Override\n\tpublic void put(E element, int priority) throws InterruptedException {\n\t\tqueue.put(element);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setMaxSize(int maxSize) {\n\n//  TODO:\n//  The code below causes a dead-lock as the take() method waits on the\n//  old queue without any chance to be waken up. Up to now I haven't\n//   found a way to awake the thread waiting on the take() method.\n//     LinkedBlockingQueue<E> oldQueue = queue;\n//     int newSize = Math.max(oldQueue.size(), maxSize);\n//\n//     queue = new LinkedBlockingQueue<E>(newSize);\n//     oldQueue.drainTo(queue);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int[] size() {\n\t\tint[] result = new int[1];\n\n\t\tresult[0] = queue.size();\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic E take() throws InterruptedException {\n\t\treturn queue.take();\n\t}\n\n\t@Override\n\tpublic int totalSize() {\n\t\treturn queue.size();\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/OSUtils.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n/**\n * Created: Dec 11, 2008 10:26:00 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class OSUtils {\n\n\tpublic enum OS {\n\t\twindows, linux, sunos, solaris, mac, unix, other;\n\t}\n\n\tpublic static OS getOSType() {\n\t\tString osName = System.getProperty(\"os.name\").toLowerCase();\n\t\tfor (OS os : OS.values()) {\n\t\t\tif (osName.contains(os.toString())) {\n\t\t\t\treturn os;\n\t\t\t}\n\t\t}\n\t\treturn OS.other;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/PatternComparator.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\nimport java.util.Comparator;\nimport java.util.regex.Pattern;\n\n/**\n * Created: Oct 22, 2009 6:08:50 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PatternComparator implements Comparator<Pattern> {\n\n\t@Override\n\tpublic int compare(Pattern o1, Pattern o2) {\n\t\treturn o1.pattern().compareTo(o2.pattern());\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/PriorityQueueAbstract.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Works like a LinkedBlockingQueue using the put() and take() methods but\n * with an additional priority integer parameter. The elemnt returned from\n * take() will honor the priority in such a way that all elements of a lower\n * priority will be returned before any elemens of a higher priority.\n *\n * Modified proposition taken from Noa Resare:\n * http://resare.com/noa/ref/MultiPrioQueue.java\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class PriorityQueueAbstract<E> {\n\n\t/** Field description */\n\tpublic static final String NONPRIORITY_QUEUE = \"nonpriority-queue\";\n\n\t/** Field description */\n\tpublic static final String QUEUE_IMPLEMENTATION = \"queue-implementation\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param maxPriority\n\t * @param maxSize\n\t */\n\tpublic abstract void init(int maxPriority, int maxSize);\n\n\t// public boolean offer(E element, int priority, String owner) {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param element\n\t * @param priority\n\t *\n\t * \n\t */\n\tpublic abstract boolean offer(E element, int priority);\n\n\t// public void put(E element, int priority, String owner) throws InterruptedException {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param element\n\t * @param priority\n\t *\n\t * @throws InterruptedException\n\t */\n\tpublic abstract void put(E element, int priority) throws InterruptedException;\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param maxSize\n\t */\n\tpublic abstract void setMaxSize(int maxSize);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract int[] size();\n\n\t// public E take(String owner) throws InterruptedException {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t *\n\t * @throws InterruptedException\n\t */\n\tpublic abstract E take() throws InterruptedException;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract int totalSize();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param maxPriority\n\t * @param maxSize\n\t * @param <E>\n\t *\n\t * \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <E> PriorityQueueAbstract<E> getPriorityQueue(int maxPriority, int maxSize) {\n\t\tPriorityQueueAbstract<E> result = null;\n\t\tString queue_class = System.getProperty(QUEUE_IMPLEMENTATION, null);\n\n\t\tif ((queue_class == null) || queue_class.isEmpty()) {\n\t\t\tif (Boolean.getBoolean(NONPRIORITY_QUEUE)) {\n\t\t\t\tresult = new NonpriorityQueue<E>(maxSize);\n\t\t\t} else {\n\t\t\t\tresult = new PriorityQueueRelaxed<E>(maxPriority, maxSize);\n\t\t\t}\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tresult = (PriorityQueueAbstract<E>) Class.forName(queue_class).newInstance();\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\tSystem.exit(1);\n\t\t\t}\n\n\t\t\tresult.init(maxPriority, maxSize);\n\t\t}\n\n//  System.out.println(\"Initialized queue implementation: \" + result.getClass().getName());\n\t\treturn result;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/PriorityQueueRelaxed.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Feb 9, 2010 11:12:56 AM\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PriorityQueueRelaxed<E> extends PriorityQueueAbstract<E> {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(PriorityQueueRelaxed.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate LinkedBlockingQueue<E>[] qs = null;\n\tprivate int lowestNonEmpty = Integer.MAX_VALUE;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic PriorityQueueRelaxed() {}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param maxPriority\n\t * @param maxSize\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected PriorityQueueRelaxed(int maxPriority, int maxSize) {\n\t\tinit(maxPriority, maxSize);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic final void init(int maxPriority, int maxSize) {\n\n//  qs = new LinkedBlockingQueue[maxPriority + 1];\n\t\tqs = new LinkedBlockingQueue[maxPriority];\n\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tqs[i] = new LinkedBlockingQueue<E>(maxSize);\n\t\t}\n\n\t\t// System.out.println(\"PriorityQueueRelaxed Initialized: \" + maxSize);\n\t}\n\n\t@Override\n\tpublic boolean offer(E element, int priority) {\n\t\ttry {\n\n\t\t\t// return add(element, priority, false, owner);\n\t\t\treturn add(element, priority, false);\n\t\t} catch (InterruptedException e) {\n\t\t\tlog.warning(\"This should not happen, this is non-blocking operation.\");\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// public void put(E element, int priority, String owner) throws InterruptedException {\n\n\t@Override\n\tpublic void put(E element, int priority) throws InterruptedException {\n\n\t\t// add(element, priority, true, owner);\n\t\tadd(element, priority, true);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setMaxSize(int maxSize) {\n\t\tfor (int i = 0; i < qs.length; i++) {\n\n\t\t\t// We don't want to lose any data so the new size must\n\t\t\t// be enough to keep all exising elements\n\t\t\tLinkedBlockingQueue<E> oldQueue = qs[i];\n\t\t\tint newSize = Math.max(oldQueue.size(), maxSize);\n\n\t\t\tqs[i] = new LinkedBlockingQueue<E>(newSize);\n\t\t\toldQueue.drainTo(qs[i]);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int[] size() {\n\t\tint[] result = new int[qs.length];\n\n\t\tfor (int i = 0; i < result.length; i++) {\n\t\t\tresult[i] = qs[i].size();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// public E take(String owner) throws InterruptedException {\n\n\t@Override\n\tpublic E take() throws InterruptedException {\n\t\tE e = null;\n\n\t\twhile (e == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Safeguard for \"java wait spurious wakeup\", google for it\n\t\t\t\t\t// if you don't know it. I have just learned about it too...\n\t\t\t\t\twhile (lowestNonEmpty == Integer.MAX_VALUE) {\n\n//          log.finest(\"[\" + owner + \"] waiting...\");\n\t\t\t\t\t\tthis.wait();\n\t\t\t\t\t}\n\t\t\t\t} catch (InterruptedException ex) {}\n\n\t\t\t\tLinkedBlockingQueue<E> q = qs[lowestNonEmpty];\n\n\t\t\t\t// log.log(Level.FINEST, \"{0} taking from queue: \", lowestNonEmpty);\n\t\t\t\te = q.poll();\n\n//      if (e != null) {\n//        log.log(Level.FINEST, \"{0} element read: {1}\", new Object[] { lowestNonEmpty, e });\n//      } else {\n//        log.log(Level.FINEST, \"{0} NULL element read!\", lowestNonEmpty);\n//      }\n\t\t\t\tif ((e == null) || q.isEmpty()) {\n\t\t\t\t\tlowestNonEmpty = findNextNonEmpty();\n\n//        log.finest(\"[\" + owner + \"] \" + \"new lowestNonEmpty: \" + lowestNonEmpty);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn e;\n\t}\n\n\t@Override\n\tpublic int totalSize() {\n\t\tint result = 0;\n\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tresult += qs[i].size();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// TODO: Reduce synchronization but be carefull many threads are writing\n\t// to queues at the same time.\n\t// private boolean add(E element, int priority, boolean blocking, String owner)\n\tprivate boolean add(E element, int priority, boolean blocking) throws InterruptedException {\n\t\tif ((priority < 0) || (qs.length <= priority)) {\n\t\t\tthrow new IllegalArgumentException(\"parameter priority must be \" + \"between 0 and \"\n\t\t\t\t\t+ (qs.length - 1));\n\t\t}\n\n\t\tboolean result = true;\n\t\tLinkedBlockingQueue<E> q = qs[priority];\n\n\t\tif (blocking) {\n\n//    log.log(Level.FINEST, \"{0} B before element add: {1}\",\n//        new Object[] { priority, element });\n\t\t\tq.put(element);\n\n\t\t\t// log.finest(\"[\" + owner + \"] \" + priority + \" B element added: \" + element.toString());\n//    log.log(Level.FINEST, \"{0} B element added: {1}\", new Object[] { priority, element });\n\t\t} else {\n\t\t\tresult = q.offer(element);\n\n//    log.log(Level.FINEST, \"{0} NB element added: {1}\", new Object[] { priority, element });\n//    log.finest(\"[\" + owner + \"] \" + priority + \" NB element added: \" +\n//            element.toString() + \", result: \" + result +\n//            \", lowestNonEmpty: \" + lowestNonEmpty + \", size: \" + q.size());\n\t\t}\n\n\t\tif (result) {\n\t\t\tsynchronized (this) {\n\t\t\t\tif (priority < lowestNonEmpty) {\n\n//        log.finest(\"[\" + owner + \"] setting new priority from \" +\n//                lowestNonEmpty + \", to: \" + priority);\n\t\t\t\t\tlowestNonEmpty = priority;\n\t\t\t\t}\n\n\t\t\t\tthis.notify();\n\t\t\t}\n\t\t} else {\n\t\t\tif (priority < qs.length - 1) {\n\n\t\t\t\t// result = add(element, priority + 1, blocking, owner);\n\t\t\t\tresult = add(element, priority + 1, blocking);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate int findNextNonEmpty() {\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tif ( !qs[i].isEmpty()) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn Integer.MAX_VALUE;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/PriorityQueueStrict.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Jul 25, 2010 4:09:05 PM\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PriorityQueueStrict<E> extends PriorityQueueAbstract<E> {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(PriorityQueueRelaxed.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate LinkedBlockingQueue<E>[] qs = null;\n\tprivate int lowestNonEmpty = Integer.MAX_VALUE;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic PriorityQueueStrict() {}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param maxPriority\n\t * @param maxSize\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected PriorityQueueStrict(int maxPriority, int maxSize) {\n\t\tinit(maxPriority, maxSize);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic final void init(int maxPriority, int maxSize) {\n\n//  qs = new LinkedBlockingQueue[maxPriority + 1];\n\t\t// Setting a fixed priority to 3 which means all standard XMPP\n\t\t// packets go to the same queue, preventing packets reordering\n\t\t// 3 - SYSTEM, CLUSTER, HIGH\n//    qs = new LinkedBlockingQueue[maxPriority];\n\t\tqs = new LinkedBlockingQueue[3];\n\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tqs[i] = new LinkedBlockingQueue<E>(maxSize);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean offer(E element, int priority) {\n\t\ttry {\n\n\t\t\t// return add(element, priority, false, owner);\n\t\t\treturn add(element, priority, false);\n\t\t} catch (InterruptedException e) {\n\t\t\tlog.warning(\"This should not happen, this is non-blocking operation.\");\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// public void put(E element, int priority, String owner) throws InterruptedException {\n\n\t@Override\n\tpublic void put(E element, int priority) throws InterruptedException {\n\n\t\t// add(element, priority, true, owner);\n\t\tadd(element, priority, true);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setMaxSize(int maxSize) {\n\t\tfor (int i = 0; i < qs.length; i++) {\n\n\t\t\t// We don't want to lose any data so the new size must\n\t\t\t// be enough to keep all exising elements\n\t\t\tLinkedBlockingQueue<E> oldQueue = qs[i];\n\t\t\tint newSize = Math.max(oldQueue.size(), maxSize);\n\n\t\t\tqs[i] = new LinkedBlockingQueue<E>(newSize);\n\t\t\toldQueue.drainTo(qs[i]);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int[] size() {\n\t\tint[] result = new int[qs.length];\n\n\t\tfor (int i = 0; i < result.length; i++) {\n\t\t\tresult[i] = qs[i].size();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic E take() throws InterruptedException {\n\t\tE e = null;\n\n\t\twhile (e == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Safeguard for \"java wait spurious wakeup\", google for it\n\t\t\t\t\t// if you don't know it. I have just learned about it too...\n\t\t\t\t\twhile (lowestNonEmpty == Integer.MAX_VALUE) {\n\n//          log.finest(\"[\" + owner + \"] waiting...\");\n\t\t\t\t\t\tthis.wait();\n\t\t\t\t\t}\n\t\t\t\t} catch (InterruptedException ex) {}\n\n\t\t\t\tLinkedBlockingQueue<E> q = qs[lowestNonEmpty];\n\n\t\t\t\t// log.finest(\"\" + lowestNonEmpty + \" taking from queue: \");\n\t\t\t\te = q.poll();\n\n//      if (e != null) {\n//        log.finest(\"[\" + owner + \"] \" + lowestNonEmpty + \" element read: \" + e.toString());\n//      } else {\n//        log.finest(\"[\" + owner + \"] \" + lowestNonEmpty + \" NULL element read!\");\n//      }\n\t\t\t\tif ((e == null) || q.isEmpty()) {\n\t\t\t\t\tlowestNonEmpty = findNextNonEmpty();\n\n//        log.finest(\"[\" + owner + \"] \" + \"new lowestNonEmpty: \" + lowestNonEmpty);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn e;\n\t}\n\n\t@Override\n\tpublic int totalSize() {\n\t\tint result = 0;\n\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tresult += qs[i].size();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// TODO: Reduce synchronization but be carefull many threads are writing\n\t// to queues at the same time.\n\t// private boolean add(E element, int priority, boolean blocking, String owner)\n\tprivate boolean add(E element, int pr, boolean blocking) throws InterruptedException {\n\t\tint priority = pr;\n\n\t\tif (priority < 0) {\n\t\t\tthrow new IllegalArgumentException(\"parameter priority must be \" + \"between 0 and \"\n\t\t\t\t\t+ (qs.length - 1));\n\t\t}\n\n\t\tif (qs.length <= priority) {\n\t\t\tpriority = qs.length - 1;\n\t\t}\n\n\t\tboolean result = true;\n\t\tLinkedBlockingQueue<E> q = qs[priority];\n\n\t\tif (blocking) {\n\t\t\tq.put(element);\n\n//    log.finest(\"[\" + owner + \"] \" + priority + \" B element added: \" + element.toString());\n\t\t\t// log.finest(\"\" + priority + \" B element added: \" + element.toString());\n\t\t} else {\n\t\t\tresult = q.offer(element);\n\n\t\t\t// log.finest(\"\" + priority + \" B element added: \" + element.toString());\n//    log.finest(\"[\" + owner + \"] \" + priority + \" NB element added: \" +\n//            element.toString() + \", result: \" + result +\n//            \", lowestNonEmpty: \" + lowestNonEmpty + \", size: \" + q.size());\n\t\t}\n\n\t\tif (result) {\n\t\t\tsynchronized (this) {\n\t\t\t\tif (priority < lowestNonEmpty) {\n\n//        log.finest(\"[\" + owner + \"] setting new priority from \" +\n//                lowestNonEmpty + \", to: \" + priority);\n\t\t\t\t\tlowestNonEmpty = priority;\n\t\t\t\t}\n\n\t\t\t\tthis.notify();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate int findNextNonEmpty() {\n\t\tfor (int i = 0; i < qs.length; i++) {\n\t\t\tif ( !qs[i].isEmpty()) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn Integer.MAX_VALUE;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/ProcessingThreads.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 21, 2009 8:50:50 PM\n *\n * @param <E>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class ProcessingThreads<E extends WorkerThread> {\n\tprivate static final Logger log = Logger.getLogger(ProcessingThreads.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long droppedPackets = 0;\n\n\t// private int maxQueueSize = 10000;\n\tprivate String name = null;\n\n\t// Packets are put in queues in such a way that all packets for the same\n\t// user end-up in the same queue. This is important in some cases as\n\t// packet processing order does matter in some cases, especially for\n\t// roster processing.\n\t// Therefore it is also recommended that there is a single thread for\n\t// each queue but we can ditribute load increasing number of queues.\n\t// private int numQueues = 2;\n\tprivate int numWorkerThreads = 1;\n\tprivate ArrayList<E> workerThreads = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n//private ArrayList<PriorityQueueAbstract<QueueItem>> queues =\n//  new ArrayList<PriorityQueueAbstract<QueueItem>>(1);\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param worker\n\t * @param numWorkerThreads\n\t * @param maxQueueSize\n\t * @param name\n\t * @throws ClassNotFoundException\n\t * @throws InstantiationException\n\t * @throws IllegalAccessException\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic ProcessingThreads(E worker, int numWorkerThreads, int maxQueueSize, String name)\n\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException {\n\n\t\t// this.numQueues = numQueues;\n\t\t// this.maxQueueSize = maxQueueSize;\n\t\tthis.numWorkerThreads = numWorkerThreads;\n\t\tworkerThreads = new ArrayList<E>(numWorkerThreads);\n\t\tthis.name = name;\n\n//  for (int i = 0; i < numQueues; i++) {\n\t\t// LinkedBlockingQueue<QueueItem> queue = new LinkedBlockingQueue<QueueItem>(maxQueueSize);\n//  queues.add(queue);\n\t\tfor (int j = 0; j < numWorkerThreads; j++) {\n\t\t\tWorkerThread t = worker.getNewInstance();\n\n\t\t\tt.setQueueMaxSize(maxQueueSize);\n\t\t\tt.setDaemon(true);\n\t\t\tt.setName(name + \" Queue Worker \" + j);\n\t\t\tt.start();\n\t\t\tworkerThreads.add((E) t);\n\t\t\tlog.log(Level.FINEST, \"Created worker thread: {0}, queueSize: {1}\", new Object[] {t.getName(), maxQueueSize});\n\t\t}\n\n//  }\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param processor\n\t * @param packet\n\t * @param conn\n\t *\n\t *\n\t */\n\tpublic boolean addItem(XMPPProcessorIfc processor, Packet packet, XMPPResourceConnection conn) {\n\t\tboolean ret = false;\n\t\tQueueItem item = new QueueItem(processor, packet, conn);\n\n\t\ttry {\n\t\t\tif ((item.getConn() != null) && item.getConn().isAuthorized()) {\n\n\t\t\t\t// Queueing packets per user...\n\t\t\t\tret = workerThreads.get(Math.abs(conn.getJID().getBareJID().hashCode())\n\t\t\t\t\t\t% numWorkerThreads).offer(item);\n\n//      ret = queues.get(Math.abs(conn.getJID().getBareJID().hashCode()\n//          % numQueues)).offer(item, packet.getPriority().ordinal());\n\t\t\t} else {\n\t\t\t\tif (packet.getPacketFrom() != null) {\n\n\t\t\t\t\t// Queueing packets per user's connection...\n\t\t\t\t\tret = workerThreads.get(Math.abs(packet.getPacketFrom().hashCode())\n\t\t\t\t\t\t\t% numWorkerThreads).offer(item);\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise per destination address\n\t\t\t\t\t// If the packet elemTo is set then used it, otherwise just packetTo:\n\t\t\t\t\tif (packet.getStanzaTo() != null) {\n\t\t\t\t\t\tret = workerThreads.get(Math.abs(packet.getStanzaTo().getBareJID().hashCode())\n\t\t\t\t\t\t\t\t% numWorkerThreads).offer(item);\n\n//          ret = queues.get(Math.abs(packet.getStanzaTo().hashCode() % numQueues)).offer(item,\n//              packet.getPriority().ordinal());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = workerThreads.get(Math.abs(packet.getTo().hashCode())).offer(item);\n\n//          ret = queues.get(Math.abs(packet.getTo().hashCode() % numQueues)).offer(item,\n//              packet.getPriority().ordinal());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\n\t\t\t// This should not happen, but just in case until we are sure all\n\t\t\t// cases are catched.\n\t\t\t// Otherwise per destination address\n\t\t\t// If the packet elemTo is set then used it, otherwise just packetTo:\n\t\t\tif (packet.getStanzaTo() != null) {\n\t\t\t\tret = workerThreads.get(Math.abs(packet.getStanzaTo().getBareJID().hashCode())\n\t\t\t\t\t\t% numWorkerThreads).offer(item);\n\t\t\t} else {\n\t\t\t\tret = workerThreads.get(Math.abs(packet.getTo().hashCode()) % numWorkerThreads).offer(item);\n\t\t\t}\n\n\t\t\t// ret = nullQueue.offer(item, packet.getPriority().ordinal());\n\t\t}\n\n\t\tif ( !ret) {\n\t\t\t++droppedPackets;\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet dropped due to queue overflow: {0}\", packet);\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic long getAverageProcessingTime() {\n\t\tlong average = 0;\n\t\tint counters = 0;\n\n\t\tfor (WorkerThread workerThread : workerThreads) {\n\t\t\tif (workerThread.getAverageProcessingTime() > 0) {\n\t\t\t\taverage += workerThread.getAverageProcessingTime();\n\t\t\t\t++counters;\n\t\t\t}\n\t\t}\n\n\t\tif (counters > 0) {\n\t\t\treturn average / counters;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic long getDroppedPackets() {\n\t\treturn droppedPackets;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic int getTotalQueueSize() {\n\t\tint ret = 0;\n\n\t\tfor (E pq : workerThreads) {\n\t\t\tret += pq.size();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic int getTotalRuns() {\n\t\tint ret = 0;\n\n\t\tfor (WorkerThread workerThread : workerThreads) {\n\t\t\tret += workerThread.getRunsCounter();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n        public void shutdown() {\n                for (WorkerThread workerThread : workerThreads) {\n                        workerThread.shutdown();\n                }\n        }\n///**\n// * Method description\n// *\n// *\n// *\n// */\n//public E getWorkerThread() {\n//  try {\n//    return workerThreads.getFirst();\n//  } catch (Exception e) {\n//    return null;\n//  }\n//}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/PropertiesUtil.java",
    "content": "package tigase.util;\n\nimport java.io.FileInputStream;\nimport java.util.Properties;\n\npublic class PropertiesUtil {\n\t\n\tprivate static final String File_Name = \"etc/init-redis.properties\";\n\n\tprivate static Properties propts;\n\n\tstatic {\n\n\t\ttry {\n\t\t\tpropts = new Properties();\n\t\t\tpropts.load(new FileInputStream(File_Name));\n\t\t} catch (Exception ex) {\n\t\t\tex.printStackTrace();\n\t\t}\n\t}\n\n\tpublic static String get(String name, String defaultValue) {\n\t\t\n\t\tString value = (String) propts.get(name);\n\n\t\treturn value != null ? value : defaultValue;\n\t}\n\t\n\tpublic static String get(String name) {\n\t\t\n\t\treturn (String) propts.get(name);\n\t}\n//\n//\t@SuppressWarnings(\"unchecked\")\n//\tpublic static Context getInitialContext() {\n//\t\tContext context = null;\n//\n//\t\tString jndiFactory = Props.get(\"jndi.factory\");\n//\t\tString providerUrl = Props.get(\"jndi.provider.url\");\n//\n//\t\tHashtable env = new Hashtable();\n//\t\tenv.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);\n//\t\tenv.put(Context.PROVIDER_URL, providerUrl);\n//\n//\t\ttry {\n//\t\t\tcontext = new InitialContext(env);\n//\t\t} catch (Exception ex) {\n//\t\t\tex.printStackTrace();\n//\t\t}\n//\n//\t\treturn context;\n//\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/QueueItem.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 21, 2009 9:05:23 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class QueueItem {\n\tprivate XMPPResourceConnection conn;\n\tprivate Packet packet;\n\tprivate XMPPProcessorIfc processor;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param processor\n\t * @param packet\n\t * @param conn\n\t */\n\tpublic QueueItem(XMPPProcessorIfc processor, Packet packet, XMPPResourceConnection conn) {\n\t\tif (processor == null) {\n\t\t\tthrow new NullPointerException(\"Processor parameter cannot be null!\");\n\t\t}\n\n\t\tif (packet == null) {\n\t\t\tthrow new NullPointerException(\"Packet parameter cannot be null!\");\n\t\t}\n\n\t\tthis.processor = processor;\n\t\tthis.packet = packet;\n\t\tthis.conn = conn;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * @return the conn\n\t */\n\tpublic XMPPResourceConnection getConn() {\n\t\treturn conn;\n\t}\n\n\t/**\n\t * @return the packet\n\t */\n\tpublic Packet getPacket() {\n\t\treturn packet;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic XMPPProcessorIfc getProcessor() {\n\t\treturn processor;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/RepositoryUtils.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.RepositoryFactory;\nimport tigase.db.AuthRepository;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserRepository;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.impl.roster.RosterAbstract;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.Writer;\n\nimport java.util.List;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class RepositoryUtils here.\n *\n *\n * Created: Sat Oct 28 13:09:26 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class RepositoryUtils {\n\tprivate static long counter = 0;\n\tprivate static BareJID user1 = BareJID.bareJIDInstanceNS(\"user111@hostname\");\n\tprivate static BareJID user2 = BareJID.bareJIDInstanceNS(\"user222@hostname\");\n\tprivate static BareJID user3 = BareJID.bareJIDInstanceNS(\"user333@hostname\");\n\tprivate static String src_class = \"tigase.db.jdbc.JDBCRepository\";\n\tprivate static String src_uri = null;\n\tprivate static String dst_class = null;\n\tprivate static String dst_uri = null;\n\tprivate static String content = null;\n\tprivate static BareJID user = null;\n\tprivate static boolean simple_test = false;\n\tprivate static boolean add_user_test = false;\n\tprivate static boolean copy_repos = false;\n\tprivate static boolean print_repo = false;\n\tprivate static boolean add = false;\n\tprivate static boolean del = false;\n\tprivate static boolean node = false;\n\tprivate static boolean key_val = false;\n\tprivate static boolean check_roster = false;\n\tprivate static boolean allowed_empty_groups = true;\n\tprivate static boolean import_data = false;\n\tprivate static boolean export_data = false;\n\tprivate static String subnode = null;\n\tprivate static String key = null;\n\tprivate static String value = null;\n\tprivate static String import_file = null;\n\tprivate static String export_file = null;\n\n\t//~--- methods --------------------------------------------------------------\n\n//public static boolean checkJID(JID jid) {\n//  String nick_check = JIDUtils.checkNickName(JIDUtils.getNodeNick(jid));\n//  if (nick_check != null) {\n//    System.out.println(\"      Invalid nickname - \" + JIDUtils.getNodeNick(jid)\n//      + \": \" + nick_check);\n//    return false;\n//  }\n//  String host_check = JIDUtils.checkNickName(JIDUtils.getNodeHost(jid));\n//  if (host_check != null) {\n//    System.out.println(\"      Invalid hostname - \" + JIDUtils.getNodeHost(jid)\n//      + \": \" + host_check);\n//    return false;\n//  }\n//  return true;\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param repo\n\t * @param cont\n\t *\n\t * \n\t *\n\t * @throws Exception\n\t */\n\tpublic static boolean checkContact(BareJID user, UserRepository repo, String cont)\n\t\t\tthrows Exception {\n\n\t\t// String[] keys = repo.getKeys(user, \"roster/\"+contact);\n\t\tJID contact = JID.jidInstanceNS(cont);\n\t\tString[] vals = repo.getDataList(user, \"roster/\" + contact, RosterAbstract.GROUPS);\n\n\t\tif ((vals == null) || (vals.length == 0)) {\n\t\t\tSystem.out.println(\"      Empty groups list\");\n\n\t\t\tif ( !allowed_empty_groups) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tfor (String val : vals) {\n\t\t\t\tif (val.equals(\"Upline Support\") || val.equals(\"Support\") || val.startsWith(\"Level \")) {\n\t\t\t\t\tSystem.out.println(\"      Invalid group: \" + val);\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param node\n\t * @param src\n\t * @param dst\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void copyNode(BareJID user, String node, UserRepository src, UserRepository dst)\n\t\t\tthrows Exception {\n\t\tString[] keys = src.getKeys(user, node);\n\n\t\tif (keys != null) {\n\t\t\tfor (String key : keys) {\n\t\t\t\tString[] vals = src.getDataList(user, node, key);\n\n\t\t\t\tif (vals != null) {\n\t\t\t\t\tdst.setDataList(user, node, key, vals);\n\t\t\t\t}    // end of if (vals != null) else\n\t\t\t}      // end of for (String key: keys)\n\t\t}        // end of if (keys != null)\n\n\t\tString[] nodes = src.getSubnodes(user, node);\n\n\t\tif (nodes != null) {\n\t\t\tfor (String subnode : nodes) {\n\t\t\t\tcopyNode(user, ((node != null) ? node + \"/\" + subnode : subnode), src, dst);\n\t\t\t}    // end of for (String node: nodes)\n\t\t}      // end of if (ndoes != null)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param src\n\t * @param dst\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void copyRepositories(UserRepository src, UserRepository dst) throws Exception {\n\t\tif (user != null) {\n\t\t\tcopyUser(user, src, dst);\n\t\t} else {\n\t\t\tList<BareJID> users = src.getUsers();\n\n\t\t\tif (users != null) {\n\t\t\t\tSystem.out.println(\"Found \" + users.size() + \" in the source repository.\");\n\n\t\t\t\tfor (BareJID usr : users) {\n\t\t\t\t\tSystem.out.println(\"Found \" + usr + \" in the source repository.\");\n\t\t\t\t\tcopyUser(usr, src, dst);\n\t\t\t\t}    // end of for (String user: users)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"There are no user accounts in source repository.\");\n\t\t\t}      // end of else\n\t\t}        // end of if (user != null) else\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param src\n\t * @param dst\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void copyRepositories(UserRepository src, AuthRepository dst) throws Exception {\n\t\tif (user != null) {\n\t\t\tcopyUser(user, src, dst);\n\t\t} else {\n\t\t\tList<BareJID> users = src.getUsers();\n\n\t\t\tif (users != null) {\n\t\t\t\tfor (BareJID usr : users) {\n\t\t\t\t\tcopyUser(usr, src, dst);\n\t\t\t\t}    // end of for (String user: users)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"There are no user accounts in source repository.\");\n\t\t\t}      // end of else\n\t\t}        // end of if (user != null) else\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param src\n\t * @param dst\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void copyUser(BareJID user, UserRepository src, UserRepository dst)\n\t\t\tthrows Exception {\n\t\tif (user == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tSystem.out.print(\"Copying user: \" + user + \"...\");\n\n\t\ttry {\n\t\t\tdst.addUser(user);\n\t\t\tcopyNode(user, null, src, dst);\n\t\t\tSystem.out.println(\"OK\");\n\t\t} catch (UserExistsException e) {\n\t\t\tSystem.out.println(\"ERROR, user already exists.\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param src\n\t * @param dst\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void copyUser(BareJID user, UserRepository src, AuthRepository dst)\n\t\t\tthrows Exception {\n\t\tif ((user == null)) {\n\t\t\treturn;\n\t\t}\n\n\t\tSystem.out.print(\"Copying user: \" + user + \"...\");\n\n\t\tString password = src.getData(user, \"password\");\n\n\t\ttry {\n\t\t\tdst.addUser(user, password);\n\t\t\tSystem.out.println(\"OK\");\n\t\t} catch (UserExistsException e) {\n\t\t\tSystem.out.println(\"ERROR, user already exists.\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t * @param w\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void exportRoster(UserRepository repo, Writer w) throws Exception {\n\t\tif (user != null) {\n\t\t\texportUserRoster(user, repo, w);\n\t\t} else {\n\t\t\tList<BareJID> users = repo.getUsers();\n\n\t\t\tif (users != null) {\n\t\t\t\tfor (BareJID usr : users) {\n\n\t\t\t\t\t// System.out.println(usr);\n\t\t\t\t\texportUserRoster(usr, repo, w);\n\t\t\t\t}    // end of for (String user: users)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"There are no user accounts in repository.\");\n\t\t\t}      // end of else\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param repo\n\t * @param w\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void exportUserRoster(BareJID user, UserRepository repo, Writer w)\n\t\t\tthrows Exception {\n\t\tSystem.out.println(\"  \" + (++counter) + \". \" + user + \" roster: \");\n\n\t\tString[] contacts = repo.getSubnodes(user, \"roster\");\n\n\t\tif (contacts != null) {\n\t\t\tfor (String contact : contacts) {\n\t\t\t\tSystem.out.println(\"    contact: \" + contact);\n\n\t\t\t\tboolean valid = checkContact(user, repo, contact);\n\n\t\t\t\tif (valid) {\n\t\t\t\t\tSystem.out.println(\"      looks OK\");\n\n\t\t\t\t\tString password = repo.getData(user, \"password\");\n\t\t\t\t\tString[] groups = repo.getDataList(user, \"roster/\" + contact, RosterAbstract.GROUPS);\n\t\t\t\t\tString contact_nick = repo.getData(user, \"roster/\" + contact, RosterAbstract.NAME);\n\t\t\t\t\tString subscription = repo.getData(user, \"roster/\" + contact,\n\t\t\t\t\t\tRosterAbstract.SUBSCRIPTION);\n\t\t\t\t\tStringBuilder sb = new StringBuilder(user.toString());\n\n\t\t\t\t\tsb.append(\",\");\n\n\t\t\t\t\tif (password != null) {\n\t\t\t\t\t\tsb.append(password);\n\t\t\t\t\t}\n\n\t\t\t\t\tsb.append(\",\" + contact);\n\t\t\t\t\tsb.append(\",\");\n\n\t\t\t\t\tif (contact_nick != null) {\n\t\t\t\t\t\tsb.append(contact_nick);\n\t\t\t\t\t}\n\n\t\t\t\t\tsb.append(\",\");\n\n\t\t\t\t\tif (subscription != null) {\n\t\t\t\t\t\tsb.append(subscription);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((groups != null) && (groups.length > 0)) {\n\t\t\t\t\t\tfor (String group : groups) {\n\t\t\t\t\t\t\tsb.append(\",\" + group);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsb.append(\"\\n\");\n\t\t\t\t\tw.write(sb.toString());\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(\"      should be REMOVED\");\n\n\t\t\t\t\tString contact_node = \"roster/\" + contact;\n\n\t\t\t\t\tSystem.out.println(\"      removing node: \" + contact_node);\n\n\t\t\t\t\t// repo.removeSubnode(user, contact_node);\n\t\t\t\t\tSystem.out.println(\"      DONE.\");\n\t\t\t\t}\n\t\t\t}    // end of for (String node: nodes)\n\t\t} else {\n\t\t\tSystem.out.println(\"    empty roster...\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void loadTestData(UserRepository repo) throws Exception {\n\t\ttry {\n\t\t\trepo.addUser(user1);\n\t\t} catch (UserExistsException e) {}\n\n\t\ttry {\n\t\t\trepo.addUser(user2);\n\t\t} catch (UserExistsException e) {}\n\n\t\ttry {\n\t\t\trepo.addUser(user3);\n\t\t} catch (UserExistsException e) {}\n\n\t\trepo.setData(user1, null, \"password\", \"secret111\");\n\t\trepo.setData(user2, null, \"password\", \"secret222\");\n\t\trepo.setData(user3, null, \"password\", \"secret333\");\n\t\trepo.setData(user1, \"roster/buddy111\", \"name\", \"budy1\");\n\t\trepo.setData(user1, \"roster/buddy222\", \"name\", \"budy2\");\n\t\trepo.setData(user1, \"roster/buddy333\", \"name\", \"budy3\");\n\t\trepo.setDataList(user1, \"roster/buddy111\", \"groups\", new String[] { \"buddies\", \"friends\" });\n\t\trepo.setDataList(user2, \"roster/buddy111\", \"groups\", new String[] { \"buddies\", \"friends\" });\n\t\trepo.addDataList(user2, \"roster/buddy111\", \"groups\", new String[] { \"family\", \"home\" });\n\t}\n\n\t/**\n\t * Describe <code>main</code> method here.\n\t *\n\t * @param args a <code>String[]</code> value\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void main(final String[] args) throws Exception {\n\t\tparseParams(args);\n\n\t\tException repo_exc = null;\n\t\tUserRepository src_repo = null;\n\t\tAuthRepository src_auth = null;\n\n\t\ttry {\n\t\t\tsrc_repo = RepositoryFactory.getUserRepository(src_class, src_uri, null);\n\t\t\tSystem.out.println(\"Loaded src_repo \" + src_repo.getClass().getName() + \" for parameters:\"\n\t\t\t\t\t+ \"\\n   src_class=\" + src_class + \"\\n   src_uri=\" + src_uri);\n\t\t} catch (Exception e) {\n\t\t\trepo_exc = e;\n\t\t\tsrc_repo = null;\n\t\t}    // end of try-catch\n\n\t\t// Unsuccessful UserRepository initialization\n\t\t// Let's try with AuthRepository....\n\t\tif (src_repo == null) {\n\t\t\ttry {\n\t\t\t\tsrc_auth = RepositoryFactory.getAuthRepository(src_class, src_uri, null);\n\t\t\t\tSystem.out.println(\"Loaded src_auth \" + src_auth.getClass().getName() + \" for parameters:\"\n\t\t\t\t\t\t+ \"\\n   src_class=\" + src_class + \"\\n   src_uri=\" + src_uri);\n\t\t\t} catch (Exception e) {\n\t\t\t\tSystem.out.println(\"Incorrect source class name given (or connection URI).\");\n\t\t\t\tSystem.out.println(\"class: \" + src_class);\n\t\t\t\tSystem.out.println(\"uri: \" + src_uri);\n\t\t\t\tSystem.out.println(\"Can't initialize repository:\");\n\t\t\t\trepo_exc.printStackTrace();\n\t\t\t\te.printStackTrace();\n\t\t\t\tSystem.exit(-1);\n\t\t\t}    // end of try-catch\n\t\t}      // end of if (src_repo == null)\n\n\t\tif (simple_test) {\n\t\t\tSystem.out.println(\"Simple test on repository:\");\n\t\t\tsimpleTest(src_repo);\n\t\t}    // end of if (simple_test)\n\n\t\tif (add_user_test) {\n\t\t\tSystem.out.println(\"Simple test on repository:\");\n\t\t\tuserAddTest(src_repo);\n\t\t}    // end of if (simple_test)\n\n\t\tif (add) {\n\t\t\tif (key_val && (src_repo != null)) {\n\t\t\t\tSystem.out.println(\"Adding key=value: \" + content);\n\t\t\t\tparseNodeKeyValue(content);\n\t\t\t\tSystem.out.println(\"Parsed parameters: user=\" + user + \", node=\" + subnode + \", key=\" + key\n\t\t\t\t\t\t+ \", value=\" + value);\n\t\t\t\tsrc_repo.setData(user, subnode, key, value);\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"Adding user: \" + user);\n\n\t\t\t\tif (src_repo != null) {\n\t\t\t\t\tsrc_repo.addUser(user);\n\t\t\t\t}\n\n\t\t\t\tif (src_auth != null) {\n\t\t\t\t\tBareJID name = user;\n\t\t\t\t\tString password = \"\";\n\n\t\t\t\t\tsrc_auth.addUser(name, password);\n\t\t\t\t}\n\t\t\t}    // end of else\n\t\t}      // end of if (add)\n\n\t\tif (del) {\n\t\t\tif (key_val || node) {\n\t\t\t\tif (key_val) {\n\t\t\t\t\tSystem.out.println(\"Deleting data: \" + content);\n\t\t\t\t\tparseNodeKeyValue(content);\n\t\t\t\t\tSystem.out.println(\"Parsed parameters: user=\" + user + \", node=\" + subnode + \", key=\"\n\t\t\t\t\t\t\t+ key + \", value=\" + value);\n\t\t\t\t\tsrc_repo.removeData(user, subnode, key);\n\t\t\t\t}    // end of if (key_val)\n\n\t\t\t\tif (node) {\n\t\t\t\t\tSystem.out.println(\"Deleting data node: \" + content);\n\t\t\t\t\tsrc_repo.removeSubnode(user, content);\n\t\t\t\t}    // end of if (node)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"Deleting user: \" + user);\n\n\t\t\t\tif (src_repo != null) {\n\t\t\t\t\tsrc_repo.removeUser(user);\n\t\t\t\t}\n\n\t\t\t\tif (src_auth != null) {\n\t\t\t\t\tsrc_auth.removeUser(user);\n\t\t\t\t}\n\t\t\t}      // end of else\n\t\t}        // end of if (del)\n\n\t\tif (copy_repos) {\n\t\t\tUserRepository dst_repo = null;\n\t\t\tException dst_exc = null;\n\t\t\tAuthRepository dst_auth = null;\n\n\t\t\ttry {\n\t\t\t\tdst_repo = RepositoryFactory.getUserRepository(dst_class, dst_uri, null);\n\t\t\t\tSystem.out.println(\"Loaded dst_repo \" + dst_repo.getClass().getName() + \" for parameters:\"\n\t\t\t\t\t\t+ \"\\n   src_class=\" + dst_class + \"\\n   src_uri=\" + dst_uri);\n\t\t\t\tcopyRepositories(src_repo, dst_repo);\n\t\t\t} catch (Exception e) {\n\t\t\t\tdst_exc = e;\n\t\t\t\tdst_repo = null;\n\t\t\t}    // end of try-catch\n\n\t\t\tif (dst_repo == null) {\n\t\t\t\ttry {\n\t\t\t\t\tdst_auth = RepositoryFactory.getAuthRepository(dst_class, dst_uri, null);\n\t\t\t\t\tSystem.out.println(\"Loaded dst_auth \" + dst_auth.getClass().getName()\n\t\t\t\t\t\t\t+ \" for parameters:\" + \"\\n   src_class=\" + dst_class + \"\\n   src_uri=\" + dst_uri);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tSystem.out.println(\"Incorrect destination class name given (or connection URI).\");\n\t\t\t\t\tSystem.out.println(\"Can't initialize repository:\");\n\t\t\t\t\tdst_exc.printStackTrace();\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t\tSystem.exit(-1);\n\t\t\t\t}    // end of try-catch\n\n\t\t\t\tcopyRepositories(src_repo, dst_auth);\n\t\t\t}      // end of if (dst_repo == null)\n\t\t}        // end of if (copy_repos)\n\n\t\tif (check_roster && (src_repo != null)) {\n\t\t\tSystem.out.println(\"Checking roster:\");\n\n\t\t\tif (user != null) {\n\t\t\t\trepairUserRoster(user, src_repo);\n\t\t\t} else {\n\t\t\t\trepairRoster(src_repo);\n\t\t\t}    // end of else\n\t\t}\n\n\t\tif (import_data && (src_repo != null)) {\n\t\t\tBufferedReader br = new BufferedReader(new FileReader(import_file));\n\t\t\tString line = null;\n\n\t\t\twhile ((line = br.readLine()) != null) {\n\t\t\t\tString[] vals = line.split(\",\");\n\t\t\t\tBareJID userId = BareJID.bareJIDInstance(vals[0].trim());\n\n\t\t\t\ttry {\n\t\t\t\t\tsrc_repo.addUser(userId);\n\t\t\t\t} catch (UserExistsException e) {}\n\n\t\t\t\tif ((vals.length >= 2) && (vals[1].trim().length() > 0)) {\n\t\t\t\t\tsrc_repo.setData(userId, null, \"password\", vals[1].trim());\n\t\t\t\t}\n\n\t\t\t\tif ((vals.length >= 3) && (vals[2].trim().length() > 0)) {\n\t\t\t\t\tsrc_repo.setData(userId, \"roster/\" + vals[2].trim(), \"name\", vals[2].trim());\n\t\t\t\t}\n\n\t\t\t\tif ((vals.length >= 4) && (vals[3].trim().length() > 0)) {\n\t\t\t\t\tsrc_repo.setData(userId, \"roster/\" + vals[2].trim(), \"name\", vals[3].trim());\n\t\t\t\t}\n\n\t\t\t\tif ((vals.length >= 5) && (vals[4].trim().length() > 0)) {\n\t\t\t\t\tsrc_repo.setData(userId, \"roster/\" + vals[2].trim(), \"subscription\", vals[4].trim());\n\t\t\t\t}\n\n\t\t\t\tif ((vals.length >= 6) && (vals[5].trim().length() > 0)) {\n\t\t\t\t\tsrc_repo.setData(userId, \"roster/\" + vals[2].trim(), \"groups\", vals[5].trim());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbr.close();\n\t\t}\n\n\t\tif (export_data && (src_repo != null)) {\n\t\t\tFileWriter fr = new FileWriter(export_file);\n\n\t\t\tif (user != null) {\n\t\t\t\texportUserRoster(user, src_repo, fr);\n\t\t\t} else {\n\t\t\t\texportRoster(src_repo, fr);\n\t\t\t}    // end of else\n\n\t\t\tfr.close();\n\t\t}\n\n\t\tif (print_repo && (src_repo != null)) {\n\t\t\tSystem.out.println(\"Printing repository:\");\n\n\t\t\tif (content != null) {\n\t\t\t\tif (node) {\n\t\t\t\t\tsubnode = content;\n\t\t\t\t} else {\n\t\t\t\t\tparseNodeKeyValue(content);\n\t\t\t\t}\n\t\t\t}        // end of if (content != null)\n\n\t\t\tif (user != null) {\n\t\t\t\tif (key_val) {\n\t\t\t\t\tSystem.out.println(src_repo.getData(user, subnode, key, null));\n\t\t\t\t} else {\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tprintNode(user, src_repo, \"  \", subnode);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprintNode(user, src_repo, \"\", null);\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of else\n\t\t\t} else {\n\t\t\t\tprintRepoContent(src_repo);\n\t\t\t}        // end of else\n\t\t}          // end of if (print_repo)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param args\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic static void parseParams(final String[] args) throws TigaseStringprepException {\n\t\tif ((args != null) && (args.length > 0)) {\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tif (args[i].equals(\"-h\")) {\n\t\t\t\t\tSystem.out.print(help());\n\t\t\t\t\tSystem.exit(0);\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-sc\")) {\n\t\t\t\t\tsrc_class = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-su\")) {\n\t\t\t\t\tsrc_uri = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-dc\")) {\n\t\t\t\t\tdst_class = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-du\")) {\n\t\t\t\t\tdst_uri = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-dt\")) {\n\t\t\t\t\tcontent = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-st\")) {\n\t\t\t\t\tsimple_test = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-at\")) {\n\t\t\t\t\tadd_user_test = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-cp\")) {\n\t\t\t\t\tcopy_repos = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-pr\")) {\n\t\t\t\t\tprint_repo = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-u\")) {\n\t\t\t\t\tuser = BareJID.bareJIDInstance(args[++i]);\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-n\")) {\n\t\t\t\t\tnode = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-kv\")) {\n\t\t\t\t\tkey_val = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-add\")) {\n\t\t\t\t\tadd = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-del\")) {\n\t\t\t\t\tdel = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-roster\")) {\n\t\t\t\t\tcheck_roster = true;\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-import\")) {\n\t\t\t\t\timport_data = true;\n\t\t\t\t\timport_file = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-export\")) {\n\t\t\t\t\texport_data = true;\n\t\t\t\t\texport_file = args[++i];\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\n\t\t\t\tif (args[i].equals(\"-aeg\")) {\n\t\t\t\t\tallowed_empty_groups = args[++i].equals(\"true\");\n\t\t\t\t}    // end of if (args[i].equals(\"-h\"))\n\t\t\t}      // end of for (int i = 0; i < args.length; i++)\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param repo\n\t * @param prefix\n\t * @param node\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void printNode(BareJID user, UserRepository repo, String prefix, String node)\n\t\t\tthrows Exception {\n\t\tif (node != null) {\n\t\t\tSystem.out.println(prefix + \"node: \" + node);\n\t\t}    // end of if (node != null)\n\n\t\tString[] keys = repo.getKeys(user, node);\n\n\t\tif (keys != null) {\n\t\t\tfor (String key : keys) {\n\t\t\t\tString[] vals = repo.getDataList(user, node, key);\n\n\t\t\t\tif (vals != null) {\n\t\t\t\t\tStringBuilder valstr = new StringBuilder();\n\n\t\t\t\t\tfor (String val : vals) {\n\t\t\t\t\t\tvalstr.append(\" \").append(val);\n\t\t\t\t\t}    // end of for (String val: vals)\n\n\t\t\t\t\tSystem.out.println(prefix + \"  \" + key + \" = \" + valstr);\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(\"    \" + key);\n\t\t\t\t}      // end of if (vals != null) else\n\t\t\t}        // end of for (String key: keys)\n\t\t}          // end of if (keys != null)\n\n\t\tString[] nodes = repo.getSubnodes(user, node);\n\n\t\tif (nodes != null) {\n\t\t\tfor (String subnode : nodes) {\n\t\t\t\tprintNode(user, repo, prefix + \"  \", ((node != null) ? node + \"/\" + subnode : subnode));\n\t\t\t}    // end of for (String node: nodes)\n\t\t}      // end of if (ndoes != null)\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void printRepoContent(UserRepository repo) throws Exception {\n\t\tif (user != null) {\n\t\t\tprintNode(user, repo, \"  \", subnode);\n\t\t} else {\n\t\t\tList<BareJID> users = repo.getUsers();\n\n\t\t\tif (users != null) {\n\t\t\t\tfor (BareJID usr : users) {\n\t\t\t\t\tSystem.out.println(usr);\n\t\t\t\t\tprintNode(usr, repo, \"  \", subnode);\n\t\t\t\t}    // end of for (String user: users)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"There are no user accounts in repository.\");\n\t\t\t}      // end of else\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void removeTestData(UserRepository repo) throws Exception {\n\t\trepo.removeUser(user1);\n\t\trepo.removeUser(user2);\n\t\trepo.removeUser(user3);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void repairRoster(UserRepository repo) throws Exception {\n\t\tif (user != null) {\n\t\t\trepairUserRoster(user, repo);\n\t\t} else {\n\t\t\tList<BareJID> users = repo.getUsers();\n\n\t\t\tif (users != null) {\n\t\t\t\tfor (BareJID usr : users) {\n\n\t\t\t\t\t// System.out.println(usr);\n\t\t\t\t\trepairUserRoster(usr, repo);\n\t\t\t\t}    // end of for (String user: users)\n\t\t\t} else {\n\t\t\t\tSystem.out.println(\"There are no user accounts in repository.\");\n\t\t\t}      // end of else\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void repairUserRoster(BareJID user, UserRepository repo) throws Exception {\n\t\tSystem.out.println(\"  \" + (++counter) + \". \" + user + \" roster: \");\n\n\t\tString[] contacts = repo.getSubnodes(user, \"roster\");\n\n\t\tif (contacts != null) {\n\t\t\tfor (String contact : contacts) {\n\t\t\t\tSystem.out.println(\"    contact: \" + contact);\n\n\t\t\t\tboolean valid = checkContact(user, repo, contact);\n\n\t\t\t\tif (valid) {\n\t\t\t\t\tSystem.out.println(\"      looks OK\");\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(\"      should be REMOVED\");\n\n\t\t\t\t\tString contact_node = \"roster/\" + contact;\n\n\t\t\t\t\tSystem.out.println(\"      removing node: \" + contact_node);\n\t\t\t\t\trepo.removeSubnode(user, contact_node);\n\t\t\t\t\tSystem.out.println(\"      DONE.\");\n\t\t\t\t}\n\t\t\t}    // end of for (String node: nodes)\n\t\t} else {\n\t\t\tSystem.out.println(\"    empty roster...\");\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void simpleTest(UserRepository repo) throws Exception {\n\t\tprintRepoContent(repo);\n\n\t\ttry {\n\t\t\trepo.addUser(user1);\n\t\t} catch (UserExistsException e) {}\n\n\t\tprintRepoContent(repo);\n\t\tremoveTestData(repo);\n\t\tprintRepoContent(repo);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param re\n\t *\n\t * @throws Exception\n\t */\n\tpublic static void userAddTest(UserRepository re) throws Exception {\n\t\tAuthRepository repo = (AuthRepository) re;\n\t\tBareJID test_user = BareJID.bareJIDInstanceNS(\"test111@localhost\");\n\n\t\tprintRepoContent(re);\n\n\t\ttry {\n\t\t\trepo.addUser(test_user, \"some-pass\");\n\t\t} catch (UserExistsException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\n\t\tprintRepoContent(re);\n\t\tSystem.out.println(re.getData(test_user, \"privacy\", \"default-list\", null));\n\t\trepo.removeUser(test_user);\n\t\tprintRepoContent(re);\n\t}\n\n\tprivate static String help() {\n\t\treturn \"\\n\" + \"Parameters:\\n\" + \" -h          this help message\\n\"\n\t\t\t\t+ \" -sc class   source repository class name\\n\"\n\t\t\t\t+ \" -su uri     source repository init string\\n\"\n\t\t\t\t+ \" -dc class   destination repository class name\\n\"\n\t\t\t\t+ \" -du uri     destination repository init string\\n\"\n\t\t\t\t+ \" -dt string  data content to set/remove in repository\\n\"\n\t\t\t\t+ \" -u user     user ID, if given all operations are only for that ID\\n\"\n\t\t\t\t+ \"             if you want to add user to AuthRepository parameter must\\n\"\n\t\t\t\t+ \"             in form: \\\"user:password\\\"\\n\"\n\t\t\t\t+ \" -st         perform simple test on repository\\n\"\n\t\t\t\t+ \" -at         simple test for adding and removing user\\n\"\n\t\t\t\t+ \" -cp         copy content from source to destination repository\\n\"\n\t\t\t\t+ \" -pr         print content of the repository\\n\"\n\t\t\t\t+ \" -n          data content string is a node string\\n\"\n\t\t\t\t+ \" -kv         data content string is node/key=value string\\n\"\n\t\t\t\t+ \" -add        add data content to repository\\n\"\n\t\t\t\t+ \" -del        delete data content from repository\\n\" + \" ------------\\n\"\n\t\t\t\t+ \" -roster     check the user roster\\n\"\n\t\t\t\t+ \" -aeg [true|false]  Allow empty group list for the contact\\n\"\n\t\t\t\t+ \" -import file  import user data from the file of following format:\\n\"\n\t\t\t\t+ \"         user_jid, password, roser_jid, roster_nick, subscription, group\\n\"\n\t\t\t\t+ \" -export file  export user roster data to the specified file in the following\\n\"\n\t\t\t\t+ \"              format: user_jid, password, roser_jid, roster_nick, subscription,\\n\"\n\t\t\t\t+ \"               group\\n\" + \"\\n\" + \"\\n\"\n\t\t\t\t+ \"Note! If you put UserAuthRepository implementation as a class name\\n\"\n\t\t\t\t+ \"      some operation are not allowed and will be silently skipped.\\n\"\n\t\t\t\t+ \"      Have a look at UserAuthRepository to see what operations are\\n\"\n\t\t\t\t+ \"      possible or what operation does make sense.\\n\"\n\t\t\t\t+ \"      Alternatively look for admin tools guide on web site.\\n\"\n\t\t;\n\t}\n\n\tprivate static void parseNodeKeyValue(String data) {\n\t\tint val_idx = data.indexOf('=');\n\n\t\tvalue = data.substring(val_idx + 1);\n\n\t\tString tmp_str = data.substring(0, val_idx);\n\t\tint key_idx = tmp_str.lastIndexOf('/');\n\n\t\tif (key_idx >= 0) {\n\t\t\tkey = tmp_str.substring(key_idx + 1);\n\t\t\tsubnode = tmp_str.substring(0, key_idx);\n\t\t}    // end of if (key_idx >= 0)\n\t\t\t\telse {\n\t\t\tkey = tmp_str;\n\t\t}    // end of if (key_idx >= 0) else\n\t}\n}    // RepositoryUtils\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/RoutingsContainer.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.util;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map.Entry;\nimport java.util.Map;\nimport java.util.logging.Logger;\nimport java.util.logging.Level;\nimport java.util.regex.Pattern;\n\n/**\n * Describe class RoutingsContainer here.\n *\n *\n * Created: Sat Feb 11 16:30:42 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class RoutingsContainer {\n\n  /**\n   * Variable <code>log</code> is a class logger.\n   */\n  private static final Logger log =\n    Logger.getLogger(\"tigase.util.RoutingsContainer\");\n\n\tprivate RoutingComputer comp = null;\n\n\t/**\n\t * Creates a new <code>RoutingsContainer</code> instance.\n\t *\n\t */\n\tpublic RoutingsContainer(boolean multiMode) {\n\t\tif (multiMode) {\n\t\t\tcomp = new MultiMode();\n\t\t} // end of if (mode)\n\t\telse {\n\t\t\tcomp = new SingleMode();\n\t\t} // end of if (mode) else\n\t}\n\n\tpublic void addRouting(final String pattern, final String address) {\n\t\tcomp.addRouting(pattern, address);\n\t}\n\n\tpublic String computeRouting(final String pattern) {\n\t\treturn comp.computeRouting(pattern);\n\t}\n\n\tprotected interface RoutingComputer {\n\n\t\tvoid addRouting(final String pattern, final String address);\n\n\t\tString computeRouting(final String pattern);\n\n\t}\n\n\tprotected static class SingleMode implements RoutingComputer {\n\n\t\tprivate String routing = null;\n\n\t\tpublic void addRouting(final String pattern, final String address) {\n\t\t\trouting = address;\n\t\t}\n\n\t\tpublic String computeRouting(final String address) {\n\t\t\treturn routing;\n\t\t}\n\n\t}\n\n\tprotected static class MultiMode implements RoutingComputer {\n\n\t\tprivate Map<Pattern, String> routings =\tnew LinkedHashMap<Pattern, String>();\n\t\tprivate String def = null;\n\n\t\tpublic void addRouting(final String pattern, final String address) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.fine(\"Adding routing: \" + pattern + \" --> \" + address);\n\t\t\t}\n\t\t\troutings.put(Pattern.compile(pattern), address);\n\t\t\tif (def == null) {\n\t\t\t\tdef = address;\n\t\t\t} // end of if (def == null)\n\t\t}\n\n\t\tpublic String computeRouting(final String address) {\n\t\t\tif (address == null) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.finer(\"For null address returning default routing: \" + def);\n\t\t\t\t}\n\t\t\t\treturn def;\n\t\t\t} // end of if (address == null)\n\t\t\tfor (Map.Entry<Pattern, String> entry: routings.entrySet()) {\n\t\t\t\tif (entry.getKey().matcher(address).find()) {\n    \t\t\t\tif (log.isLoggable(Level.FINEST)) {\n        \t\t\t\tlog.finest(\"For address: \" + address + \" pattern: \"\n            \t\t\t\t+ entry.getKey().pattern() + \" matched.\");\n                    }\n\t\t\t\t\treturn entry.getValue();\n\t\t\t\t} // end of if (pattern.matcher(address).find())\n\t\t\t} // end of for ()\n\t\t\treturn def;\n\t\t}\n\n\t}\n\n} // RoutingsContainer\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/SchemaLoader.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014, \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.util;\n\nimport java.util.Properties;\n\n/**\n *\n * @author andrzej\n */\npublic abstract class SchemaLoader {\n\t\n\tpublic static enum Result {\n\t\tok,\n\t\terror,\n\t\twarning,\n\t\tskipped\n\t}\n\t\n\tpublic static SchemaLoader newInstance(Properties props) {\n\t\treturn new DBSchemaLoader(props);\n\t}\n\t\n\t/**\n\t * Method validates whether the connection can at least be established. If yes\n\t * then appropriate flag is set.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tpublic abstract Result validateDBConnection( Properties variables );\n\n\t/**\n\t * Method, if the connection is validated by {@code validateDBConnection},\n\t * checks whether desired database exists. If not it creates such database\n\t * using {@code *-installer-create-db.sql} schema file substituting it's\n\t * variables with ones provided.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tpublic abstract Result validateDBExists( Properties variables );\n\tpublic abstract Result validateDBSchema( Properties variables );\n\tpublic abstract Result postInstallation( Properties variables );\n\tpublic abstract Result printInfo( Properties variables );\n\n\t/**\n\t * Method attempts to add XMPP admin user account to the database using\n\t * {@code AuthRepository}.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tpublic abstract Result addXmppAdminAccount( Properties variables );\n\n\t/**\n\t * Method checks whether the connection to the database is possible and that\n\t * database of specified name exists. If yes then a schema file from\n\t * properties is loaded.\n\t *\n\t * @param variables set of {@code Properties} with all configuration options\n\t */\n\tpublic abstract Result loadSchemaFile( Properties variables );\n\tpublic abstract Result shutdown( Properties variables );\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/ThreadPoolUtils.java",
    "content": "package tigase.util;\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class ThreadPoolUtils {\n\n\tprivate static final int DEFAULT_THREAD_MIN_SIZE = 10;\n\n\tprivate static final int DEFAULT_THREAD_MAX_SIZE = 30;\n\n\tprivate static final int DEFAULT_QUEUE_CAPACITY = 5000;\n\n\tpublic static ThreadPoolExecutor newCachePool(String threadName,\n\t\t\tString minSize, String maxSize, String queueSize) {\n\t\tint core = DEFAULT_THREAD_MIN_SIZE;\n//\t\tint core = JiveGlobals.getIntProperty(minSize, DEFAULT_THREAD_MIN_SIZE);\n\t\tint max = DEFAULT_THREAD_MAX_SIZE;\n//\t\tint max = JiveGlobals.getIntProperty(maxSize, DEFAULT_THREAD_MAX_SIZE);\n\t\tint capacity = DEFAULT_QUEUE_CAPACITY;\n//\t\tint capacity = JiveGlobals.getIntProperty(queueSize, DEFAULT_QUEUE_CAPACITY);\n\t\treturn new ThreadPoolExecutor(core, max, 60L, TimeUnit.SECONDS,\n\t\t\t\tnew LinkedBlockingQueue<Runnable>(capacity),\n\t\t\t\tnew NamedThreadFactory(threadName),\n\t\t\t\tnew ThreadPoolExecutor.CallerRunsPolicy());\n\t}\n\n\tpublic static ThreadPoolExecutor newFixedPool(String threadName, String size) {\n\t\tint core = DEFAULT_THREAD_MAX_SIZE;\n//\t\tint core = JiveGlobals.getIntProperty(size, DEFAULT_THREAD_MAX_SIZE);\n\t\treturn new ThreadPoolExecutor(core, core, 60L, TimeUnit.SECONDS,\n\t\t\t\tnew LinkedBlockingQueue<Runnable>(), new NamedThreadFactory(\n\t\t\t\t\t\tthreadName), new ThreadPoolExecutor.CallerRunsPolicy());\n\t}\n\n\tpublic static ScheduledThreadPoolExecutor newScheduledPool(\n\t\t\tString threadName, String size) {\n\t\tint core = DEFAULT_THREAD_MAX_SIZE;\n//\t\tint core = JiveGlobals.getIntProperty(size, DEFAULT_THREAD_MAX_SIZE);\n\t\treturn new ScheduledThreadPoolExecutor(core, new NamedThreadFactory(\n\t\t\t\tthreadName), new ThreadPoolExecutor.CallerRunsPolicy());\n\t}\n\n\tpublic static class NamedThreadFactory implements ThreadFactory {\n\t\tprivate static final AtomicInteger threadPoolNumber = new AtomicInteger(\n\t\t\t\t1);\n\t\tprivate final ThreadGroup group;\n\t\tprivate final AtomicInteger threadNumber = new AtomicInteger(1);\n\t\tprivate static final String NAME_PATTERN = \"%s-%d-thread\";\n\t\tprivate final String threadNamePrefix;\n\n\t\t/**\n\t\t * Creates a new {@link NamedThreadFactory} instance\n\t\t * \n\t\t * @param threadNamePrefix\n\t\t *            the name prefix assigned to each thread created.\n\t\t */\n\t\tpublic NamedThreadFactory(String threadNamePrefix) {\n\t\t\tfinal SecurityManager s = System.getSecurityManager();\n\t\t\tgroup = (s != null) ? s.getThreadGroup() : Thread.currentThread()\n\t\t\t\t\t.getThreadGroup();\n\t\t\tthis.threadNamePrefix = String.format(NAME_PATTERN,\n\t\t\t\t\tcheckPrefix(threadNamePrefix),\n\t\t\t\t\tthreadPoolNumber.getAndIncrement());\n\t\t}\n\n\t\tprivate static String checkPrefix(String prefix) {\n\t\t\treturn prefix == null || prefix.length() == 0 ? \"pool\" : prefix;\n\t\t}\n\n\t\t/**\n\t\t * Creates a new {@link Thread}\n\t\t * \n\t\t * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)\n\t\t */\n\t\tpublic Thread newThread(Runnable r) {\n\t\t\tfinal Thread t = new Thread(group, r, String.format(\"%s-%d\",\n\t\t\t\t\tthis.threadNamePrefix, threadNumber.getAndIncrement()), 0);\n\t\t\tt.setDaemon(false);\n\t\t\tt.setPriority(Thread.NORM_PRIORITY);\n\t\t\treturn t;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/TimeUtils.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Calendar;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * This is too slow.\n *\n *\n * Created: Tue Oct 28 21:08:58 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class TimeUtils {\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static int getHourNow() {\n\t\tCalendar cal = Calendar.getInstance();\n\n\t\treturn cal.get(Calendar.HOUR_OF_DAY);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static int getMinuteNow() {\n\t\tCalendar cal = Calendar.getInstance();\n\n\t\treturn cal.get(Calendar.MINUTE);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/TimerTask.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2013 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\npackage tigase.util;\n\nimport java.util.concurrent.ScheduledFuture;\n\n/**\n * TimerTask class is basic implementation of java.util.TimerTask class which\n * is used with ScheduledExecutorService in AbstractMessageRecevier.\n */\npublic abstract class TimerTask implements Runnable {\n\n\tprivate ScheduledFuture<?> future = null;\n\t\n\tpublic void setScheduledFuture(ScheduledFuture<?> future) {\n\t\tthis.future = future;\n\t}\n\n\tpublic boolean isScheduled() {\n\t\treturn future != null && !future.isCancelled() && !future.isDone();\n\t}\n\t\n\tpublic void cancel() {\n\t\tif (future != null) {\n\t\t\tfuture.cancel(false);\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/TimingRecord.java",
    "content": "/*\n * TimingRecord.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.util;\n\n/**\n *\n * @author kobit\n */\npublic class TimingRecord {\n\tprivate String id;\n\tprivate long[] timings;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param id\n\t * @param accuracy\n\t */\n\tpublic TimingRecord(String id, int accuracy) {\n\t\tthis.id = id;\n\t\ttimings = new long[accuracy];\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void recordEnd() {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void recordStart() {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic long getAverageTiming() {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tlong getMaxRecordedTiming() {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Not supported yet.\");    // To change body of generated methods, choose Tools | Templates.\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/04/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/TimingRecorder.java",
    "content": "/*\n * TimingRecorder.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.Map;\n\n/**\n *\n * @author kobit\n */\npublic class TimingRecorder {\n\t/** Field description */\n\tpublic static final int ACCURACY_PROP_DEF = 10;\n\n\t/** Field description */\n\tpublic static final String                     ACCURACY_PROP_KEY = \"timing-accuracy\";\n\tprivate static final Map<String, TimingRecord> timings =\n\t\t\tnew ConcurrentSkipListMap<String, TimingRecord>();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t */\n\tpublic static void endTiming(String id) {\n\t\ttimings.get(id).recordEnd();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t * @param accuracy\n\t */\n\tpublic static void initTiming(String id, int accuracy) {\n\t\ttimings.put(id, new TimingRecord(id, accuracy));\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t */\n\tpublic static void startTiming(String id) {\n\t\ttimings.get(id).recordStart();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static long getAverageTiming(String id) {\n\t\treturn timings.get(id).getAverageTiming();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static long getMaxRecordedTiming(String id) {\n\t\treturn timings.get(id).getMaxRecordedTiming();\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/04/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/UpdatesChecker.java",
    "content": "/*\n *   Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.AbstractMessageReceiver;\nimport tigase.server.Packet;\nimport tigase.server.XMPPServer;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.io.BufferedReader;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\n\nimport java.net.URL;\nimport java.net.URLConnection;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class UpdatesChecker here.\n *\n *\n * Created: Fri Apr 18 09:35:32 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class UpdatesChecker extends Thread {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.util.UpdatesChecker\");\n\tprivate static final long SECOND = 1000;\n\tprivate static final long MINUTE = 60 * SECOND;\n\tprivate static final long HOUR = 60 * MINUTE;\n\tprivate static final long DAY = 24 * HOUR;\n\tprivate static final String VERSION_URL =\n\t\t\"http://www.tigase.org/files/downloads/tigase-server/descript-redmine.ion\";\n\tprivate static final String FILE_START = \"tigase-server-\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int bugfix_ver = 0;\n\tprivate String intro_msg = null;\n\tprivate int major_ver = 0;\n\tprivate int minor_ver = 0;\n\tprivate AbstractMessageReceiver receiver = null;\n\tprivate long interval = 7 * DAY;\n\tprivate boolean stopped = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param interval\n\t * @param receiver\n\t * @param intro_msg\n\t */\n\tpublic UpdatesChecker(long interval, AbstractMessageReceiver receiver, String intro_msg) {\n\t\tsuper();\n\t\tthis.interval = interval * DAY;\n\n\t\t// this.interval = 30*SECOND;\n\t\tthis.receiver = receiver;\n\t\tthis.intro_msg = intro_msg;\n\t\tsetName(\"UpdatesChecker\");\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void run() {\n\t\tString version = XMPPServer.getImplementationVersion();\n\t\tint idx = version.indexOf('-');\n\n\t\tif (idx > 0) {\n\t\t\tversion = version.substring(0, idx);\n\t\t}\n\n\t\tlog.info(\"Server version: \" + version);\n\n\t\tString[] nums = version.split(\"\\\\.\");\n\n\t\ttry {\n\t\t\tmajor_ver = Integer.parseInt(nums[0]);\n\t\t\tminor_ver = Integer.parseInt(nums[1]);\n\t\t\tbugfix_ver = Integer.parseInt(nums[2]);\n\t\t} catch (NumberFormatException e) {\n\t\t\tlog.warning(\"Can not detect the server version.... \" + version);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Problem parsing server version.... \" + version, e);\n\t\t}\n\n\t\twhile ( !stopped) {\n\t\t\tElement message = null;\n\n\t\t\ttry {\n\t\t\t\tsleep(interval);\n\n\t\t\t\tURLConnection connection = new URL(VERSION_URL).openConnection();\n\n\t\t\t\tconnection.setConnectTimeout(1000 * 60);\n\t\t\t\tconnection.setReadTimeout(1000 * 60);\n\n\t\t\t\tBufferedReader buffr =\n\t\t\t\t\tnew BufferedReader(new InputStreamReader(connection.getInputStream()));\n\t\t\t\tString line = null;\n\t\t\t\tint major = 0;\n\t\t\t\tint minor = 0;\n\t\t\t\tint bugfix = 0;\n\t\t\t\tString build = \"\";\n\n\t\t\t\twhile ((line = buffr.readLine()) != null) {\n\t\t\t\t\tif (line.startsWith(FILE_START)) {\n\t\t\t\t\t\tString file = line.substring(FILE_START.length());\n\n\t\t\t\t\t\tidx = file.indexOf('-');\n\t\t\t\t\t\tversion = file.substring(0, idx);\n\t\t\t\t\t\tlog.info(\"Found version: \" + version);\n\t\t\t\t\t\tnums = version.split(\"\\\\.\");\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tint major_t = Integer.parseInt(nums[0]);\n\t\t\t\t\t\t\tint minor_t = Integer.parseInt(nums[1]);\n\t\t\t\t\t\t\tint bugfix_t = Integer.parseInt(nums[2]);\n\n\t\t\t\t\t\t\tif ((major_t > major) || ((major_t == major) && (minor_t > minor))\n\t\t\t\t\t\t\t\t\t|| ((major_t == major) && (minor_t == minor) && (bugfix_t > bugfix))) {\n\t\t\t\t\t\t\t\tmajor = major_t;\n\t\t\t\t\t\t\t\tminor = minor_t;\n\t\t\t\t\t\t\t\tbugfix = bugfix_t;\n\n\t\t\t\t\t\t\t\tint b_idx = file.indexOf('.', idx);\n\n\t\t\t\t\t\t\t\tbuild = file.substring(idx, b_idx);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (NumberFormatException e) {\n\t\t\t\t\t\t\tlog.warning(\"Problem detecting new server version.... \" + version);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ((major > major_ver) || ((major == major_ver) && (minor > minor_ver))\n\t\t\t\t\t\t|| ((major == major_ver) && (minor == minor_ver) && (bugfix > bugfix_ver))) {\n\t\t\t\t\tString os_name = System.getProperty(\"os.name\");\n\t\t\t\t\tString link = null;\n\n\t\t\t\t\tif (os_name.toLowerCase().contains(\"windows\")) {\n\t\t\t\t\t\tlink = \"http://www.tigase.org/files/downloads/tigase-server/tigase-server-\"\n\t\t\t\t\t\t\t\t+ major + \".\" + minor + \".\" + bugfix + build + \".exe\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlink = \"http://www.tigase.org/files/downloads/tigase-server/tigase-server-\"\n\t\t\t\t\t\t\t\t+ major + \".\" + minor + \".\" + bugfix + build + \".tar.gz\";\n\t\t\t\t\t}\n\n\t\t\t\t\tmessage = new Element(\"message\", new String[] { \"to\", \"from\" },\n\t\t\t\t\t\t\tnew String[] { receiver.getDefHostName().getDomain(),\n\t\t\t\t\t\t\t\"updates.checker@\" + receiver.getDefHostName() });\n\n\t\t\t\t\tElement subject = new Element(\"subject\",\n\t\t\t\t\t\t\"Updates checker - new version of the Tigase server\");\n\n\t\t\t\t\tmessage.addChild(subject);\n\n\t\t\t\t\tElement body = new Element(\"body\",\n\t\t\t\t\t\t\"You are currently using: '\" + major_ver + \".\" + minor_ver + \".\" + bugfix_ver\n\t\t\t\t\t\t+ \"' version of Tigase\"\n\t\t\t\t\t\t+ \" server. A new version of the server has been released: '\" + major + \".\"\n\t\t\t\t\t\t+ minor + \".\" + bugfix + \"' and it is available for\" + \" download at address: \"\n\t\t\t\t\t\t+ link + \"\\n\\n\" + intro_msg);\n\n\t\t\t\t\tmessage.addChild(body);\n\t\t\t\t\treceiver.addPacket(Packet.packetInstance(message));\n\t\t\t\t}\n\t\t\t} catch (TigaseStringprepException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Incorrect stanza address settings: \" + message.toString(), e);\n\t\t\t} catch (FileNotFoundException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can not check the server updates\");\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Can not check updates for URL: \" + VERSION_URL, e);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\tstopped = true;\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Unknown exception for: \" + VERSION_URL, e);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/WorkerThread.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Apr 21, 2009 9:02:57 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class WorkerThread extends Thread {\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprotected static final Logger log = Logger.getLogger(WorkerThread.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long averageProcessingTime = 0;\n\n//private PriorityQueueAbstract<QueueItem> queue = null;\n\tprivate LinkedBlockingQueue<QueueItem> queue = null;\n\tprivate long runsCnt = 0;\n\tprivate boolean stopped = false;\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t */\n\tpublic abstract WorkerThread getNewInstance();\n\n\t//~--- methods --------------------------------------------------------------\n\n//{\n//  WorkerThread worker = new WorkerThread();\n//  worker.setQueue(queue);\n//  return worker;\n//}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param item\n\t */\n\tpublic abstract void process(QueueItem item);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic long getAverageProcessingTime() {\n\t\treturn averageProcessingTime;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic long getRunsCounter() {\n\t\treturn runsCnt;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param item\n\t *\n\t *\n\t */\n\tpublic boolean offer(QueueItem item) {\n\t\treturn queue.offer(item);\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\tQueueItem item = null;\n\n\t\twhile ( !stopped) {\n\t\t\ttry {\n\t\t\t\titem = queue.take();\n\n\t\t\t\tlong start = System.currentTimeMillis();\n\n\t\t\t\tprocess(item);\n\n\t\t\t\tlong end = System.currentTimeMillis() - start;\n\n\t\t\t\tif (end > 0) {\n\t\t\t\t\taverageProcessingTime = (averageProcessingTime + end) / 2;\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (!stopped)\n\t\t\t\t\tlog.log(Level.SEVERE,\n\t\t\t\t\t\t\tthis.getClass().getName() + \",(\" + getName() + \") Exception during packet processing: \"\n\t\t\t\t\t\t\t\t+ item.getPacket(), e);\n\t\t\t}\n\n\t\t\t++runsCnt;\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param maxSize\n\t */\n\tpublic void setQueueMaxSize(int maxSize) {\n\t\tLinkedBlockingQueue<QueueItem> oldQueue = queue;\n\n\t\tqueue = new LinkedBlockingQueue<QueueItem>(maxSize);\n\n\t\tif (oldQueue != null) {\n\t\t\tqueue.addAll(oldQueue);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t */\n\tpublic int size() {\n\t\treturn queue.size();\n\t}\n\n\tpublic void shutdown() {\n\t\tstopped = true;\n\t\ttry {\n\t\t\tthis.interrupt();\n\t\t} catch (Exception ex) {\n\t\t}\n\t}\n\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/util/tracer/TigaseTracer.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n * \n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.util.tracer;\n\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.Writer;\nimport java.util.Calendar;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.server.Packet;\n\n/**\n * Created: Jun 30, 2009 5:18:10 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class TigaseTracer {\n\n\tprivate static final Logger log =\n\t\t\t\t\tLogger.getLogger(TigaseTracer.class.getName());\n\n\tpublic static final String TRACER_IPS_PROP_KEY = \"--tracer-ips\";\n\tpublic static final String TRACER_JIDS_PROP_KEY = \"--tracer-jids\";\n\tpublic static final String TRACER_CIDS_PROP_KEY = \"--tracer-cids\";\n\t\n\tprivate static final String DEF_DIR = \"logs\";\n\tprivate static final long DEF_MAX_FILE_SIZE = 10000000;\n\tprivate static final int DEF_FILES_COUNT = 5;\n\tprivate static final String DEF_FILE_NAME = \"packet-tracing.log\";\n\n\tprivate static TigaseTracer instance = null;\n\tprivate static ConcurrentSkipListSet<String> ips =\n\t\t\t\t\tnew ConcurrentSkipListSet<String>();\n\tprivate static ConcurrentSkipListSet<String> jids =\n\t\t\t\t\tnew ConcurrentSkipListSet<String>();\n\tprivate static ConcurrentSkipListSet<String> cids =\n\t\t\t\t\tnew ConcurrentSkipListSet<String>();\n\n\tprivate ArrayBlockingQueue<String> waiting =\n\t\t\t\t\tnew ArrayBlockingQueue<String>(10000, true);\n\tprivate Runnable worker = null;\n\tprivate File files[] = null;\n\tprivate long maxFileSize = DEF_MAX_FILE_SIZE;\n\tprivate int filesCount = DEF_FILES_COUNT;\n\tprivate String dir = DEF_DIR;\n\tprivate String fileName = DEF_FILE_NAME;\n\n\tpublic static TigaseTracer getTracer(String name) {\n\t\tif (instance == null) {\n\t\t\ttry {\n\t\t\t\tinstance = new TigaseTracer();\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error initializing Tigase tracer: \", e);\n\t\t\t}\n\t\t}\n\t\treturn instance;\n\t}\n\n\tpublic static void addIP(String ip) {\n\t\tips.add(ip);\n\t}\n\n\tpublic static void removeIP(String ip) {\n\t\tips.remove(ip);\n\t}\n\n\tpublic static void addJid(String jid) {\n\t\tjids.add(jid);\n\t}\n\n\tpublic static void removeJid(String jid) {\n\t\tjids.remove(jid);\n\t}\n\n\tpublic static void addCid(String cid) {\n\t\tcids.add(cid);\n\t}\n\n\tpublic static void removeCid(String cid) {\n\t\tcids.remove(cid);\n\t}\n\n\tprivate TigaseTracer() throws IOException {\n\t\tinit();\n\t}\n\n\tprivate void init() throws IOException {\n\t\tfiles = new File[filesCount];\n\t\tfor (int i = 0; i < files.length; i++) {\n\t\t\tfiles[i] = new File(dir, fileName + \".\" + i);\n\t\t}\n\t\tworker = new TracingWorker(new FileWriter(files[0], true), files[0].length());\n\t\tThread thr = new Thread(worker);\n\t\tthr.setName(\"tracing-worker\");\n\t\tthr.setDaemon(true);\n\t\tthr.start();\n\t}\n\n\tpublic boolean trace(String ip, String to_jid, String from_jid, String cid,\n\t\t\t\t\tString id, String point, String msg, Packet packet) {\n\t\tif (ip != null && ips.contains(ip)) {\n\t\t\treturn waiting.offer(format(ip, id, point, msg, packet));\n\t\t}\n\t\tif (to_jid != null && jids.contains(to_jid)) {\n\t\t\treturn waiting.offer(format(\"TO: \" + to_jid, id, point, msg, packet));\n\t\t}\n\t\tif (from_jid != null && jids.contains(from_jid)) {\n\t\t\treturn waiting.offer(format(\"FROM: \" + from_jid, id, point, msg, packet));\n\t\t}\n\t\tif (cid != null && cids.contains(cid)) {\n\t\t\treturn waiting.offer(format(cid, id, point, msg, packet));\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate String format(String filter, String id, String point, String msg, Packet packet) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tCalendar cal = Calendar.getInstance();\n\t\tsb.append(cal.get(Calendar.YEAR));\n\t\tsb.append(\"-\");\n\t\tsb.append(cal.get(Calendar.MONTH)+1);\n\t\tsb.append(\"-\");\n\t\tsb.append(cal.get(Calendar.DAY_OF_MONTH));\n\t\tsb.append(\" \");\n\t\tsb.append(cal.get(Calendar.HOUR_OF_DAY));\n\t\tsb.append(\":\");\n\t\tsb.append(cal.get(Calendar.MINUTE));\n\t\tsb.append(\":\");\n\t\tsb.append(cal.get(Calendar.SECOND));\n\t\tsb.append(\".\");\n\t\tsb.append(cal.get(Calendar.MILLISECOND));\n\t\tsb.append(\"[\");\n\t\tsb.append(filter);\n\t\tsb.append(\"] {\");\n\t\tsb.append(id);\n\t\tsb.append('-');\n\t\tsb.append(point);\n\t\tsb.append(\"} \");\n\t\tif (msg != null) {\n\t\t\tsb.append(msg);\n\t\t}\n\t\tif (packet != null) {\n\t\t\tsb.append(packet);\n\t\t}\n\t\tsb.append('\\n');\n\t\treturn sb.toString();\n\t}\n\t\n\tpublic boolean tracegByIP(String ip, String point, String msg, Packet packet) {\n\t\treturn trace(ip, null, null, null, null, point, msg, packet);\n\t}\n\t\n\tpublic boolean traceByToJid(String jid, String point, String msg, Packet packet) {\n\t\treturn trace(null, jid, null, null, null, point, msg, packet);\n\t}\n\t\n\tpublic boolean traceByFromJid(String jid, String point, String msg, Packet packet) {\n\t\treturn trace(null, null, jid, null, null, point, msg, packet);\n\t}\n\tpublic boolean traceByCid(String cid, String point, String msg, Packet packet) {\n\t\treturn trace(null, null, null, cid, null, point, msg, packet);\n\t}\n\n\tprivate Writer rotateFiles(Writer writer) throws IOException {\n\t\twriter.close();\n\t\tfor (int i = files.length-2; i >= 0; --i) {\n\t\t\tFile file1 = files[i];\n\t\t\tFile file2 = files[i+1];\n\t\t\tif (file1.exists()) {\n\t\t\t\tif (file2.exists()) {\n\t\t\t\t\tfile2.delete();\n\t\t\t\t}\n\t\t\t\tfile1.renameTo(file2);\n\t\t\t}\n\t\t}\n\t\treturn new FileWriter(files[0], false);\n\t}\n\n\tprivate class TracingWorker implements Runnable {\n\n\t\tprivate boolean stopped = false;\n\t\tprivate Writer writer = null;\n\t\tprivate long size = 0;\n\n    protected TracingWorker(Writer writer, long initSize) {\n\t\t\tthis.writer = writer;\n\t\t\tthis.size = initSize;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (!stopped) {\n\t\t\t\ttry {\n\t\t\t\t\tString entry = waiting.take();\n\t\t\t\t\tif (entry != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Save the log entry\n\t\t\t\t\t\t\twriter.write(entry);\n\t\t\t\t\t\t\twriter.flush();\n\t\t\t\t\t\t\tsize += entry.length();\n\t\t\t\t\t\t\tif (size >= maxFileSize) {\n\t\t\t\t\t\t\t\twriter = rotateFiles(writer);\n\t\t\t\t\t\t\t\tsize = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (IOException ex) {\n\t\t\t\t\t\t\tlog.log(Level.WARNING, \"Can not write to trace file: \", ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (InterruptedException ex) {\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostItem.java",
    "content": "/*\n * VHostItem.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.vhosts;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.lang.reflect.Array;\nimport tigase.vhosts.filter.DomainFilterPolicy;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.db.comp.RepositoryItemAbstract;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.server.XMPPServer;\nimport tigase.server.xmppclient.ClientTrustManagerFactory;\nimport tigase.util.DataTypes;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.util.StringUtilities;\nimport tigase.xmpp.BareJID;\n\n/**\n * Objects of this class represent virtual host with all hosts configuration\n * settings. In most cases simple domain name string is not enough to deal with\n * the virtual host. VHost can be enabled/disabled. Can be available to selected\n * server components only and so on. Therefore every time there is a detailed\n * information needed for a vhost this classed must be used.\n *\n * This class has it's own XML representation which can be used for creating an\n * instance of the class or can be exported to the XML form for permanent\n * storage:\n *\n * {@code\n * <vhost hostname=\"vhost.something.com\"\n *        enabled=\"true\"\n *        anon=\"true\"\n *        register=\"true\"\n *        max-users=\"99999999999L\">\n *   <comps/>\n *   <other/>\n * }\n *\n * From the init.property file it is also possible to set additional parameters\n * for the vhost. By default everything is enabled and max accounts set to\n * unlimited. In the example below we configure 2 domains:\n * <strong>devel.tigase.org</strong> and <strong>test.tigase.org</strong>. For\n * the first domain there are no additional settings, hence the domain has\n * everything on by default, whereas the second has everything switched off and\n * max user accounts set to 100.\n *\n * <pre>\n * --virt-hosts = devel.tigase.org,test.tigase.org:-anon:-register:max-users=100\n * </pre>\n *\n * It also possible to set forwarding for the domain:\n *\n * <pre>\n * --virt-hosts = test.tigase.org:pres-forw=lpart@domain/res:mess-forw=lpart@domain/res\n * </pre>\n *\n * Please note, forwarding address set this way cannot contain any of\n * characters: [,:=] The order features are set for domain is unimportant.\n *\n * Created: 22 Nov 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class VHostItem\n\t\t\t\textends RepositoryItemAbstract\n\t\t\t\timplements Comparable<VHostItem> {\n\t\n\tpublic static class DataType { \n\t\tprivate final String name;\n\t\tprivate final String key;\n\t\tprivate final Class cls;\n\t\tprivate final Class collectionCls;\n\t\tprivate final Object defValue;\n\t\tprivate final Object[] options;\n\t\tprivate final String[] optionsNames;\n\t\t\n\t\tpublic DataType(String key, String name, Class cls, Class<? extends Collection> collectionCls, Object defValue, Object[] options, String[] optionsNames) {\n\t\t\tthis.key = key;\n\t\t\tthis.name = name;\n\t\t\tthis.cls = cls;\n\t\t\tthis.collectionCls = collectionCls;\n\t\t\tthis.defValue = defValue;\n\t\t\tthis.options = options;\n\t\t\tthis.optionsNames = optionsNames;\n\t\t\t\n\t\t\tif (defValue != null && !cls.isAssignableFrom(defValue.getClass())) {\n\t\t\t\tthrow new IllegalArgumentException(\"default value paratemeter must of class \" + cls.getCanonicalName());\n\t\t\t}\n\t\t\t\n\t\t\tif (options != null) {\n\t\t\t\tfor (Object option : options) {\n\t\t\t\t\tif (option != null && !cls.isAssignableFrom(option.getClass())) {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\"option values must of class \" + cls.getCanonicalName());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (optionsNames != null && options.length != optionsNames.length) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"if passed options name must be specified for each option\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic DataType(String key, String name, Class cls, Class<? extends Collection> collectionCls, Object defValue, Object[] options) {\n\t\t\tthis(key, name, cls, collectionCls, defValue, options, null);\n\t\t}\n\t\t\n\t\tpublic DataType(String key, String name, Class cls, Class<? extends Collection> collectionCls, Object defValue) {\n\t\t\tthis(key, name, cls, collectionCls, defValue, null, null);\n\t\t}\n\t\t\n\t\tpublic DataType(String key, String name, Class cls, Object defValue, Object[] options) {\n\t\t\tthis(key, name, cls, null, defValue, options, null);\n\t\t}\n\t\t\n\t\tpublic DataType(String key, String name, Class cls, Object defValue) {\n\t\t\tthis(key, name, cls, null, defValue, null, null);\n\t\t}\n\t\t\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\n\t\tpublic String getKey() {\n\t\t\treturn key;\n\t\t}\n\n\t\tpublic Class getCls() {\n\t\t\treturn cls;\n\t\t}\n\t\t\n\t\tpublic Class<? extends Collection> getCollectionCls() {\n\t\t\treturn collectionCls;\n\t\t}\n\t\t\n\t\tpublic <T> T getDefValue() {\n\t\t\treturn (T) defValue;\n\t\t}\n\t\t\n\t\tpublic <T> T[] getOptions() {\n\t\t\treturn (T[]) options;\n\t\t}\n\t\t\n\t\tpublic String[] getOptionsNames() {\n\t\t\treturn optionsNames;\n\t\t}\n\t}\n\t\n\t/**\n\t * This is an attribute name for storing information whether anonymous user\n\t * can login for this domain.\n\t */\n\tpublic static final String ANONYMOUS_ENABLED_ATT = \"anon\";\n\n\t/** Field description */\n\tpublic static final String ANONYMOUS_ENABLED_LABEL = \"Anonymous enabled\";\n\n\t/**\n\t * List of SASL mechanisms allowed for domain\n\t */\n\tpublic static final String SASL_MECHANISM_ATT = \"sasl-mechanisms\";\n\n\tpublic static final String SASL_MECHANISM_LABEL = \"Allowed SASL mechanisms\";\n\n\t/** Field description */\n\tpublic static final String COMPONENTS_ATT = \"comps\";\n\n\t/**\n\t * Element name for the VHostItem XML child keeping list of the server\n\t * component which can handle packets for this domain. In most cases this\n\t * element should be empty.\n\t */\n\tpublic static final String COMPONENTS_ELEM = \"comps\";\n\n\t/**\n\t * This is an attribute name for storing information on which ports VHost\n\t * should be enabled.\n\t */\n\tpublic static final String C2S_PORTS_ALLOWED_ATT = \"c2s-ports-allowed\";\n\n\t/** Field description */\n\tpublic static final String C2S_PORTS_ALLOWED_LABEL = \"Allowed C2S,BOSH,WebSocket ports\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_FILTER_POLICY_ATT = \"domain-filter\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_FILTER_POLICY_DOMAINS_ATT = \"domain-filter-domains\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_FILTER_POLICY_LABEL = \"Domain filter policy\";\n\n\t/** Field description */\n\tpublic static final String DOMAIN_FILTER_POLICY_DOMAINS_LABEL = \"Domain filter domains (only LIST and BLACKLIST)\";\n\n\t/**\n\t * This is an attribute name for storing information whether the VHost is\n\t * enabled or disabled.\n\t */\n\tpublic static final String ENABLED_ATT = \"enabled\";\n\n\t/** Field description */\n\tpublic static final String ENABLED_LABEL = \"Enabled\";\n\n\t/**\n\t * This is an attribute name for storing the VHost name.\n\t */\n\tpublic static final String HOSTNAME_ATT = \"hostname\";\n\n\t/** Field description */\n\tpublic static final String HOSTNAME_LABEL = \"Domain name\";\n\n\t/**\n\t * This is an attribute name for storing the maximum number of users for this\n\t * virtual domain.\n\t */\n\tpublic static final String MAX_USERS_NUMBER_ATT = \"max-users\";\n\n\t/** Field description */\n\tpublic static final String MAX_USERS_NUMBER_LABEL = \"Max users\";\n\n\t/** Field description */\n\tpublic static final String MESSAGE_FORWARD_ADDRESS_ATT = \"mess-forw\";\n\n\t/** Field description */\n\tpublic static final String MESSAGE_FORWARD_ADDRESS_LABEL = \"Message forward address\";\n\n\t/**\n\t * Element name for the VHostItem XML child keeping all the extra parameters\n\t * for the domain. This is a container for future extensions and parameters\n\t * which are not defined yet.\n\t */\n\tpublic static final String OTHER_PARAMS_ELEM = \"other\";\n\n\t/** Field description */\n\tpublic static final String OTHER_PARAMS_LABEL = \"Other parameters\";\n\n\t/** Field description */\n\tpublic static final String PRESENCE_FORWARD_ADDRESS_ATT = \"pres-forw\";\n\n\t/** Field description */\n\tpublic static final String PRESENCE_FORWARD_ADDRESS_LABEL = \"Presence forward address\";\n\n\t/**\n\t * This is an attribute name for storing information whether user registration\n\t * is allowed for this domain.\n\t */\n\tpublic static final String REGISTER_ENABLED_ATT = \"register\";\n\n\t/** Field description */\n\tpublic static final String REGISTER_ENABLED_LABEL = \"In-band registration\";\n\n\t/** Field description */\n\tpublic static final String S2S_SECRET_ATT = \"s2s-secret\";\n\n\t/** Field description */\n\tpublic static final String S2S_SECRET_LABEL = \"S2S secret\";\n\n\t/** Field description */\n\tpublic static final String TLS_REQUIRED_ATT = \"tls-required\";\n\n\t/** Field description */\n\tpublic static final String TLS_REQUIRED_LABEL = \"TLS required\";\n\n\t/** Field description */\n\tpublic static final String TRUSTED_JIDS_ATT = \"trusted-jids\";\n\t\n\t/**\n\t * Element name to for the VHostItem XML storage.\n\t */\n\tpublic static final String VHOST_ELEM = \"vhost\";\n\n\t/** Field description */\n\tprotected static final String DOMAIN_FILTER_POLICY_PROP_KEY = \"domain-filter-policy\";\n\n\t/** Field description */\n\tprotected static final String S2S_SECRET_PROP_DEF = null;\n\n\t/** Field description */\n\tprotected static final String S2S_SECRET_PROP_KEY = \"s2s-secret\";\n\n\t/** Field description */\n\tprotected static final String VHOST_ANONYMOUS_ENABLED_PROP_KEY =\n\t\t\t\"vhost-anonymous-enabled\";\n\n\t/** Field description */\n\tprotected static final Boolean VHOST_ANONYMOUS_ENABLED_PROP_DEF = Boolean.TRUE;\n\n\t/** Field description */\n\tprotected static final String VHOST_MAX_USERS_PROP_KEY = \"vhost-max-users\";\n\n\t/** Field description */\n\tprotected static final Long VHOST_MAX_USERS_PROP_DEF = Long.valueOf(0l);\n\n\t/** Field description */\n\tprotected static final String VHOST_MESSAGE_FORWARD_PROP_DEF = null;\n\n\t/** Field description */\n\tprotected static final String VHOST_MESSAGE_FORWARD_PROP_KEY =\n\t\t\t\"vhost-message-forward-jid\";\n\n\t/** Field description */\n\tprotected static final String VHOST_PRESENCE_FORWARD_PROP_DEF = null;\n\n\t/** Field description */\n\tprotected static final String VHOST_PRESENCE_FORWARD_PROP_KEY =\n\t\t\t\"vhost-presence-forward-jid\";\n\n\t/** Field description */\n\tprotected static final String VHOST_REGISTER_ENABLED_PROP_KEY =\n\t\t\t\"vhost-register-enabled\";\n\n\t/** Field description */\n\tprotected static final Boolean VHOST_REGISTER_ENABLED_PROP_DEF = Boolean.TRUE;\n\n\t/** Field description */\n\tprotected static final String VHOST_TLS_REQUIRED_PROP_KEY = \"vhost-tls-required\";\n\n\t/** Field description */\n\tprotected static final Boolean VHOST_TLS_REQUIRED_PROP_DEF = Boolean.FALSE;\n\n\t/** Field description */\n\tprotected static final DomainFilterPolicy DOMAIN_FILTER_POLICY_PROP_DEF =\n\t\t\tDomainFilterPolicy.ALL;\n\tprivate static final Logger log = Logger.getLogger(VHostItem.class.getName());\n\n\t/** Field description */\n\tprotected static final String[] VHOST_OTHER_PARAMS_PATH = { VHOST_ELEM,\n\t\t\tOTHER_PARAMS_ELEM };\n\n\t/** Field description */\n\tprotected static final String[] VHOST_COMPONENTS_PATH = { VHOST_ELEM, COMPONENTS_ELEM };\n\n\tprotected static final Map<String,DataType> dataTypes = new ConcurrentHashMap<String,DataType>();\n\t\n\tprivate static ConcurrentSkipListSet<String> GLOBAL_TRUSTED_JIDS = null;\n\t\n\tpublic static void registerData(List<DataType> types) {\n\t\tfor (DataType type : types) {\n\t\t\tdataTypes.put(type.getKey(), type);\n\t\t}\n\t}\n\t\n\tprotected static void initGlobalTrustedJids() {\n\t\tString trustedJidsStr = System.getProperty(\"trusted\");\n\t\tif (trustedJidsStr == null || trustedJidsStr.isEmpty())\n\t\t\tGLOBAL_TRUSTED_JIDS = null;\n\t\telse {\n\t\t\tConcurrentSkipListSet<String> trusted = new ConcurrentSkipListSet<>();\n\t\t\tfor (String trustedStr : trustedJidsStr.split(\",\")) {\n\t\t\t\tif (!trustedStr.contains(\"{\"))\n\t\t\t\t\ttrusted.add(trustedStr);\n\t\t\t}\n\t\t\tif (trusted.isEmpty())\n\t\t\t\tGLOBAL_TRUSTED_JIDS = null;\n\t\t\telse\n\t\t\t\tGLOBAL_TRUSTED_JIDS = trusted;\n\t\t}\n\t}\n\t\n\tstatic {\n\t\tList<DataType> types = new ArrayList<VHostItem.DataType>();\n\t\ttypes.add(new DataType(ClientTrustManagerFactory.CA_CERT_PATH, \"Client Certificate CA\", String.class, null));\n\t\ttypes.add(new DataType(ClientTrustManagerFactory.CERT_REQUIRED_KEY, \"Client Certificate Required\", Boolean.class,\n\t\t\t\tBoolean.FALSE));\n\t\ttypes.add(new DataType(TRUSTED_JIDS_ATT, \"Trusted JIDs\", String[].class, \n\t\t\t\tConcurrentSkipListSet.class, null, null));\n\t\tVHostItem.registerData(types);\n\t\t\n\t\tinitGlobalTrustedJids();\n\t}\n\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] comps = null;\n\tprivate int[] c2sPortsAllowed = null;\n\tprivate String[] saslAllowedMechanisms = null;\n\tprivate long     maxUsersNumber = Long.getLong(VHOST_MAX_USERS_PROP_KEY,\n\t\t\tVHOST_MAX_USERS_PROP_DEF);\n\tprivate JID messageForward = JID.jidInstanceNS(System.getProperty(\n\t\t\tVHOST_MESSAGE_FORWARD_PROP_KEY, VHOST_MESSAGE_FORWARD_PROP_DEF));\n\tprivate String otherDomainParams = null;\n\tprivate JID    presenceForward = JID.jidInstanceNS(System.getProperty(\n\t\t\tVHOST_PRESENCE_FORWARD_PROP_KEY, VHOST_PRESENCE_FORWARD_PROP_DEF));\n\tprivate VHostItem unmodifiableItem = null;\n\tprivate JID       vhost            = null;\n\tprivate boolean   tlsRequired = DataTypes.getProperty(VHOST_TLS_REQUIRED_PROP_KEY,\n\t\t\tVHOST_TLS_REQUIRED_PROP_DEF);\n\tprivate String  s2sSecret = System.getProperty(S2S_SECRET_PROP_KEY,\n\t\t\tS2S_SECRET_PROP_DEF);\n\tprivate boolean registerEnabled = DataTypes.getProperty(\n\t\t\tVHOST_REGISTER_ENABLED_PROP_KEY, VHOST_REGISTER_ENABLED_PROP_DEF);\n\tprivate boolean            enabled = true;\n\tprivate DomainFilterPolicy domainFilter = DomainFilterPolicy.valueof(System.getProperty(\n\t\t\tDOMAIN_FILTER_POLICY_PROP_KEY, DOMAIN_FILTER_POLICY_PROP_DEF.toString()));\n\tprivate String[] domainFilterDomains = null;\n\tprivate boolean anonymousEnabled = DataTypes.getProperty(\n\t\t\tVHOST_ANONYMOUS_ENABLED_PROP_KEY, VHOST_ANONYMOUS_ENABLED_PROP_DEF);\n\tprivate Map<String,Object> data = new ConcurrentHashMap<String,Object>();\n\t\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic VHostItem() {\n\t\t// added to ensure that we have s2sSecret set, as without it S2S connections\n\t\t// will always fail (needed mostly for newly added vhosts).\n\t\tif (s2sSecret == null) {\n\t\t\ts2sSecret = UUID.randomUUID().toString();\n\t\t}\n\t\tif (GLOBAL_TRUSTED_JIDS != null) {\n\t\t\tdata.put(TRUSTED_JIDS_ATT, GLOBAL_TRUSTED_JIDS);\n\t\t}\n\t}\n\n\t/**\n\t * The constructor creates the <code>VHostItem</code> instance from a given\n\t * XML element. Please refer to the class documentation for more details of\n\t * the XML element.\n\t *\n\t * @param elem\n\t *          is an <code>Element</code> object with virtual domain settings.\n\t */\n\tpublic VHostItem(Element elem) {\n\t\tinitFromElement(elem);\n\t}\n\n\t/**\n\t * The constructor creates the <code>VHostItem</code> instance for a given\n\t * domain name with default values for all other parameters. By the default\n\t * all domain parameters are set to true.\n\t *\n\t * @param vhost\n\t *          is a <code>String</code> value with a domain name.\n\t */\n\tpublic VHostItem(JID vhost) {\n\t\tsetVHost(vhost);\n\t}\n\n\t/**\n\t * The constructor creates the <code>VHostItem</code> instance for a given\n\t * domain name with default values for all other parameters. By the default\n\t * all domain parameters are set to true.\n\t *\n\t * @param vhost\n\t *          is a <code>String</code> value with a domain name.\n\t * @throws TigaseStringprepException\n\t *           if the provided string causes stringprep processing errors.\n\t */\n\tpublic VHostItem(String vhost) throws TigaseStringprepException {\n\t\tsetVHost(vhost);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addCommandFields(Packet packet) {\n\t\tCommand.addFieldValue(packet, HOSTNAME_LABEL, (vhost != null)\n\t\t\t\t? vhost.getDomain()\n\t\t\t\t: \"\");\n\t\tCommand.addCheckBoxField(packet, ENABLED_LABEL, enabled);\n\t\tCommand.addCheckBoxField(packet, ANONYMOUS_ENABLED_LABEL, anonymousEnabled);\n\t\tCommand.addCheckBoxField(packet, REGISTER_ENABLED_LABEL, registerEnabled);\n\t\tCommand.addCheckBoxField(packet, TLS_REQUIRED_LABEL, tlsRequired);\n\t\tCommand.addFieldValue(packet, S2S_SECRET_LABEL, (s2sSecret != null)\n\t\t\t\t? s2sSecret\n\t\t\t\t: \"\");\n\t\tCommand.addFieldValue(packet, DOMAIN_FILTER_POLICY_LABEL, domainFilter.toString(),\n\t\t\t\tDOMAIN_FILTER_POLICY_LABEL, DomainFilterPolicy.valuesStr(), DomainFilterPolicy\n\t\t\t\t.valuesStr());\n\t\tCommand.addFieldValue(packet, DOMAIN_FILTER_POLICY_DOMAINS_LABEL,\n\t\t\t\t\t\t\tdomainFilterDomains != null ? stringArrayToString( domainFilterDomains, \";\") : \"\");\n\t\tCommand.addFieldValue(packet, MAX_USERS_NUMBER_LABEL, \"\" + maxUsersNumber);\n\t\tString c2sPortsAllowedStr = intArrayToString(c2sPortsAllowed,\",\");\n\t\tCommand.addFieldValue(packet, C2S_PORTS_ALLOWED_LABEL,\n\t\t\t\tc2sPortsAllowedStr != null ? c2sPortsAllowedStr : \"\");\n\t\tCommand.addFieldValue(packet, PRESENCE_FORWARD_ADDRESS_LABEL, ((presenceForward !=\n\t\t\t\tnull)\n\t\t\t\t? presenceForward.toString()\n\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, MESSAGE_FORWARD_ADDRESS_LABEL, ((messageForward != null)\n\t\t\t\t? messageForward.toString()\n\t\t\t\t: \"\"));\n\t\tCommand.addFieldValue(packet, OTHER_PARAMS_LABEL, (otherDomainParams != null)\n\t\t\t\t? otherDomainParams\n\t\t\t\t: \"\");\n\t\tCommand.addFieldValue(packet, SASL_MECHANISM_LABEL,\n\t\t\t\tsaslAllowedMechanisms != null ? stringArrayToString(saslAllowedMechanisms, \",\") : \"\");\n\n\t\tsuper.addCommandFields(packet);\n\t\t\n\t\tfor (DataType type : dataTypes.values()) {\n\t\t\tif (type.cls != Boolean.class) {\n\t\t\t\tObject[] options = type.getOptions();\n\t\t\t\tObject val = getData(type.getKey());\n\t\t\t\tif (val instanceof Collection) {\n\t\t\t\t\tCollection collection = (Collection) val;\n\t\t\t\t\tval = Array.newInstance(type.getCls().getComponentType(), collection.size());\n\t\t\t\t\tint i=0;\n\t\t\t\t\tfor (Object v : collection) {\n\t\t\t\t\t\tArray.set(val, i, v);\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tString valueStr = val != null ? DataTypes.valueToString(val) : \"\";\n\t\t\t\tif (options == null || options.length == 0) {\n\t\t\t\t\tCommand.addFieldValue(packet, type.getName(), valueStr);\n\t\t\t\t} else {\n\t\t\t\t\tString[] optionsStr = new String[options.length];\n\t\t\t\t\tfor (int i=0; i<options.length; i++) {\n\t\t\t\t\t\toptionsStr[i] = (options[i] != null) ? DataTypes.valueToString(options[i]) : \"\";\n\t\t\t\t\t}\n\t\t\t\t\tString[] optionsNames = type.getOptionsNames();\n\t\t\t\t\tif (optionsNames == null) \n\t\t\t\t\t\toptionsNames = optionsStr;\n\t\t\t\t\tCommand.addFieldValue(packet, type.getName(), valueStr, type.getName(), optionsNames, optionsStr);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tboolean val = isData(type.getKey());\n\t\t\t\tCommand.addCheckBoxField(packet, type.getName(), val);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int compareTo( VHostItem o ) {\n\t\treturn vhost.compareTo( o.vhost );\n\t}\n\n\t@Override\n\tpublic boolean equals( Object v ) {\n\t\tboolean result = false;\n\t\tif ( v instanceof VHostItem ){\n\n\t\t\tresult = vhost.equals( ( (VHostItem) v ).vhost );\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn vhost.hashCode();\n\t}\n\n\t@Override\n\tpublic void initFromCommand(Packet packet) {\n\t\tsuper.initFromCommand(packet);\n\n\t\tString tmp = Command.getFieldValue(packet, HOSTNAME_LABEL);\n\n\t\ttry {\n\t\t\tsetVHost(tmp);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new IllegalArgumentException(\"Incorrect domain, unable to parse it: \" + tmp,\n\t\t\t\t\tex);\n\t\t}\n\t\tenabled          = Command.getCheckBoxFieldValue(packet, ENABLED_LABEL);\n\t\tanonymousEnabled = Command.getCheckBoxFieldValue(packet, ANONYMOUS_ENABLED_LABEL);\n\t\tregisterEnabled  = Command.getCheckBoxFieldValue(packet, REGISTER_ENABLED_LABEL);\n\t\ttlsRequired      = Command.getCheckBoxFieldValue(packet, TLS_REQUIRED_LABEL);\n\t\ttmp              = Command.getFieldValue(packet, S2S_SECRET_LABEL);\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\ts2sSecret = tmp;\n\t\t} else {\n\t\t\ts2sSecret = null;\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, DOMAIN_FILTER_POLICY_LABEL);\n\t\ttry {\n\t\t\tdomainFilter = DomainFilterPolicy.valueof(tmp);\n\t\t\tif (domainFilter == null) {\n\t\t\t\tdomainFilter = DomainFilterPolicy.valueof(System.getProperty(\n\t\t\t\t\t\tDOMAIN_FILTER_POLICY_PROP_KEY, DOMAIN_FILTER_POLICY_PROP_DEF.toString()));\n\t\t\t} else if (domainFilter == DomainFilterPolicy.LIST || domainFilter == DomainFilterPolicy.BLACKLIST\n\t\t\t\t\t|| domainFilter == DomainFilterPolicy.CUSTOM) {\n\t\t\t\ttmp = Command.getFieldValue(packet, DOMAIN_FILTER_POLICY_DOMAINS_LABEL);\n\t\t\t\tif ( tmp != null && !tmp.trim().isEmpty() ){\n\t\t\t\t\tdomainFilterDomains = StringUtilities.stringToArrayOfString( tmp, \";\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (Exception ex) {\n\t\t\tdomainFilter = DOMAIN_FILTER_POLICY_PROP_DEF;\n\t\t}\n\t\ttry {\n\t\t\tmaxUsersNumber = Long.parseLong(Command.getFieldValue(packet,\n\t\t\t\t\tMAX_USERS_NUMBER_LABEL));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can not parse max users number: {0}\", Command.getFieldValue(\n\t\t\t\t\tpacket, MAX_USERS_NUMBER_LABEL));\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, PRESENCE_FORWARD_ADDRESS_LABEL);\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\ttry {\n\t\t\t\tpresenceForward = JID.jidInstance(tmp);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tpresenceForward = null;\n\n\t\t\t\tthrow new IllegalArgumentException(\"Incorrect presence forward address: \" + tmp,\n\t\t\t\t\t\tex);\n\t\t\t}\n\t\t}\n\t\ttmp = Command.getFieldValue(packet, MESSAGE_FORWARD_ADDRESS_LABEL);\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\ttry {\n\t\t\t\tmessageForward = JID.jidInstance(tmp);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tmessageForward = null;\n\n\t\t\t\tthrow new IllegalArgumentException(\"Incorrect message forward address: \" + tmp,\n\t\t\t\t\t\tex);\n\t\t\t}\n\t\t}\n\t\totherDomainParams = Command.getFieldValue(packet, OTHER_PARAMS_LABEL);\n\t\ttmp = Command.getFieldValue(packet, C2S_PORTS_ALLOWED_LABEL);\n\t\tc2sPortsAllowed = parseIntArray(tmp, \",\");\n\n\t\ttmp = Command.getFieldValue(packet, SASL_MECHANISM_LABEL);\n\t\tif ((tmp != null) && !tmp.trim().isEmpty()) {\n\t\t\tsetSaslAllowedMechanisms(tmp.split(\",\"));\n\t\t}\n\n\t\tfor (DataType type : dataTypes.values()) {\n\t\t\tString valueStr = Command.getFieldValue(packet, type.getName());\n\t\t\tchar typeId = DataTypes.typesMap.get(type.cls.getName());\n\t\t\tObject value = (valueStr == null || valueStr.isEmpty()) ? null :DataTypes.decodeValueType(typeId, valueStr);\n\t\t\tif (value != null && type.getCollectionCls() != null) {\n\t\t\t\ttry {\n\t\t\t\t\tCollection collection = type.getCollectionCls().newInstance();\n\t\t\t\t\tfor (int i = 0; i < Array.getLength(value); i++) {\n\t\t\t\t\t\tcollection.add(Array.get(value, i));\n\t\t\t\t\t}\n\t\t\t\t\tvalue = collection;\n\t\t\t\t} catch (InstantiationException | IllegalAccessException ex) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Could not instantiate collection of class: \" \n\t\t\t\t\t\t\t+ type.getCollectionCls().getCanonicalName(), ex);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetData(type.getKey(), value);\n\t\t}\n\n\t\tlog.log( Level.FINE, \"Initialized from command: {0}\", this);\n\n\t}\n\n\t@Override\n\tpublic void initFromElement(Element elem) {\n\t\tif (elem.getName() != VHOST_ELEM) {\n\t\t\tthrow new IllegalArgumentException(\"Incorrect element name, expected: \" +\n\t\t\t\t\tVHOST_ELEM);\n\t\t}\n\t\tsuper.initFromElement(elem);\n\t\tsetVHost(JID.jidInstanceNS(elem.getAttributeStaticStr(HOSTNAME_ATT)));\n\t\tenabled = Boolean.parseBoolean(elem.getAttributeStaticStr(ENABLED_ATT));\n\t\tanonymousEnabled = Boolean.parseBoolean(elem.getAttributeStaticStr(\n\t\t\t\tANONYMOUS_ENABLED_ATT));\n\t\tregisterEnabled = Boolean.parseBoolean(elem.getAttributeStaticStr(\n\t\t\t\tREGISTER_ENABLED_ATT));\n\t\ttlsRequired = Boolean.parseBoolean(elem.getAttributeStaticStr(TLS_REQUIRED_ATT));\n\t\ts2sSecret   = elem.getAttributeStaticStr(S2S_SECRET_ATT);\n\t\ttry {\n\t\t\tdomainFilter = DomainFilterPolicy.valueof(elem.getAttributeStaticStr(\n\t\t\t\t\tDOMAIN_FILTER_POLICY_ATT));\n\t\t\tif (domainFilter == null) {\n\t\t\t\tdomainFilter = DomainFilterPolicy.valueof(System.getProperty(\n\t\t\t\t\t\tDOMAIN_FILTER_POLICY_PROP_KEY, DOMAIN_FILTER_POLICY_PROP_DEF.toString()));\n\t\t\t} else if (domainFilter == DomainFilterPolicy.LIST || domainFilter == DomainFilterPolicy.BLACKLIST\n\t\t\t\t\t|| domainFilter == DomainFilterPolicy.CUSTOM) {\n\t\t\t\tString tmp = elem.getAttributeStaticStr(DOMAIN_FILTER_POLICY_DOMAINS_ATT);\n\t\t\t\tif ( tmp != null && !tmp.trim().isEmpty() ){\n\t\t\t\t\tdomainFilterDomains = StringUtilities.stringToArrayOfString( tmp, \";\" );\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tdomainFilter = DOMAIN_FILTER_POLICY_PROP_DEF;\n\t\t}\n\t\ttry {\n\t\t\tmaxUsersNumber = Long.parseLong(elem.getAttributeStaticStr(MAX_USERS_NUMBER_ATT));\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can not parse max users number: {0}\", elem\n\t\t\t\t\t.getAttributeStaticStr(MAX_USERS_NUMBER_ATT));\n\t\t\tmaxUsersNumber = Long.getLong(VHOST_MAX_USERS_PROP_KEY, VHOST_MAX_USERS_PROP_DEF);\n\t\t}\n\n\t\tString tmp = elem.getAttributeStaticStr(PRESENCE_FORWARD_ADDRESS_ATT);\n\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\tpresenceForward = JID.jidInstanceNS(tmp);\n\t\t}\n\t\ttmp = elem.getAttributeStaticStr(MESSAGE_FORWARD_ADDRESS_ATT);\n\t\tif ((tmp != null) &&!tmp.trim().isEmpty()) {\n\t\t\tmessageForward = JID.jidInstanceNS(tmp);\n\t\t}\n\n\t\tString comps_str = elem.getCDataStaticStr(VHOST_COMPONENTS_PATH);\n\n\t\tif ((comps_str != null) &&!comps_str.isEmpty()) {\n\t\t\tcomps = comps_str.split(\",\");\n\t\t}\n\t\totherDomainParams = elem.getCDataStaticStr(VHOST_OTHER_PARAMS_PATH);\n\n\t\tthis.c2sPortsAllowed = parseIntArray(elem.getAttributeStaticStr(C2S_PORTS_ALLOWED_ATT), \",\");\n\n\t\ttmp = elem.getAttributeStaticStr(SASL_MECHANISM_ATT);\n\t\tif (tmp != null) {\n\t\t\tsetSaslAllowedMechanisms(tmp.split(\";\"));\n\t\t}\n\t\t\n\t\tElement data = elem.getChild(\"data\");\n\t\tif (data != null) {\n\t\t\tList<Element> items = data.getChildren();\n\t\t\tif (items != null) {\n\t\t\t\tfor (Element item : items) {\n\t\t\t\t\tDataType type = dataTypes.get(item.getName());\n\t\t\t\t\tchar typeChar = type != null ? DataTypes.typesMap.get(type.getCls().getName()) : item.getAttributeStaticStr(\"type\").charAt(0);\n\t\t\t\t\tObject value = DataTypes.decodeValueType(typeChar, item.getCData());\n\t\t\t\t\tif (type != null && type.getCollectionCls() != null && value != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tCollection collection = type.getCollectionCls().newInstance();\n\t\t\t\t\t\t\tfor (int i = 0; i < Array.getLength(value); i++) {\n\t\t\t\t\t\t\t\tcollection.add(Array.get(value, i));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvalue = collection;\n\t\t\t\t\t\t} catch (InstantiationException | IllegalAccessException ex) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"Could not instantiate collection of class: \"\n\t\t\t\t\t\t\t\t\t+ type.getCollectionCls().getCanonicalName(), ex);\n\t\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\tsetData(item.getName(), value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlog.log( Level.FINE, \"Initialized from element: {0}\", this);\n\t}\n\n\t@Override\n\tpublic void initFromPropertyString(String propString) {\n\t\tString[] props = propString.split(\":\");\n\n\t\ttry {\n\t\t\tsetVHost(props[0]);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tthrow new IllegalArgumentException(\"Domain misconfiguration, cannot parse it: \" +\n\t\t\t\t\tprops[0], ex);\n\t\t}\n\t\tfor (String tmp : props) {\n\t\t\tboolean val = true;\n\n\t\t\tif (tmp.startsWith(\"-\")) {\n\t\t\t\tval = false;\n\t\t\t}\n\t\t\tif (tmp.endsWith(ANONYMOUS_ENABLED_ATT)) {\n\t\t\t\tanonymousEnabled = val;\n\t\t\t}\n\t\t\tif (tmp.endsWith(REGISTER_ENABLED_ATT)) {\n\t\t\t\tregisterEnabled = val;\n\t\t\t}\n\t\t\tif (tmp.endsWith(TLS_REQUIRED_ATT)) {\n\t\t\t\ttlsRequired = val;\n\t\t\t}\n\t\t\tif (tmp.startsWith(S2S_SECRET_ATT)) {\n\t\t\t\tString[] s2 = tmp.split(\"=\");\n\n\t\t\t\ts2sSecret = s2[1];\n\t\t\t}\n\t\t\tif (tmp.startsWith(COMPONENTS_ATT)) {\n\t\t\t\tString[] c         = tmp.split(\"=\");\n\t\t\t\tString   comps_str = c[1];\n\n\t\t\t\tif (!comps_str.isEmpty()) {\n\t\t\t\t\tcomps = comps_str.split(\";\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmp.startsWith(DOMAIN_FILTER_POLICY_ATT)) {\n\t\t\t\tString[] df = tmp.split(\"=\");\n\t\t\t\tString[] domains;\n\n\t\t\t\ttry {\n\t\t\t\t\tif ( df.length == 2 ){\n\t\t\t\t\t\tdomainFilter = DomainFilterPolicy.valueof( df[1] );\n\t\t\t\t\t} else if ( df.length == 3 ){\n\t\t\t\t\t\tdomainFilter = DomainFilterPolicy.valueof( df[1] );\n\t\t\t\t\t\tif ( df[2] != null && !df[2].trim().isEmpty() ){\n\t\t\t\t\t\t\tdomainFilterDomains = StringUtilities.stringToArrayOfString( df[2], \";\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( domainFilter == null ){\n\t\t\t\t\t\tdomainFilter = DomainFilterPolicy.valueof( System.getProperty(\n\t\t\t\t\t\t\t\tDOMAIN_FILTER_POLICY_PROP_KEY, DOMAIN_FILTER_POLICY_PROP_DEF.toString() ) );\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tdomainFilter = DOMAIN_FILTER_POLICY_PROP_DEF;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmp.startsWith(MAX_USERS_NUMBER_ATT)) {\n\t\t\t\tString[] mu = tmp.split(\"=\");\n\n\t\t\t\ttry {\n\t\t\t\t\tmaxUsersNumber = Long.parseLong(mu[1]);\n\t\t\t\t} catch (NumberFormatException ex) {\n\t\t\t\t\tmaxUsersNumber = 0;\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Incorrect max users number for vhost settings, number parsing error: {0}\",\n\t\t\t\t\t\t\ttmp);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmp.startsWith(PRESENCE_FORWARD_ADDRESS_ATT)) {\n\t\t\t\tString[] mu = tmp.split(\"=\");\n\n\t\t\t\ttry {\n\t\t\t\t\tpresenceForward = JID.jidInstance(mu[1]);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tpresenceForward = null;\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Incorrect presence forwarding address, address parsing error: {0}\", tmp);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmp.startsWith(MESSAGE_FORWARD_ADDRESS_ATT)) {\n\t\t\t\tString[] mu = tmp.split(\"=\");\n\n\t\t\t\ttry {\n\t\t\t\t\tmessageForward = JID.jidInstance(mu[1]);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tmessageForward = null;\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Incorrect presence forwarding address, address parsing error: {0}\", tmp);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmp.startsWith(C2S_PORTS_ALLOWED_ATT)) {\n\t\t\t\tString[] mu = tmp.split(\"=\");\n\n\t\t\t\tc2sPortsAllowed = parseIntArray(mu[1], \";\");\n\t\t\t}\n\t\t\tif(tmp.startsWith(SASL_MECHANISM_ATT)){\n\t\t\t\tString[] mu = tmp.split(\"=\");\n\t\t\t\tsetSaslAllowedMechanisms(mu[1].split(\";\"));\n\t\t\t}\n\n\t\t\tString[] mu = tmp.split(\"=\");\n\t\t\tif (mu != null && mu.length == 2 && dataTypes.containsKey(mu[0])) {\n\t\t\t\tparseDataValue(mu[0], mu[1]);\n\t\t\t}\n\n\t\t}\n\t\tlog.log( Level.FINE, \"Initialized from property string: {0}\", this);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * The method exports the <code>VHostItem</code> object to XML representation.\n\t *\n\t * @return an <code>Element</code> object with VHost information.\n\t */\n\t@Override\n\tpublic Element toElement() {\n\t\tElement elem      = super.toElement();\n\t\tString  comps_str = \"\";\n\n\t\tif ((comps != null) && (comps.length > 0)) {\n\t\t\tfor (String comp : comps) {\n\t\t\t\tif (!comps_str.isEmpty()) {\n\t\t\t\t\tcomps_str += \",\";\n\t\t\t\t}\n\t\t\t\tcomps_str += comp;\n\t\t\t}\n\t\t}\n\n\t\tString other_params = (otherDomainParams != null)\n\t\t\t\t? otherDomainParams\n\t\t\t\t: \"\";\n\n\t\telem.addChild(new Element(COMPONENTS_ELEM, comps_str));\n\t\telem.addChild(new Element(OTHER_PARAMS_ELEM, other_params));\n\t\telem.addAttribute(HOSTNAME_ATT, vhost.getDomain());\n\t\telem.addAttribute(ENABLED_ATT, \"\" + enabled);\n\t\telem.addAttribute(ANONYMOUS_ENABLED_ATT, \"\" + anonymousEnabled);\n\t\tif (saslAllowedMechanisms != null)\n\t\t\telem.addAttribute(SASL_MECHANISM_ATT, stringArrayToString(saslAllowedMechanisms, \";\"));\n\t\telem.addAttribute(REGISTER_ENABLED_ATT, \"\" + registerEnabled);\n\t\telem.addAttribute(TLS_REQUIRED_ATT, \"\" + tlsRequired);\n\t\tif (s2sSecret != null) {\n\t\t\telem.addAttribute(S2S_SECRET_ATT, s2sSecret);\n\t\t}\n\t\tif (domainFilter != null) {\n\t\t\telem.addAttribute(DOMAIN_FILTER_POLICY_ATT, domainFilter.toString());\n\t\t}\n\t\tif (domainFilterDomains != null) {\n\t\t\telem.addAttribute(DOMAIN_FILTER_POLICY_DOMAINS_ATT, stringArrayToString( domainFilterDomains, \";\"));\n\t\t}\n\t\telem.addAttribute(MAX_USERS_NUMBER_ATT, \"\" + maxUsersNumber);\n\t\tif (presenceForward != null) {\n\t\t\telem.addAttribute(PRESENCE_FORWARD_ADDRESS_ATT, presenceForward.toString());\n\t\t}\n\t\tif (messageForward != null) {\n\t\t\telem.addAttribute(MESSAGE_FORWARD_ADDRESS_ATT, messageForward.toString());\n\t\t}\n\t\tif (c2sPortsAllowed != null) {\n\t\t\tString c2sPortsAllowedStr = intArrayToString(c2sPortsAllowed, \",\");\n\t\t\telem.addAttribute(C2S_PORTS_ALLOWED_ATT, c2sPortsAllowedStr);\n\t\t}\n\n\t\tif (!data.isEmpty()) {\n\t\t\tElement data = new Element(\"data\");\n\t\t\tfor (Map.Entry<String,Object> e : this.data.entrySet()) {\n\t\t\t\tElement item = new Element(e.getKey());\n\t\t\t\titem.addAttribute(\"type\", String.valueOf(DataTypes.getTypeId(e.getValue())));\n\t\t\t\tObject val = e.getValue();\n\t\t\t\tDataType type = dataTypes.get(e.getKey());\n\t\t\t\tif (type != null && val instanceof Collection && type.getCollectionCls() != null) {\n\t\t\t\t\tCollection collection = (Collection) val;\n\t\t\t\t\tval = Array.newInstance(type.getCls().getComponentType(), collection.size());\n\t\t\t\t\tint i=0;\n\t\t\t\t\tfor (Object v : collection) {\n\t\t\t\t\t\tArray.set(val, i, v);\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\titem.setCData(DataTypes.valueToString(val));\n\t\t\t\tdata.addChild(item);\n\t\t\t}\n\t\t\telem.addChild(data);\n\t\t}\n\t\t\n\t\treturn elem;\n\t}\n\n\t@Override\n\tpublic String toPropertyString() {\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tsb.append(vhost.toString());\n\t\tif (!anonymousEnabled) {\n\t\t\tsb.append(\":-\").append(ANONYMOUS_ENABLED_ATT);\n\t\t}\n\t\tif (!registerEnabled) {\n\t\t\tsb.append(\":-\").append(REGISTER_ENABLED_ATT);\n\t\t}\n\t\tif (!tlsRequired) {\n\t\t\tsb.append(\":-\").append(TLS_REQUIRED_ATT);\n\t\t}\n\t\tif (s2sSecret != null) {\n\t\t\tsb.append(':').append(S2S_SECRET_ATT).append('=').append(s2sSecret);\n\t\t}\n\t\tsb.append(':').append(DOMAIN_FILTER_POLICY_ATT).append('=').append(domainFilter\n\t\t\t\t.toString());\n\t\tif (domainFilterDomains!=null) {\n\t\t\tsb.append( \"=\").append( stringArrayToString( domainFilterDomains, \";\"));\n\t\t}\n\t\tif (maxUsersNumber > 0) {\n\t\t\tsb.append(':').append(MAX_USERS_NUMBER_ATT).append('=').append(maxUsersNumber);\n\t\t}\n\t\tif (presenceForward != null) {\n\t\t\tsb.append(':').append(PRESENCE_FORWARD_ADDRESS_ATT).append('=').append(\n\t\t\t\t\tpresenceForward.toString());\n\t\t}\n\t\tif (messageForward != null) {\n\t\t\tsb.append(':').append(MESSAGE_FORWARD_ADDRESS_ATT).append('=').append(messageForward\n\t\t\t\t\t.toString());\n\t\t}\n\t\tif (c2sPortsAllowed != null) {\n\t\t\tsb.append(':').append(C2S_PORTS_ALLOWED_ATT).append('=').append(intArrayToString(c2sPortsAllowed, \";\"));\n\t\t}\n\n\t\tif (saslAllowedMechanisms != null) {\n\t\t\tsb.append(':').append(SASL_MECHANISM_ATT).append('=').append(stringArrayToString(saslAllowedMechanisms, \";\"));\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tString str = \"Domain: \" + vhost + \", enabled: \" + enabled\n\t\t\t\t\t\t\t\t + \", anonym: \" + anonymousEnabled + \", register: \" + registerEnabled\n\t\t\t\t\t\t\t\t + \", maxusers: \" + maxUsersNumber + \", tls: \" + tlsRequired\n\t\t\t\t\t\t\t\t + \", s2sSecret: \" + s2sSecret + \", domainFilter: \" + domainFilter\n\t\t\t\t\t\t\t\t + \", domainFilterDomains: \" + stringArrayToString( domainFilterDomains, \";\")\n\t\t\t\t\t\t\t\t + \", c2sPortsAllowed: \" + intArrayToString( c2sPortsAllowed, \",\" )\n\t\t\t\t\t\t\t\t + \", saslAllowedMechanisms: \" + Arrays.toString( saslAllowedMechanisms );\n\t\t\n\t\tfor (Map.Entry<String,Object> e : data.entrySet()) {\n\t\t\tObject val = e.getValue();\n\t\t\tDataType type = dataTypes.get(e.getKey());\n\t\t\tif (type != null && val instanceof Collection && type.getCollectionCls() != null) {\n\t\t\t\tCollection collection = (Collection) val;\n\t\t\t\tval = Array.newInstance(type.getCls().getComponentType(), collection.size());\n\t\t\t\tint i = 0;\n\t\t\t\tfor (Object v : collection) {\n\t\t\t\t\tArray.set(val, i, v);\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t}\t\t\t\n\t\t\tstr += \", \" + e.getKey() + \": \" + DataTypes.valueToString(val);\n\t\t}\n\t\t\n\t\treturn str;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns an array with the server components names which should process\n\t * packets sent to this domain or <code>null</code> (default) if there is no\n\t * specific component assigned to this domain.\n\t *\n\t * @return a <code>String[]</code> object with server component names.\n\t */\n\tpublic String[] getComps() {\n\t\treturn comps;\n\t}\n\n\t/**\n\t * Returns an array with ports on which C2S connections for this VHosts\n\t * are allowed.\n\t *\n\t * @return a <code>int[]</code> object with allowed C2S ports.\n\t */\n\tpublic int[] getC2SPortsAllowed() {\n\t\treturn c2sPortsAllowed;\n\t}\n\n\t/**\n\t * Return value for key for this VHost\n\t * \n\t * @param <T>\n\t * @param key\n\t * @return \n\t */\n\tpublic <T> T getData(String key) {\n\t\tT val = (T) data.get(key);\n\t\tif (val == null) {\n\t\t\tDataType type = dataTypes.get(key);\n\t\t\tif (type != null) {\n\t\t\t\tval = type.getDefValue();\n\t\t\t}\n\t\t}\n\t\treturn val;\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>DomainFilterPolicy</code>\n\t */\n\tpublic DomainFilterPolicy getDomainFilter() {\n\t\tif (domainFilter == null) {\n\t\t\tdomainFilter = DomainFilterPolicy.valueof(System.getProperty(\n\t\t\t\t\tDOMAIN_FILTER_POLICY_PROP_KEY, DOMAIN_FILTER_POLICY_PROP_DEF.toString()));\n\t\t}\n\n\t\treturn domainFilter;\n\t}\n\n\tpublic String[] getDomainFilterDomains() {\n\t\treturn domainFilterDomains;\n\t}\n\t\n\t@Override\n\tpublic String getElemName() {\n\t\treturn VHOST_ELEM;\n\t}\n\n\t@Override\n\tpublic String getKey() {\n\t\treturn this.vhost.getDomain();\n\t}\n\n\t/**\n\t * This method returns the maximum number of user accounts allowed for this\n\t * domain. This parameter is to allow for limiting number of users on per\n\t * domain basis.\n\t *\n\t * @return a <code>long</code> value indicating the maximum number of user\n\t *         accounts allowed for this domain.\n\t */\n\tpublic long getMaxUsersNumber() {\n\t\treturn maxUsersNumber;\n\t}\n\n\t/**\n\t * @return the messageForward\n\t */\n\tpublic JID getMessageForward() {\n\t\treturn messageForward;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tpublic JID getMessageForwardAddress() {\n\t\treturn messageForward;\n\t}\n\n\t/**\n\t * This method allows to access the virtual domain other configuration\n\t * parameters. This is future feature API and it is not used right now. It\n\t * allows to access configuration parameters which are not specified at the\n\t * time of API definition.\n\t *\n\t * @return a <code>String</code> value with domain extra parameters.\n\t */\n\tpublic String getOtherDomainParams() {\n\t\treturn otherDomainParams;\n\t}\n\n\t/**\n\t * @return the presenceForward\n\t */\n\tpublic JID getPresenceForward() {\n\t\treturn presenceForward;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tpublic JID getPresenceForwardAddress() {\n\t\treturn presenceForward;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getS2sSecret() {\n\t\treturn s2sSecret;\n\t}\n\n\tpublic Set<String> getTrustedJIDs() {\n\t\treturn getData(TRUSTED_JIDS_ATT);\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>VHostItem</code>\n\t */\n\tpublic VHostItem getUnmodifiableVHostItem() {\n\t\tif (unmodifiableItem == null) {\n\t\t\tunmodifiableItem = new UnmodifiableVHostItem();\n\t\t}\n\n\t\treturn unmodifiableItem;\n\t}\n\n\t/**\n\t * This method return a virtual host name as a <code>String</code> value.\n\t *\n\t * @return a <code>String</code> value with the virtual domain name.\n\t */\n\tpublic JID getVhost() {\n\t\treturn this.vhost;\n\t}\n\n\t/**\n\t * This method checks whether anonymous login is enabled for this domain. This\n\t * is the domain own configuration parameter which allows to disable anonymous\n\t * logins on per domain basis.\n\t *\n\t * @return a <code>boolean</code> value indicating whether anonymous logins\n\t *         are allowed for this domain.\n\t */\n\tpublic boolean isAnonymousEnabled() {\n\t\treturn anonymousEnabled;\n\t}\n\n\t/**\n\t * Get boolean value contained by this VHost for key\n\t * \n\t * @param key\n\t * @return \n\t */\n\tpublic boolean isData(String key) {\n\t\tif (data.containsKey(key))\n\t\t\treturn (Boolean) data.get(key);\n\t\telse {\n\t\t\tDataType type = dataTypes.get(key);\n\t\t\tBoolean defValue = (type == null) ? null : (Boolean)type.getDefValue();\n\t\t\treturn defValue != null ? defValue : false;\n\t\t}\n\t}\n\t\n\t/**\n\t * Checks whether this domain is set as enabled or not. This is domain own\n\t * configuration parameter which allows to temporarly disable domain so\n\t * packets for this domain are not processed normally. Instead the server\n\t * returns an error.\n\t *\n\t * @return a <code>boolean</code> value <code>true</code> if the domain is\n\t *         enabled and <code>false</code> if the domain is disabled.\n\t */\n\tpublic boolean isEnabled() {\n\t\treturn enabled;\n\t}\n\t\n\t/**\n\t * The method checks whether user registration is enabled for this domain or\n\t * not. This is the domain own configuration parameter which allows to disable\n\t * user accounts registration via XMPP per domain basis.\n\t *\n\t * @return a <code>boolean</code> value indicating whether user account\n\t *         registration is allowed for this domain.\n\t */\n\tpublic boolean isRegisterEnabled() {\n\t\treturn registerEnabled;\n\t}\n\n\t/**\n\t * The method returns TLS required settings for the vhost.\n\t *\n\t *\n\t * @return a <code>boolean</code> value whether TLS is required for the vhost or not.\n\t */\n\tpublic boolean isTlsRequired() {\n\t\treturn tlsRequired || XMPPServer.isHardenedModeEnabled();\n\t}\n\t\n\tpublic boolean isTrustedJID(JID jid) {\n\t\tSet<String> trustedJids = VHostItem.this.getTrustedJIDs();\n\t\tif (trustedJids == null)\n\t\t\treturn false;\n\t\t\n\t\treturn trustedJids.contains(jid.toString()) || trustedJids.contains(jid.getBareJID().toString()) \n\t\t\t\t|| trustedJids.contains(jid.getDomain());\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * This method allows to enable or disable anonymous logins for this domain.\n\t * By default anonymous logins are enabled.\n\t *\n\t *\n\t * @param value\n\t */\n\tpublic void setAnonymousEnabled(boolean value) {\n\t\tthis.anonymousEnabled = value;\n\t}\n\n\t/**\n\t * Sets an array with the server component names by which packets to this\n\t * domain can be processed. Every local domain will be handled by\n\t * <code>VHostListener</code> which returns <code>true</code> for\n\t * <code>handlesLocalDomains()</code> method call and by all components set\n\t * via this method.\n\t *\n\t * @param comps\n\t *          is an <code>String[]</code> array with server component names.\n\t */\n\tpublic void setComps(String[] comps) {\n\t\tthis.comps = comps;\n\t}\n\n\t/**\n\t * Sets an array of ports for which C2S connections for this VHost will be\n\t * allowed.\n\t *\n\t * @param ports\n\t *\t\t\tis an <code>int[]</code> array of allowed C2S ports.\n\t */\n\tpublic void setC2SPortsAllowed(int[] ports) {\n\t\tthis.c2sPortsAllowed = ports;\n\t}\n\n\t/**\n\t * Set value for specified key for this VHost\n\t * \n\t * @param key\n\t * @param value \n\t */\n\tpublic void setData(String key, Object value) {\n\t\tif (value == null) {\n\t\t\tthis.data.remove(key);\n\t\t} else {\n\t\t\tthis.data.put(key, value);\n\t\t}\n\t}\n\t\n\tpublic void parseDataValue(String key, String valueStr) {\n\t\tDataType type = dataTypes.get(key);\n\t\tif (type == null)\n\t\t\tthrow new RuntimeException(\"Key \" + key + \" is not registered\");\n\n\t\tif (valueStr == null) {\n\t\t\tthis.data.remove(key);\n\t\t} else {\n\t\t\tchar typeId = DataTypes.typesMap.get(type.cls.getName());\n\t\t\tif (valueStr.contains(\";\")) \n\t\t\t\tvalueStr = valueStr.replace(';', ',');\n\t\t\tObject value = (valueStr == null || valueStr.isEmpty()) ? null : DataTypes.decodeValueType(typeId, valueStr);\n\t\t\tif (type.getCollectionCls() != null && value != null) {\n\t\t\t\ttry {\n\t\t\t\t\tCollection collection = type.getCollectionCls().newInstance();\n\t\t\t\t\tfor (int i = 0; i < Array.getLength(value); i++) {\n\t\t\t\t\t\tcollection.add(Array.get(value, i));\n\t\t\t\t\t}\n\t\t\t\t\tvalue = collection;\n\t\t\t\t} catch (InstantiationException | IllegalAccessException ex) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Could not instantiate collection of class: \"\n\t\t\t\t\t\t\t+ type.getCollectionCls().getCanonicalName(), ex);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tsetData(type.getKey(), value);\n\t\t}\n\t}\n\t\n\t/**\n\t * This method allow configure DomainFilterPolicy to be applied during packet\n\t * filtering.\n\t *\n\t * @param domainFilter name of the DomainFilterPolicy to be applied\n\t */\n\tpublic void setDomainFilter(DomainFilterPolicy domainFilter) {\n\t\tthis.domainFilter = domainFilter;\n\t}\n\n\t/**\n\t * This method allow specify list of domains that will be used for packet\n\t * filtering when DomainFilteringPolicy is set to either LIST or BLACKLIST.\n\t *\n\t * @param domainFilterDomains  array of domains to be applied during filtering\n\t */\n\tpublic void setDomainFilterDomains(String[] domainFilterDomains) {\n\t\tthis.domainFilterDomains = StringUtilities.internStringArray( domainFilterDomains);\n\n\t}\n\n\t/**\n\t * This method allows to enable or disable local domain. If the domain is\n\t * disabled packets sent for this domain are not processed normally, instead\n\t * the server returns an error to the sender. Domain is enabled by default.\n\t *\n\t *\n\t * @param value\n\t */\n\tpublic void setEnabled(boolean value) {\n\t\tthis.enabled = value;\n\t}\n\n\t/**\n\t * This method allows to set the maximum number of user accounts allowed for\n\t * this domain. The default value of this parameter is: <code>0L</code>.\n\t *\n\t * @param maxUsersNumber\n\t *          is a <code>long</code> value specifying the maximum number of user\n\t *          accounts allowed for this domain.\n\t */\n\tpublic void setMaxUsersNumber(long maxUsersNumber) {\n\t\tthis.maxUsersNumber = maxUsersNumber;\n\t}\n\n\t/**\n\t * @param messageForward the messageForward to set\n\t */\n\tpublic void setMessageForward(JID messageForward) {\n\t\tthis.messageForward = messageForward;\n\t}\n\n\t/**\n\t * This method allows to set extra configuration parameters for the virtual\n\t * domain. This is future feature API and it is not used right now. It allows\n\t * to access configuration parameters which are not specified at the time of\n\t * API definition.\n\t *\n\t * @param otherParams\n\t *          is a <code>String</code> value with domain extra parameters.\n\t */\n\tpublic void setOtherDomainParams(String otherParams) {\n\t\tthis.otherDomainParams = otherParams;\n\t}\n\n\t/**\n\t * @param presenceForward the presenceForward to set\n\t */\n\tpublic void setPresenceForward(JID presenceForward) {\n\t\tthis.presenceForward = presenceForward;\n\t}\n\n\t/**\n\t * This method allows to enable or disable user account registration for this\n\t * domain. By default user account registration is enabled.\n\t *\n\t *\n\t * @param value\n\t */\n\tpublic void setRegisterEnabled(boolean value) {\n\t\tthis.registerEnabled = value;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param s2sSecret\n\t */\n\tpublic void setS2sSecret(String s2sSecret) {\n\t\tthis.s2sSecret = s2sSecret;\n\t}\n\n\t/**\n\t * The method sets TLS required property for the vhost. By default TLS is not required.\n\t *\n\t *\n\t * @param value is a <code>boolean</code> parameter specifying whether TLS is required\n\t * for the virtual domain.\n\t */\n\tpublic void setTlsRequired(boolean value) {\n\t\tthis.tlsRequired = value;\n\t}\n\n\tpublic void setTrustedJIDs(JID[] trustedJids) {\n\t\tsetData(TRUSTED_JIDS_ATT, trustedJids);\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param vhost\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic void setVHost(String vhost) throws TigaseStringprepException {\n\t\tif (vhost == null) {\n\t\t\tvhost = \"\";\n\t\t}\n\t\tthis.vhost = JID.jidInstance(vhost);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param vhost\n\t */\n\tpublic void setVHost(JID vhost) {\n\t\tthis.vhost = vhost;\n\t}\n\n\tprivate int[] parseIntArray(String tmp, String separator) {\n\t\tint[] c2s_ports_allowed = null;\n\t\tif (tmp != null && !tmp.isEmpty()) {\n\t\t\tString[] tmpPorts = tmp.split(separator);\n\t\t\tc2s_ports_allowed = new int[tmpPorts.length];\n\t\t\tint filled = 0;\n\t\t\tfor (String portStr : tmpPorts) {\n\t\t\t\ttry {\n\t\t\t\t\tc2s_ports_allowed[filled] = Integer.parseInt(portStr);\n\t\t\t\t\tfilled++;\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can not parse allowed c2s port: {0}\", portStr);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (filled == 0) {\n\t\t\t\tc2s_ports_allowed = null;\n\t\t\t}\n\t\t\telse if (filled < c2s_ports_allowed.length) {\n\t\t\t\tc2s_ports_allowed = Arrays.copyOf(c2s_ports_allowed, filled);\n\t\t\t}\n\t\t\tif (c2s_ports_allowed != null) {\n\t\t\t\tArrays.sort(c2s_ports_allowed);\n\t\t\t}\n\t\t}\n\t\treturn c2s_ports_allowed;\n\t}\n\n\tprivate String intArrayToString(int[] arr, String separator) {\n\t\tif (arr == null) {\n\t\t\treturn null;\n\t\t}\n\t\tStringBuilder buf = new StringBuilder();\n\t\tfor (int i = 0; i < arr.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbuf.append(separator);\n\t\t\t}\n\t\t\tbuf.append(arr[i]);\n\t\t}\n\t\treturn buf.toString();\n\t}\n\n\tprivate String stringArrayToString(String[] arr, String separator) {\n\t\tif (arr == null) {\n\t\t\treturn null;\n\t\t}\n\t\tStringBuilder buf = new StringBuilder();\n\t\tfor (int i = 0; i < arr.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbuf.append(separator);\n\t\t\t}\n\t\t\tbuf.append(arr[i]);\n\t\t}\n\t\treturn buf.toString();\n\t}\n\n\t//~--- inner classes --------------------------------------------------------\n\n\tprivate class UnmodifiableVHostItem\n\t\t\t\t\textends VHostItem {\n\t\t@Override\n\t\tpublic void initFromElement(Element elem) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void initFromPropertyString(String propString) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic Element toElement() {\n\t\t\treturn VHostItem.this.toElement();\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn VHostItem.this.toString();\n\t\t}\n\n\t\t//~--- get methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic String[] getComps() {\n\t\t\treturn VHostItem.this.getComps();\n\t\t}\n\n\t\t@Override\n\t\tpublic <T> T getData(String key) {\n\t\t\treturn VHostItem.this.getData(key);\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic DomainFilterPolicy getDomainFilter() {\n\t\t\treturn VHostItem.this.getDomainFilter();\n\t\t}\n\n\t\t@Override\n\t\tpublic String[] getDomainFilterDomains() {\n\t\t\treturn VHostItem.this.getDomainFilterDomains();\n\t\t}\n\n\n\t\t@Override\n\t\tpublic long getMaxUsersNumber() {\n\t\t\treturn VHostItem.this.getMaxUsersNumber();\n\t\t}\n\n\t\t@Override\n\t\tpublic JID getMessageForward() {\n\t\t\treturn VHostItem.this.messageForward;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getOtherDomainParams() {\n\t\t\treturn VHostItem.this.getOtherDomainParams();\n\t\t}\n\n\t\t@Override\n\t\tpublic JID getPresenceForward() {\n\t\t\treturn VHostItem.this.presenceForward;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getS2sSecret() {\n\t\t\treturn VHostItem.this.getS2sSecret();\n\t\t}\n\n\t\t@Override\n\t\tpublic String[] getSaslAllowedMechanisms() {\n\t\t\treturn VHostItem.this.getSaslAllowedMechanisms();\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic Set<String> getTrustedJIDs() {\n\t\t\treturn Collections.unmodifiableSet(VHostItem.this.getTrustedJIDs());\n\t\t}\n\n\t\t@Override\n\t\tpublic VHostItem getUnmodifiableVHostItem() {\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic JID getVhost() {\n\t\t\treturn VHostItem.this.getVhost();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isAnonymousEnabled() {\n\t\t\treturn VHostItem.this.isAnonymousEnabled();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isData(String key) {\n\t\t\treturn VHostItem.this.isData(key);\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic boolean isEnabled() {\n\t\t\treturn VHostItem.this.isEnabled();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isRegisterEnabled() {\n\t\t\treturn VHostItem.this.isRegisterEnabled();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isTlsRequired() {\n\t\t\treturn VHostItem.this.isTlsRequired();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isTrustedJID(JID jid) {\n\t\t\treturn VHostItem.this.isTrustedJID(jid);\n\t\t}\n\t\t\n\t\t//~--- set methods --------------------------------------------------------\n\n\t\t@Override\n\t\tpublic void setAnonymousEnabled(boolean enabled) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setComps(String[] comps) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setC2SPortsAllowed(int[] ports) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setData(String key, Object value) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void setDomainFilter(DomainFilterPolicy filter) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\tpublic void setDomainFilterDomains(String[] domainFilterDomains) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t}\n\n\t\t@Override\n\t\tpublic void setEnabled(boolean enabled) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setMaxUsersNumber(long maxUsersNumber) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setMessageForward(JID messageForward) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOtherDomainParams(String otherParams) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setPresenceForward(JID presenceForward) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setRegisterEnabled(boolean enabled) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setS2sSecret(String s2sSecret) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void setTlsRequired(boolean enabled) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"This is unmodifiable instance of VHostItem\");\n\t\t}\n\t}\n\n\t/**\n\t * @return the saslAllowedMechanisms\n\t */\n\tpublic String[] getSaslAllowedMechanisms() {\n\t\treturn saslAllowedMechanisms;\n\t}\n\n\t/**\n\t * @param saslAllowedMechanisms the saslAllowedMechanisms to set\n\t */\n\tpublic void setSaslAllowedMechanisms(String[] saslAllowedMechanisms) {\n\t\tthis.saslAllowedMechanisms = saslAllowedMechanisms == null || saslAllowedMechanisms.length == 0 ? null\n\t\t\t\t: saslAllowedMechanisms;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostJDBCRepository.java",
    "content": "/*\n * VHostJDBCRepository.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.vhosts;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.DBInitException;\nimport tigase.db.comp.UserRepoRepository;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.DNSEntry;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.DNSResolverIfc;\nimport tigase.util.TigaseStringprepException;\n\nimport java.net.UnknownHostException;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * This implementation stores virtual domains in the UserRepository database. It\n * loads initial settings and virtual hosts from the configuration file and then\n * loads more vhosts from the database. Virtual domains from the database can\n * overwrite (disable) vhosts loaded from the configuration file.\n *\n * This implementation keeps all virtual hosts and their parameters in a single\n * database field. This might not be very efficient if you want to manager big\n * number of virtual domains. It is sufficient for hundreds of vhosts. If you\n * need thousands of VHosts support I advice to implement this storage in more\n * efficient way using separate database tables instead of UserRepository.\n * Please note there is a limit of about 300 vhosts if you use Derby database.\n *\n *\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @since Nov 29, 2008 2:32:48 PM\n */\npublic class VHostJDBCRepository\n\t\t\t\textends UserRepoRepository<VHostItem> {\n\t/**\n\t * Configuration option allowing specify default IP to which VHost should resolve\n\t * vhost-man/dns-def-ip=\n\t */\n\tpublic static final String DNS_DEF_IP_PROP_KEY = \"dns-def-ip\";\n\n\t/** Field description */\n\tpublic static String DNS_DEF_IP_PROP_VAL = null;\n\n\t/**\n\t * Configuration option allowing specify default hostname to which VHost should resolve\n\t * vhost-man/dns-srv-def-addr=\n\t */\n\tpublic static final String DNS_SRV_DEF_ADDR_PROP_KEY = \"dns-srv-def-addr\";\n\n\t/** Field description */\n\tpublic static String DNS_SRV_DEF_ADDR_PROP_VAL = null;\n\n\t/**\n\t * Configuration option allowing specify default maximum number that user can register\n\t * in service\n\t *\n\t * vhost-man/domains-per-user-limit=\n\t */\n\tpublic static final String DOMAINS_PER_USER_LIMIT_PROP_KEY = \"domains-per-user-limit\";\n\n\t/** Field description */\n\tpublic static final int DOMAINS_PER_USER_LIMIT_PROP_VAL = 25;\n\tprivate static final Logger log                         =\n\t\tLogger.getLogger(VHostJDBCRepository.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String def_ip_address    = null;\n\tprivate String def_srv_address   = null;\n\tprivate int max_domains_per_user = DOMAINS_PER_USER_LIMIT_PROP_VAL;\n\n\t@Override\n\tpublic void destroy() {\n\t\t// Nothing to do\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic String getConfigKey() {\n\t\treturn VHostRepoDefaults.getConfigKey();\n\t}\n\n\t@Override\n\tpublic String[] getDefaultPropetyItems() {\n\t\treturn VHostRepoDefaults.getDefaultPropetyItems();\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"deprecation\")\n\tpublic void getDefaults(Map<String, Object> defs, Map<String, Object> params) {\n\n\t\t// Something to initialize database with, in case it is empty\n\t\t// Otherwise the server would not work at all with empty Items database\n\t\tsuper.getDefaults(defs, params);\n\t\tDNSResolverIfc resolver = DNSResolverFactory.getInstance();\n\t\tDNS_SRV_DEF_ADDR_PROP_VAL = resolver.getDefaultHost();\n\t\ttry {\n\t\t\tDNS_DEF_IP_PROP_VAL = resolver.getHostIP(resolver.getDefaultHost());\n\t\t} catch (Exception e) {\n\t\t\tDNS_DEF_IP_PROP_VAL = resolver.getDefaultHost();\n\t\t}\n\t\tdefs.put(DNS_SRV_DEF_ADDR_PROP_KEY, DNS_SRV_DEF_ADDR_PROP_VAL);\n\t\tdefs.put(DNS_DEF_IP_PROP_KEY, DNS_DEF_IP_PROP_VAL);\n\t\tdefs.put(DOMAINS_PER_USER_LIMIT_PROP_KEY, DOMAINS_PER_USER_LIMIT_PROP_VAL);\n\t}\n\n\t@Override\n\tpublic VHostItem getItemInstance() {\n\t\treturn VHostRepoDefaults.getItemInstance();\n\t}\n\n\t@Override\n\tpublic String getItemsListPKey() {\n\t\treturn VHostRepoDefaults.getItemsListPKey();\n\t}\n\n\t@Override\n\tpublic String getPropertyKey() {\n\t\treturn VHostRepoDefaults.getPropertyKey();\n\t}\n\n\t@Override\n\tpublic BareJID getRepoUser() {\n\t\treturn VHostRepoDefaults.getRepoUser();\n\t}\n\n\t@Override\n\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t// Nothing to do\n\t}\n\t\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setProperties(Map<String, Object> properties) {\n\n\t\t// Let's load items from configuration first. Later we can overwrite\n\t\t// them with items settings in the database.\n\t\tsuper.setProperties(properties);\n\t\tdef_srv_address = (String) properties.get(DNS_SRV_DEF_ADDR_PROP_KEY);\n\t\tif ((def_srv_address != null) &&!def_srv_address.endsWith(\".\")) {\n\t\t\tdef_srv_address = def_srv_address + \".\";\n\t\t}\n\t\tdef_ip_address       = (String) properties.get(DNS_DEF_IP_PROP_KEY);\n\t\tmax_domains_per_user = (Integer) properties.get(DOMAINS_PER_USER_LIMIT_PROP_KEY);\n\t\tsetAutoloadTimer(60);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String validateItem(VHostItem item) {\n\t\tif ((item.getVhost() == null) || (item.getVhost().getDomain() == null) ||\n\t\t\t\titem.getVhost().getDomain().isEmpty()) {\n\t\t\treturn \"Domain name not specified\";\n\t\t}\n\n\t\tint vhost_count = 0;\n\n\t\tfor (VHostItem it : allItems()) {\n\t\t\tif (it.isOwner(item.getOwner())) {\n\t\t\t\t++vhost_count;\n\t\t\t}\n\t\t}\n\t\tif (vhost_count >= max_domains_per_user) {\n\t\t\treturn \"Maximum number of domains exceeded for the user! Current number is: \" +\n\t\t\t\t\t\t vhost_count;\n\t\t}\n\t\t\n\t\tif (item.getS2sSecret() == null) {\n\t\t\treturn \"S2S Secret is required\";\n\t\t}\n\t\t\n\t\tif (System.getProperty(\"vhost-disable-dns-check\") != null) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// verify all SRV DNS records\n\t\ttry {\n\t\t\tDNSEntry[] entries = DNSResolverFactory.getInstance().getHostSRV_Entries(item.getKey());\n\n\t\t\tif (entries != null) {\n\t\t\t\tfor (DNSEntry dNSEntry : entries) {\n\t\t\t\t\tlog.finest(\"Validating DNS SRV settings ('\" + dNSEntry +\n\t\t\t\t\t\t\t\t\t\t \"') for the given hostname: \" + item.getKey() + \" (defaults: \" +\n\t\t\t\t\t\t\t\t\t\t def_ip_address + \", \" + def_srv_address);\n\t\t\t\t\tif (Arrays.asList(dNSEntry.getIps()).contains(def_ip_address) ||\n\t\t\t\t\t\t\tdef_srv_address.equals(dNSEntry.getDnsResultHost())) {\n\n\t\t\t\t\t\t// configuration is OK\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn \"Incorrect DNS SRV settings\" + Arrays.asList(entries);\n\t\t\t}\n\t\t} catch (UnknownHostException ex) {\n\n\t\t\t// Ignore, maybe simply IP address is set in DNS\n\t\t}\n\n\t\t// verify DNS records\n\t\ttry {\n\t\t\tString[] ipAddress = DNSResolverFactory.getInstance().getHostIPs(item.getKey());\n\n\t\t\tif (ipAddress != null) {\n\t\t\t\tif (Arrays.asList(ipAddress).contains(def_ip_address)) {\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\treturn \"Incorrect IP address: '\" + Arrays.asList(ipAddress) +\n\t\t\t\t\t\t\t\t \"' found in DNS for the given host: \" + item.getKey();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn \"No DNS settings found for given host: \" + item.getKey();\n\t\t\t}\n\t\t} catch (UnknownHostException ex1) {\n\t\t\treturn \"There is no DNS settings for given host: \" + item.getKey();\n\t\t}\n\t}\n\n\t/**\n\t * Simple verification of VHost validation\n\t *\n\t * @param args\n\t */\n\tpublic static void main(String[] args) {\n\t\tMap<String, Object> props  = new HashMap<String, Object>();\n\t\tMap<String, Object> params = new HashMap<String, Object>();\n\t\tVHostJDBCRepository repo   = new VHostJDBCRepository();\n\n\t\trepo.getDefaults(props, params);\n\t\tprops.put(DNS_SRV_DEF_ADDR_PROP_KEY, \"tigase.me\");\n\t\tprops.put(DOMAINS_PER_USER_LIMIT_PROP_KEY, 50);\n\t\trepo.setProperties(props);\n\n\t\tVHostItem domain = null;\n\n\t\ttry {\n\t\t\tdomain = new VHostItem(\"tigase.im\");\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(VHostJDBCRepository.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t\tSystem.out.println(\"repo.validateItem( domain ) :: \" + repo.validateItem(domain));\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/09\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostListener.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.vhosts;\n\nimport tigase.server.ServerComponent;\n\n/**\n * Interface VHostListener needs to be implemented by every class wanting\n * to accept and process XMPP packets sent to virtual domains. It allows\n * for basic component settings and retrieve information and configuration\n * about virtual domains server by the installation.\n *\n *\n * Created: Fri Nov 21 14:29:49 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface VHostListener\n\t\t\t\textends ServerComponent {\n\n\t/**\n\t * Sets the VHostManager which works on this server installation.\n\t * The VHostManager allows for accessing vritual domain data.\n\t * @param manager is a reference to VHostManager available on the server\n\t * installation.\n\t */\n\tvoid setVHostManager(VHostManagerIfc manager);\n\n\t/**\n\t * Indicates whether the component accepts packets to all local domains.\n\t * The best example would be SM component which usually handles all requests\n\t * sent to any local domain.\n\t * @return 'true' if the component accepts packets to local domains\n\t * 'false' otherwise.\n\t */\n\tboolean handlesLocalDomains();\n\n\t/**\n\t * Indicates whether the component can handle all packets to\n\t * non-local domains. S2s connection manager component is the best\n\t * example of the component which handles all requests sent to non-local\n\t * domains.\n\t * @return 'true' if the component accepts packets to non-local domains\n\t * 'false' otherwise.\n\t */\n\tboolean handlesNonLocalDomains();\n\n\t/**\n\t * Indicates whether the component can handle packets to 'name' subdomain.\n\t * Name subdomain is an artificial domain created from the component name\n\t * and the domain name. The best example would be a 'MUC' component or\n\t * a 'PubSub' component. They are usually named respectively 'muc' and\n\t * 'pubsub' and they accept requests sent to domains 'muc.tigase.org' or\n\t * 'pubsub.tigase.org', even though a local domain is just 'tigase.org'.\n\t * @return 'true' if the component accepts packets to 'name' subdomains\n\t * 'false' otherwise.\n\t */\n\tboolean handlesNameSubdomains();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostManager.java",
    "content": "/*\n * VHostManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.vhosts;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.conf.ConfigurationException;\nimport tigase.db.TigaseDBException;\nimport tigase.db.comp.ComponentRepository;\nimport tigase.server.AbstractComponentRegistrator;\nimport tigase.server.ServerComponent;\nimport tigase.stats.StatisticsContainer;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\nimport javax.script.Bindings;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- JDK imports ------------------------------------------------------------\n\n/**\n * Describe class VHostManager here.\n *\n *\n * Created: Fri Nov 21 14:28:20 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class VHostManager\n\t\t\t\textends AbstractComponentRegistrator<VHostListener>\n\t\t\t\timplements VHostManagerIfc, StatisticsContainer {\n\t/** Field description */\n\tpublic static final String VHOSTS_REPO_CLASS_PROP_KEY = \"repository-class\";\n\n\t/** Field description */\n\tpublic static final String VHOSTS_REPO_CLASS_PROP_VAL =\n\t\t\t\"tigase.vhosts.VHostJDBCRepository\";\n\n\t/** Field description */\n\tpublic static final String  VHOSTS_REPO_CLASS_PROPERTY = \"--vhost-repo-class\";\n\tprivate static final Logger log = Logger.getLogger(VHostManager.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long getComponentsForLocalDomainCalls    = 0;\n\tprivate long getComponentsForNonLocalDomainCalls = 0;\n\n\t// private ServiceEntity serviceEntity = null;\n\tprivate String                       identity_type           = \"generic\";\n\tprivate long                         isAnonymousEnabledCalls = 0;\n\tprivate long                         isLocalDomainCalls      = 0;\n\tprivate LinkedHashSet<VHostListener> localDomainsHandlers =\n\t\t\tnew LinkedHashSet<VHostListener>(10);\n\tprivate LinkedHashSet<VHostListener> nonLocalDomainsHandlers =\n\t\t\tnew LinkedHashSet<VHostListener>(10);\n\tprivate LinkedHashSet<VHostListener> nameSubdomainsHandlers =\n\t\t\tnew LinkedHashSet<VHostListener>(10);\n\tprivate ConcurrentSkipListSet<String> registeredComponentDomains =\n\t\t\tnew ConcurrentSkipListSet<String>();\n\tprotected ComponentRepository<VHostItem> repo = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>VHostManager</code> instance.\n\t *\n\t */\n\tpublic VHostManager() {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addComponentDomain(String domain) {\n\t\tregisteredComponentDomains.add(domain);\n\t}\n\n\t@Override\n\tpublic void componentAdded(VHostListener component) {\n\t\tcomponent.setVHostManager(this);\n\t\tif (component.handlesLocalDomains()) {\n\t\t\tlocalDomainsHandlers.add(component);\n\t\t}\n\t\tif (component.handlesNonLocalDomains()) {\n\t\t\tnonLocalDomainsHandlers.add(component);\n\t\t}\n\t\tif (component.handlesNameSubdomains()) {\n\t\t\tnameSubdomainsHandlers.add(component);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void componentRemoved(VHostListener component) {\n\t\tlocalDomainsHandlers.remove(component);\n\t\tnonLocalDomainsHandlers.remove(component);\n\t\tnameSubdomainsHandlers.remove(component);\n\t}\n\n\t@Override\n\tpublic void initBindings(Bindings binds) {\n\t\tsuper.initBindings(binds);\n\t\tbinds.put(ComponentRepository.COMP_REPO_BIND, repo);\n\t}\n\n\t@Override\n\tpublic void removeComponentDomain(String domain) {\n\t\tregisteredComponentDomains.remove(domain);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic List<JID> getAllVHosts() {\n\t\tList<JID> list = new ArrayList<JID>();\n\n\t\ttry {\n\t\t\tfor (VHostItem item : repo.allItems()) {\n\t\t\t\tlist.add(item.getVhost());\n\t\t\t}\n\t\t} catch (TigaseDBException ex) {\n\t\t\tLogger.getLogger(VHostManager.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic ServerComponent[] getComponentsForLocalDomain(String domain) {\n\t\t++getComponentsForLocalDomainCalls;\n\n\t\tVHostItem vhost = repo.getItem(domain);\n\n\t\tif (vhost == null) {\n\n\t\t\t// This is not a local domain.\n\t\t\t// Maybe this is a 'name' subdomain: 'pubsub'.domain.name\n\t\t\tint idx = domain.indexOf('.');\n\n\t\t\tif (idx > 0) {\n\t\t\t\tString        name       = domain.substring(0, idx);\n\t\t\t\tString        basedomain = domain.substring(idx + 1);\n\t\t\t\tVHostListener listener   = components.get(name);\n\n\t\t\t\tif ((listener != null) && listener.handlesNameSubdomains() && isLocalDomain(\n\t\t\t\t\t\tbasedomain)) {\n\t\t\t\t\treturn new ServerComponent[] { listener };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t} else {\n\n//    // First check whether the domain has special configuration\n//    // specifying what components are for this domain:\n//    String[] comps = vhost.getComps();\n//    if (comps != null && comps.length > 0) {\n//      !!\n//    }\n\t\t\t// Return all components for local domains and components selected\n\t\t\t// for this specific domain\n\t\t\tLinkedHashSet<ServerComponent> results = new LinkedHashSet<ServerComponent>(10);\n\n\t\t\t// are there any components explicitly bound to this domain?\n\t\t\tString[] comps = vhost.getComps();\n\n\t\t\tif ((comps != null) && (comps.length > 0)) {\n\t\t\t\tfor (String name : comps) {\n\t\t\t\t\tVHostListener listener = components.get(name);\n\n\t\t\t\t\tif (listener != null) {\n\t\t\t\t\t\tresults.add(listener);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if not, then add any generic handlers\n\t\t\tif (results.size() == 0) {\n\t\t\t\tresults.addAll(localDomainsHandlers);\n\t\t\t}\n\t\t\tif (results.size() > 0) {\n\t\t\t\treturn results.toArray(new ServerComponent[results.size()]);\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ServerComponent[] getComponentsForNonLocalDomain(String domain) {\n\t\t++getComponentsForNonLocalDomainCalls;\n\n\t\t// Return components for non-local domains\n\t\tif (nonLocalDomainsHandlers.size() > 0) {\n\t\t\treturn nonLocalDomainsHandlers.toArray(\n\t\t\t\t\tnew ServerComponent[nonLocalDomainsHandlers.size()]);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic Map<String, Object> getDefaults(Map<String, Object> params) {\n\t\tMap<String, Object> defs       = super.getDefaults(params);\n\t\tString              repo_class = (String) params.get(VHOSTS_REPO_CLASS_PROPERTY);\n\n\t\tif (repo_class == null) {\n\t\t\trepo_class = VHOSTS_REPO_CLASS_PROP_VAL;\n\t\t}\n\t\tdefs.put(VHOSTS_REPO_CLASS_PROP_KEY, repo_class);\n\t\ttry {\n\t\t\tComponentRepository<VHostItem> repo_tmp = (ComponentRepository<VHostItem>) Class\n\t\t\t\t\t.forName(repo_class).newInstance();\n\n\t\t\trepo_tmp.getDefaults(defs, params);\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.SEVERE, \"Can not instantiate VHosts repository for class: \" +\n\t\t\t\t\trepo_class, e);\n\t\t}\n\n\t\treturn defs;\n\t}\n\n\t@Override\n\tpublic BareJID getDefVHostItem() {\n\t\tIterator<VHostItem> vhosts = repo.iterator();\n\n\t\tif ((vhosts != null) && vhosts.hasNext()) {\n\t\t\treturn vhosts.next().getVhost().getBareJID();\n\t\t}\n\n\t\treturn getDefHostName();\n\t}\n\n\t@Override\n\tpublic String getDiscoCategoryType() {\n\t\treturn identity_type;\n\t}\n\n\t@Override\n\tpublic String getDiscoDescription() {\n\t\treturn \"VHost Manager\";\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tlist.add(getName(), \"Number of VHosts\", repo.size(), Level.FINE);\n\t\tlist.add(getName(), \"Checks: is local domain\", isLocalDomainCalls, Level.FINER);\n\t\tlist.add(getName(), \"Checks: is anonymous domain\", isAnonymousEnabledCalls, Level\n\t\t\t\t.FINER);\n\t\tlist.add(getName(), \"Get components for local domain\",\n\t\t\t\tgetComponentsForLocalDomainCalls, Level.FINER);\n\t\tlist.add(getName(), \"Get components for non-local domain\",\n\t\t\t\tgetComponentsForNonLocalDomainCalls, Level.FINER);\n\t}\n\n\t@Override\n\tpublic VHostItem getVHostItem(String domain) {\n\t\treturn repo.getItem(domain);\n\t}\n\n\t@Override\n\tpublic VHostItem getVHostItemDomainOrComponent(String domain) {\n\t\tVHostItem item = getVHostItem(domain);\n\t\tif (item == null) {\n\t\t\tint idx = domain.indexOf('.');\n\n\t\t\tif (idx > 0) {\n\t\t\t\tString        name       = domain.substring(0, idx);\n\t\t\t\tString        basedomain = domain.substring(idx + 1);\n\t\t\t\tVHostListener listener   = components.get(name);\n\t\t\t\tif (listener != null && listener.handlesNameSubdomains()) {\n\t\t\t\t\titem = getVHostItem(basedomain);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn item;\n\t}\n\t\n\t@Override\n\tpublic boolean isAnonymousEnabled(String domain) {\n\t\t++isAnonymousEnabledCalls;\n\n\t\tVHostItem vhost = repo.getItem(domain);\n\n\t\tif (vhost == null) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn vhost.isAnonymousEnabled();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isCorrectType(ServerComponent component) {\n\t\treturn component instanceof VHostListener;\n\t}\n\n\t@Override\n\tpublic boolean isLocalDomain(String domain) {\n\t\t++isLocalDomainCalls;\n\n\t\treturn repo.contains(domain);\n\t}\n\n\t@Override\n\tpublic boolean isLocalDomainOrComponent(String domain) {\n\t\tboolean result = isLocalDomain(domain);\n\n\t\tif (!result) {\n\t\t\tresult = registeredComponentDomains.contains(domain);\n\t\t}\n\t\tif (!result) {\n\t\t\tint idx = domain.indexOf('.');\n\n\t\t\tif (idx > 0) {\n\t\t\t\tString        name       = domain.substring(0, idx);\n\t\t\t\tString        basedomain = domain.substring(idx + 1);\n\t\t\t\tVHostListener listener   = components.get(name);\n\n\t\t\t\tresult = ((listener != null) && listener.handlesNameSubdomains() && isLocalDomain(\n\t\t\t\t\t\tbasedomain));\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setName(String name) {\n\t\tsuper.setName(name);\n\t}\n\n\t@Override\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic void setProperties(Map<String, Object> properties) throws ConfigurationException {\n\t\tsuper.setProperties(properties);\n\n\t\tString repo_class = (String) properties.get(VHOSTS_REPO_CLASS_PROP_KEY);\n\n\t\tif (repo_class != null && !isInitializationComplete()) {\n\t\t\ttry {\n\t\t\t\tComponentRepository<VHostItem> repo_tmp = (ComponentRepository<VHostItem>) Class\n\t\t\t\t\t\t.forName(repo_class).newInstance();\n\n\t\t\t\trepo_tmp.setProperties(properties);\n\t\t\t\trepo = repo_tmp;\n\t\t\t\tlog.warning(repo.toString());\n\t\t\t\tinitializeRepository();\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Can not create VHost repository instance for class: \" +\n\t\t\t\t\t\trepo_class, e);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic void initializeRepository() throws TigaseDBException {\n\t\t// loading all items\n\t\trepo.reload();\n\t\t\n\t\tList<VHostItem> items = new ArrayList<VHostItem>(repo.allItems());\n\t\tfor (VHostItem item : items) {\n\t\t\t// if there is no S2S secret set for vhost, then we need to generate it\n\t\t\tif (item.getS2sSecret() == null) {\n\t\t\t\tString secret = generateSecret();\n\t\t\t\titem.setS2sSecret(secret);\n\t\t\t\trepo.addItem(item);\n\t\t\t}\n\t\t}\t\n\t}\n\t\n\tpublic String generateSecret() {\n\t\tString random = UUID.randomUUID().toString();\n\t\treturn random;\n\t}\n\n\tpublic ComponentRepository<VHostItem> getComponentRepository() {\n\t\treturn repo;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/10/05\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostManagerIfc.java",
    "content": "/*\n * VHostManagerIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.vhosts;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.ServerComponent;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\n\n/**\n * This is VHostManagerIfc interface which allows to access data for\n * virtual domains server by this installation. There can be normally only\n * one instance of this interface implementation loaded on the server at\n * any given time. The instance is responsible for managing all virtual\n * hosts and assigning correct component to each of the virtual hosts or\n * non-local domains.\n *\n * Created: 22 Nov 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface VHostManagerIfc {\n\t/**\n\t * This method checks whether given domain is server by this server instance.\n\t * That is if this domain is local to this server installation. It doesn't\n\t * check however whether the domain is disabled or enabled. It only checks\n\t * if tthe list of local domains contains this virtual host.\n\t *\n\t * @param domain is a String with domain name to check.\n\t * @return a boolean value indicating whether given domain is local or not.\n\t */\n\tboolean isLocalDomain(String domain);\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t * @return \n\t *\n\t * \n\t */\n\tboolean isLocalDomainOrComponent(String domain);\n\n\t/**\n\t * This method checks whether anonymous login is enabled for a given domain.\n\t * That is it checks whether this domains is local and anonymousEnabled\n\t * parameter for this domain is set to true.\n\t * @param domain is a String with domain name to check.\n\t * @return a boolean value indicating whether given domain is enabled for\n\t * anonymous logins or not.\n\t */\n\tboolean isAnonymousEnabled(String domain);\n\n\t/**\n\t * The method returns an array with server components which can process\n\t * packets for a given local domain. If the domain is not local\n\t * <code>null</code> is returned. The given domain may also consist of:\n\t * component name <code>ServerComponent.getName()</code> plus any local\n\t * domain but only if the component returns <code>true</code> from method\n\t * call: <code>VHostListener.handlesNameSubdomains()</code>\n\t *\n\t * @param domain is a <code>String</code> with a domain name to check. It may\n\t * by just a local domain or string created with component name and localdomain.\n\t * @return an array with ServerComponents which can handle packets for a\n\t * given domain or <code>null</code> if no component found for a given domain.\n\t */\n\tServerComponent[] getComponentsForLocalDomain(String domain);\n\n\t/**\n\t * The method returns an array of server components which can process packets\n\t * sent to non-local domain. Most commonly there is only one such component:\n\t * server-2-server connections manager. It is possible however there might\n\t * be more such components. All of them will get the packet for processing.\n\t * @param domain is a <code>String</code> with a domain to check. At the moment\n\t * this parameter is ignored. In the future it will be possible to assign a\n\t * specific component for any non-local domain.\n\t * @return an array with ServerComponents which can handle packets to\n\t * non-local domains.\n\t */\n\tServerComponent[] getComponentsForNonLocalDomain(String domain);\n\n\t/**\n\t * Returns an object with all domain properties for given domain.\n\t * @param domain is a domain name\n\t * @return a VHostItem object with all domain properties.\n\t */\n\tVHostItem getVHostItem(String domain);\n\n\t/**\n\t * Returns an object with all domain properties for a given domain or base domain\n\t * if passed domain is name of subdomain used by  component.\n\t * @param domain is a domain name\n\t * @return a VHostItem object with all domain properties.\n\t */\n\tVHostItem getVHostItemDomainOrComponent(String domain);\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Adds a component domain to the collection of local component domains.\n\t * This is mainly needed/used by an external components connecting to the\n\t * server and binding hostnames. Normally the s2s component have no way of\n\t * knowing about this new and temporary domains handled by the server and\n\t * would refuse all connections for these domains. Adding them to a collection\n\t * of component domains allows the s2s to detect them and accept connection\n\t * for them.\n\t * @param domain is a component domain name added to the collection.\n\t */\n\tvoid addComponentDomain(String domain);\n\n\t/**\n\t * Removes a domain previously registered by a component. It should not be\n\t * normally used.\n\t * @param domain is a component domain name being removed from the collection.\n\t */\n\tvoid removeComponentDomain(String domain);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method <code>getDefVHostItem</code> returns a default VHost for the installation.\n\t * In most cases this is the first VHost defined in the server configuration.\n\t *\n\t * @return a <code>BareJID</code> value of the default VHost for the installation.\n\t */\n\tBareJID getDefVHostItem();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tList<JID> getAllVHosts();\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/19\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/VHostRepoDefaults.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.vhosts;\n\nimport tigase.xmpp.BareJID;\n\nimport tigase.util.DNSResolverFactory;\n\nimport static tigase.conf.Configurable.GEN_VIRT_HOSTS;\nimport static tigase.conf.Configurable.HOSTNAMES_PROP_KEY;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Created: Oct 3, 2009 4:26:09 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class VHostRepoDefaults {\n\tprivate static final BareJID vhost_user = BareJID.bareJIDInstanceNS(\"vhost-manager\");\n\tprivate static final String vhost_list_pkey = \"vhosts-lists\";\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getConfigKey() {\n\t\treturn HOSTNAMES_PROP_KEY;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String[] getDefaultPropetyItems() {\n\t\treturn DNSResolverFactory.getInstance().getDefaultHosts();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static VHostItem getItemInstance() {\n\t\treturn new VHostItem();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getItemsListPKey() {\n\t\treturn vhost_list_pkey;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static String getPropertyKey() {\n\t\treturn GEN_VIRT_HOSTS;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic static BareJID getRepoUser() {\n\t\treturn vhost_user;\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/filter/CustomDomainFilter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts.filter;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.impl.DomainFilter;\n\nimport tigase.vhosts.filter.Rule.RuleType;\n\nimport java.text.ParseException;\nimport java.util.Arrays;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n *\n * @author Wojtek\n */\npublic final class CustomDomainFilter {\n\n\tprivate CustomDomainFilter() {\n\t}\n\n\tprivate static final Logger log = Logger.getLogger( CustomDomainFilter.class.getName() );\n\n\tpublic static Set<Rule> parseRules( String rules ) throws ParseException {\n\t\tString[] rulesArr = rules.split( \";\" );\n\t\tif ( rulesArr != null ){\n\t\t\treturn parseRules( rulesArr );\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic static Set<Rule> parseRules( String[] rules ) throws ParseException {\n\n\t\tSet rulesSet = new TreeSet<Rule>();\n\t\tfor ( String rule : rules ) {\n\n\t\t\tString[] split = rule.split( \"\\\\|\" );\n\t\t\tif ( split != null && ( split.length == 3 || split.length == 4 ) ){\n\n\t\t\t\ttry {\n\t\t\t\t\tInteger id = Integer.valueOf( split[0] );\n\t\t\t\t\tboolean allow = false;\n\t\t\t\t\tif ( split[1].equalsIgnoreCase( \"allow\" ) ){\n\t\t\t\t\t\tallow = true;\n\t\t\t\t\t} else if ( split[1].equalsIgnoreCase( \"deny\" ) ){\n\t\t\t\t\t\tallow = false;\n\t\t\t\t\t}\n\t\t\t\t\tRuleType type = RuleType.valueOf( split[2].toLowerCase() );\n\n\t\t\t\t\tJID jid = null;\n\n\t\t\t\t\tif ( split.length == 4 ){\n\t\t\t\t\t\tjid = JID.jidInstance( split[3] );\n\t\t\t\t\t}\n\n\t\t\t\t\tif (type == RuleType.jid && jid == null ) {\n\t\t\t\t\t\tthrow new ParseException( \"Error while pasing rule (no value for JID provided): \" + rule, 0 );\n\t\t\t\t\t}\n\n\t\t\t\t\trulesSet.add( new Rule( id, allow, type, jid ) );\n\t\t\t\t} catch ( Exception ex ) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Error while pasing rule: \" + rule, ex);\n\t\t\t\t\tthrow new ParseException( \"Error while pasing rule: \" + rule, 0 );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog.log(Level.FINEST, \"Error while pasing rule (wrong number of parameters): \" + rule);\n\t\t\t\tthrow new ParseException( \"Error while pasing rule: \" + rule, 0 );\n\t\t\t}\n\t\t}\n\n\t\treturn rulesSet;\n\t}\n\n\tpublic static boolean isAllowed( JID source, JID destination, String rules ) {\n\t\ttry {\n\t\t\tSet<Rule> parseRules = parseRules( rules );\n\t\t\tif ( parseRules != null ){\n\t\t\t\treturn isAllowed( source, destination, parseRules );\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch ( ParseException e ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic static boolean isAllowed( JID source, JID destination, String[] rules ) {\n\t\tSet<Rule> parseRules = null;\n\t\ttry {\n\t\t\tparseRules = parseRules( rules );\n\t\t} catch ( ParseException e ) {\n\t\t\tif (log.isLoggable( Level.WARNING)) {\n\t\t\t\tlog.log( Level.WARNING, \"Error while parsing rules: \" + Arrays.toString( rules ), e);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif ( parseRules != null ){\n\t\t\treturn isAllowed( source, destination, parseRules );\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic static boolean isAllowed( JID source, JID destination, Set<Rule> rules ) {\n\t\tif ( rules != null ){\n\t\t\tfor ( Rule rule : rules ) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing source: {0}, destination: {1}, against rule: {2}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {source, destination, rule} );\n\t\t\t\tif ( rule.isMatched( source, destination ) ){\n\t\t\t\tlog.log(Level.FINEST, \"Matched source: {0}, destination: {1}, allowed: {2}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {source, destination, rule.isAllowed()} );\n\t\t\t\t\treturn rule.isAllowed();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/filter/DomainFilterPolicy.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\npackage tigase.vhosts.filter;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\n\n/**\n *\tEnumeration of all possible filtering modes\n */\npublic enum DomainFilterPolicy {\n\n\t/** user can communicate with anyone */\n\tALL(false),\n\n\t/** user can communicate with other local users\n\t * (i.e. of the domains hosted on the same Tigase instance) */\n\tLOCAL(false),\n\n\t/** user can communicate with other users of the same domain */\n\tOWN(false),\n\n\t/** user can communicate with users of the domains within listen domains */\n\tLIST(true),\n\n\t/** user can communicate with anyone except of the users within listed domains */\n\tBLACKLIST(true),\n\n\t/** Custom rules defining communication policies in CSV (using semicolon) in the\n\t * format of {@code rule_number;(allow|deny);[type_of_value];[value]}\n\t * where {@code type_of_value::(jid)}\n\t * <pre>\n\t * 1|allow|self;\n\t * 2|allow|jid|admin@test2.com;\n\t * 3|allow|jid|pubsub@test.com;\n\t * 4|deny|all;\n\t * </pre>\n\t */\n\tCUSTOM(true),\n\n\t/** user can not communicate with anyone, account virtually disabled */\n\tBLOCK(false);\n\n\tboolean domainListRequired;\n\n\tDomainFilterPolicy(boolean domainListRequired) {\n\t\tthis.domainListRequired = domainListRequired;\n\t}\n\n\tprivate static String[] valuesStr = null;\n\tprivate static HashSet<String> valuesDomainsListStr = null;\n\n\n\t/**\n\t * Helper method returning proper defaults in case parsed value doesn't\n\t * correspond to any of the available modes.\n\t *\n\t * @param domainFilteringPolicy policy name as string\n\t *\n\t * @return enum value of corresponding mode, ALL if value doesn't match any mode or null for null parameter.\n\t */\n\tpublic static DomainFilterPolicy valueof( String domainFilteringPolicy ) {\n\t\tif ( domainFilteringPolicy == null ){\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\treturn DomainFilterPolicy.valueOf( domainFilteringPolicy );\n\t\t} catch ( Exception e ) {\n\t\t\treturn ALL;\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Helper method to generate string array with mode values\n\t *\n\t * @return String array with mode values\n\t */\n\tpublic static String[] valuesStr() {\n\t\tif ( valuesStr == null ){\n\t\t\tDomainFilterPolicy[] vals = values();\n\n\t\t\tvaluesStr = new String[ vals.length ];\n\t\t\tfor ( int i = 0 ; i < vals.length ; i++ ) {\n\t\t\t\tvaluesStr[i] = vals[i].name();\n\t\t\t}\n\t\t}\n\n\t\treturn valuesStr;\n\t}\n\n\tpublic static HashSet<String> valuePoliciesWithDomainListStr() {\n\t\tif ( valuesDomainsListStr == null ){\n\t\t\tDomainFilterPolicy[] vals = values();\n\n\t\t\tvaluesDomainsListStr = new HashSet<>();\n\t\t\tfor ( DomainFilterPolicy val : vals ) {\n\t\t\t\tif ( val.isDomainListRequired() ){\n\t\t\t\t\tvaluesDomainsListStr.add( val.name() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn valuesDomainsListStr;\n\t}\n\n\tpublic boolean isDomainListRequired() {\n\t\treturn domainListRequired;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/vhosts/filter/Rule.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts.filter;\n\nimport tigase.xmpp.JID;\n\nimport java.util.Objects;\n\n/**\n *\n * @author Wojtek\n */\npublic class Rule implements Comparable<Rule> {\n\n\tint id;\n\tboolean allow;\n\tRuleType type;\n\tJID value;\n\n\tpublic Rule( int id, boolean allow, RuleType type, JID value ) {\n\t\tthis.id = id;\n\t\tthis.allow = allow;\n\t\tthis.type = type;\n\t\tthis.value = value;\n\t}\n\n\t@Override\n\tpublic int compareTo( Rule o ) {\n\t\treturn id > o.getId() ? +1 : id < o.getId() ? -1 : 0;\n\t}\n\n\t@Override\n\tpublic boolean equals( Object obj ) {\n\t\tif ( obj == null ){\n\t\t\treturn false;\n\t\t}\n\t\tif ( getClass() != obj.getClass() ){\n\t\t\treturn false;\n\t\t}\n\t\tfinal Rule other = (Rule) obj;\n\t\tif ( this.id != other.id ){\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.allow != other.allow ){\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.type != other.type ){\n\t\t\treturn false;\n\t\t}\n\t\tif ( !Objects.equals( this.value, other.value ) ){\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic boolean isAllowed() {\n\t\treturn allow;\n\t}\n\n\tprotected int getId() {\n\t\treturn id;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tint hash = 5;\n\t\thash = 11 * hash + this.id;\n\t\thash = 11 * hash + ( this.allow ? 1 : 0 );\n\t\thash = 11 * hash + Objects.hashCode( this.type );\n\t\tif ( value != null ){\n\t\t\thash = 11 * hash + value.toString().hashCode();\n\t\t}\n\t\treturn hash;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Rule{\" + \"id=\" + id + \", allow=\" + allow + \", type=\" + type + \", value=\" + value + '}';\n\t}\n\n\tpublic String toConfigurationString() {\n\t\treturn id + \"|\" + (allow ? \"allow\" : \"deny\") + \"|\" + type +\n\t\t\t\t\t (type == RuleType.domain || type == RuleType.jid ? \"|\" + value :  \"\") + \";\";\n\t}\n\n\tboolean isMatched( JID source, JID destination ) {\n\t\tboolean result = false;\n\t\tswitch ( type ) {\n\t\t\tcase all:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase self:\n\t\t\t\tif ( source != null && destination != null ){\n\t\t\t\t\tresult = source.getBareJID().equals( destination.getBareJID() );\n\t\t\t\t} else if (source == null ) {\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase domain:\n\t\t\t\tif ( value != null && destination != null ){\n\t\t\t\t\tresult = value.getDomain().equals( destination.getDomain() );\n\t\t\t\t}\n\t\t\t\tif ( value != null && destination != null ){\n\t\t\t\t\tresult |= value.getDomain().equals( source.getDomain() );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase jid:\n\t\t\t\tif ( value != null && destination != null ){\n\t\t\t\t\tresult = value.getBareJID().equals( destination.getBareJID() );\n\t\t\t\t}\n\t\t\t\tif ( value != null && destination != null ){\n\t\t\t\t\tresult |= value.getBareJID().equals( source.getBareJID() );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic static enum RuleType {\n\n\t\tjid, self, domain, all\n\t};\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/Authorization.java",
    "content": "\n/*\n* @(#)Authorization.java   2010.01.12 at 09:57:32 PST\n*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport tigase.server.Packet;\n\n//~--- enums ------------------------------------------------------------------\n\n/**\n * <code>Authorization</code> enumeration type defines authorization error\n * codes.\n * It has also capability to build error response message relevant to\n * specific error code (or success code). It is used not only for authorization\n * process but also by other features implementation accessing session\n * data.<br>\n * All defined errors comes directly from <em>XMPP</em> core RFC. For each error\n * has assigned error code - from old <em>Jabber</em> spec. and error condition -\n * <em>XMPP</em> error spec.\n *\n * <p>\n * Created: Thu Oct 14 22:19:11 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum Authorization {\n\tAUTHORIZED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 0;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic Packet getResponseMessage(Packet p, String t, boolean i) {\n\t\t\treturn p.okResult(t, 0);\n\t\t}\n\t},\n\tBAD_REQUEST {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"bad-request\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 400;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_MODIFY;\n\t\t}\n\t},\n\tCONFLICT {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"conflict\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 409;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tFEATURE_NOT_IMPLEMENTED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"feature-not-implemented\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 501;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tFORBIDDEN {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"forbidden\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 403;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_AUTH;\n\t\t}\n\t},\n\tGONE {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"gone\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 302;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_MODIFY;\n\t\t}\n\t},\n\tINTERNAL_SERVER_ERROR {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"internal-server-error\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 500;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_WAIT;\n\t\t}\n\t},\n\tITEM_NOT_FOUND {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"item-not-found\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 404;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tJID_MALFORMED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"jid-malformed\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 400;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_MODIFY;\n\t\t}\n\t},\n\tNOT_ACCEPTABLE {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"not-acceptable\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 406;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_MODIFY;\n\t\t}\n\t},\n\tNOT_ALLOWED {\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"not-allowed\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 405;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tNOT_AUTHORIZED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"not-authorized\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 401;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_AUTH;\n\t\t}\n\t},\n\tPAYMENT_REQUIRED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"payment-required\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 402;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_AUTH;\n\t\t}\n\t},\n\tPOLICY_VIOLATION {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"policy-violation\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 0;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tRECIPIENT_UNAVAILABLE {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"recipient-unavailable\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 404;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_WAIT;\n\t\t}\n\t},\n\tREDIRECT {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"redirect\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 302;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_MODIFY;\n\t\t}\n\t},\n\tREGISTRATION_REQUIRED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"registration-required\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 407;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_AUTH;\n\t\t}\n\t},\n\tREMOTE_SERVER_NOT_FOUND {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"remote-server-not-found\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 404;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tREMOTE_SERVER_TIMEOUT {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"remote-server-timeout\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 504;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_WAIT;\n\t\t}\n\t},\n\tRESOURCE_CONSTRAINT {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"resource-constraint\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 500;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_WAIT;\n\t\t}\n\t},\n\tSERVICE_UNAVAILABLE {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"service-unavailable\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 503;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_CANCEL;\n\t\t}\n\t},\n\tSUBSCRIPTION_REQUIRED {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"subscription-required\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 407;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_AUTH;\n\t\t}\n\t},\n\tUNDEFINED_CONDITION {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"undefined-condition\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 500;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn \"[undefined]\";\n\t\t}\n\t},\n\tUNEXPECTED_REQUEST {\n\n\t\t@Override\n\t\tpublic String getCondition() {\n\t\t\treturn \"unexpected-request\";\n\t\t}\n\n\t\t@Override\n\t\tpublic int getErrorCode() {\n\t\t\treturn 400;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getErrorType() {\n\t\t\treturn ERR_TYPE_WAIT;\n\t\t}\n\t};\n\n\tprotected static final String ERR_TYPE_AUTH = \"auth\";\n\tprotected static final String ERR_TYPE_CANCEL = \"cancel\";\n\tprotected static final String ERR_TYPE_MODIFY = \"modify\";\n\tprotected static final String ERR_TYPE_WAIT = \"wait\";\n\n\tprivate static final Map<String,Authorization> BY_CONDITION = new ConcurrentHashMap<String,Authorization>();\n\t\n\tstatic {\n\t\tfor (Authorization v : values()) {\n\t\t\tif (v.getCondition() == null)\n\t\t\t\tcontinue;\n\t\t\tBY_CONDITION.put(v.getCondition(), v);\n\t\t}\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\tpublic static Authorization getByCondition(String condition) {\n\t\tif (condition == null)\n\t\t\treturn null;\n\t\treturn BY_CONDITION.get(condition);\n\t}\n\t\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract String getCondition();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract int getErrorCode();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic abstract String getErrorType();\n\n\t/**\n\t * Utility method for generating an error response for a stanza (enclosed by the given\n\t * <code>Packet</code>). In some cases it may happen that the error packet is bounced\n\t * back to the sender which triggers another attempt to generate an error response for\n\t * the error packet. This may lead to an infinite loop inside the component\n\t * (Tigase server) eating up CPU and slowing everything down. To prevent this the\n\t * method detects the <em>error</em> stanza typy and generates an exception.\n\t * @param packet is the packet for which the error response is generated.\n\t * @param text is an error human readable text message.\n\t * @param includeOriginalXML is a boolean value indicating whether the original\n\t * content of the stanza (children of the top level element) have to be included in the\n\t * error stanza.\n\t * @return a new <code>Packet</code> instance with an error response for a given\n\t * packet.\n\t * @throws PacketErrorTypeException if the packet given as a parameter encloses\n\t * an error stanza already.\n\t */\n\tpublic Packet getResponseMessage(Packet packet, String text, boolean includeOriginalXML)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif ((packet.getType() == null) || (packet.getType() != StanzaType.error)) {\n\t\t\treturn packet.errorResult(getErrorType(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetErrorCode(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetCondition(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tincludeOriginalXML);\n\t\t} else {\n\t\t\tthrow new PacketErrorTypeException(\"The packet has already 'error' type: \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + packet.toString());\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/ConnectionStatus.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n/**\n * The XMPPResourceConnection Object can be put in special states\n * when all packets received to by this connection are threated in\n * different way:\n * <code>INIT</code> - Behaviour is like in <code>NORMAL</code> state. It is\n * just an indication that the session is in an initial phase before authentication.\n * <code>ON_HOLD</code> - packets are not processed at all, they are\n * collected by instead for later time.\n * <code>REDIRECT</code> - packets received by this connection are\n * being redirected to a different SM for processing.\n * <code>NORMAL</code> - packets are processed in normal way.\n *\n *\n * Created: Wed Aug 13 20:58:33 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Deprecated\npublic enum ConnectionStatus {\n\n\tINIT, ON_HOLD, REDIRECT, NORMAL,\n  // The TEMP state is a special state used in the session transfer\n  TEMP,\n\t// The REMOTE state is for user session on remote cluster nodes\n\tREMOTE;\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/ElementMatcher.java",
    "content": "/*\n * ElementMatcher.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\n\n/**\n *\n * @author andrzej\n */\npublic class ElementMatcher {\n\n\tprivate final String[] path;\n\tprivate final String xmlns;\n\tprivate final boolean value;\n\n\tpublic static ElementMatcher create(String str) {\n\t\tList<String> path = new ArrayList<String>();\n\t\tString xmlns = null;\n\t\tint offset = 0;\n\t\tboolean value = !str.startsWith(\"-\");\n\t\tif (str.charAt(0) == '-' || str.charAt(0) == '+') {\n\t\t\tstr = str.substring(1);\n\t\t}\n\t\twhile (true) {\n\t\t\tString elemName = null;\n\n\t\t\tint slashIdx = str.indexOf('/', offset);\n\t\t\tint sIdx = str.indexOf('[', offset);\n\t\t\tif (slashIdx < 0) {\n\t\t\t\tslashIdx = str.length();\n\t\t\t}\n\n\t\t\tElement c = null;\n\t\t\tif (slashIdx < sIdx || sIdx < 0) {\n\t\t\t\telemName = str.substring(offset, slashIdx);\n\t\t\t\txmlns = null;\n\t\t\t} else {\n\t\t\t\tint eIdx = str.indexOf(']', sIdx);\n\t\t\t\telemName = str.substring(offset, sIdx);\n\t\t\t\txmlns = str.substring(sIdx + 1, eIdx);\n\t\t\t\tslashIdx = str.indexOf('/', eIdx);\n\t\t\t\tif (slashIdx < 0) {\n\t\t\t\t\tslashIdx = str.length();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (elemName != null && !elemName.isEmpty()) {\n\t\t\t\tpath.add(elemName.intern());\n\t\t\t}\n\n\t\t\tif (slashIdx == str.length()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\toffset = slashIdx + 1;\n\t\t}\n\t\tif (xmlns != null) {\n\t\t\txmlns = xmlns.intern();\n\t\t}\n\n\t\treturn new ElementMatcher(path.toArray(new String[0]), xmlns, value);\n\t}\n\n\tpublic ElementMatcher(String[] path, String xmlns, boolean value) {\n\t\tthis.path = path;\n\t\tthis.xmlns = xmlns;\n\t\tthis.value = value;\n\t}\n\n\tpublic boolean matches(Packet packet) {\n\t\tElement child = packet.getElement().findChildStaticStr(path);\n\t\treturn child != null && (xmlns == null || xmlns == child.getXMLNS());\n\t}\n\n\tpublic boolean getValue() {\n\t\treturn value;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/NoConnectionIdException.java",
    "content": "\n/*\n* Tigase Jabber/XMPP Server\n* Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as published by\n* the Free Software Foundation, version 3 of the License.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. Look for COPYING file in the top folder.\n* If not, see http://www.gnu.org/licenses/.\n*\n* $Rev$\n* Last modified by $Author$\n* $Date$\n */\npackage tigase.xmpp;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n *\n * @author kobit\n */\npublic class NoConnectionIdException extends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic NoConnectionIdException() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param message\n\t */\n\tpublic NoConnectionIdException(String message) {\n\t\tsuper(message);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param cause\n\t */\n\tpublic NoConnectionIdException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param message\n\t * @param cause\n\t */\n\tpublic NoConnectionIdException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/NotAuthorizedException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n/**\n * This exception is usually trown when there is kind of access violation error.\n * If some code try to access data to which it doesn't have permission to or if\n * try to access data before successful authorization process.\n *\n * <p>\n * Created: Sat Oct 30 08:44:37 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class NotAuthorizedException extends XMPPException {\n\n  private static final long serialVersionUID = 1L;\n\n  /**\n   * Creates a new <code>NotAuthorizedException</code> instance.\n   *\n   */\n  public NotAuthorizedException(String message) { super(message); }\n\n  public NotAuthorizedException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n} // NotAuthorizedException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/PacketErrorTypeException.java",
    "content": "/*\n * PacketErrorTypeException.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n/**\n * Describe class PacketErrorTypeException here.\n *\n *\n * Created: Tue Oct  9 13:41:43 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class PacketErrorTypeException\n\t\t\t\textends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>PacketErrorTypeException</code> instance.\n\t *\n\t *\n\t * @param message\n\t */\n\tpublic PacketErrorTypeException(String message) {\n\t\tsuper(message);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param message\n\t * @param cause\n\t */\n\tpublic PacketErrorTypeException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/ProcessorFactory.java",
    "content": "/*\n * ProcessorFactory.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.annotations.TODO;\n\nimport tigase.util.ClassUtil;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.lang.reflect.Modifier;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeMap;\n\n/**\n * <code>ProcessorFactory</code> class contains functionality to load and\n * provide all classes which are <code>XMPPProcessor</code> extensions (not\n * abstract extensions) available in classpath.\n * These extensions are normally used for processing data transfered between\n * <em>XMPP</em> entities.<br>\n * It automatically loads and provides all available processors unless\n * configuration says to behave differently. You can for example exclude in\n * configuration some processors from loading or even you can turn off automatic\n * loading processors and provide explicity names of classes which should be\n * loaded as <em>XMPP</em> processors. In all cases loaded classes ae checked\n * whether they are <code>XMPPProcessor</code> extensions, because only those\n * classes can be used as processors.\n *\n * <p>\n * Created: Tue Oct  5 20:45:33 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@TODO(\n\t\tnote = \"Make loading processors configurable: exclude specific classes, turn-off automatic\" +\n\t\t\" loading and include specific classes. In all cases checking agains XMPPProcessor \" +\n\t\t\"compatibility should be performed.\")\npublic class ProcessorFactory {\n\tprivate static final Logger                   log = Logger.getLogger(\n\t\t\tProcessorFactory.class.getName());\n\tprivate static final Map<String, XMPPImplIfc> processors = new TreeMap<String,\n\t\t\tXMPPImplIfc>();\n\n\t//~--- static initializers --------------------------------------------------\n\n\tstatic {\n\t\ttry {\n\t\t\tSet<Class<XMPPImplIfc>> procs = ClassUtil.getClassesImplementing(XMPPImplIfc.class);\n\t\t\tArrayList<String>       elems = new ArrayList<String>(32);\n\n\t\t\tfor (Class<XMPPImplIfc> cproc : procs) {\n\t\t\t\tif (!Modifier.isPublic(cproc.getModifiers())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tXMPPImplIfc xproc = cproc.newInstance();\n\n\t\t\t\tprocessors.put(xproc.id(), xproc);\n\n\t\t\t\tString[][] els = xproc.supElementNamePaths();\n\t\t\t\tString[]   nss = xproc.supNamespaces();\n\n\t\t\t\tif ((els != null) && (nss != null)) {\n\t\t\t\t\tfor (int i = 0; i < els.length; i++) {\n\t\t\t\t\t\tString el_name = \"\";\n\n\t\t\t\t\t\tfor (int j = 0; j < els[i].length; j++) {\n\t\t\t\t\t\t\tel_name += \"/\" + els[i][j];\n\t\t\t\t\t\t}\n\t\t\t\t\t\telems.add(\"  <\" + el_name + \" xmlns='\" + nss[i] + \"'/>\\n\");\n\t\t\t\t\t}    // end of for (int i = 0; i < els.length; i++)\n\t\t\t\t}      // end of if (nss != null)\n\t\t\t}        // end of for ()\n\t\t\tCollections.sort(elems);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tStringBuilder sb = new StringBuilder(200);\n\n\t\t\t\tfor (String elm : elems) {\n\t\t\t\t\tsb.append(elm);\n\t\t\t\t}      // end of for ()\n\t\t\t\tlog.log(Level.FINEST, \"Loaded XMPPProcessors:\\n{0}\", sb);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tSystem.out.println(\"Can not load XMPPProcessor implementations\");\n\t\t\te.printStackTrace();\n\t\t\tlog.log(Level.SEVERE, \"Can not load XMPPProcessor implementations\", e);\n\t\t\tSystem.exit(1);\n\t\t}          // end of try-catch\n\t}\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tprivate ProcessorFactory() {}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static XMPPPacketFilterIfc getPacketFilter(String id) {\n\t\tXMPPImplIfc imp = processors.get(id);\n\n\t\tif (imp instanceof XMPPPacketFilterIfc) {\n\t\t\treturn (XMPPPacketFilterIfc) imp;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static XMPPPostprocessorIfc getPostprocessor(String id) {\n\t\tXMPPImplIfc imp = processors.get(id);\n\n\t\tif (imp instanceof XMPPPostprocessorIfc) {\n\t\t\treturn (XMPPPostprocessorIfc) imp;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static XMPPPreprocessorIfc getPreprocessor(String id) {\n\t\tXMPPImplIfc imp = processors.get(id);\n\n\t\tif (imp instanceof XMPPPreprocessorIfc) {\n\t\t\treturn (XMPPPreprocessorIfc) imp;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static XMPPProcessorIfc getProcessor(String id) {\n\t\tXMPPImplIfc imp = processors.get(id);\n\n\t\tif (imp instanceof XMPPProcessorIfc) {\n\t\t\treturn (XMPPProcessorIfc) imp;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param id\n\t *\n\t * \n\t */\n\tpublic static XMPPStopListenerIfc getStopListener(String id) {\n\t\tXMPPImplIfc imp = processors.get(id);\n\n\t\tif (imp instanceof XMPPStopListenerIfc) {\n\t\t\treturn (XMPPStopListenerIfc) imp;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Check if plugin implementation is in server jar\n\t *\n\t * @param id\n\t * \n\t */\n\tpublic static boolean hasImplementation(String id) {\n\t\treturn processors.containsKey(id);\n\t}\n}    // ProcessorFactory\n\n\n//~ Formatted in Tigase Code Convention on 13/03/11\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/RepositoryAccess.java",
    "content": "/*\n * RepositoryAccess.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthorizationException;\nimport tigase.db.AuthRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserNotFoundException;\nimport tigase.db.UserRepository;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.vhosts.VHostItem;\n\nimport static tigase.db.NonAuthUserRepository.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.UUID;\n\n/**\n * Describe class RepositoryAccess here.\n *\n *\n * Created: Tue Oct 24 10:38:41 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class RepositoryAccess {\n\t/** Field description */\n\tprotected static final String NO_ACCESS_TO_REP_MSG = \"Can not access user repository.\";\n\n\t/** Field description */\n\tprotected static final String NOT_AUTHORIZED_MSG =\n\t\t\t\"Session has not been yet authorised.\";\n\tprivate static final String ANONYMOUS_MECH = \"ANONYMOUS\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(\"tigase.xmpp.RepositoryAccess\");\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t// ~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected AuthRepository authRepo = null;\n\n\t/** Field description */\n\tprotected VHostItem domain = null;\n\n\t/**\n\t * Handle to user repository - permanent data base for storing user data.\n\t */\n\tprivate UserRepository repo = null;\n\n\t// private boolean anon_allowed = false;\n\n\t/** Field description */\n\tprotected boolean is_anonymous = false;\n\n\t/**\n\t * Current authorization state - initialy session i\n\t * <code>NOT_AUTHORIZED</code>. It becomes <code>AUTHORIZED</code>\n\t */\n\tprotected Authorization authState = Authorization.NOT_AUTHORIZED;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t// ~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>RepositoryAccess</code> instance.\n\t *\n\t *\n\t * @param rep\n\t * @param auth\n\t */\n\tpublic RepositoryAccess(UserRepository rep, AuthRepository auth) {\n\t\trepo     = rep;\n\t\tauthRepo = auth;\n\n\t\t// this.anon_allowed = anon_allowed;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void addDataList(final String subnode, final String key, final String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\trepo.addDataList(getBareJID(), subnode, key, list);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void addOfflineDataList(String subnode, String key, String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\taddDataList(calcNode(OFFLINE_DATA_NODE, subnode), key, list);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void addPublicDataList(String subnode, String key, String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\taddDataList(calcNode(PUBLIC_DATA_NODE, subnode), key, list);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param digest\n\t * @param id\n\t * @param alg\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws AuthorizationException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\t@Deprecated\n\tpublic Authorization loginDigest(BareJID userId, String digest, String id, String alg)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException {\n\t\tisLoginAllowed();\n\t\ttry {\n\t\t\tif (authRepo.digestAuth(userId, digest, id, alg)) {\n\t\t\t\tauthState = Authorization.AUTHORIZED;\n\t\t\t\tlogin();\n\t\t\t}    // end of if (authRepo.loginPlain())auth.login();\n\n\t\t\treturn authState;\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(\"Authorization failed\", e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t\t// throw new NotAuthorizedException(\"Authorization failed\", e);\n\t\t}      // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param props\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws AuthorizationException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\t@Deprecated\n\tpublic Authorization loginOther(Map<String, Object> props)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException {\n\t\tisLoginAllowed();\n\t\ttry {\n\t\t\tString mech = (String) props.get(AuthRepository.MACHANISM_KEY);\n\n\t\t\tif (domain.isAnonymousEnabled() && (mech != null) && mech.equals(ANONYMOUS_MECH)) {\n\t\t\t\tis_anonymous = true;\n\t\t\t\tprops.put(AuthRepository.USER_ID_KEY, BareJID.bareJIDInstanceNS(UUID.randomUUID()\n\t\t\t\t\t\t.toString(), getDomain().getVhost().getDomain()));\n\t\t\t\tauthState = Authorization.AUTHORIZED;\n\t\t\t\tlogin();\n\t\t\t} else {\n\t\t\t\tif (authRepo.otherAuth(props)) {\n\t\t\t\t\tauthState = Authorization.AUTHORIZED;\n\t\t\t\t\tlogin();\n\t\t\t\t}    // end of if (authRepo.loginPlain())auth.login();\n\t\t\t}\n\n\t\t\treturn authState;\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"User not found: \", e);\n\n\t\t\tthrow new NotAuthorizedException(\"Authorization failed\", e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t\t// throw new NotAuthorizedException(\"Authorization failed\", e);\n\t\t}        // end of try-catch\n\t}\n\n\t/**\n\t * <code>authorize</code> method performs authorization with given password as\n\t * plain text. If <code>AUTHORIZED</code> has been returned it means\n\t * authorization process is successful and session has been activated,\n\t * otherwise session hasn't been authorized and return code gives more\n\t * detailed information of fail reason. Please refer to\n\t * <code>Authorization</code> documentation for more details.\n\t *\n\t * @param userId\n\t * @param password\n\t * @return a <code>Authorization</code> value of result code.\n\t * @throws NotAuthorizedException\n\t * @throws AuthorizationException\n\t * @throws TigaseDBException\n\t */\n\t@Deprecated\n\tpublic Authorization loginPlain(BareJID userId, String password)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException {\n\t\tisLoginAllowed();\n\t\ttry {\n\t\t\tif (authRepo.plainAuth(userId, password)) {\n\t\t\t\tauthState = Authorization.AUTHORIZED;\n\t\t\t\tlogin();\n\t\t\t}    // end of if (authRepo.loginPlain())auth.login();\n\n\t\t\treturn authState;\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.info(\"User not found, authorization failed: \" + userId);\n\n\t\t\tthrow new NotAuthorizedException(\"Authorization failed\", e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t\t// throw new NotAuthorizedException(\"Authorization failed\", e);\n\t\t}      // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param userId\n\t * @param xmpp_sessionId\n\t * @param token\n\t *\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws AuthorizationException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\t@Deprecated\n\tpublic Authorization loginToken(BareJID userId, String xmpp_sessionId, String token)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException {\n\t\tisLoginAllowed();\n\t\ttry {\n\t\t\tString db_token = repo.getData(userId, \"tokens\", xmpp_sessionId);\n\n\t\t\tif (token.equals(db_token)) {\n\t\t\t\tauthState = Authorization.AUTHORIZED;\n\t\t\t\tlogin();\n\t\t\t\trepo.removeData(userId, \"tokens\", xmpp_sessionId);\n\t\t\t}\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\n\t\treturn authState;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t */\n\tpublic void logout() throws NotAuthorizedException {\n\t\tauthState = Authorization.NOT_AUTHORIZED;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param authProps\n\t * @throws TigaseDBException\n\t */\n\tpublic void queryAuth(Map<String, Object> authProps) throws TigaseDBException {\n\t\tif (authRepo == null) {\n\t\t\tlog.severe(\n\t\t\t\t\t\"Authentication repository is not available! Misconfiguration error or \" +\n\t\t\t\t\t\"authentication database is not available. Please check your logs from the \" +\n\t\t\t\t\t\"server startup time.\");\n\n\t\t\treturn;\n\t\t}\n\t\tauthProps.put(AuthRepository.SERVER_NAME_KEY, getDomain().getVhost().getDomain());\n\t\tauthRepo.queryAuth(authProps);\n\t\tif (domain.isAnonymousEnabled() && (authProps.get(AuthRepository.PROTOCOL_KEY) ==\n\t\t\t\tAuthRepository.PROTOCOL_VAL_SASL)) {\n\t\t\tString[] auth_mechs = (String[]) authProps.get(AuthRepository.RESULT_KEY);\n\n\t\t\tif (auth_mechs == null) {\n\t\t\t\tthrow new TigaseDBException(\"No euthentication mechanisms found, probably \" +\n\t\t\t\t\t\t\"DB misconfiguration problem.\");\n\t\t\t}\n\t\t\tauth_mechs                        = Arrays.copyOf(auth_mechs, auth_mechs.length +\n\t\t\t\t\t1);\n\t\t\tauth_mechs[auth_mechs.length - 1] = ANONYMOUS_MECH;\n\t\t\tauthProps.put(AuthRepository.RESULT_KEY, auth_mechs);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name_param\n\t * @param pass_param\n\t * @param email_param\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws TigaseStringprepException\n\t *\n\t * @deprecated\n\t */\n\t@Deprecated\n\tpublic Authorization register(String name_param, String pass_param, String email_param)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, TigaseStringprepException {\n\t\tMap<String, String> reg_params = null;\n\n\t\tif ((email_param != null) &&!email_param.trim().isEmpty()) {\n\t\t\treg_params = new LinkedHashMap<String, String>();\n\t\t\treg_params.put(\"email\", email_param);\n\t\t}\n\n\t\treturn register(name_param, pass_param, reg_params);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name_param\n\t * @param pass_param\n\t * @param reg_params\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws TigaseStringprepException\n\t */\n\tpublic Authorization register(String name_param, String pass_param, Map<String,\n\t\t\tString> reg_params)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, TigaseStringprepException {\n\n\t\t// Some clients send plain user name and others send\n\t\t// jid as user name. Let's resolve this here.\n\t\tString user_name = BareJID.parseJID(name_param)[0];\n\n\t\tif ((user_name == null) || user_name.trim().isEmpty()) {\n\t\t\tuser_name = name_param;\n\t\t}    // end of if (user_mame == null || user_name.equals(\"\"))\n\t\tif (isAuthorized()) {\n\t\t\treturn changeRegistration(user_name, pass_param, reg_params);\n\t\t}\n\n\t\t// new user registration, let's check limits...\n\t\tif (!domain.isRegisterEnabled()) {\n\t\t\tthrow new NotAuthorizedException(\"Registration is now allowed for this domain\");\n\t\t}\n\t\tif (domain.getMaxUsersNumber() > 0) {\n\t\t\tlong domainUsers = authRepo.getUsersCount(domain.getVhost().getDomain());\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Current number of users for domain: \" + domain.getVhost()\n\t\t\t\t\t\t.getDomain() + \" is: \" + domainUsers);\n\t\t\t}\n\t\t\tif (domainUsers >= domain.getMaxUsersNumber()) {\n\t\t\t\tthrow new NotAuthorizedException(\"Maximum users number for the domain exceeded.\");\n\t\t\t}\n\t\t}\n\t\tif ((user_name == null) || user_name.equals(\"\") || (pass_param == null) || pass_param\n\t\t\t\t.equals(\"\")) {\n\t\t\treturn Authorization.NOT_ACCEPTABLE;\n\t\t}\n\t\ttry {\n\t\t\tauthRepo.addUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()\n\t\t\t\t\t.getDomain()), pass_param);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"User added: {0}, pass: {1}\", new Object[]{BareJID.toString(user_name, getDomain().getVhost()\n\t\t\t\t\t\t\t\t.getDomain()), pass_param});\n\t\t\t}\n\t\t\tsetRegistration(user_name, pass_param, reg_params);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Registration data set for: {0}, pass: {1}, reg_params: {2}\", new Object[]{BareJID.toString(user_name, getDomain()\n\t\t\t\t\t\t\t\t.getVhost().getDomain()), pass_param, reg_params});\n\t\t\t}\n\n\t\t\treturn Authorization.AUTHORIZED;\n\t\t} catch (UserExistsException e) {\n\t\t\treturn Authorization.CONFLICT;\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.SEVERE, \"Repository access exception.\", e);\n\n\t\t\treturn Authorization.INTERNAL_SERVER_ERROR;\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void removeData(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\ttry {\n\t\t\trepo.removeData(getBareJID(), subnode, key);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Removes the last data node given in subnode path as parameter to this\n\t * method. All subnodes are moved as well an all data stored as\n\t * <code>(key, val)</code> are removed as well. Changes are commited to\n\t * repository immediatelly and there is no way to undo this operation so use\n\t * it with care.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value of path to node which has to be\n\t *          removed.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic void removeDataGroup(final String subnode)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\trepo.removeSubnode(getBareJID(), subnode);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void removeOfflineData(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tremoveData(calcNode(OFFLINE_DATA_NODE, subnode), key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void removeOfflineDataGroup(String subnode)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tremoveDataGroup(calcNode(OFFLINE_DATA_NODE, subnode));\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void removePublicData(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tremoveData(calcNode(PUBLIC_DATA_NODE, subnode), key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void removePublicDataGroup(String subnode)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tremoveDataGroup(calcNode(PUBLIC_DATA_NODE, subnode));\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param name_param\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws TigaseStringprepException\n\t */\n\tpublic Authorization unregister(String name_param)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, TigaseStringprepException {\n\t\tif (!isAuthorized()) {\n\t\t\treturn Authorization.FORBIDDEN;\n\t\t}\n\n\t\t// Some clients send plain user name and others send\n\t\t// jid as user name. Let's resolve this here.\n\t\tString user_name = BareJID.parseJID(name_param)[0];\n\n\t\tif ((user_name == null) || user_name.trim().isEmpty()) {\n\t\t\tuser_name = name_param;\n\t\t}    // end of if (user_mame == null || user_name.equals(\"\"))\n\t\tif (getUserName().equals(user_name)) {\n\t\t\ttry {\n\t\t\t\tauthRepo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()\n\t\t\t\t\t\t.getDomain()));\n\t\t\t\ttry {\n\t\t\t\t\trepo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()\n\t\t\t\t\t\t\t.getDomain()));\n\t\t\t\t} catch (UserNotFoundException ex) {\n\n\t\t\t\t\t// We ignore this error here. If auth_repo and user_repo are in fact\n\t\t\t\t\t// the same\n\t\t\t\t\t// database, then user has been already removed with the\n\t\t\t\t\t// auth_repo.removeUser(...)\n\t\t\t\t\t// then the second call to user_repo may throw the exception which is\n\t\t\t\t\t// fine.\n\t\t\t\t}\n\n\t\t\t\t// We mark the session as no longer authorized to prevent data access through\n\t\t\t\t// this session.\n\t\t\t\tlogout();\n\n\t\t\t\t// Session authorized is returned only to indicate successful operation.\n\t\t\t\treturn Authorization.AUTHORIZED;\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\treturn Authorization.REGISTRATION_REQUIRED;\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.SEVERE, \"Repository access exception.\", e);\n\n\t\t\t\treturn Authorization.INTERNAL_SERVER_ERROR;\n\t\t\t}    // end of catch\n\t\t} else {\n\t\t\treturn Authorization.FORBIDDEN;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param xmpp_sessionId\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String getAuthenticationToken(String xmpp_sessionId)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tUUID token = UUID.randomUUID();\n\n\t\tsetData(\"tokens\", xmpp_sessionId, token.toString());\n\n\t\treturn token.toString();\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Gets the value of authState\n\t *\n\t * @return the value of authState\n\t */\n\tpublic final Authorization getAuthState() {\n\t\treturn this.authState;\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns user JID but without <em>resource</em> part. This is real user ID\n\t * not session ID. To retrieve session ID - full JID refer to\n\t * <code>getJID()</code> method.<br>\n\t * If session has not been authorized yet this method throws\n\t * <code>NotAuthorizedException</code>.\n\t *\n\t * @return a <code>String</code> value of user ID - this is user JID without\n\t *         resource part. To obtain full user JID please refer to\n\t *         <code>getJID</code> method.\n\t *\n\t * @exception NotAuthorizedException when this session has not been authorized\n\t *                                   yet and some parts of user JID are not\n\t *                                   known yet.\n\t */\npublic abstract BareJID getBareJID() throws NotAuthorizedException;\n\n\t/**\n\t * <code>getData</code> method is a twin sister (brother?) of\n\t * <code>setData(String, String, String)</code> method. It allows you to\n\t * retrieve data stored with above method. It is data stored in given node\n\t * with given key identifier. If there are no data associated with given key\n\t * or given node does not exist given <code>def</code> value is returned.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value is path to node where pair\n\t *          <code>(key, value)</code> are stored.\n\t * @param key\n\t *          a <code>String</code> value of key ID for data to retrieve.\n\t * @param def\n\t *          a <code>String</code> value of default returned if there is\n\t *          nothing stored with given key. <code>def</code> can be set to any\n\t *          value you wish to have back as default value or <code>null</code>\n\t *          if you want to have back <code>null</code> if no data was found.\n\t *          If you set <code>def</code> to <code>null</code> it has exactly\n\t *          the same effect as if you use <code>getData(String)</code> method.\n\t * @return a <code>String</code> value of data found for given key or\n\t *         <code>def</code> if there was no data associated with given key.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic String getData(String subnode, String key, String def)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\treturn repo.getData(getBareJID(), subnode, key, def);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\n\t\t// return null;\n\t}\n\n\t/**\n\t * This method retrieves list of all direct subnodes for given node. It works\n\t * in similar way as <code>ls</code> unix command or <code>dir</code> under\n\t * DOS/Windows systems.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value of path to node for which we want to\n\t *          retrieve list of direct subnodes.\n\t * @return a <code>String[]</code> array of direct subnodes names for given\n\t *         node.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic String[] getDataGroups(String subnode)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\treturn repo.getSubnodes(getBareJID(), subnode);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\n\t\t// return null;\n\t}\n\n\t/**\n\t * This method returns all data keys available in permanent storage in given\n\t * node. There is not though any information what kind of data is stored with\n\t * this key. This is up to user (developer) to determine what data type is\n\t * associated with key and what is it's meaning.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value pointing to specific subnode in user\n\t *          reposiotry where data have to be stored.\n\t * @return a <code>String[]</code> array containing all data keys found in\n\t *         given subnode.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic String[] getDataKeys(final String subnode)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\treturn repo.getKeys(getBareJID(), subnode);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\n\t\t// return null;\n\t}\n\n\t/**\n\t * This method allows to retrieve list of values associated with one key. As\n\t * it is possible to store many values with one key there are a few methods\n\t * which provides this functionality. If given key does not exists in given\n\t * subnode <code>null</code> is returned.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value pointing to specific subnode in user\n\t *          reposiotry where data have to be stored.\n\t * @param key\n\t *          a <code>String</code> value of data key ID.\n\t * @return a <code>String[]</code> array containing all values found for given\n\t *         key.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic String[] getDataList(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\treturn repo.getDataList(getBareJID(), subnode, key);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\n\t\t// return null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>VHostItem</code>\n\t */\n\tpublic VHostItem getDomain() {\n\t\treturn domain;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tpublic JID getDomainAsJID() {\n\t\treturn domain.getVhost();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param def\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String getOfflineData(String subnode, String key, String def)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn getData(calcNode(OFFLINE_DATA_NODE, subnode), key, def);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String[] getOfflineDataList(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn getDataList(calcNode(OFFLINE_DATA_NODE, subnode), key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param def\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String getPublicData(String subnode, String key, String def)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn getData(calcNode(PUBLIC_DATA_NODE, subnode), key, def);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String[]</code>\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String[] getPublicDataList(String subnode, String key)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn getDataList(calcNode(PUBLIC_DATA_NODE, subnode), key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t * @throws NotAuthorizedException\n\t */\n\tpublic abstract String getUserName() throws NotAuthorizedException;\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isAnonymous() {\n\t\treturn is_anonymous;\n\t}\n\n\t// /**\n\t// * Sets the value of authState\n\t// *\n\t// * @param argAuthState Value to assign to this.authState\n\t// */\n\t// protected void setAuthState(final Authorization argAuthState) {\n\t// this.authState = argAuthState;\n\t// }\n\n\t/**\n\t * This method allows you test this session if it already has been authorized.\n\t * If <code>true</code> is returned as method result it means session has\n\t * already been authorized, if <code>false</code> however session is still not\n\t * authorized.\n\t *\n\t * @return a <code>boolean</code> value which informs whether this session has\n\t *         been already authorized or not.\n\t */\n\tpublic boolean isAuthorized() {\n\t\treturn authState == Authorization.AUTHORIZED;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t// ~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * This method stores given data in permanent storage in given point of\n\t * hierarchy of data base. This method is similar to\n\t * <code>setData(String, String)</code> and differs in one additional\n\t * parameter which point to user data base subnode where data must be stored.\n\t * It helps to organize user data in more logical hierarchy.<br>\n\t * User data is kind of tree where you can store data in each tree node. The\n\t * most relevant sample might be structure like typical file system or XML\n\t * like or LDAP data base. The first implementation is actually done as XML\n\t * file to make it easier test application and deploy simple installation\n\t * where there is no more users than 1000.<br>\n\t * To find out more about user repository refer to <code>UserRepository</code>\n\t * interface for general info and to <code>XMLRepository</code> for detailed\n\t * explanation regarding XML implementation of user repository.\n\t * <br>\n\t * Thus <code>subnode</code> is kind of path to data node. If you specify\n\t * <code>null</code> or empty node data will be stored in root user node. This\n\t * has exactly the same effect as you call\n\t * <code>setData(String, String)</code>. If you want to store data in\n\t * different node you must just specify node path like you do it to directory\n\t * on most file systems:\n\t *\n\t * <pre>\n\t * /roster\n\t * </pre>\n\t *\n\t * Or, if you need access deeper node:\n\t *\n\t * <pre>\n\t * /just/like/path/to/file\n\t * </pre>\n\t *\n\t * <br>\n\t * If given node does not yet exist it will be automaticaly created with all\n\t * nodes in given path so there is no need for developer to perform additional\n\t * action to create node. There is, however method\n\t * <code>removeDataGroup(String)</code> for deleting specified node as nodes\n\t * are not automaticaly deleted.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value pointing to specific subnode in user\n\t *          reposiotry where data have to be stored.\n\t * @param key\n\t *          a <code>String</code> value of data key ID.\n\t * @param value\n\t *          a <code>String</code> actual data stored in user repository.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #removeDataGroup(String)\n\t * @see UserRepository\n\t */\n\tpublic void setData(String subnode, String key, String value)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\ttry {\n\t\t\trepo.setData(getBareJID(), subnode, key, value);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * This method allows to store list of values under one key ID reference. It\n\t * is often necessary to keep set of values which can be refered by one key.\n\t * As an example might be list of groups for specific buddy in roster. There\n\t * is no actual need to store each group with separate key because we usually\n\t * need to acces whole list of groups.\n\t *\n\t * @param subnode\n\t *          a <code>String</code> value pointing to specific subnode in user\n\t *          reposiotry where data have to be stored.\n\t * @param key\n\t *          a <code>String</code> value of data key ID.\n\t * @param list\n\t *          a <code>String[]</code> keeping list of actual data to be stored\n\t *          in user repository.\n\t * @exception NotAuthorizedException\n\t *              is thrown when session has not been authorized yet and there\n\t *              is no access to permanent storage.\n\t * @throws TigaseDBException\n\t * @see #setData(String, String, String)\n\t */\n\tpublic void setDataList(final String subnode, final String key, final String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (is_anonymous) {\n\t\t\treturn;\n\t\t}\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG);\n\t\t}\n\t\ttry {\n\t\t\trepo.setDataList(getBareJID(), subnode, key, list);\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.FINEST, \"Problem accessing reposiotry: \", e);\n\n\t\t\tthrow new NotAuthorizedException(NO_ACCESS_TO_REP_MSG, e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param domain\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic void setDomain(final VHostItem domain) throws TigaseStringprepException {\n\t\tthis.domain = domain;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param value\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void setOfflineData(String subnode, String key, String value)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsetData(calcNode(OFFLINE_DATA_NODE, subnode), key, value);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void setOfflineDataList(String subnode, String key, String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsetDataList(calcNode(OFFLINE_DATA_NODE, subnode), key, list);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param value\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void setPublicData(String subnode, String key, String value)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsetData(calcNode(PUBLIC_DATA_NODE, subnode), key, value);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param subnode\n\t * @param key\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void setPublicDataList(String subnode, String key, String[] list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsetDataList(calcNode(PUBLIC_DATA_NODE, subnode), key, list);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tprotected abstract void login();\n\n\tprivate String calcNode(String base, String subnode) {\n\t\tif (subnode == null) {\n\t\t\treturn base;\n\t\t}    // end of if (subnode == null)\n\n\t\treturn base + \"/\" + subnode;\n\t}\n\n\tprivate Authorization changeRegistration(final String name_param,\n\t\t\tfinal String pass_param, final Map<String, String> registr_params)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, TigaseStringprepException {\n\t\tif ((name_param == null) || name_param.equals(\"\") || (pass_param == null) ||\n\t\t\t\tpass_param.equals(\"\")) {\n\t\t\treturn Authorization.BAD_REQUEST;\n\t\t}\n\t\tif (getUserName().equals(name_param)) {\n\t\t\tsetRegistration(name_param, pass_param, registr_params);\n\n\t\t\treturn Authorization.AUTHORIZED;\n\t\t} else {\n\t\t\treturn Authorization.NOT_AUTHORIZED;\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate boolean isLoginAllowed() throws AuthorizationException {\n\t\tif (isAuthorized()) {\n\t\t\tthrow new AuthorizationException(\"User session already authenticated. \" +\n\t\t\t\t\t\"Subsequent login is forbidden. You must loggin on a different connection.\");\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t// ~--- set methods ----------------------------------------------------------\n\tprivate void setRegistration(final String name_param, final String pass_param,\n\t\t\tfinal Map<String, String> registr_params)\n\t\t\t\t\tthrows TigaseDBException, TigaseStringprepException {\n\t\ttry {\n\t\t\tauthRepo.updatePassword(BareJID.bareJIDInstance(name_param, getDomain().getVhost()\n\t\t\t\t\t.getDomain()), pass_param);\n\t\t\tif (registr_params != null) {\n\t\t\t\tfor (Map.Entry<String, String> entry : registr_params.entrySet()) {\n\t\t\t\t\trepo.setData(BareJID.bareJIDInstance(name_param, getDomain().getVhost()\n\t\t\t\t\t\t\t.getDomain()), entry.getKey(), entry.getValue());\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (UserNotFoundException e) {\n\t\t\tlog.log(Level.WARNING, \"Problem accessing reposiotry: \", e);\n\n\t\t\t// } catch (TigaseDBException e) {\n\t\t\t// log.log(Level.SEVERE, \"Repository access exception.\", e);\n\t\t}    // end of try-catch\n\t}\n}    // RepositoryAccess\n\n\n//~ Formatted in Tigase Code Convention on 13/11/02\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/StanzaType.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Describe class StanzaType here.\n *\n *\n * Created: Fri Feb 10 13:13:50 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic enum StanzaType {\n\n\terror,                                      // Common type\n\t\tget, set, result,                         // iq types\n\t\tavailable, unavailable, probe, subscribe, // presence types\n\t\tsubscribed, unsubscribe, unsubscribed,    // presence types\n\t\tchat, groupchat, headline, normal,        // message types\n\t\tvalid, invalid,                           // Dialback verification packets\n\t\tterminate,                                // Bosh - session termination stanza\n    invisible;                                // Other unknown types...\n\n\tprivate static Set<StanzaType> subTypes;\n\n\tpublic static StanzaType valueof(String cmd) {\n\t\ttry {\n\t\t\treturn StanzaType.valueOf(cmd);\n\t\t} catch (IllegalArgumentException e) {\n\t\t\treturn null;\n\t\t} // end of try-catch\n\t}\n\n\tpublic static Set<StanzaType> getSubsTypes() {\n\t\tif ( subTypes == null ){\n\t\t\tsubTypes = new HashSet<>();\n\t\t\tsubTypes.add( subscribe );\n\t\t\tsubTypes.add( subscribed );\n\t\t\tsubTypes.add( unsubscribe );\n\t\t\tsubTypes.add( unsubscribed );\n\t\t}\n\t\treturn subTypes;\n\t}\n\n} // StanzaType\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/StreamError.java",
    "content": "/*\n * StreamError.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n *\n * @author andrzej\n */\npublic enum StreamError {\n\t\n\tBadFormat(\"bad-format\"),\n\tBadNamespacePrefix(\"bad-namespace-prefix\"),\n\tConflict(\"conflict\"),\n\tConnectionTimeout(\"connection-timeout\"),\n\tHostGone(\"host-gone\"),\n\tHostUnknown(\"host-unknown\"),\n\tImproperAddressing(\"improper-addressing\"),\n\tInternalServerError(\"internal-server-error\"),\n\tInvalidFrom(\"invalid-from\"),\n\tInvalidNamespace(\"invalid-namespace\"),\n\tInvalidXml(\"invalid-xml\"),\n\tNotAuthorized(\"not-authorized\"),\n\tNotWellFormed(\"not-well-formed\"),\n\tPolicyViolation(\"policy-violation\"),\n\tRemoteConnectionFailed(\"remote-connection-failed\"),\n\tReset(\"reset\"),\n\tResourceConstraint(\"resource-constraint\"),\n\tRestrictedXml(\"restricted-xml\"),\n\tSeeOtherHost(\"see-other-host\"),\n\tSystemShutdown(\"system-shutdown\"),\n\tUndefinedCondition(\"undefined-condition\"),\n\tUnsupportedEncoding(\"unsupported-encoding\"),\n\tUnsupportedFeature(\"unsupported-feature\"),\n\tUnsupportedStanzaType(\"unsupported-stanza-type\"),\n\tUnsupportedVersion(\"unsupported-version\");\n\t\n\tprivate static final Map<String,StreamError> BY_CONDITION = new HashMap<>();\n\t\n\tstatic {\n\t\tfor (StreamError err : StreamError.values()) {\n\t\t\tBY_CONDITION.put(err.getCondition(), err);\n\t\t}\n\t}\n\t\n\tpublic static StreamError getByCondition(String condition) {\n\t\tStreamError err = BY_CONDITION.get(condition);\n\t\tif (err == null)\n\t\t\treturn UndefinedCondition;\n\t\treturn err;\n\t}\n\n\tprivate final String condition;\n\t\n\tprivate StreamError(String condition) {\n\t\tthis.condition = condition;\n\t}\n\n\tpublic String getCondition() {\n\t\treturn condition;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPDomBuilderHandler.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.DefaultElementFactory;\nimport tigase.xml.Element;\nimport tigase.xml.ElementFactory;\nimport tigase.xml.SimpleHandler;\n\nimport static tigase.server.ConnectionManager.ELEMENTS_NUMBER_LIMIT_PROP_KEY;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TreeMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * <code>XMPPDomBuilderHandler</code> - implementation of\n *  <code>SimpleHandler</code> building <em>DOM</em> strctures during parsing\n *  time.\n *  It also supports creation multiple, sperate document trees if parsed\n *  buffer contains a few <em>XML</em> documents. As a result of work it returns\n *  always <code>Queue</code> containing all found <em>XML</em> trees in the\n *  same order as they were found in network data.<br>\n *  Document trees created by this <em>DOM</em> builder consist of instances of\n *  <code>Element</code> class or instances of class extending\n *  <code>Element</code> class. To receive trees built with instances of proper\n *  class user must provide <code>ElementFactory</code> implementation creating\n *  instances of required <code>ELement</code> extension.\n *\n * <p>\n * Created: Sat Oct  2 22:01:34 2004\n * </p>\n * @param <RefObject>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class XMPPDomBuilderHandler<RefObject> implements SimpleHandler {\n\tprivate static final Logger log = Logger.getLogger(XMPPDomBuilderHandler.class.getName());\n\n\tprivate static final String ELEM_STREAM_STREAM = \"stream:stream\";\n\tprivate static ElementFactory defaultFactory = new DefaultElementFactory();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate ElementFactory customFactory = null;\n\tprivate Object parserState = null;\n\tprivate XMPPIOService<RefObject> service = null;\n\tprivate String top_xmlns = null;\n\tprivate Map<String, String> namespaces = new TreeMap<>();\n\tprivate boolean error = false;\n\tprivate ArrayDeque<Element> el_stack = new ArrayDeque<>(10);\n\tprivate ArrayDeque<Element> all_roots = new ArrayDeque<>(1);\n\tprivate boolean streamClosed = false;\n\n\t/**\n\t * Protection from the system overload and DOS attack. We want to limit number\n\t * of elements created within a single XMPP stanza.\n\t *\n\t */\n\tprivate int elements_number_limit_count = 0;\n\tprivate int elements_number_limit;\n\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param ioserv\n\t */\n\tpublic XMPPDomBuilderHandler(XMPPIOService<RefObject> ioserv) {\n\t\tcustomFactory = defaultFactory;\n\t\tservice = ioserv;\n//\t\telements_number_limit = (int)service.getSessionData().get( ELEMENTS_NUMBER_LIMIT_PROP_KEY);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param ioserv\n\t * @param factory\n\t */\n\tpublic XMPPDomBuilderHandler(XMPPIOService<RefObject> ioserv, ElementFactory factory) {\n\t\tcustomFactory = factory;\n\t\tservice = ioserv;\n//\t\telements_number_limit = (int)service.getSessionData().get( ELEMENTS_NUMBER_LIMIT_PROP_KEY);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void elementCData(StringBuilder cdata) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Element CDATA: \" + cdata);\n\t\t}\n\n\t\tElement elem = el_stack.peek();\n\t\tif (elem != null) {\n\t\t\telem.addCData(cdata.toString());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean endElement(StringBuilder name) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"End element name: \" + name);\n\t\t}\n\n\t\tString tmp_name = name.toString();\n\n\t\tif (tmp_name.equals(ELEM_STREAM_STREAM)) {\n\t\t\t// we should not call xmppStreamClosed() as we still may have received \n\t\t\t// some packets which may not be processed correctly if we close stream now!\n\t\t\t//service.xmppStreamClosed();\n\t\t\tstreamClosed = true;\n\t\t\treturn true;\n\t\t}    // end of if (tmp_name.equals(ELEM_STREAM_STREAM))\n\n\t\tif (el_stack.isEmpty()) {\n\t\t\tel_stack.push(newElement(tmp_name, null, null, null));\n\t\t}    // end of if (tmp_name.equals())\n\n\t\tElement elem = el_stack.pop();\n\t\tint idx = tmp_name.indexOf(':');\n\t\tString tmp_xmlns = null;\n\n\t\tif (idx > 0) {\n\t\t\tString tmp_name_prefix = tmp_name.substring(0, idx);\n\t\t\tif (tmp_name_prefix != null) {\n\t\t\t\tfor (String pref : namespaces.keySet()) {\n\t\t\t\t\tif (tmp_name_prefix.equals(pref)) {\n\t\t\t\t\t\ttmp_xmlns = namespaces.get(pref);\n\t\t\t\t\t\ttmp_name = tmp_name.substring(pref.length() + 1, tmp_name.length());\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"new_xmlns = \" + tmp_xmlns);\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (tmp_name.startsWith(xmlns))\n\t\t\t\t}      // end of for (String xmlns: namespaces.keys())\n\t\t\t}\t\t\n\t\t}\t\t\n\t\tif (elem.getName() != tmp_name.intern() || (tmp_xmlns != null && !tmp_xmlns.equals(elem.getXMLNS())))\n\t\t\treturn false;\n\n\t\tif (el_stack.isEmpty()) {\n\t\t\telements_number_limit_count = 0;\n\t\t\tall_roots.offer(elem);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Adding new request: \" + elem.toString());\n\t\t\t}\n\t\t} else {\n\t\t\tel_stack.peek().addChild(elem);\n\t\t}    // end of if (el_stack.isEmpty()) else\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void error(String errorMessage) {\n\t\tlog.warning(\"XML content parse error.\");\n\n\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\tlog.fine(errorMessage);\n\t\t}\n\n\t\terror = true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic Queue<Element> getParsedElements() {\n\t\treturn all_roots;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tpublic boolean isStreamClosed() {\n\t\treturn streamClosed;\n\t}\n\t\n\t@Override\n\tpublic void otherXML(StringBuilder other) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Other XML content: \" + other);\n\t\t}\n\n\t\t// Just ignore\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic boolean parseError() {\n\t\treturn error;\n\t}\n\n\t@Override\n\tpublic Object restoreParserState() {\n\t\treturn parserState;\n\t}\n\n\t@Override\n\tpublic void saveParserState(Object state) {\n\t\tparserState = state;\n\t}\n\n\tpublic void setElementsLimit(int limit) {\n\t\telements_number_limit = limit;\n\t}\n\n\t@Override\n\tpublic void startElement(StringBuilder name, StringBuilder[] attr_names,\n\t\t\tStringBuilder[] attr_values) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Start element name: \" + name);\n\t\t\tlog.finest(\"Element attributes names: \" + Arrays.toString(attr_names));\n\t\t\tlog.finest(\"Element attributes values: \" + Arrays.toString(attr_values));\n\t\t}\n\n\t\t// Look for 'xmlns:' declarations:\n\t\tif (attr_names != null) {\n\t\t\tfor (int i = 0; i < attr_names.length; ++i) {\n\n\t\t\t\t// Exit the loop as soon as we reach end of attributes set\n\t\t\t\tif (attr_names[i] == null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (attr_names[i].toString().startsWith(\"xmlns:\")) {\n\n\t\t\t\t\t// TODO should use a StringCache instead of intern() to avoid potential\n\t\t\t\t\t// DOS by exhausting permgen\n\t\t\t\t\tnamespaces.put(attr_names[i].substring(\"xmlns:\".length(),\n\t\t\t\t\t\t\tattr_names[i].length()).intern(), attr_values[i].toString());\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Namespace found: \" + attr_values[i].toString());\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (att_name.startsWith(\"xmlns:\"))\n\t\t\t}      // end of for (String att_name : attnames)\n\t\t}        // end of if (attr_names != null)\n\n\t\tString tmp_name = name.toString();\n\n\t\tif (tmp_name.equals(ELEM_STREAM_STREAM)) {\n\t\t\tstreamClosed = false;\n\t\t\tMap<String, String> attribs = new HashMap<String, String>();\n\n\t\t\tif (attr_names != null) {\n\t\t\t\tfor (int i = 0; i < attr_names.length; i++) {\n\t\t\t\t\tif ((attr_names[i] != null) && (attr_values[i] != null)) {\n\t\t\t\t\t\tattribs.put(attr_names[i].toString(), attr_values[i].toString());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}    // end of else\n\t\t\t\t}      // end of for (int i = 0; i < attr_names.length; i++)\n\t\t\t}        // end of if (attr_name != null)\n\n\t\t\tservice.xmppStreamOpened(attribs);\n\n\t\t\treturn;\n\t\t}          // end of if (tmp_name.equals(ELEM_STREAM_STREAM))\n\n\t\tString new_xmlns = null;\n\t\tString prefix = null;\n\t\tString tmp_name_prefix = null;\n\t\tint idx = tmp_name.indexOf(':');\n\n\t\tif (idx > 0) {\n\t\t\ttmp_name_prefix = tmp_name.substring(0, idx);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Found prefixed element name, prefix: \" + tmp_name_prefix);\n\t\t\t}\n\t\t}\n\n\t\tif (tmp_name_prefix != null) {\n\t\t\tfor (String pref : namespaces.keySet()) {\n\t\t\t\tif (tmp_name_prefix.equals(pref)) {\n\t\t\t\t\tnew_xmlns = namespaces.get(pref);\n\t\t\t\t\ttmp_name = tmp_name.substring(pref.length() + 1, tmp_name.length());\n\t\t\t\t\tprefix = pref;\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"new_xmlns = \" + new_xmlns);\n\t\t\t\t\t}\n\t\t\t\t}    // end of if (tmp_name.startsWith(xmlns))\n\t\t\t}      // end of for (String xmlns: namespaces.keys())\n\t\t}\n\n\t\tElement elem = newElement(tmp_name, null, attr_names, attr_values);\n\t\tString ns = elem.getXMLNS();\n\n\t\tif (ns == null) {\n\t\t\tif (el_stack.isEmpty() || (el_stack.peek().getXMLNS() == null)) {\n\n\t\t\t\t// elem.setDefXMLNS(top_xmlns);\n\t\t\t} else {\n\t\t\t\telem.setDefXMLNS(el_stack.peek().getXMLNS());\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"DefXMLNS assigned: \" + elem.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (new_xmlns != null) {\n\t\t\telem.setXMLNS(new_xmlns);\n\t\t\telem.removeAttribute(\"xmlns:\" + prefix);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"new_xmlns assigned: \" + elem.toString());\n\t\t\t}\n\t\t}\n\n\t\tel_stack.push(elem);\n\t}\n\n\tprivate Element newElement( String name, String cdata, StringBuilder[] attnames,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tStringBuilder[] attvals ) {\n\t\t++elements_number_limit_count;\n\t\tElement el = customFactory.elementInstance( name, cdata, attnames, attvals );\n\n\t\tif ( elements_number_limit_count > elements_number_limit ){\n\t\t\tthrow new XMPPParserException( \"Too many elements for staza, possible DoS attack.\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t + \"Current service \" + service.getClass() + \" limit of elements: \" + elements_number_limit );\n\t\t}\n\t\treturn el;\n\t}\n}    // XMPPDomBuilderHandler\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPException.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n/**\n * Base exception type used for other eceptions defined for <em>XMPP</em>\n * protocol. This type and all descendants are thrown by this package runtime.\n *\n * <p>\n * Created: Sat Oct 30 08:38:18 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class XMPPException extends Exception {\n\n  private static final long serialVersionUID = 1L;\n\n  public XMPPException() { super(); }\n  public XMPPException(String message) { super(message); }\n  public XMPPException(String message, Throwable cause) {\n    super(message, cause);\n  }\n  public XMPPException(Throwable cause) { super(cause); }\n\n} // XMPPException\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPIOService.java",
    "content": "/*\n * XMPPIOService.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.net.IOService;\nimport tigase.server.Packet;\nimport tigase.server.xmppclient.XMPPIOProcessor;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.text.SimpleDateFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- JDK imports ------------------------------------------------------------\n\n/**\n * Describe class XMPPIOService here.\n *\n *\n * Created: Tue Feb 7 07:15:02 2006\n *\n * @param <RefObject>\n *          is a reference object stored by this service. This is e reference to\n *          higher level data object keeping more information about the\n *          connection.\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class XMPPIOService<RefObject>\n\t\t\t\textends IOService<RefObject> {\n\t/** Field description */\n\tpublic static final String ACK_NAME = \"ack\";\n\n\t/** Field description */\n\tpublic static final String CROSS_DOMAIN_POLICY_FILE_PROP_KEY =\n\t\t\t\"cross-domain-policy-file\";\n\n\t/** Field description */\n\tpublic static final String CROSS_DOMAIN_POLICY_FILE_PROP_VAL =\n\t\t\t\"etc/cross-domain-policy.xml\";\n\n\t/**\n\t * Key name of the system property for configuration protection\n\t * from system overload and DOS attack.\n\t */\n\tpublic static final String DOM_HANDLER = \"XMPPDomBuilderHandler\";\n\n\t/** Field description */\n\tpublic static final String ID_ATT = \"id\";\n\n\t/** Field description */\n\tpublic static final String REQ_NAME            = \"req\";\n\n\tpublic static final String STREAM_CLOSING        = \"stream-closing\";\n\n\tprivate static String      cross_domain_policy = null;\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(XMPPIOService.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate XMPPDomBuilderHandler<RefObject> domHandler = null;\n\t\n\t/** Field description */\n\tprotected SimpleParser        parser = SingletonFactory.getParserInstance();\n\tprivate String                jid                  = null;\n\tprivate long                  packetsReceived      = 0;\n\tprivate long                  packetsSent          = 0;\n\tprotected XMPPIOProcessor[]     processors           = null;\n\tprivate long                  req_idx              = 0;\n\t@SuppressWarnings(\"rawtypes\")\n\tprivate XMPPIOServiceListener serviceListener      = null;\n\tprivate long                  totalPacketsReceived = 0;\n\tprivate long                  totalPacketsSent     = 0;\n\t/**\n\t * This variable keeps the time of last received XMPP packet, it is used to\n\t * help detect dead connections.\n\t */\n\tprivate long                                    lastXmppPacketReceivedTime = 0;\n\n\t/**\n\t * The <code>waitingPackets</code> queue keeps data which have to be\n\t * processed.\n\t */\n\tprivate ConcurrentLinkedQueue<Packet> waitingPackets =\n\t\t\tnew ConcurrentLinkedQueue<Packet>();\n\tprivate ConcurrentSkipListMap<String, Packet> waitingForAck =\n\t\t\tnew ConcurrentSkipListMap<String, Packet>();\n\tprivate boolean white_char_ack = false;\n\tprivate String  xmlns          = null;\n\tprivate boolean xmpp_ack       = false;\n\tprivate boolean strict_ack     = false;\n\t\n\tSimpleDateFormat format2 = new SimpleDateFormat(\"MM-dd HH:mm:ss\");\n\n\t/**\n\t * The <code>readyPackets</code> queue keeps data which have been already\n\t * processed and they are actual processing results.\n\t */\n\tprivate ConcurrentLinkedQueue<Packet> receivedPackets =\n\t\t\tnew ConcurrentLinkedQueue<Packet>();\n\tprivate boolean firstPacket = true;\n\n\t/** Field description */\n\tpublic ReentrantLock writeInProgress = new ReentrantLock();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>XMPPIOService</code> instance.\n\t *\n\t */\n\tpublic XMPPIOService() {\n\t\tsuper();\n\t\tdomHandler = new XMPPDomBuilderHandler<>( this );\n\t\tgetSessionData().put( DOM_HANDLER, domHandler );\n\t\tif (cross_domain_policy == null) {\n\t\t\tString file_name = System.getProperty(CROSS_DOMAIN_POLICY_FILE_PROP_KEY,\n\t\t\t\t\tCROSS_DOMAIN_POLICY_FILE_PROP_VAL);\n\n\t\t\ttry {\n\t\t\t\tBufferedReader br   = new BufferedReader(new FileReader(file_name));\n\t\t\t\tString         line = br.readLine();\n\t\t\t\tStringBuilder  sb   = new StringBuilder();\n\n\t\t\t\twhile (line != null) {\n\t\t\t\t\tsb.append(line);\n\t\t\t\t\tline = br.readLine();\n\t\t\t\t}\n\t\t\t\tsb.append('\\0');\n\t\t\t\tbr.close();\n\t\t\t\tcross_domain_policy = sb.toString();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem reading cross domain poicy file: \" + file_name,\n\t\t\t\t\t\tex);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method <code>addPacketToSend</code> adds new data which will be processed\n\t * during next run. Data are kept in proper order like in <em>FIFO</em> queue.\n\t *\n\t * @param packet\n\t *          a <code>Packet</code> value of data to process.\n\t */\n\tpublic void addPacketToSend(Packet packet) {\n\n\t\t// processing packet using io level processors\n\t\tif (processors != null) {\n\t\t\tfor (XMPPIOProcessor processor : processors) {\n\t\t\t\tif (processor.processOutgoing(this, packet)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (xmpp_ack) {\n\t\t\tString req = \"\" + (++req_idx);\n\n\t\t\tpacket.getElement().addChild(new Element(REQ_NAME, new String[] { ID_ATT },\n\t\t\t\t\tnew String[] { req }));\n\t\t\twaitingForAck.put(req, packet);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Added req {1} for packet: {2}\", new Object[] {\n\t\t\t\t\t\ttoString(),\n\t\t\t\t\t\treq, packet });\n\t\t\t}\n\t\t}\n\t\t++packetsSent;\n\t\t++totalPacketsSent;\n\t\twaitingPackets.offer(packet);\n\t}\n\n\t\t@Override\n\tpublic IOService<?> call() throws IOException {\n\t\tIOService<?> io = super.call();\n\t\t// needed to send packets added by addPacketToSent when it was not able\n\t\t// to acquire lock for write as when this packet would not be followed by\n\t\t// next packet then it would stay in waitingPackets queue, however this\n\t\t// may slow down processing packets in SocketThread thread.\n\t\tif (isConnected() && !waitingPackets.isEmpty() && writeInProgress.tryLock()) {\n\t\t\ttry {\n\t\t\t\tprocessWaitingPackets();\n\t\t\t} finally {\n\t\t\t\twriteInProgress.unlock();\n\t\t\t}\t\t\t\n\t\t}\n\t\treturn io;\n\t}\n\t\n\t@Override\n\tpublic boolean checkBufferLimit(int bufferSize) {\n\t\tif (!super.checkBufferLimit(bufferSize)) {\n\t\t\ttry {\n\t\t\t\twriteRawData(\"<stream:error>\" + \"<policy-violation \"\n\t\t\t\t\t\t+ \"xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>\"\n\t\t\t\t\t\t+ \"</stream:error></stream:stream>\");\n\t\t\t\tint counter = 0;\n\n\t\t\t\twhile (isConnected() && waitingToSend() && (++counter < 10)) {\n\t\t\t\t\twriteData(null);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(10);\n\t\t\t\t\t} catch (InterruptedException ex) {\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (IOException ex) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Exception sending policy-violation stream error\", \n\t\t\t\t\t\tnew Object[]{toString()});\n\t\t\t}\n\t\t\tthis.forceStop();\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\t\n\t\n\t/**\n\t *\n\t * @param data\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t * @throws IOException\n\t */\n\tpublic boolean checkData(char[] data) throws IOException {\n\n\t\t// by default do nothing and return false\n\t\treturn false;\n\t}\n\n\t/**\n\t * Clears queue of packets waiting to send.\n\t * In case of connection close this packets may be sent to offline store \n\t * but some processors may want stop this from happening - for that they \n\t * may use this method\n\t */\n\tpublic void clearWaitingPackets() {\n\t\tthis.waitingPackets.clear();\n\t}\n\t\n\t/**\n\t * Returns queue with packets waiting to send. For use by ConnectionManager\n\t * which may need to get undelivered packets \n\t * \n\t * @return \n\t */\n\tpublic Queue<Packet> getWaitingPackets() {\n\t\treturn waitingPackets;\n\t}\n\t\n\t@Override\n\tpublic void forceStop() {\n\t\tboolean stop = false;\n\n\t\tif (processors != null) {\n\t\t\tfor (XMPPIOProcessor processor : processors) {\n\t\t\t\tstop |= processor.serviceStopped(this, false);\n\t\t\t}\n\t\t}\n\t\tif (!stop) {\n\t\t\tsuper.forceStop();\n\t\t}\n\t}\n\n\n\t@Override\n\tpublic void processWaitingPackets() throws IOException {\n\t\tPacket packet = null;\n\n\t\t// int cnt = 0;\n\t\t// while ((packet = waitingPackets.poll()) != null && (cnt < 1000)) {\n\t\t\n\t\t// we should only peek for packet now, and poll it after sending it\n\t\twhile ((packet = waitingPackets.peek()) != null) {\n\n\t\t\t// ++cnt;\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending packet: {1}\", new Object[] { toString(),\n\t\t\t\t\t\tpacket });\n\t\t\t}\n\t\t\twriteRawData(packet.getElement().toString());\n\t\t\t\n\t\t\t// and after sending it we should remove it to minimalize chances of lost packets\n\t\t\twaitingPackets.poll();\n\t\t\t\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, SENT: {1}\", new Object[] { toString(),\n\t\t\t\t\t\tpacket.getElement().toString() });\n\t\t\t}\n\t\t}    // end of while (packet = waitingPackets.poll() != null)\n\n\t\t// notify io processors that all waiting packets were sent\n\t\tif (processors != null) {\n\t\t\tfor (XMPPIOProcessor processor : processors) {\n\t\t\t\tprocessor.packetsSent(this);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stop() {\n\n\t\t// if (!streamClosed) {\n\t\t// streamClosed = true;\n\t\t// serviceListener.xmppStreamClosed(this);\n\t\t// } // end of if (!streamClosed)\n\t\tsuper.stop();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn super.toString() + \", jid: \" + jid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t *\n\t * @throws IOException\n\t */\n\tpublic void writeRawData(String data) throws IOException {\n\n\t\t// We change state of this object in this method\n\t\t// It can be called by many threads simultanously\n\t\t// so we need to make it thread-safe\n\t\t// writeLock.lock();\n\t\t// try {\n\t\t\n\t\tSystem.out.println(\"\\t\\tS2C: \" + data);\n\t\t\n\t\t\n\t\twriteData(data);\n\n\t\t// } finally {\n\t\t// writeLock.unlock();\n\t\t// }\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param data\n\t */\n\tpublic void xmppStreamOpen(final String data) {\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending data: {1}\", new Object[] { toString(),\n\t\t\t\t\t\tdata });\n\t\t\t}\n\t\t\twriteRawData(data);\n\t\t\tassert debug(data, \"--SENT:\");\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.WARNING, \"{0}, Error sending stream open data: {1}\", new Object[] {\n\t\t\t\t\ttoString(),\n\t\t\t\t\te });\n\t\t\tforceStop();\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n//\t/**\n//\t *\n//\t * @return\n//\t */\n//\tpublic int getElementLimits() {\n//\t\treturn elements_number_limit;\n//\t}\n\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getPacketsReceived(boolean reset) {\n\t\tlong tmp = packetsReceived;\n\n\t\tif (reset) {\n\t\t\tpacketsReceived = 0;\n\t\t}\n\n\t\treturn tmp;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param reset\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getPacketsSent(boolean reset) {\n\t\tlong tmp = packetsSent;\n\n\t\tif (reset) {\n\t\t\tpacketsSent = 0;\n\t\t}\n\n\t\treturn tmp;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code Queue<Packet>}\n\t */\n\tpublic Queue<Packet> getReceivedPackets() {\n\t\treturn receivedPackets;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getTotalPacketsReceived() {\n\t\treturn totalPacketsReceived;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getTotalPacketsSent() {\n\t\treturn totalPacketsSent;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getUserJid() {\n\t\treturn this.jid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code Map<String,Packet>}\n\t */\n\tpublic Map<String, Packet> getWaitingForAct() {\n\t\tfor (Packet p : waitingForAck.values()) {\n\t\t\tElement req = p.getElement().getChild(REQ_NAME);\n\n\t\t\tif (req == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"{0}, Missing req element in waiting for ACK packet: {1}\", new Object[] {\n\t\t\t\t\t\t\ttoString(),\n\t\t\t\t\t\t\tp });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tp.getElement().removeChild(req);\n\t\t\t}\n\t\t}\n\n\t\treturn waitingForAck;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getXMLNS() {\n\t\treturn this.xmlns;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param white_char_ack\n\t * @param xmpp_ack\n\t * @param strict\n\t */\n\tpublic void setAckMode(boolean white_char_ack, boolean xmpp_ack, boolean strict) {\n\t\tthis.white_char_ack = white_char_ack;\n\t\tthis.xmpp_ack       = xmpp_ack;\n\t\tthis.strict_ack     = strict;\n\t}\n\n\n\t/**\n\t *\n\t * @param limit\n\t */\n\tpublic void setElementLimits(int limit) {\n\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param servList\n\t */\n\t@SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n\tpublic void setIOServiceListener(XMPPIOServiceListener servList) {\n\t\tthis.serviceListener = servList;\n\t\tsuper.setIOServiceListener(servList);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param processors is a <code>XMPPIOProcessor[]</code>\n\t */\n\tpublic void setProcessors(XMPPIOProcessor[] processors) {\n\t\tthis.processors = processors;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t */\n\tpublic void setUserJid(String jid) {\n\t\tthis.jid = jid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param xmlns\n\t */\n\tpublic void setXMLNS(String xmlns) {\n\t\tthis.xmlns = xmlns;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method <code>addReceivedPacket</code> puts processing results to queue. The\n\t * processing results are usually data (messages) which has been just received\n\t * from socket.\n\t *\n\t * @param packet\n\t *          a <code>Packet</code> value of processing results.\n\t */\n\tprotected void addReceivedPacket(final Packet packet) {\n\t\tif (firstPacket) {\n\t\t\tif (\"policy-file-request\" == packet.getElemName()) {\n\t\t\t\tlog.fine(\"Got flash cross-domain request\" + packet);\n\t\t\t\tif (cross_domain_policy != null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\twriteRawData(cross_domain_policy);\n\t\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\t\tlog.log(Level.INFO, \"Can't send cross-domain policy: \", ex);\n\t\t\t\t\t}\n\t\t\t\t\tlog.log(Level.FINER, \"Cross-domain policy sent: {1}\", cross_domain_policy);\n\t\t\t\t} else {\n\t\t\t\t\tlog.log(Level.FINER, \"No cross-domain policy defined to sent.\");\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfirstPacket = false;\n\t\t}\n\t\tif (processors != null) {\n\t\t\tboolean stop = false;\n\n\t\t\tfor (XMPPIOProcessor processor : processors) {\n\t\t\t\tstop |= processor.processIncoming(this, packet);\n\t\t\t}\n\t\t\tif (stop) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (packet.getElemName() == ACK_NAME) {\n\t\t\tString ack_id = packet.getAttributeStaticStr(ID_ATT);\n\t\t} else {\n\t\t\tsendAck(packet);\n\t\t\t++packetsReceived;\n\t\t\t++totalPacketsReceived;\n\t\t\tsetLastXmppPacketReceiveTime();\n\t\t\treceivedPackets.offer(packet);\n\t\t}\n\t}\n\n\tprotected String prepareStreamClose() {\n\t\treturn \"</stream:stream>\";\n\t}\t\n\t\n\t@Override\n\tprotected void processSocketData() throws IOException {\n\n\t\t// We change state of this object in this method\n\t\t// It can be called by many threads simultanously\n\t\t// so we need to make it thread-safe\n\t\t// log.finer(\"About to read socket data.\");\n\t\t// Correction:\n\t\t// The design is that this method should not be called concurrently by\n\t\t// multiple threads. However it may happen in some specific cases.\n\t\t// There is a 'non-blocking' synchronization in IOService.call() method\n\t\t// implemented instead.\n\t\t// readLock.lock();\n\t\t// try {\n\t\tif (isConnected()) {\n\t\t\tchar[] data = readData();\n\n\t\t\twhile (isConnected() && (data != null) && (data.length > 0)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, READ:{1}\", new Object[] { toString(),\n\t\t\t\t\t\t\tnew String(data) });\n\t\t\t\t}\n\n\t\t\t\tboolean disconnect = checkData(data);\n\n\t\t\t\tif (disconnect) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"{0}, checkData says disconnect: {1}\", new Object[] {\n\t\t\t\t\t\t\t\ttoString(),\n\t\t\t\t\t\t\t\tnew String(data) });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"{0}, checkData says disconnect\", toString());\n\t\t\t\t\t}\n\t\t\t\t\tforceStop();\n\n\t\t\t\t\treturn;\n\n\t\t\t\t\t// domHandler = new XMPPDomBuilderHandler<RefObject>(this);\n\t\t\t\t}\n\n\t\t\t\t// This is log for debugging only,\n\t\t\t\t// in normal mode don't even call below code\n\t\t\t\tassert debug(new String(data), \"--RECEIVED:\");\n\n\t\t\t\tElement elem = null;\n\n\t\t\t\ttry {\n\t\t\t\t\tparser.parse(domHandler, data, 0, data.length);\n\t\t\t\t\tif (domHandler.parseError()) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"{0}, Data parsing error: {1}\", new Object[] {\n\t\t\t\t\t\t\t\t\ttoString(),\n\t\t\t\t\t\t\t\t\tnew String(data) });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.log(Level.WARNING, \"{0}, data parsing error, stopping connection\",\n\t\t\t\t\t\t\t\t\ttoString());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (serviceListener != null) {\n\t\t\t\t\t\t\tElement err = new Element(\"not-well-formed\", new String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-streams\" });\n\t\t\t\t\t\t\tString streamErrorStr = serviceListener.xmppStreamError(this, Collections.singletonList(err));\n\t\t\t\t\t\t\twriteRawData(streamErrorStr);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tforceStop();\n\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t// domHandler = new XMPPDomBuilderHandler<RefObject>(this);\n\t\t\t\t\t}\n\n\t\t\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\n\t\t\t\t\tif (elems.size() > 0) {\n\t\t\t\t\t\treadCompleted();\n\t\t\t\t\t}\n\t\t\t\t\twhile ((elem = elems.poll()) != null) {\n\n\t\t\t\t\t\t// assert debug(elem.toString() + \"\\n\");\n\t\t\t\t\t\t// log.finer(\"Read element: \" + elem.getName());\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Read packet: {1}\", new Object[] { toString(),\n\t\t\t\t\t\t\t\t\telem });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tSystem.out.println(format2.format(new Date()) + \"  C2S: \" + elem.toString());\n\n\t\t\t\t\t\t// System.out.print(elem.toString());\n\t\t\t\t\t\tPacket pack = Packet.packetInstance(elem);\n\n\t\t\t\t\t\taddReceivedPacket(pack);\n\t\t\t\t\t\tsendAck(pack);\n\t\t\t\t\t}    // end of while ((elem = elems.poll()) != null)\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.INFO, toString() +\n\t\t\t\t\t\t\t\", Incorrect to/from JID format for stanza: \" + elem.toString(), ex);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tlog.log(Level.INFO, toString() + \", Incorrect XML data: \" + new String(data) +\n\t\t\t\t\t\t\t\", stopping connection: \" + getConnectionId() + \", exception: \", ex);\n\t\t\t\t\tforceStop();\n\t\t\t\t} finally {\n\t\t\t\t\tif (domHandler.isStreamClosed())\n\t\t\t\t\t\txmppStreamClosed();\n\t\t\t\t}  // end of try-catch\n\t\t\t\tdata = readData();\n\t\t\t}\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\"{0}, function called when the service is not connected! forceStop()\",\n\t\t\t\t\t\ttoString());\n\t\t\t}\n\t\t\tforceStop();\n\t\t}\n\n\t\t// } finally {\n\t\t// readLock.unlock();\n\t\t// }\n\t}\n\n\t@Override\n\tprotected int receivedPackets() {\n\t\treturn receivedPackets.size();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected void xmppStreamClosed() {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0}, Received STREAM-CLOSE from the client\", toString());\n\t\t}\n\n\t\tif (processors != null) {\n\t\t\tfor (XMPPIOProcessor processor : processors) {\n\t\t\t\tprocessor.serviceStopped(this, true);\n\t\t\t}\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tif (isConnected()) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending data: </stream:stream>, as socket is still connected\", toString());\n\t\t\t\t}\n\t\t\t\twriteRawData(prepareStreamClose());\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Not sending data: </stream:stream>, as socket is alreadt closed\", toString());\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tlog.log(Level.INFO, \"{0}, Error sending stream closed data: {1}\", new Object[] {\n\t\t\t\t\ttoString(),\n\t\t\t\t\te });\n\t\t}\n\n\t\t// streamClosed = true;\n\t\tif (serviceListener != null) {\n\t\t\tserviceListener.xmppStreamClosed(this);\n\t\t}\n\n\t\t// try {\n\t\t// stop();\n\t\t// } catch (IOException e) {\n\t\t// log.warning(\"Error stopping service: \" + e);\n\t\t// } // end of try-catch\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param attribs\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected void xmppStreamOpened(Map<String, String> attribs) {\n\t\tif (serviceListener != null) {\n\t\t\tString response = serviceListener.xmppStreamOpened(this, attribs);\n\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0}, Sending data: {1}\", new Object[] { toString(),\n\t\t\t\t\t\t\tresponse });\n\t\t\t\t}\n\t\t\t\twriteRawData(response);\n\t\t\t\tprocessWaitingPackets();\n\t\t\t\tif ((response != null) && response.endsWith(\"</stream:stream>\")) {\n\t\t\t\t\tstop();\n\t\t\t\t}    // end of if (response.endsWith())\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.log(Level.WARNING, \"{0}, Error sending stream open data: {1}\", new Object[] {\n\t\t\t\t\t\ttoString(),\n\t\t\t\t\t\te });\n\t\t\t\tforceStop();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void sendAck(Packet packet) {\n\n\t\t// If stanza receiving confirmation is configured, try to send confirmation\n\t\t// back\n\t\tif (white_char_ack || xmpp_ack) {\n\t\t\tString ack = null;\n\n\t\t\tif (white_char_ack) {\n\n\t\t\t\t// If confirming via white space is enabled then prepare space ack.\n\t\t\t\tack = \" \";\n\t\t\t}\n\t\t\tif (xmpp_ack) {\n\t\t\t\tElement req = packet.getElement().getChild(REQ_NAME);\n\n\t\t\t\tif (req != null) {\n\t\t\t\t\tpacket.getElement().removeChild(req);\n\n\t\t\t\t\tString req_val = req.getAttributeStaticStr(ID_ATT);\n\n\t\t\t\t\tif (req_val != null) {\n\n\t\t\t\t\t\t// XMPP ack might be enabled in configuration but the client may not\n\t\t\t\t\t\t// support it. In such a case we do not send XMPP ack.\n\t\t\t\t\t\tack = \"<\" + ACK_NAME + \" \" + ID_ATT + \"=\\\"\" + req_val + \"\\\"/>\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ack != null) {\n\t\t\t\ttry {\n\t\t\t\t\twriteRawData(ack);\n\t\t\t\t\tlog.log(Level.FINEST, \"Sent ack confirmation: '\" + ack + \"'\");\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tforceStop();\n\t\t\t\t\tlog.log(Level.FINE, \"Can't send ack confirmation: '\" + ack + \"'\", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * This method sets the time of last received XMPP packet, it is used to\n\t * help detect dead connections.\n\t */\n\tprivate void setLastXmppPacketReceiveTime() {\n\t\tlastXmppPacketReceivedTime = System.currentTimeMillis();\n\t}\n\n\t/**\n\t * This method returns the time when the last XMPP packet was received, it is\n\t * used to help detect dead connections.\n\t *\n\t * @return {@code long} number denoting time when the last XMPP packet was\n\t *         received.\n\t */\n\tpublic long getLastXmppPacketReceiveTime() {\n\t\treturn lastXmppPacketReceivedTime;\n\t}\n}    // XMPPIOService\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPIOServiceListener.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.List;\nimport tigase.net.IOServiceListener;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport tigase.xml.Element;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Describe interface XMPPIOServiceListener here.\n *\n *\n * Created: Wed Feb  8 10:19:41 2006\n *\n * @param <IO>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface XMPPIOServiceListener<IO extends XMPPIOService<?>> extends IOServiceListener<IO> {\n\tvoid xmppStreamClosed(IO serv);\n\n\tString xmppStreamOpened(IO serv, Map<String, String> attribs);\n\t\n\tString xmppStreamError(IO serv, List<Element> err_el); \n}    // XMPPIOServiceListener\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPImplIfc.java",
    "content": "/*\n * XMPPImplIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Set;\nimport tigase.server.ComponentInfo;\nimport tigase.server.ServerComponent;\n\n/**\n * This is a base interface for all session manager plugins. There are packet\n * processing plugins, pre-processing, post-processing and packet filters. They all\n * have a common basic methods which are defined here.\n *\n *\n * Created: Sat Oct 14 16:11:22 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPImplIfc\n\t\t\t\textends Comparable<XMPPImplIfc> {\n\t/** Field description */\n\tpublic static final String CLIENT_XMLNS = \"jabber:client\";\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * By default the method uses {@link #supElementNamePaths() } and\n\t * {@link #supTypes() } method results to determine whether the plugin would process\n\t * given packet. However, a plugin can implement own logic to determine packet\n\t * processing capabilities or conditions. Please note, this method must be very fast\n\t * and efficient. No I/O processing is recommended as it may impact performance of\n\t * the whole system.\n\t *\n\t *\n\t * @param packet is a <code>Packet</code> for processing.\n\t * @param conn is a user session object or null.\n\t *\n\t * @return returns <code>Authorization</code> enum value or null. Null means the\n\t * plugin is simply not processing the packet. {@link Authorization#AUTHORIZED} means\n\t * the plugin can process the packet, any other {@link Authorization} enum value\n\t * means an error which has to be returned to the sender.\n\t */\n\tAuthorization canHandle(Packet packet, XMPPResourceConnection conn);\n\n\t/**\n\t * Methods returns a preferable number of threads/packets queues for the plugin.\n\t * This number can be overwritten through configuration settings, however, a default\n\t * value should be reasonably good for most standard installations.\n\t * It is recommended to assign at least as much as twice a number of CPUs cores for I/O\n\t * bound processing and number a number equal to CPUs cores for fast processing not\n\t * slowed down by any I/O.\n\t *\n\t *\n\t * @return an integer preferred number of processing threads for the plugin.\n\t */\n\tdefault int concurrentQueuesNo() {\n\t\treturn Runtime.getRuntime().availableProcessors();\n\t}\n\n\t/**\n\t * Number of threads per single packets queue. Not used anymore. At the moment only\n\t * one thread is always used for each queue. For a higher concurrency set more queues\n\t * using {@link #concurrentQueuesNo() }.\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>int</code>\n\t */\n\t@Deprecated\n\tint concurrentThreadsPerQueue();\n\n\t/**\n\t * Method <code>id</code> returns a unique ID of the plugin. Each plugin has\n\t * own, unique ID which is used in the configuration file to determine whether\n\t * it needs to be loaded or not. In most cases the ID can be equal to XMLNS of\n\t * the packages processed by the plugin.\n\t *\n\t * @return a <code>String</code> value\n\t */\n\tString id();\n\n\t/**\n\t * Method <code>init</code> is called just after the plugin has been loaded\n\t * into memory. The idea behind this is to allow it to initialize or check the\n\t * database. This might be especially useful for plugins which want to have a\n\t * database access via non-standard stored procedures or need schema upgrade.\n\t *\n\t * @param settings\n\t *          is a Map with initial processor settings from the configuration\n\t *          file.\n\t * @throws TigaseDBException\n\t */\n\tvoid init(Map<String, Object> settings) throws TigaseDBException;\n\n\t/**\n\t * Method <code>supDiscoFeatures</code> returns an array of XML\n\t * <code>Element</code>s with service discovery features which have to be\n\t * returned to the client uppon request. Service discovery features returned\n\t * by this method correspond to services supported by this plugin.\n\t *\n\t * @param session\n\t *          a <code>XMPPResourceConnection</code> value\n\t * @return an <code>Element[]</code> value\n\t */\n\tElement[] supDiscoFeatures(XMPPResourceConnection session);\n\n\t/**\n\t * Method <code>supElementNamePaths</code> returns an array of element\n\t * names in form of a full path to the XML element for\n\t * stanzas which can be processed by this plugin. Each element name path\n\t * corresponds to XMLNS returned in array by <code>supNamespaces()</code>\n\t * method. The element path itself is represented by a String array with each path\n\t * element as a separate String.\n\t *\n\t * @return a <code>String[][]</code> value is an array for element paths for which\n\t * the plugin offers processing capabilities. Each path is in form of a String array\n\t * in order to reduce parsing overhead.\n\t */\n\tString[][] supElementNamePaths();\n\n\t/**\n\t * Method <code>supElements</code> returns an array of element names for\n\t * stanzas which can be processed by this plugin. Each element name\n\t * corresponds to XMLNS returned in array by <code>supNamespaces()</code>\n\t * method.\n\t * This method has been deprecated in favor of <code>supElementNamePaths</code>.\n\t *\n\t * @return a <code>String[]</code> value\n\t * @see #supElementNamePaths\n\t */\n\t@Deprecated\n\tString[] supElements();\n\n\t/**\n\t * Method <code>supNamespaces</code> returns an array of name-spaces for\n\t * stanzas which can be processed by this plugin. Each namespace\n\t * corresponds to element name returned in array by\n\t * <code>supElemenets()</code> method.\n\t *\n\t * @return a <code>String[]</code> value\n\t */\n\tString[] supNamespaces();\n\n\t/**\n\t * Method <code>supStreamFeatures</code> returns an array of XML\n\t * <code>Element</code>s with stream features which have to be returned to the\n\t * client uppon request. Stream features returned by this method correspond to\n\t * features supported by this plugin.\n\t *\n\t * @param session\n\t *          a <code>XMPPResourceConnection</code> value\n\t * @return an <code>Element[]</code> value\n\t */\n\tElement[] supStreamFeatures(XMPPResourceConnection session);\n\n\t/**\n\t * Method returns an array of all stanza types which the plugin is able\n\t * to handle. If the method returns NULL, then all stanzas of all types\n\t * will be passed to the plugin for processing.\n\t * Otherwise only stanzas with selected types, assuming that\n\t * element names and name-spaces match as well.\n\t *\n\t *\n\t * @return a <code>StanzaType[]</code> array of supported stanza types.\n\t */\n\tSet<StanzaType> supTypes();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Allows to obtain various informations about components\n\t *\n\t * @return information about particular component\n\t */\n\tComponentInfo getComponentInfo();\n\t/**\n\t * The method allows to retrieve plugin own statistics if it generates any.\n\t * @param list is a statistics collection to which plugins own metrics can be added.\n\t */\n\tvoid getStatistics(StatisticsList list);\n\n\t/**\n\t * Method <code>isSupporting</code> takes element name and name-space for this\n\t * element and determines whether this element can be processed by this\n\t * plugin.\n\t *\n\t * @param elem\n\t *          a <code>String</code> value\n\t * @param ns\n\t *          a <code>String</code> value\n\t * @return a <code>boolean</code> value\n\t */\n\t@Deprecated\n\tboolean isSupporting(String elem, String ns);\n}    // XMPPImplIfc\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPPacketFilterIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n\n/**\n * Created: Dec 30, 2008 12:53:16 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPPacketFilterIfc extends XMPPImplIfc {\n\tvoid filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results);\n}\n\n\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPParserException.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n/**\n * Describe class XMPPParserException here.\n *\n *\n * Created: Tue Oct  9 13:41:43 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class XMPPParserException extends RuntimeException {\n\n  private static final long serialVersionUID = 1L;\n\n  /**\n   * Creates a new <code>XMPPParserException</code> instance.\n   *\n   */\n  public XMPPParserException(String message) { super(message); }\n\n  public XMPPParserException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPPostprocessorIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n/**\n * Describe interface XMPPPostprocessorIfc here.\n *\n *\n * Created: Sat Oct 14 17:41:09 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPPostprocessorIfc extends XMPPImplIfc {\n\n\t/**\n\t * Performs processing of\n\t * <code>packet</code> for which there was no processor.\n\t *\n\t * @param packet   packet is which being processed. This parameter may never\n\t *                 be null. Even though this is not immutable object it\n\t *                 mustn't be altered. None of it's fields or attributes can\n\t *                 be changed during processing.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data. It allows\n\t *                 for storing information in a permanent storage or in memory\n\t *                 only during the live of the online session. This parameter\n\t *                 can be null if there is no online user session at the time\n\t *                 of the packet processing.\n\t * @param repo     this is a user data storage which is normally used when the\n\t *                 user session (parameter above) is null. This is repository\n\t *                 allows for a very restricted access only. It allows for\n\t *                 storing some user private data (doesn't allow overwriting\n\t *                 existing data) like messages for offline users and it also\n\t *                 allows for reading user public data like VCard.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results. Regardless a response to a\n\t *                 user request is sent or the packet is forwarded to it's\n\t *                 destination it is always required that a copy of the input\n\t *                 packet is created and stored in the results queue.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration. In most cases it is unused,\n\t *                 however if the plugin needs to access an external database\n\t *                 that this is a way to pass database connection string to\n\t *                 the plugin.\n\t */\n\tvoid postProcess( Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\t\t\t\t\t\t\t\tQueue<Packet> results, Map<String, Object> settings );\n}    // XMPPPostprocessorIfc\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPPreprocessorIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n/**\n * Describe interface XMPPPreprocessorIfc here.\n *\n *\n * Created: Sat Oct 14 16:16:50 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPPreprocessorIfc extends XMPPImplIfc {\n\n\t/**\n\t * Performs pre-processing of\n\t * <code>packet</code>. Intention for the pre-processors is to allow them for\n\t * packet blocking.\n\t *\n\t * @param packet   packet is which being processed. This parameter may never\n\t *                 be null. Even though this is not immutable object it\n\t *                 mustn't be altered. None of it's fields or attributes can\n\t *                 be changed during processing.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data. It allows\n\t *                 for storing information in a permanent storage or in memory\n\t *                 only during the live of the online session. This parameter\n\t *                 can be null if there is no online user session at the time\n\t *                 of the packet processing.\n\t * @param repo     this is a user data storage which is normally used when the\n\t *                 user session (parameter above) is null. This is repository\n\t *                 allows for a very restricted access only. It allows for\n\t *                 storing some user private data (doesn't allow overwriting\n\t *                 existing data) like messages for offline users and it also\n\t *                 allows for reading user public data like VCard.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results. Regardless a response to a\n\t *                 user request is sent or the packet is forwarded to it's\n\t *                 destination it is always required that a copy of the input\n\t *                 packet is created and stored in the results queue.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration. In most cases it is unused,\n\t *                 however if the plugin needs to access an external database\n\t *                 that this is a way to pass database connection string to\n\t *                 the plugin.\n\t *\n\t * @return the pre-processing result; if the value is ‘true’ then the packet\n\t *         is blocked and no further processing is performed.\n\t */\n\tboolean preProcess( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings );\n}    // XMPPPreprocessorIfc\n//~ Formatted in Sun Code Convention\n\n\n//~ Formatted by Jindent --- http://www.jindent.com\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPPresenceUpdateProcessorIfc.java",
    "content": "/*\n * To change this template, choose Tools | Templates\n * and open the template in the editor.\n */\npackage tigase.xmpp;\n\nimport java.util.Queue;\nimport tigase.server.Packet;\n\n/**\n *\n * @author andrzej\n */\npublic interface XMPPPresenceUpdateProcessorIfc {\n\t\n\tvoid presenceUpdate(XMPPResourceConnection session, Packet packet, Queue<Packet> results) throws NotAuthorizedException;\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPProcessor.java",
    "content": "/*\n * XMPPProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collection;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Set;\nimport tigase.server.ComponentInfo;\n\n/**\n * <code>XMPPProcessor</code> abstract class contains basic definition for\n * <em>XMPP</em> processor.\n * To create new processor implementing particular <em>XMPP</em> functionality\n * it is enough to extend this class and implement one abstract method.<br>\n * Additionally to allow system properly recognise this processor you need also\n * to implement own constructor which sets proper values to parent constructor.\n * You must implement exactly one constructor with zero parameters which calls\n * parent constructor with proper values. Refer to constructor documentation\n * for information about required parameters.<br>\n * To fully interact with entity connected to the session or with other entities\n * in <em>XMPP</em> network you should be also familiar with\n * <code>addReply(...)</code>, <code>addMessage(...)</code> and\n * <code>addBroadcast(...)</code> methods.<br>\n * There is also partially implemented functionality to send messages to entities\n * in other networks like <em>SMTP</em> or other implemented by the server.\n * Once this implementation is finished there will be more information available.\n * If you, however, are interested in this particular feature send a question\n * to author.\n *\n * <p>\n * Created: Tue Oct  5 20:31:23 2004\n * </p>\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class XMPPProcessor\n\t\t\t\timplements XMPPImplIfc {\n\t/** Field description */\n\tprotected static final String ALL_NAMES = \"*\";\n\n\t/** Field description */\n\tprotected static final String[][] ALL_PATHS = {\n\t\t{ \"*\" }\n\t};\n\tprotected static ComponentInfo cmpInfo = null;\n\n\t{\n\t\tcmpInfo = new ComponentInfo( id(), this.getClass() );\n\t}\n\n\t/**\n\t * Variable <code>log</code> is a class logger.\n\t */\n\tprivate static final Logger log = Logger.getLogger(XMPPProcessor.class.getName());\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tprotected XMPPProcessor() {}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Authorization canHandle(Packet packet, XMPPResourceConnection conn) {\n\t\tAuthorization result    = null;\n\t\tString[][]    elemPaths = supElementNamePaths();\n\n\t\tif (elemPaths != null) {\n\n\t\t\t// This is the new API style\n\t\t\tString[]        elemXMLNS = supNamespaces();\n\t\t\tSet<StanzaType> types     = supTypes();\n\n\t\t\tresult = checkPacket(packet, elemPaths, elemXMLNS, types);\n\t\t} else {\n\n\t\t\t// And this is the old API left for backward compatibility with plugins\n\t\t\t// from earlier versions\n\t\t\tif (walk(packet.getElement())) {\n\t\t\t\tresult = Authorization.AUTHORIZED;\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"XMPPProcessorIfc: {0} ({1})\\n Request: \" +\n\t\t\t\t\t\"{2}, conn: {3}, authorization: {4}\", new Object[] { this.getClass()\n\t\t\t\t\t.getSimpleName(),\n\t\t\t\t\tid(), packet, conn, result });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic final int compareTo(XMPPImplIfc proc) {\n\t\treturn getClass().getName().compareTo(proc.getClass().getName());\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic int concurrentThreadsPerQueue() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn null;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic String[] supElements() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Set<StanzaType> supTypes() {\n\t\treturn null;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * \n\t */\n\tpublic XMPPProcessor getInstance() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {}\n\n\t@Override\n\tpublic ComponentInfo getComponentInfo() {\n\t\tif ( cmpInfo == null ){\n\t\t\tcmpInfo = new ComponentInfo( id(), this.getClass() );\n\t\t}\n\t\treturn cmpInfo;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn id() + getComponentInfo();\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic boolean isSupporting(final String element, final String ns) {\n\t\tString[] impl_elements = supElements();\n\t\tString[] impl_xmlns    = supNamespaces();\n\n\t\tif ((impl_elements != null) && (impl_xmlns != null)) {\n\t\t\tfor (int i = 0; (i < impl_elements.length) && (i < impl_xmlns.length); i++) {\n\n\t\t\t\t// ******   WARNING!!!! WARNING!!!!    *****\n\t\t\t\t// This is intentional reference comparison!\n\t\t\t\t// This method is called very, very often and it is also very expensive\n\t\t\t\t// therefore all XML element names and xmlns are created using\n\t\t\t\t// String.intern()\n\t\t\t\tif (((impl_elements[i] == element) || (impl_elements[i] == ALL_NAMES)) &&\n\t\t\t\t\t\t((impl_xmlns[i] == ns) || (impl_xmlns[i] == ALL_NAMES))) {\n\t\t\t\t\treturn true;\n\t\t\t\t}    // end of if (ELEMENTS[i].equals(element) && XMLNSS[i].equals(ns))\n\t\t\t}      // end of for (int i = 0; i < ELEMENTS.length; i++)\n\t\t}        // end of if (impl_elements != null && impl_xmlns != null)\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate Authorization checkPacket(Packet packet, String[][] elemPaths,\n\t\t\tString[] elemXMLNS, Set<StanzaType> types) {\n\t\tAuthorization result   = null;\n\t\tboolean       names_ok = elemPaths == ALL_PATHS;\n\n\t\tif (!names_ok) {\n\t\t\tfor (int i = 0; i < elemPaths.length; i++) {\n\t\t\t\tif (packet.isXMLNSStaticStr(elemPaths[i], elemXMLNS[i])) {\n\t\t\t\t\tnames_ok = true;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (names_ok && ((types == null) || types.contains(packet.getType()))) {\n\t\t\tresult = Authorization.AUTHORIZED;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate boolean walk(Element elem) {\n\t\tboolean result;\n\t\tString  xmlns = elem.getXMLNS();\n\n\t\tif (xmlns == null) {\n\t\t\txmlns = \"jabber:client\";\n\t\t}\n\t\tresult = isSupporting(elem.getName(), xmlns);\n\t\tif (!result) {\n\t\t\tCollection<Element> children = elem.getChildren();\n\n\t\t\tif (children != null) {\n\t\t\t\tfor (Element child : children) {\n\t\t\t\t\tresult = walk(child);\n\t\t\t\t}    // end of for (Element child: children)\n\t\t\t}      // end of if (children != null)\n\t\t}\n\n\t\treturn result;\n\t}\n}    // XMPPProcessor\n\n\n//~ Formatted in Tigase Code Convention on 13/04/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPProcessorAbstract.java",
    "content": "/*\n * XMPPProcessorAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Message;\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor;\n\n/**\n * Utility abstract class detecting what kind of packet is processed. Releases developers from\n * checking whether the packet is addressed to the user of the session or from the user\n * of the sesion or packet to the server itself.\n *\n * Created: Mar 1, 2010 10:21:29 AM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class XMPPProcessorAbstract\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final Logger log = Logger.getLogger(XMPPProcessorAbstract.class\n\t\t\t.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\ttry {\n\t\t\tif (session == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processNullSessionPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessNullSessionPacket(packet, repo, results, settings);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.isServerSession()) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processServerSessionPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessServerSessionPacket(packet, session, repo, results, settings);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tJID connectionId = session.getConnectionId();\n\n\t\t\t\tif (connectionId.equals(packet.getPacketFrom())) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\t\tnew Object[] { \"processFromUserPacket\",\n\t\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t\t}\n\t\t\t\t\tprocessFromUserPacket(connectionId, packet, session, repo, results, settings);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"This should not happen, this is not a server session and \" +\n\t\t\t\t\t\t\"still connection id is not set: \" + session + \", packet: \" + packet, ex);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (session.isUserId(packet.getStanzaTo().getBareJID())) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\t\tnew Object[] { \"processToUserPacket\",\n\t\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t\t}\n\t\t\t\t\tprocessToUserPacket(packet, session, repo, results, settings);\n\t\t\t\t}\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"Packet to a user session which is not yet authenticated: \" + session +\n\t\t\t\t\t\t\", packet: \" + packet);\n\t\t\t}\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tlog.info(\"Attempt to send an error response to the error packet: \" + packet +\n\t\t\t\t\t\", session: \" + session + \", plugin: \" + id());\n\t\t}\n\t}\n\n\t/**\n\t * The method is called when a packet is sent from the user, owner of the session\n\t * somewhere else to other XMPP entity (other user on the server, other user on a\n\t * different server, different server, component, transport, etc....).\n\t * The default implementation just forwards the packet doing nothing else, which is good\n\t * enough in most cases. You can overwrite the method to change the default behaviour.\n\t *\n\t *\n\t * @param connectionId is a <code>JID</code> instance with the session connection ID.\n\t * @param session is a <code>XMPPResourceConnection</code> instance with all the sending\n\t * user session data.\n\t * @param packet is a <code>Packet</code> sent by the user.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic void processFromUserOutPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tresults.offer(packet.copyElementOnly());\n\t}\n\n\t/**\n\t * The method is called for all packets sent by the user, owner of this connection/session.\n\t * Please note, it is likely that a user sends a packet addressed to his own server, like\n\t * get server version information. In such a case only this method is called. Such a packet\n\t * is not later passed to the <code>processServerSessionPacket(...)</code>.\n\t * Note, the default implementation checks whether the packet is addressed to the server\n\t * or is being sent to another XMPP entity. In the first case it calls\n\t * <code>processFromUserToServerPacket(...)</code> method, otherwise it calls\n\t * <code>processFromUserOutPacket</code>. You can overwrite the method to change\n\t * the default behavior or implement the two called methods to handle each case\n\t * separately.\n\t *\n\t *\n\t * @param connectionId is a <code>JID</code> instance with the session connection ID.\n\t * @param session is a <code>XMPPResourceConnection</code> instance with all the sending\n\t * user session data.\n\t * @param packet is a <code>Packet</code> sent by the user.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic void processFromUserPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\ttry {\n\n\t\t\t// Check whether the packet is addressed to the server or some other, XMPP entity\n\t\t\tif ((packet.getStanzaTo() == null) || session.isLocalDomain(packet.getStanzaTo()\n\t\t\t\t\t.toString(), false) || session.isUserId(packet.getStanzaTo().getBareJID())) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processFromUserToServerPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessFromUserToServerPacket(connectionId, packet, session, repo, results,\n\t\t\t\t\t\tsettings);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processFromUserOutPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessFromUserOutPacket(connectionId, packet, session, repo, results, settings);\n\t\t\t}\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\tlog.info(\"Session not yet authorized to send ping requests: \" + session +\n\t\t\t\t\t\", packet: \" + packet);\n\t\t}\n\t}\n\n\t/**\n\t * The method is called when a packet is send from the user who is owner of the session\n\t * to the local server (ping, roster management, privacy lists, etc...). There is no default\n\t * implementation for the method.\n\t *\n\t *\n\t * @param connectionId is a <code>JID</code> instance with the session connection ID.\n\t * @param session is a <code>XMPPResourceConnection</code> instance with all the sending\n\t * user session data.\n\t * @param packet is a <code>Packet</code> sent by the user.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic abstract void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException;\n\n\t/**\n\t * The method is called for packets received by the server for which no user session\n\t * is found - neither sender session or receiver session. The default implementation does\n\t * nothing, just ignores such a packet. To change the default behaviour the method\n\t * has to be overwritten.\n\t *\n\t *\n\t * @param packet is a <code>Packet</code> received by the server.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\n\t\t// Do nothing, which is a correct thing to do in most cases.\n\t}\n\n\t/**\n\t * The method is called when a packet addressed to the server domain is received. Please\n\t * note, if a local user sends a packet to the server, the packet is handled by the\n\t * <code>processFromUserPacket(...)</code> method. This method is not called for such\n\t * packets.\n\t *\n\t *\n\t * @param session is a <code>XMPPResourceConnection</code> instance with all the server\n\t * session data.\n\t * @param packet is a <code>Packet</code> received by the server and addressed to the\n\t * server - the server virtual domain name.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic abstract void processServerSessionPacket(Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException;\n\n\t/**\n\t * Method is called for all the packets sent TO the user - owner of the session. The default\n\t * implementation just forwards the packet to the user connection. To change the default\n\t * behavior the method has to be overwritten.\n\t *\n\t *\n\t * @param session is a <code>XMPPResourceConnection</code> instance with all the receiving\n\t * user session data.\n\t * @param packet is a <code>Packet</code> received by the server and addressed to the\n\t * server - the server virtual domain name.\n\t * @param repo is a <code>NonAuthUserRepository</code> instance giving access to a part\n\t * of the user repository which is accessible regardless the session is authenticated or not.\n\t * @param results is a packets <code>Queue</code> with all the processing results from\n\t * the plugin.\n\t * @param settings is a <code>Map</code> with all the configuration settings passed to the\n\t * plugin.\n\t * @throws PacketErrorTypeException on attempt to send an error response to the error\n\t * packet.\n\t */\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\ttry {\n\n\t\t\tList<XMPPResourceConnection> conns    = new ArrayList<XMPPResourceConnection>(5);\n\t\t\tString                       resource = packet.getStanzaTo().getResource();\n\n\t\t\tif ((resource == null) && (packet.getElemName() == Message.ELEM_NAME)) {\n\t\t\t\tconns.addAll(session.getActiveSessions());\n\t\t\t} else {\n\t\t\t\tXMPPResourceConnection con = session.getParentSession().getResourceForResource(\n\t\t\t\t\t\tresource);\n\n\t\t\t\tif (con != null) {\n\t\t\t\t\tconns.add(con);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (conns.size() > 0) {\n\t\t\t\tfor (XMPPResourceConnection con : conns) {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\tresult.setPacketTo(con.getConnectionId());\n\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Delivering packet: {0}, to session: {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\t\t\tcon });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tPacket result = Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\"The recipient is no longer available.\", true);\n\n\t\t\t\tresult.setPacketFrom(null);\n\t\t\t\tresult.setPacketTo(null);\n\t\t\t\tresults.offer(result);\n\t\t\t}\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t} catch (NoConnectionIdException ex) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"This should not happen, this is not a server session and \" +\n\t\t\t\t\t\"still connection id is not set: \" + session + \", packet: \" + packet, ex);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/05/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPProcessorIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\nimport java.util.Queue;\nimport java.util.Map;\nimport tigase.server.Packet;\nimport tigase.db.NonAuthUserRepository;\n\n/**\n * Describe interface XMPPProcessorIfc here.\n *\n *\n * Created: Wed Feb 8 13:47:56 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPProcessorIfc extends XMPPImplIfc {\n\n\t/**\n\t * @param packet   packet is which being processed. This parameter may never\n\t *                 be null. Even though this is not immutable object it\n\t *                 mustn't be altered. None of it's fields or attributes can\n\t *                 be changed during processing.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data. It allows\n\t *                 for storing information in a permanent storage or in memory\n\t *                 only during the live of the online session. This parameter\n\t *                 can be null if there is no online user session at the time\n\t *                 of the packet processing.\n\t * @param repo     this is a user data storage which is normally used when the\n\t *                 user session (parameter above) is null. This is repository\n\t *                 allows for a very restricted access only. It allows for\n\t *                 storing some user private data (doesn't allow overwriting\n\t *                 existing data) like messages for offline users and it also\n\t *                 allows for reading user public data like VCard.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results. Regardless a response to a\n\t *                 user request is sent or the packet is forwarded to it's\n\t *                 destination it is always required that a copy of the input\n\t *                 packet is created and stored in the results queue.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration. In most cases it is unused,\n\t *                 however if the plugin needs to access an external database\n\t *                 that this is a way to pass database connection string to\n\t *                 the plugin.\n\t *\n\t * @throws XMPPException\n\t */\n\tvoid process( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results,\n\t\t\t\t\t\t\t\tMap<String, Object> settings ) throws XMPPException;\n} // XMPPProcessorIfc\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPResourceConnection.java",
    "content": "/*\n * XMPPResourceConnection.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.AuthorizationException;\nimport tigase.db.AuthRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserRepository;\nimport tigase.server.Presence;\nimport tigase.server.XMPPServer;\nimport tigase.server.xmppsession.SessionManager;\nimport tigase.server.xmppsession.SessionManagerHandler;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\n\n\n\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.function.Function;\n\n/**\n * Describe class XMPPResourceConnection here.\n *\n *\n * Created: Wed Feb 8 22:30:37 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class XMPPResourceConnection\n\t\t\t\textends RepositoryAccess {\n\t/** Field description */\n\tpublic static final String ALL_RESOURCES_CAPS_KEY = \"caps\";\n\n\t/** Field description */\n\tpublic static final String ALL_RESOURCES_KEY = \"all-resources\";\n\n\t/** Field description */\n\tpublic static final String ALL_RESOURCES_PRIORITY_KEY = \"priority\";\n\n\t/** Field description */\n\tpublic static final String AUTHENTICATION_TIMEOUT_KEY = \"authentication-timeout\";\n\n\t/** Field description */\n\tpublic static final String CLOSING_KEY = \"closing-conn\";\n\n\t/** Field description */\n\tpublic static final String ERROR_KEY = \"error-key\";\n\n\t/**\n\t * Constant <code>PRESENCE_KEY</code> is a key in temporary session data where\n\t * the last presence sent by the user to server is stored, either initial\n\t * presence or off-line presence before disconnecting.\n\t */\n\tpublic static final String PRESENCE_KEY = \"user-presence\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(XMPPResourceConnection.class\n\t\t\t.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate long authenticationTime = 0;\n\n\t/**\n\t * This variable is to keep relates XMPPIOService ID only.\n\t */\n\tprivate JID    connectionId    = null;\n\tprivate String connectionState = null;\n\tprivate long   creationTime    = 0;\n\tprivate String defLang         = \"en\";\n\tprivate long   id_counter      = 0;\n\n\t/**\n\t * Value of <code>System.currentTimeMillis()</code> from the time when this\n\t * session last active from user side.\n\t */\n\tprivate long                  lastAccessed    = 0;\n\tprivate SessionManagerHandler loginHandler    = null;\n\tprivate long                  packets_counter = 0;\n\tprivate XMPPSession           parentSession   = null;\n\tprivate int                   priority        = 0;\n\n\t/**\n\t * Session resource - part of user's JID for this session\n\t */\n\tprivate String resource = null;\n\n\t/**\n\t * Session temporary data. All data stored in this <code>Map</code> disappear\n\t * when session finishes.\n\t */\n\tprivate Map<String, Object> sessionData = null;\n\n\t/**\n\t * <code>sessionId</code> keeps XMPP stream session ID given at connection\n\t * initialization time.\n\t */\n\tprivate String  sessionId  = null;\n\tprivate boolean tmpSession = false;\n\tprivate JID     userJid    = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>XMPPResourceConnection</code> instance.\n\t *\n\t *\n\t * @param connectionId\n\t * @param rep\n\t * @param authRepo\n\t * @param loginHandler\n\t */\n\tpublic XMPPResourceConnection(JID connectionId, UserRepository rep,\n\t\t\tAuthRepository authRepo, SessionManagerHandler loginHandler) {\n\t\tsuper(rep, authRepo);\n\n\t\tlong currTime = System.currentTimeMillis();\n\n\t\tthis.connectionId = connectionId;\n\t\tthis.loginHandler = loginHandler;\n\t\tthis.creationTime = currTime;\n\t\tthis.lastAccessed = currTime;\n\t\tsessionData       = new ConcurrentHashMap<String, Object>(4, 0.9f);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param anonymous\n\t * @throws TigaseStringprepException \n\t */\n\tpublic void authorizeJID(BareJID jid, boolean anonymous) throws TigaseStringprepException {\n\t\tauthState = Authorization.AUTHORIZED;\n\t\tis_anonymous = anonymous;\n\t\tif (jid != null && getDomain().getVhost() != null && !jid.getDomain().equals(getDomain().getVhost().getDomain())) {\n\t\t\tloginHandler.handleDomainChange(jid.getDomain(), this);\n\t\t}\n\t\tloginHandler.handleLogin(jid, this);\n//\t\tif (jid != null && getDomain().getVhost() != null && !jid.getDomain().equals(getDomain().getVhost().getDomain())) {\n//\t\t\tif (log.isLoggable(Level.INFO)) {\n//\t\t\t\tlog.log(Level.INFO, \"Replacing session VHost: {0} instead of {1}\", new Object[] { jid.getDomain(),\n//\t\t\t\t\t\tgetDomain().getVhost().getDomain() });\n//\t\t\t}\n//\t\t\tthis.userJid = JID.jidInstanceNS(jid.getLocalpart(), jid.getDomain(), this.userJid.getResource());\n//\t\t\tSessionManager sessMan = (SessionManager) XMPPServer.getConfigurator().getComponent(\"sess-man\");\n//\t\t\tVHostItem vHostItem = sessMan.getVHostItem(this.userJid.getDomain());\n//\t\t\tif (vHostItem == null) {\n//\t\t\t\tif (log.isLoggable(Level.INFO)) {\n//\t\t\t\t\tlog.log(Level.INFO, \"Can't get VHostItem for domain: {0}, using default one instead: {1}\", new Object[] {\n//\t\t\t\t\t\t\tdomain, sessMan.getDefHostName() });\n//\t\t\t\t}\n//\t\t\t\tvHostItem = new VHostItem(sessMan.getDefHostName().getDomain());\n//\t\t\t}\n//\t\t\tsetDomain(vHostItem.getUnmodifiableVHostItem());\n//\t\t}\n\t\tlogin();\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method checks if in {@code parentSession} in session data there is value\n\t * for passed {@code key} and returns it if exists. If not then it uses\n\t * passed {@code valueFactory} to generate value and sets it in\n\t * {@code parentSession} in session data under passed {@code key} and\n\t * returns newly set value\n\t *\n\t * @param key\n\t * @param valueFactory\n\t * @return \n\t */\n\tpublic Object computeCommonSessionDataIfAbsent(String key, Function<String,Object> valueFactory) {\n\t\tif (parentSession != null) {\n\t\t\treturn parentSession.computeCommonSessionDataIfAbsent(key, valueFactory);\n\t\t}\n\t\treturn valueFactory.apply(key);\n\t}\n\t\n\t/**\n\t * Method checks if in session data is value for passed {@code key} and\n\t * returns it if exists. If not then it uses passed {@code valueFactory} to\n\t * generate value and sets it in session data under passed {@code key} and\n\t * returns newly set value\n\t *\n\t * @param key\n\t * @param valueFactory\n\t * @return\n\t */\t\n\tpublic Object computeSessionDataIfAbsent(String key, Function<String,Object> valueFactory) {\n\t\tlastAccessed = System.currentTimeMillis();\n\t\treturn sessionData.computeIfAbsent(key, valueFactory);\n\t}\n\t\n\t/**\n\t * Returns full user JID for this session without throwing the\n\t * <code>NotAuthorizedException</code> exception if session is not authorized\n\t * yet and therefore user name and resource is not known yet. Please note this\n\t * method is for logging using only to avoid excessive use of try/catch for\n\t * debugging code. It may return null.\n\t *\n\t * @return a <code>String</code> value of calculated user full JID for this\n\t *         session including resource name.\n\t */\n\tpublic final JID getjid() {\n\t\treturn userJid;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void incPacketsCounter() {\n\t\t++packets_counter;\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param digest\n\t * @param id\n\t * @param alg\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws AuthorizationException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws TigaseStringprepException\n\t */\n\t@Deprecated\n\tpublic final Authorization loginDigest(String user, String digest, String id,\n\t\t\tString alg)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException,\n\t\t\t\t\t\t\tTigaseStringprepException {\n\t\tBareJID       userId = BareJID.bareJIDInstance(user, getDomain().getVhost()\n\t\t\t\t.getDomain());\n\t\tAuthorization result = super.loginDigest(userId, digest, id, alg);\n\n\t\tif (result == Authorization.AUTHORIZED) {\n\t\t\tloginHandler.handleLogin(userId, this);\n\t\t}    // end of if (result == Authorization.AUTHORIZED)\n\n\t\treturn result;\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic final Authorization loginOther(Map<String, Object> props)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException {\n\t\tAuthorization result = super.loginOther(props);\n\n\t\tif (result == Authorization.AUTHORIZED) {\n\t\t\tBareJID user = (BareJID) props.get(AuthRepository.USER_ID_KEY);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"UserAuthRepository.USER_ID_KEY: \" + user);\n\t\t\t}\n\t\t\tloginHandler.handleLogin(user, this);\n\t\t}    // end of if (result == Authorization.AUTHORIZED)\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param user\n\t * @param password\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Authorization</code>\n\t * @throws AuthorizationException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws TigaseStringprepException\n\t */\n\t@Deprecated\n\tpublic final Authorization loginPlain(String user, String password)\n\t\t\t\t\tthrows NotAuthorizedException, AuthorizationException, TigaseDBException,\n\t\t\t\t\t\t\tTigaseStringprepException {\n\t\tBareJID       userId = BareJID.bareJIDInstance(user, getDomain().getVhost()\n\t\t\t\t.getDomain());\n\t\tAuthorization result = super.loginPlain(userId, password);\n\n\t\tif (result == Authorization.AUTHORIZED) {\n\t\t\tloginHandler.handleLogin(userId, this);\n\t\t}    // end of if (result == Authorization.AUTHORIZED)\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic final void logout() throws NotAuthorizedException {\n\t\tloginHandler.handleLogout(getBareJID(), this);\n\t\tstreamClosed();\n\t\tsuper.logout();\n\t}\n\n\t// public boolean isDummy() {\n\t// return dummy;\n\t// }\n\t// public void setDummy(boolean dummy) {\n\t// this.dummy = dummy;\n\t// }\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String nextStanzaId() {\n\t\treturn \"tig\" + (++id_counter);\n\t}\n\n\t/**\n\t * Method sets passed value under passed key in common sessionData kept\n\t * in parentSession\n\t *\n\t * @param key\n\t * @param value\n\t */\n\tpublic void putCommonSessionData(String key, Object value) {\n\t\tif (parentSession != null) {\n\t\t\tparentSession.putCommonSessionData(key, value);\n\t\t}\n\t}\n\t\n\t/**\n\t * Method sets passed value under passed {@code key} in common {@code sessionData} kept\n\t * in {@code parentSession} but only if there is no value for this {@code key} already\n\t *\n\t * @param key\n\t * @param value\n\t * @return previous value\n\t */\n\tpublic Object putCommonSessionDataIfAbsent(String key, Object value) {\n\t\tif (parentSession != null) {\n\t\t\treturn parentSession.putCommonSessionDataIfAbsent(key, value);\n\t\t}\n\t\treturn null;\n\t}\n\n\t// public void setOnHold() {\n\t// onHold = true;\n\t// }\n\t// public boolean isOnHold() {\n\t// return onHold;\n\t// }\n\n\t/**\n\t * Saves given session data. Data are saved to temporary storage only and are\n\t * accessible during this session life only and only from this session\n\t * instance.<br>\n\t * Any <code>Object</code> can be stored and retrieved through\n\t * <code>getSessionData(...)</code>.<br>\n\t * To access permanent storage to keep data between session instances you must\n\t * use one of <code>get/setData...(...)</code> methods familly. They gives you\n\t * access to hierachical permanent data base. Permanent data base however can\n\t * be accessed after successuf authorization while session storage is availble\n\t * all the time.\n\t *\n\t * @param key\n\t *          a <code>String</code> value of stored data key ID.\n\t * @param value\n\t *          a <code>Object</code> value of data stored in session.\n\t * @see #getSessionData(String)\n\t */\n\tpublic final void putSessionData(final String key, final Object value) {\n\t\tlastAccessed = System.currentTimeMillis();\n\t\tsessionData.put(key, value);\n\t}\n\n\t/**\n\t * Method sets passed value under passed {@code key} in {@code sessionData} \n\t * but only if there is no value for this {@code key} already\n\t *\n\t * @param key\n\t * @param value\n\t * @return previous value\n\t */\n\tpublic Object putSessionDataIfAbsent(String key, Object value) {\n\t\tlastAccessed = System.currentTimeMillis();\n\t\treturn sessionData.putIfAbsent(key, value);\n\t}\t\n\t\n\t@Override\n\tpublic void queryAuth(Map<String, Object> authProps) throws TigaseDBException {\n\t\tsuper.queryAuth(authProps);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t *\n\t *\n\t *\n\t * @return a value of <code>Object</code>\n\t */\n\tpublic Object removeCommonSessionData(String key) {\n\t\treturn (parentSession == null)\n\t\t\t\t? null\n\t\t\t\t: parentSession.removeCommonSessionData(key);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param parent\n\t */\n\tpublic void removeParentSession(final XMPPSession parent) {\n\t\tsynchronized (this) {\n\t\t\tparentSession = null;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param key\n\t */\n\tpublic final void removeSessionData(final String key) {\n\t\tlastAccessed = System.currentTimeMillis();\n\t\tsessionData.remove(key);\n\t}\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t */\n\tpublic void streamClosed() {\n\t\tsynchronized (this) {\n\t\t\tif (parentSession != null) {\n\t\t\t\tparentSession.streamClosed(this);\n\t\t\t\tparentSession = null;\n\t\t\t}\n\t\t}    // end of if (parentSession != null)\n\t\tresource  = null;\n\t\tsessionId = null;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"XMPPResourceConnection=[user_jid=\" + userJid + \", packets=\" + packets_counter + \", connectioId=\" +\n\t\t\t\tconnectionId + \", domain=\" + domain.getVhost().getDomain() + \", authState=\" +\n\t\t\t\tgetAuthState().name() + \", isAnon=\" + isAnonymous()\n\t\t\t\t\t + \", isTmp=\" + isTmpSession()\n\t\t\t\t\t + \", parentSession hash=\" + System.identityHashCode( parentSession )\n\t\t\t\t\t + \", parentSession liveTime=\" + (parentSession != null ? parentSession.getLiveTime() : \"\")\n\t\t\t\t\t + \"]\";\n\t}\n\n\t@Override\n\tpublic Authorization unregister(String name_param)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, TigaseStringprepException {\n\t\tAuthorization auth_res = super.unregister(name_param);\n\n\t\treturn auth_res;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<XMPPResourceConnection>}\n\t * @throws NotAuthorizedException\n\t */\n\tpublic List<XMPPResourceConnection> getActiveSessions() throws NotAuthorizedException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\n\t\treturn parentSession.getActiveResources();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID[]</code>\n\t */\n\tpublic JID[] getAllResourcesJIDs() {\n\t\treturn (parentSession == null)\n\t\t\t\t? null\n\t\t\t\t: parentSession.getJIDs();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>AuthRepository</code>\n\t */\n\tpublic AuthRepository getAuthRepository() {\n\t\treturn authRepo;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getAuthTime() {\n\t\treturn authenticationTime - creationTime;\n\t}\n\n\t@Override\n\tpublic final BareJID getBareJID() throws NotAuthorizedException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\n\t\treturn userJid.getBareJID();\n\t}\n\n\t/**\n\t *\n\t * @param key\n\t *\n\t *\n\t * @return a value of <code>Object</code>\n\t */\n\tpublic Object getCommonSessionData(String key) {\n\t\treturn (parentSession == null)\n\t\t\t\t? null\n\t\t\t\t: parentSession.getCommonSessionData(key);\n\t}\n\n\t/**\n\t * Gets the value of connectionId\n\t *\n\t * @return the value of connectionId\n\t * @throws NoConnectionIdException\n\t */\n\tpublic JID getConnectionId() throws NoConnectionIdException {\n\t\tlastAccessed = System.currentTimeMillis();\n\t\tif (this.connectionId == null) {\n\t\t\tthrow new NoConnectionIdException(\"Connection ID not set for this session. \" +\n\t\t\t\t\t\"This is probably the SM session to handle traffic \" +\n\t\t\t\t\t\"addressed to the server itself. Or maybe it's a bug.\");\n\t\t}\n\n\t\treturn this.connectionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t * @throws NoConnectionIdException\n\t */\n\tpublic JID getConnectionId(JID jid) throws NoConnectionIdException {\n\t\tJID result = null;\n\n\t\tif ((jid != null)) {\n\t\t\tif ((jid.getResource() != null) && (parentSession != null)) {\n\t\t\t\tXMPPResourceConnection conn = parentSession.getResourceForResource(jid\n\t\t\t\t\t\t.getResource());\n\n\t\t\t\tif (conn == null) {\n\t\t\t\t\tthrow new NoConnectionIdException(\n\t\t\t\t\t\t\t\"No connection available for given resource.\");\n\t\t\t\t} else {\n\t\t\t\t\tresult = conn.getConnectionId();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ((jid.getResource() == null) || jid.getResource().equals(this.resource)) {\n\t\t\t\t\tresult = this.connectionId;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult = this.connectionId;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getCreationTime() {\n\t\treturn creationTime;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>String</code>\n\t */\n\tpublic String getDefLang() {\n\t\treturn this.defLang;\n\t}\n\n\t/**\n\t * Returns full user JID for this session or throws\n\t * <code>NotAuthorizedException</code> if session is not authorized yet and\n\t * therefore user name and resource is not known yet.\n\t *\n\t * @return a <code>String</code> value of calculated user full JID for this\n\t *         session including resource name.\n\t * @throws NotAuthorizedException\n\t */\n\tpublic final JID getJID() throws NotAuthorizedException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\n\t\treturn userJid;\n\t}\n\n\t/**\n\t * Gets the value of lastAccessed\n\t *\n\t * @return the value of lastAccessed\n\t */\n\tpublic long getLastAccessed() {\n\t\treturn this.lastAccessed;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>long</code>\n\t */\n\tpublic long getPacketsCounter() {\n\t\treturn packets_counter;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>XMPPSession</code>\n\t */\n\tpublic XMPPSession getParentSession() {\n\t\treturn parentSession;\n\t}\n\n\t/**\n\t * Returns last presence packet with the user presence status or\n\t * <code>null</code> if the user has not yet sent an initial presence.\n\t *\n\t * @return an <code>Element</code> with last presence status received from the\n\t *         user.\n\t */\n\tpublic Element getPresence() {\n\t\treturn (Element) getSessionData(PRESENCE_KEY);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>int</code>\n\t */\n\tpublic int getPriority() {\n\t\treturn priority;\n\t}\n\n\t/**\n\t * Gets the value of resource\n\t *\n\t * @return the value of resource\n\t */\n\tpublic String getResource() {\n\t\treturn this.resource;\n\t}\n\n\t/**\n\t * Retrieves session data. This method gives access to temporary session data\n\t * only. You can retrieve earlier saved data giving key ID to receive needed\n\t * value. Please see <code>putSessionData</code> description for more details.\n\t *\n\t * @param key\n\t *          a <code>String</code> value of stored data ID.\n\t * @return a <code>Object</code> value of data for given key.\n\t * @see #putSessionData(String, Object)\n\t */\n\tpublic final Object getSessionData(final String key) {\n\t\tlastAccessed = System.currentTimeMillis();\n\n\t\treturn sessionData.get(key);\n\t}\n\n\t/**\n\t * Gets the value of sessionId\n\t *\n\t * @return the value of sessionId\n\t */\n\tpublic String getSessionId() {\n\t\treturn this.sessionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID</code>\n\t */\n\tpublic JID getSMComponentId() {\n\t\treturn loginHandler.getComponentId();\n\t}\n\n\t/**\n\t * To get the user bare JID please use <code>getBareJID</code> method, to\n\t * check the whether the user with given BareJID is owner of the session\n\t * please use method <code>isUserId(...)</code>. From now one the user session\n\t * may handle more than a single userId, hence getting just userId is not\n\t * enough to check whether the user Id belongs to the session.\n\t *\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>BareJID</code>\n\t * @throws NotAuthorizedException\n\t *\n\t * @deprecated\n\t */\n\t@Deprecated\n\tpublic BareJID getUserId() throws NotAuthorizedException {\n\t\treturn this.getBareJID();\n\t}\n\n\t@Override\n\tpublic final String getUserName() throws NotAuthorizedException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\n\t\treturn parentSession.getUserName();\n\t}\n\n\t// ~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic boolean isAuthorized() {\n\t\treturn super.isAuthorized() && (parentSession != null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param outDomain\n\t * @param includeComponents\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isLocalDomain(String outDomain, boolean includeComponents) {\n\t\treturn loginHandler.isLocalDomain(outDomain, includeComponents);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isResourceSet() {\n\t\treturn this.resource != null;\n\t}\n\n\t/**\n\t * Returns information whether this is a server (SessionManager) session or\n\t * normal user session. The server session is used to handle packets addressed\n\t * to the server itself (local domain name).\n\t *\n\t * @return a <code>boolean</code> value of <code>true</code> if this is the\n\t *         server session and <code>false</code> otherwise.\n\t */\n\tpublic boolean isServerSession() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t */\n\tpublic boolean isTmpSession() {\n\t\treturn tmpSession;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param bareJID\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>boolean</code>\n\t * @throws NotAuthorizedException\n\t */\n\tpublic boolean isUserId(BareJID bareJID) throws NotAuthorizedException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\n\t\treturn userJid.getBareJID().equals(bareJID);\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Sets the value of connectionId\n\t *\n\t * @param connectionId is a <code>JID</code>\n\t */\n\tpublic void setConnectionId(JID connectionId) {\n\t\tthis.connectionId = connectionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param lang\n\t */\n\tpublic void setDefLang(String lang) {\n\t\tthis.defLang = lang;\n\t}\n\n\t/**\n\t * Sets the value of lastAccessed\n\t *\n\t * @param argLastAccessed\n\t *          Value to assign to this.lastAccessed\n\t */\n\tpublic void setLastAccessed(final long argLastAccessed) {\n\t\tthis.lastAccessed = argLastAccessed;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param parent\n\t *\n\t * @throws TigaseStringprepException\n\t */\n\tpublic void setParentSession(final XMPPSession parent)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tsynchronized (this) {\n\t\t\tif (parent != null) {\n\t\t\t\tuserJid = JID.jidInstance(parent.getUserName(), domain.getVhost().getDomain(),\n\t\t\t\t\t\t((resource != null)\n\t\t\t\t\t\t? resource\n\t\t\t\t\t\t: sessionId));\n\t\t\t}\n\t\t\tthis.parentSession = parent;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic void setPresence(Element packet) {\n\t\tputSessionData(PRESENCE_KEY, packet);\n\n\t\t// Parse resource priority:\n\t\tString pr_str = packet.getCDataStaticStr(Presence.PRESENCE_PRIORITY_PATH);\n\n\t\tif (pr_str != null) {\n\t\t\tint pr = 1;\n\n\t\t\ttry {\n\t\t\t\tpr = Integer.decode(pr_str);\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.finer(\"Incorrect priority value: \" + pr_str + \", setting 1 as default.\");\n\t\t\t\t}\n\t\t\t\tpr = 1;\n\t\t\t}\n\t\t\tsetPriority(pr);\n\t\t} else {\n\t\t\t// workaround for case when presence update came before presence was broadcasted due to \n\t\t\t// loading of roster data in roster processing thread\n\t\t\tif (getPriority() != 0 && !\"unavailable\".equals(packet.getAttributeStaticStr(\"type\"))) {\n\t\t\t\tpacket.addChild(new Element(\"priority\", String.valueOf(getPriority())));\n\t\t\t}\n\t\t\tputSessionData(PRESENCE_KEY, packet);\n\t\t}\n\t\tloginHandler.handlePresenceSet(this);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param priority\n\t */\n\tpublic void setPriority(final int priority) {\n\t\tthis.priority = priority;\n\t}\n\n\t/**\n\t * Sets the connection resource\n\t *\n\t * @param argResource\n\t *          Value to assign to this.resource\n\t * @throws NotAuthorizedException\n\t * @throws TigaseStringprepException\n\t */\n\tpublic void setResource(final String argResource)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseStringprepException {\n\t\tif (!isAuthorized()) {\n\t\t\tthrow new NotAuthorizedException(NOT_AUTHORIZED_MSG);\n\t\t}    // end of if (username == null)\n\t\tthis.resource = argResource;\n\n\t\t// This is really unlikely a parent session would be null here but it may\n\t\t// happen when the user disconnects just after sending resource bind.\n\t\t// Due to asynchronous nature of packets processing in the Tigase the\n\t\t// the authorization might be canceled while resource bind packet still\n\t\t// waits in the queue.....\n\t\t// This has already happened....\n\t\tif (parentSession != null) {\n\t\t\tparentSession.addResourceConnection(this);\n\t\t}\n\t\tuserJid = userJid.copyWithResource((resource == null)\n\t\t\t\t? sessionId\n\t\t\t\t: resource);\n\t\tloginHandler.handleResourceBind(this);\n\t}\n\n\t/**\n\t * Sets the value of sessionId\n\t *\n\t * @param argSessionId\n\t *          Value to assign to this.sessionId\n\t */\n\tpublic void setSessionId(final String argSessionId) {\n\t\tthis.sessionId = argSessionId;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param tmp is a <code>boolean</code>\n\t */\n\tpublic void setTmpSession(boolean tmp) {\n\t\ttmpSession = tmp;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tprotected void login() {\n\t\tauthenticationTime = System.currentTimeMillis();\n\t}\n\n\tpublic boolean isEncrypted() {\n\t\tString tls = (String) getSessionData(\"starttls\");\n\t\treturn tls != null && \"true\".equals(tls);\n\t}\n\t\n\tpublic boolean isTlsRequired() {\n\t\tVHostItem vhost = getDomain();\n\t\ttry {\n\t\t\tif ( null != getSessionData( \"SSL\" ) && (boolean) getSessionData( \"SSL\" ) ){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (\"c2s\".equals(getConnectionId().getLocalpart()) )\n\t\t\t\treturn vhost.isTlsRequired();\n\t\t\telse\n\t\t\t\treturn false;\n\t\t} catch (NoConnectionIdException e) {\n\t\t\tlog.log(Level.WARNING, \"Can't check sessionId\", e);\n\t\t\treturn vhost.isTlsRequired();\n\t\t}\n\t}\n\t\n}    // XMPPResourceConnection\n\n\n//~ Formatted in Tigase Code Convention on 13/11/02\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPSession.java",
    "content": "/*\n * XMPPSession.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.util.TigaseStringprepException;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.function.Function;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * XMPPSession class is a container class for all {@link XMPPResourceConnection} objects for\n * particular user (i.e. all user's connected resources)\n */\npublic class XMPPSession {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(XMPPSession.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CopyOnWriteArrayList<XMPPResourceConnection> activeResources = null;\n\tprivate long                                         creationTime    = 0;\n\tprivate long                                         packets_counter = 0;\n\tprivate Map<String, Object>                          sessionData     = null;\n\n\t/**\n\t * User name - localpart of user's JID\n\t */\n\tprivate String username = null;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>XMPPSession</code> instance.\n\t *\n\t * @param username - localpart of user's JID\n\t */\n\tpublic XMPPSession(final String username) {\n\t\tsessionData       = new ConcurrentHashMap<String, Object>();\n\t\tactiveResources   = new CopyOnWriteArrayList<XMPPResourceConnection>();\n\t\tthis.username     = username;\n\t\tthis.creationTime = System.currentTimeMillis();\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * This method is called each time the resource is set for connection.\n\t *\n\t * Method performs checking whether there is no collision of the resources.\n\t *\n\t * @param conn {@link XMPPResourceConnection} that is being added.\n\t * @throws TigaseStringprepException\n\t */\n\tpublic void addResourceConnection(XMPPResourceConnection conn)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Adding resource connection for username : \" + username + \", id: \" +\n\t\t\t\t\tconn);\n\t\t}\n\n\t\t// There is a bug somewhere which causes to allow for 2 or more connections\n\t\t// with the same resource. Let's try to catch the case here and fix it....\n\t\tString resource = conn.getResource();\n\n\t\tif (resource != null) {\n\t\t\tArrayDeque<XMPPResourceConnection> old_ress =\n\t\t\t\t\tnew ArrayDeque<XMPPResourceConnection>();\n\n\t\t\tfor (XMPPResourceConnection act_conn : activeResources) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Resource checking for: \" + username + \" :: \" + act_conn.getResource() +\n\t\t\t\t\t\t\t\", connectionID: \" + act_conn);\n\t\t\t\t}\n\t\t\t\tif (resource.equalsIgnoreCase(act_conn.getResource())) {\n\t\t\t\t\told_ress.add(act_conn);\n\t\t\t\t}    // end of if (resource.equals(conn.getResource()))\n\t\t\t}      // end of for (XMPPResourceConnection conn: activeResources)\n\n\t\t\tXMPPResourceConnection old_res = null;\n\n\t\t\twhile ((old_res = old_ress.poll()) != null) {\n\n\t\t\t\t// If they are equal, just ignore this. It may happen only for USER_STATUS\n\t\t\t\t// command where the user session is artificially created....\n\t\t\t\tif (old_res != conn) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Found old resource connection for: \" + username + \", id: \" + old_res);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\told_res.putSessionData(XMPPResourceConnection.ERROR_KEY, \"conflict\");\n\t\t\t\t\t\told_res.logout();\n\t\t\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\t\t\tlog.log(Level.INFO, \"Exception during closing old connection, ignoring.\", e);\n\t\t\t\t\t}\n\t\t\t\t\tremoveResourceConnection(old_res);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// The connection could have been already added with null resource\n\t\t// to avoid adding it twice let's check if it is already there\n\t\tXMPPResourceConnection old_res;\n\n\t\ttry {\n\t\t\told_res = getResourceForConnectionId(conn.getConnectionId());\n\t\t} catch (NoConnectionIdException ex) {\n\t\t\told_res = null;\n\t\t}\n\t\tif (old_res == null) {\n\t\t\tactiveResources.add(conn);\n\t\t\tconn.setParentSession(this);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Number of active resources of [\" + username + \"] = \"\n\t\t\t\t\t\t\t\t + activeResources.size() + \" : \" + activeResources);\n\t\t}\n\t}\n\n\t/**\n\t * Increments counter of processed packet for the given\n\t * user session (i.e. all users connections in total)\n\t */\n\tpublic void incPacketsCounter() {\n\t\t++packets_counter;\n\t}\n\n\t/**\n\t * Removes particular {@link XMPPResourceConnection} user's resource connection\n\t * from the list of all active user connections within given {@link XMPPSession}\n\t * and detaches {@link XMPPSession} from the removed {@link XMPPResourceConnection}\n\t *\n\t * @param conn\n\t */\n\tpublic void removeResourceConnection(XMPPResourceConnection conn) {\n\t\tif (activeResources.remove(conn))\n\t\t\tconn.removeParentSession(null);\n\t}\n\n\t/**\n\t * Method is called upon closing stream connection and removes particular\n\t * {@link XMPPResourceConnection}\n\t *\n\t * @param conn - {@link XMPPResourceConnection} for which stream was closed.\n\t */\n\tpublic void streamClosed(XMPPResourceConnection conn) {\n\t\tremoveResourceConnection(conn);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tsb.append(\"XMPPSession=[\");\n\t\tsb.append( \"hash=\" + System.identityHashCode( this ) );\n\t\tsb.append( \", username: \" ).append( username );\n\t\tsb.append(\", resources: \").append(activeResources.toString());\n\t\tsb.append(\"];\");\n\n\t\treturn sb.toString();\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method returns a List of all {@link XMPPResourceConnection} objects related\n\t * to this {@link XMPPSession} object\n\t */\n\tpublic List<XMPPResourceConnection> getActiveResources() {\n\t\treturn (List<XMPPResourceConnection>) activeResources;\n\t}\n\n\t/**\n\t * Method returns a cloned List of all {@link XMPPResourceConnection} objects\n\t * related to this {@link XMPPSession} object\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic List<XMPPResourceConnection> getActiveResourcesClone() {\n\t\treturn (List<XMPPResourceConnection>) activeResources.clone();\n\t}\n\n\t/**\n\t * Method returns number of all {@link XMPPResourceConnection} objects\n\t * related to this {@link XMPPSession} object\n\t */\n\tpublic int getActiveResourcesSize() {\n\t\treturn activeResources.size();\n\t}\n\n\t/**\n\t * Method returns a data for particular {@code key} which is common to all resource\n\t * connections within this {@link XMPPSession}\n\t *\n\t * related to this {@link XMPPSession} object\n\t *\n\t * @param key for which data should be returned\n\t */\n\tpublic Object getCommonSessionData(String key) {\n\t\treturn sessionData.get(key);\n\t}\n\n\t/**\n\t * Method returns an array of all ConnectionIDs related to this\n\t * {@link XMPPSession}\n\t */\n\tpublic JID[] getConnectionIds() {\n\t\tJID[] result = new JID[activeResources.size()];\n\t\tint   idx    = 0;\n\n\t\tfor (XMPPResourceConnection conn : activeResources) {\n\t\t\ttry {\n\t\t\t\tresult[idx] = conn.getConnectionId();\n\t\t\t\t++idx;\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// Skip connection with no connectionId set\n\t\t\t}\n\t\t}    // end of for (XMPPResourceConnection conn: activeResources)\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method returns an array of all FullJIDs related to this\n\t * {@link XMPPSession}\n\t */\n\tpublic JID[] getJIDs() {\n\t\tJID[] result = new JID[activeResources.size()];\n\t\tint   idx    = 0;\n\n\t\tfor (XMPPResourceConnection conn : activeResources) {\n\t\t\tresult[idx++] = conn.getjid();\n\t\t}    // end of for (XMPPResourceConnection conn: activeResources)\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Method returns time of how long the session is active (in milliseconds)\n\t */\n\tpublic long getLiveTime() {\n\t\treturn (System.currentTimeMillis() - creationTime);\n\t}\n\n\t/**\n\t * Returns number of processed packet for the given\n\t * user session (i.e. all users connections in total)\n\t */\n\tpublic long getPacketsCounter() {\n\t\treturn packets_counter;\n\t}\n\n\t/**\n\t * Method returns {@link XMPPResourceConnection} for particular FullJID. In\n\t * case there are no sessions {@code null} is returned, in case there is more\n\t * than one active session a session with the highest priority is returned. In\n\t * case there are still more than one connections with the same priority then\n\t * the latest active one is returned.\n\t *\n\t * @param jid FullJID for which a {@code XMPPResourceConnection} should be\n\t *            returned\n\t */\n\tpublic synchronized XMPPResourceConnection getResourceConnection(JID jid) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Called for: \" + jid);\n\t\t}\n\t\tif (activeResources.size() == 0) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"No active resources found!\");\n\t\t\t}\n\t\t\treturn null;\n\t\t}    // end of if (activeResources.size() == 0)\n\t\tif (jid.getResource() != null) {\n\t\t\treturn this.getResourceForResource(jid.getResource());\n\t\t}\n\t\tif (activeResources.size() == 1) {\n\t\t\tXMPPResourceConnection result = activeResources.get(0);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Only 1 active resource: \" + result.getResource());\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}    // end of if (activeResources.size() == 1)\n\n\t\tXMPPResourceConnection conn = getResourceForJID(jid);\n\n\t\tif (conn != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Number of resources: \" + activeResources.size() +\n\t\t\t\t\t\t\", got resource for jid: \" + jid);\n\t\t\t}\n\n\t\t\treturn conn;\n\t\t}    // end of if (conn != null)\n\n\t\t// There is no single active resource for this jid, so let's return\n\t\t// connection with the highest priority:\n\t\tArrayList<XMPPResourceConnection> al = new ArrayList<XMPPResourceConnection>();\n\n\t\tint highest_priority = 0;\n\t\tint priority;\n\n\t\tfor ( XMPPResourceConnection conn_tmp : activeResources ) {\n\t\t\tif (!conn_tmp.isAuthorized()) {\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.finest(\"Connection either not yet authorized or already gone, ignoring while processing: \" + conn_tmp);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// if connections priority matches current highest priority add it only, otherwise if\n\t\t\t// it's greater clear current list and set new highest priority\n\t\t\tpriority = conn_tmp.getPriority();\n\t\t\tif (priority == highest_priority) {\n\t\t\t\tal.add(conn_tmp);\n\t\t\t}\n\t\t\tif (priority > highest_priority) {\n\t\t\t\tal.clear();\n\t\t\t\tal.add(conn_tmp);\n\t\t\t\thighest_priority = priority;\n\t\t\t}\n\t\t}\n\t\tif (al.size() == 0) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"No active resources found!\");\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tif (al.size() == 1) {\n\t\t\t// We found 1 connection with highest priority\n\t\t\treturn al.get(0);\n\t\t}    // end of if (al.size() == 1)\n\n\t\t// We have a few connections with the same highest priority\n\t\t// Let's return the one which was the most recently used.\n\t\tXMPPResourceConnection conn_last = al.get(0);\n\t\tlong                   time      = conn_last.getLastAccessed();\n\n\t\tfor (int i = 1; i < al.size(); ++i) {\n\t\t\tif (al.get(i).getLastAccessed() > time) {\n\t\t\t\tconn_last = al.get(i);\n\t\t\t\ttime      = conn_last.getLastAccessed();\n\t\t\t}    // end of if (al.get(i).getLastAccessed() > time)\n\t\t}\n\n\t\treturn conn_last;\n\t}\n\n\t/**\n\t * Method returns {@link XMPPResourceConnection} for particular ConnectionID.\n\t * In case there is no session that match given ConnectionID then {@code null}\n\t * is returned.\n\t *\n\t * @param connectionId  ConnectionID for which {@code XMPPResourceConnection} should be\n\t *            returned\n\t */\n\tpublic XMPPResourceConnection getResourceForConnectionId(JID connectionId) {\n\t\ttry {\n\t\t\tfor (XMPPResourceConnection conn : activeResources) {\n\t\t\t\tif (connectionId.equals(conn.getConnectionId())) {\n\t\t\t\t\treturn conn;\n\t\t\t\t}    // end of if (resource.equals(conn.getResource()))\n\t\t\t}      // end of for (XMPPResourceConnection conn: activeResources)\n\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t// Logger.getLogger(XMPPSession.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method returns {@link XMPPResourceConnection} for particular FullJID (using\n\t * {@code resource} name as determinant. In case there is no session that\n\t * match - {@code null} is returned.\n\t *\n\t * @param jid FullJID for which a {@code XMPPResourceConnection} should be\n\t *            returned\n\t */\n\tpublic XMPPResourceConnection getResourceForJID(JID jid) {\n\t\tfinal String resource = jid.getResource();\n\n\t\treturn getResourceForResource(resource);\n\t}\n\n\t/**\n\t * Method returns {@link XMPPResourceConnection} for particular\n\t * {@code resource}. In case there is no session that match - {@code null} is\n\t * returned.\n\t *\n\t * @param resource resource string for which a {@code XMPPResourceConnection} should be\n\t *            returned\n\t */\n\tpublic XMPPResourceConnection getResourceForResource(String resource) {\n\t\tif ((resource != null) && (resource.length() > 0)) {\n\t\t\tfor (XMPPResourceConnection conn : activeResources) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Resource checking: \" + conn.getResource() + \", connectionID: \" +\n\t\t\t\t\t\t\tconn);\n\t\t\t\t}\n\t\t\t\tif (resource.equalsIgnoreCase(conn.getResource())) {\n\t\t\t\t\treturn conn;\n\t\t\t\t}    // end of if (resource.equals(conn.getResource()))\n\t\t\t}      // end of for (XMPPResourceConnection conn: activeResources)\n\t\t}        // end of if (resource.length() > 0)\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method returns username that is related to this {@code XMPPSession} (i.e.\n\t * mostly localpart of JID)\n\t */\n\tpublic String getUserName() {\n\t\treturn username;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprotected Object computeCommonSessionDataIfAbsent(String key, Function<String,Object> valueFactory) {\n\t\treturn sessionData.computeIfAbsent(key, valueFactory);\n\t}\n\t\n\t/**\n\t * Method used to store data common for all connections of the user.\n\t *\n\t * @param key under which data should be store\n\t * @param value data to be stored\n\t */\n\tprotected void putCommonSessionData(String key, Object value) {\n\t\tsessionData.put(key, value);\n\t}\n\n\tprotected Object putCommonSessionDataIfAbsent(String key, Object value) {\n\t\treturn sessionData.putIfAbsent(key, value);\n\t}\n\t\n\t/**\n\t * Method used to remove data common for all connections of the user.\n\t *\n\t * @param key for which data should be removed\n\t */\n\tprotected Object removeCommonSessionData(String key) {\n\t\treturn sessionData.remove(key);\n\t}\n}    // XMPPSession\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/XMPPStopListenerIfc.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.server.Packet;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\n\n//~--- interfaces -------------------------------------------------------------\n/**\n * Describe interface XMPPStopListener here.\n *\n *\n * Created: Sat Oct 14 16:14:18 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic interface XMPPStopListenerIfc extends XMPPImplIfc {\n\n\t/**\n\t * Performs additional processing upon closing user session (user either\n\t * disconnects or logs-out).\n\t *\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data. It allows\n\t *                 for storing information in a permanent storage or in memory\n\t *                 only during the live of the online session. This parameter\n\t *                 can be null if there is no online user session at the time\n\t *                 of the packet processing.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results. Regardless a response to a\n\t *                 user request is sent or the packet is forwarded to it's\n\t *                 destination it is always required that a copy of the input\n\t *                 packet is created and stored in the results queue.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration. In most cases it is unused,\n\t *                 however if the plugin needs to access an external database\n\t *                 that this is a way to pass database connection string to\n\t *                 the plugin.\n\t */\n\tvoid stopped( XMPPResourceConnection session, Queue<Packet> results, Map<String, Object> settings );\n}    // XMPPStopListener\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/AbstractAuthPreprocessor.java",
    "content": "/*\n * AbstractAuthPreprocessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl;\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Packet;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Abstract class which should be extended by any authorization processor as it\n * implements preprocessor feature which is responsible for stopping not allowed \n * packets from not yet authorized client connections.\n * \n * @author andrzej\n */\npublic abstract class AbstractAuthPreprocessor \n\t\t\t\textends XMPPProcessor \n\t\t\t\timplements XMPPPreprocessorIfc {\n\t\n\tprivate static final Logger log = Logger.getLogger(AbstractAuthPreprocessor.class.getCanonicalName());\n\t\n\tprivate static final String[] AUTH_ONLY_ELEMS = { \"message\", \"presence\" };\n\t\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tif ((session == null) || session.isServerSession()) {\n\t\t\treturn false;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\t\t\t\n\t\t\t// For all messages coming from the owner of this account set\n\t\t\t// proper 'from' attribute. This is actually needed for the case\n\t\t\t// when the user sends a message to himself.\n\t\t\tif (session.getConnectionId().equals(packet.getPacketFrom())) {\n\t\t\t\tif (!session.isAuthorized()) {\n\n\t\t\t\t\t// We allow only certain packets here...\n\t\t\t\t\t// For now it is simpler to disallow all messages and presences\n\t\t\t\t\t// packets, the rest should be bounced back anyway\n\t\t\t\t\tfor (String elem : AUTH_ONLY_ELEMS) {\n\t\t\t\t\t\tif (packet.getElemName() == elem) {\n\t\t\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\t\"You must authenticate session first, before you\" +\n\t\t\t\t\t\t\t\t\t\" can send any message or presence packet.\", true));\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\t\"Packet received before the session has been authenticated.\" +\n\t\t\t\t\t\t\t\t\t\t\"Session details: connectionId=\" + \"{0}, sessionId={1}, packet={2}\",\n\t\t\t\t\t\t\t\t\t\tnew Object[] { session.getConnectionId(),\n\t\t\t\t\t\t\t\t\t\tsession.getSessionId(), packet.toStringSecure() });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t}\n\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t// Ignore this packet\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Ignoring packet with an error to non-existen user session: {0}\", packet\n\t\t\t\t\t\t.toStringSecure());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.FINEST, \"Packet preprocessing exception: \", e);\n\n\t\t\treturn false;\n\t\t}    // end of try-catch\n\t\n\t\treturn false;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/BindResource.java",
    "content": "/*\n * BindResource.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.xmpp.BareJID;\nimport tigase.util.DNSResolver;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.apns.APNSDBFactory;\nimport tigase.apns.APNSDBProvider;\nimport tigase.apns.APNSManager;\nimport tigase.conf.ConfigurationException;\n\n/**\n * RFC-3920, 7. Resource Binding\n *\n *\n * Created: Mon Feb 20 21:07:29 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class BindResource\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc {\n\t/** Field description */\n\tprivate static final String[]   COMPRESS_PATH   = { \"compress\" };\n\tpublic static final String      DEF_RESOURCE_PREFIX_PROP_KEY = \"def-resource-prefix\";\n\tprivate static final String     EL_NAME                      = \"bind\";\n\tprivate static final String[][] ELEMENTS                     = {\n\t\tIq.IQ_BIND_PATH\n\t};\n\tprivate static final Logger     log = Logger.getLogger(BindResource.class.getName());\n\tprivate static int              resGenerator                 = 0;\n\n\t// protected static final String RESOURCE_KEY = \"Resource-Binded\";\n\tprivate static final String    XMLNS  = \"urn:ietf:params:xml:ns:xmpp-bind\";\n\tprivate static final String    ID     = XMLNS;\t\n\tprivate static final String[]  XMLNSS = { XMLNS };\n\tprivate static final Element[] FEATURES = { new Element(EL_NAME, new String[] {\n\t\t\t\"xmlns\" }, new String[] { XMLNS }) };\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }) };\n\n\tprivate static final String RESOURCE_PREFIX_DEF = \"tigase-\";\n\n\tprotected APNSDBProvider apnsDBProvider;\n\n\t//~--- fields ---------------------------------------------------------------\n\tprivate String resourceDefPrefix = RESOURCE_PREFIX_DEF;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\n\t\tint hostnameHash = Math.abs( DNSResolverFactory.getInstance().getDefaultHost().hashCode() );\n\n\t\t// Init plugin configuration\n\t\tresourceDefPrefix = hostnameHash + \"-\" + settings.getOrDefault(DEF_RESOURCE_PREFIX_PROP_KEY, RESOURCE_PREFIX_DEF);\n\t\t\n\t\t// apns配置初始化 C-103\n\t\ttry {\n\t\t\tthis.apnsDBProvider = APNSDBFactory.getAPNSDBManager(settings);\n\t\t\tthis.apnsDBProvider.init(settings);\n\t\t\tAPNSManager.initToken(this.apnsDBProvider.getAllTokens());\n\t\t} catch (ConfigurationException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tif ((session == null) || session.isServerSession() || !session.isAuthorized() || C2SDeliveryErrorProcessor.isDeliveryError( packet )) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tif (session.getConnectionId().equals(packet.getPacketFrom())) {\n\t\t\t\t// After authentication we require resource binding packet and\n\t\t\t\t// nothing else:\n\t\t\t\t// actually according to XEP-0170:\n\t\t\t\t// http://xmpp.org/extensions/xep-0170.html\n\t\t\t\t// stream compression might occur between authentication and resource\n\t\t\t\t// binding\n\t\t\t\tif (session.isResourceSet() || packet.isXMLNSStaticStr(Iq.IQ_BIND_PATH,\n\t\t\t\t\t\t\"urn:ietf:params:xml:ns:xmpp-bind\") || packet.isXMLNSStaticStr(COMPRESS_PATH,\n\t\t\t\t\t\t\"http://jabber.org/protocol/compress\")) {\n\t\t\t\t\tJID from_jid = session.getJID();\n\n\t\t\t\t\tif (from_jid != null) {\n\n\t\t\t\t\t\t// http://xmpp.org/rfcs/rfc6120.html#stanzas-attributes-from\n\t\t\t\t\t\t\tif ( packet.getElemName() == tigase.server.Presence.ELEM_NAME\n\t\t\t\t\t\t\t\t && StanzaType.getSubsTypes().contains( packet.getType() )\n\t\t\t\t\t\t\t\t && ( packet.getStanzaFrom() == null\n\t\t\t\t\t\t\t\t\t\t\t|| !from_jid.getBareJID().equals( packet.getStanzaFrom().getBareJID() )\n\t\t\t\t\t\t\t\t\t\t\t|| packet.getStanzaFrom().getResource() != null ) ){\n\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Setting correct from attribute: {0}\", from_jid );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpacket.initVars( JID.jidInstance( from_jid.getBareJID() ), packet.getStanzaTo() );\n\t\t\t\t\t\t} else if ( ( packet.getStanzaFrom() == null )\n\t\t\t\t\t\t\t\t\t\t\t\t|| ( ( packet.getElemName() == tigase.server.Presence.ELEM_NAME\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t && !StanzaType.getSubsTypes().contains( packet.getType() )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t || packet.getElemName() != tigase.server.Presence.ELEM_NAME )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t && !from_jid.equals( packet.getStanzaFrom() ) ) ){\n\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Setting correct from attribute: {0}\", from_jid );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpacket.initVars( from_jid, packet.getStanzaTo() );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\t\t\"Skipping setting correct from attribute: {0}, is already correct.\",\n\t\t\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\t\"Session is authenticated but session.getJid() is empty: {0}\", packet\n\t\t\t\t\t\t\t\t.toStringSecure());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// We do not accept anything without resource binding....\n\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"You must bind the resource first: \" +\n\t\t\t\t\t\t\t\"http://www.xmpp.org/rfcs/rfc3920.html#bind\", true));\n\t\t\t\t\tif (log.isLoggable(Level.INFO)) {\n\t\t\t\t\t\tlog.log(Level.INFO, \"Session details: connectionId={0}, sessionId={1}\",\n\t\t\t\t\t\t\t\tnew Object[] { session.getConnectionId(),\n\t\t\t\t\t\t\t\tsession.getSessionId() });\n\t\t\t\t\t}\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Session more detais: JID={0}\", session.getjid());\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t} catch (PacketErrorTypeException e) {\n\n\t\t\t// Ignore this packet\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"Ignoring packet with an error to non-existen user session: {0}\", packet\n\t\t\t\t\t\t.toStringSecure());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.FINEST, \"Packet preprocessing exception: \", e);\n\n\t\t\treturn false;\n\t\t}    // end of try-catch\t\n\t\t\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (!session.isAuthorized()) {\n\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\"Session is not yet authorized.\", false));\n\n\t\t\treturn;\n\t\t}    // end of if (!session.isAuthorized())\n\n\t\t// TODO: test what happens if resource is bound multiple times for the same\n\t\t// user session. in particular if XMPPSession object removes the old\n\t\t// resource from the list.\n\t\tElement    request = packet.getElement();\n\t\tStanzaType type    = packet.getType();\n\n\t\ttry {\n\t\t\tswitch (type) {\n\t\t\tcase set :\n\t\t\t\t// String resource = request.getChildCDataStaticStr(Iq.IQ_BIND_RESOURCE_PATH);\n\t\t\t\t\n\t\t\t\t//从客户端带上来的resourc中获取token,维护内存和数据库记录  C-103\n\t\t\t\tString $token = request.getChildCDataStaticStr(Iq.IQ_BIND_RESOURCE_PATH);\n\t\t\t\t\n\t\t\t\tBareJID bareJID = session.getBareJID();\n\t\t\t\tString uid = bareJID.getLocalpart();\n\t\t\t\tif($token != null && $token.startsWith(\"iOS:\")){\n\t\t\t\t\tString token = $token.split(\":\")[1];\n\n\t\t\t\t\tString oldToken = APNSManager.getToken(uid);\n\t\t\t\t\tif(oldToken == null || !oldToken.equals(token)){\n\t\t\t\t\t\tthis.apnsDBProvider.updateToken(bareJID, token);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE, \"#IOS token add : \" + token);\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t\tAPNSManager.addToken(uid, token);\n\t\t\t\t} else if(APNSManager.getToken(uid) != null) {\n\t\t\t\t\tAPNSManager.delToken(uid);\n\t\t\t\t\tthis.apnsDBProvider.delToken(bareJID);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tAPNSManager.msgCountClear(uid);\n\t\t\t\t\n\t\t\t\tString resource = \"app\";\n\n\t\t\t\ttry {\n\t\t\t\t\tif ((resource == null) || resource.trim().isEmpty()) {\n\t\t\t\t\t\tresource = resourceDefPrefix + (++resGenerator);\n\t\t\t\t\t\tsession.setResource(resource);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsession.setResource(resource);\n\t\t\t\t\t\t} catch (TigaseStringprepException ex) {\n\n\t\t\t\t\t\t\t// User provided resource is invalid, generating different\n\t\t\t\t\t\t\t// server one\n\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\"Incrrect resource provided by the user: {0}, generating a \" +\n\t\t\t\t\t\t\t\t\t\"different one by the server.\", resource);\n\t\t\t\t\t\t\tresource = resourceDefPrefix + (++resGenerator);\n\t\t\t\t\t\t\tsession.setResource(resource);\n\t\t\t\t\t\t}\n\t\t\t\t\t}    // end of if (resource == null) else\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"stringprep problem with the server generated resource: {0}\", resource);\n\t\t\t\t}\n\t\t\t\tpacket.initVars(session.getJID(), packet.getStanzaTo());\n\n\t\t\t\t// session.putSessionData(RESOURCE_KEY, \"true\");\n\t\t\t\tresults.offer(packet.okResult(new Element(\"jid\", session.getJID().toString()),\n\t\t\t\t\t\t1));\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Bind type is incorrect\", false));\n\n\t\t\t\tbreak;\n\t\t\t}    // end of switch (type)\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\tif ((session != null) && (!session.isResourceSet()) && session.isAuthorized()) {\n\t\t\treturn FEATURES;\n\t\t} else {\n\t\t\treturn null;\n\t\t}    // end of if (session.isAuthorized()) else\n\t}\n}    // BindResource\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/BlockingCommand.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * Original ource code provided on 2015-03-08 (https://projects.tigase.org/issues/2819) by:\n * - Behnam Hatami\n * - Daniele Ricci\n * under the “Shared code ownership agreement” as described at the address:\n * https://projects.tigase.org/projects/tigase-server/wiki/Submitting_patches_and_other_code\n *\n */\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\nimport tigase.xmpp.impl.annotation.DiscoFeatures;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.HandleStanzaTypes;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\nimport tigase.xmpp.impl.roster.RosterFactory;\n\n/**\n * XEP-0191: Blocking Command. Based on privacy lists.\n *\n * @author Andrzej Wójcik \n * \n * Originally submitted by:\n * @author Daniele Ricci\n * @author Behnam Hatami\n */\n@Id(BlockingCommand.ID)\n@DiscoFeatures({BlockingCommand.XMLNS})\n@Handles({\n\t@Handle(path = {Iq.ELEM_NAME, BlockingCommand.BLOCKLIST}, xmlns = BlockingCommand.XMLNS),\n\t@Handle(path = {Iq.ELEM_NAME, BlockingCommand.BLOCK}, xmlns = BlockingCommand.XMLNS),\n\t@Handle(path = {Iq.ELEM_NAME, BlockingCommand.UNBLOCK}, xmlns = BlockingCommand.XMLNS)})\n@HandleStanzaTypes({StanzaType.set, StanzaType.get})\npublic class BlockingCommand extends XMPPProcessorAbstract implements XMPPProcessorIfc {\n\n\tprivate static final Logger log = Logger.getLogger(BlockingCommand.class.getName());\n\tprotected static final String XMLNS = \"urn:xmpp:blocking\";\n\tprotected static final String XMLNS_ERRORS = XMLNS + \":errors\";\n\tprotected static final String ID = XMLNS;\n\n\tprotected static final String BLOCKLIST = \"blocklist\";\n\tprotected static final String BLOCK = \"block\";\n\tprotected static final String UNBLOCK = \"unblock\";\n\tprivate static final String ITEM = \"item\";\n\tprivate static final String _JID = \"jid\";\n\t\n\tprivate final RosterAbstract roster_util = RosterFactory.getRosterImplementation(true);\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) throws XMPPException {\n\t\tif (session == null || packet.getElemName() != Iq.ELEM_NAME) {\n\t\t\treturn;\n\t\t}\n\n\t\tStanzaType type = packet.getType();\n\t\ttry {\n\t\t\tswitch (type) {\n\t\t\t\tcase get:\n\t\t\t\t\tprocessGet(packet, session, results);\n\t\t\t\t\tbreak;\n\t\t\t\tcase set:\n\t\t\t\t\tElement e = packet.getElement().findChild(c -> c.getXMLNS() == XMLNS);\n\t\t\t\t\tif (e != null) {\n\t\t\t\t\t\tswitch (e.getName()) {\n\t\t\t\t\t\t\tcase BLOCK:\n\t\t\t\t\t\t\t\tprocessSetBlock(packet, e, session, results);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase UNBLOCK:\n\t\t\t\t\t\t\t\tprocessSetUnblock(packet, e, session, results);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tresults.offer(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet, null, true));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch (TigaseStringprepRuntimeException ex) {\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, ex.getMessage(), true));\n\t\t} catch (TigaseDBException ex) {\n\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet, \"Database error\", true));\n\t\t}\n\t}\n\n\tprivate void processGet(Packet packet, XMPPResourceConnection session, Queue<Packet> results) throws XMPPException, NotAuthorizedException, TigaseDBException {\n\t\tif (packet.getElement().getChild(BLOCKLIST, XMLNS) != null) {\n\t\t\tElement list = new Element(BLOCKLIST);\n\t\t\tlist.setXMLNS(XMLNS);\n\t\t\tList<String> jids = Privacy.getBlocked(session);\n\t\t\tif (jids != null) {\n\t\t\t\tfor (String jid : jids) {\n\t\t\t\t\tlist.addChild(new Element(ITEM, new String[]{_JID}, new String[]{jid}));\n\t\t\t\t}\n\t\t\t}\n\t\t\tsession.putSessionData(ID, ID);\n\t\t\tresults.offer(packet.okResult(list, 0));\n\t\t} else {\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Bad request\", true));\n\t\t}\n\t}\n\n\tprivate void processSetBlock(Packet packet, Element e, XMPPResourceConnection session, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException, PacketErrorTypeException {\n\t\tList<JID> jids = collectJids(e);\n\t\tif (jids != null && !jids.isEmpty()) {\n\t\t\tfor (JID jid : jids) {\n\t\t\t\tPrivacy.block(session, jid.toString());\n\t\t\t\tsendBlockPresences(session, jid, results);\n\t\t\t}\n\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\t\t\tsendPush(session.getParentSession(), packet, results);\n\t\t} else {\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Bad request\", true));\n\t\t}\n\t}\n\n\tprivate void processSetUnblock(Packet packet, Element e, XMPPResourceConnection session, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException {\n\t\tList<JID> jids = collectJids(e);\n\t\tif (jids == null || jids.isEmpty()) {\n\t\t\tList<String> jidsStr = Privacy.getBlocked(session);\n\t\t\tif (jidsStr != null) {\n\t\t\t\tjids = new ArrayList<>(jidsStr.size());\n\t\t\t\tfor (String jidStr : jidsStr) {\n\t\t\t\t\tjids.add(JID.jidInstanceNS(jidStr));\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t\t\n\t\tif (jids != null) {\n\t\t\tfor (JID jid : jids) {\n\t\t\t\tPrivacy.unblock(session, jid.toString());\n\t\t\t\tsendUnblockPresences(session, jid, results);\n\t\t\t}\n\t\t}\n\t\tresults.offer(packet.okResult((Element) null, 0));\n\t\tsendPush(session.getParentSession(), packet, results);\n\t}\n\t\n\tprivate List<JID> collectJids(Element el) {\n\t\treturn el.mapChildren(item -> {\n\t\t\tString jid = item.getAttributeStaticStr(_JID);\n\t\t\ttry {\n\t\t\t\treturn JID.jidInstance(jid);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tthrow new TigaseStringprepRuntimeException(\"Invalid JID: \" + jid, ex);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void sendUnblockPresences(XMPPResourceConnection session, JID jid, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType stype = roster_util.getBuddySubscription(session, jid);\n\t\tif (stype == SubscriptionType.both || stype == SubscriptionType.from) {\n\t\t\tPresenceAbstract.sendPresence(StanzaType.probe, JID.jidInstance(session.getBareJID()), jid, results, null);\n\t\t}\n\t\tif (stype == SubscriptionType.both || stype == SubscriptionType.to) {\n\t\t\tList<XMPPResourceConnection> conns = session.getActiveSessions();\n\t\t\tif (conns != null) {\n\t\t\t\tfor (XMPPResourceConnection conn : conns) {\n\t\t\t\t\tElement pres = conn.getPresence();\n\t\t\t\t\tif (pres != null) {\n\t\t\t\t\t\tPresenceAbstract.sendPresence(null, conn.getjid(), jid, results, pres);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void sendBlockPresences(XMPPResourceConnection session, JID jid, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType stype = roster_util.getBuddySubscription(session, jid);\n\t\tJID[] froms = session.getAllResourcesJIDs();\n\t\tif (stype == SubscriptionType.both || stype == SubscriptionType.to) {\n\t\t\tif (froms != null) {\n\t\t\t\tfor (JID from : froms) {\n\t\t\t\t\tPresenceAbstract.sendPresence(StanzaType.unavailable, from, jid, results, null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void sendPush(XMPPSession session, Packet packet, Queue<Packet> results) {\n\t\tfor (XMPPResourceConnection conn : session.getActiveResources()) {\n\t\t\tif (conn.getSessionData(ID) == ID) {\n\t\t\t\ttry {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\tresult.initVars(null, conn.getJID());\n\t\t\t\t\tresult.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\t\tlog.log(Level.FINEST, \"failed to send push notification as session is not yet authorized\");\n\t\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\t\tlog.log(Level.FINEST, \"failed to send push notification as session is do not have connection id\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t}\n\t\n\tprivate static class TigaseStringprepRuntimeException extends RuntimeException {\n\n\t\tpublic TigaseStringprepRuntimeException(String message, Throwable cause) {\n\t\t\tsuper(message, cause);\n\t\t}\n\t\t\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/C2SDeliveryErrorProcessor.java",
    "content": "/*\n * C2SDeliveryErrorProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Class implements static methods used to create packets to resend messages undelivered \n * to client by C2S and methods used later to distinguish if packet was resent for redelivery \n * \n * @author andrzej\n*/\npublic class C2SDeliveryErrorProcessor {\n\t\n\tprivate static final Logger log = Logger.getLogger(C2SDeliveryErrorProcessor.class.getCanonicalName());\n\t\n\tpublic static final String ELEM_NAME = \"delivery-error\";\n\tpublic static final String XMLNS = \"http://tigase.org/delivery-error\";\n\tprivate static final String[] DELAY_PATH = { Message.ELEM_NAME, \"delay\" };\n\t\t\n\t/**\n\t * Filters packets created by processors to remove delivery-error payload\n\t * \n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param toIgnore \n\t */\n\tpublic static void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, JID toIgnore) {\n\t\tfor (Packet p : results) {\n\t\t\tif (p.getElemName() != tigase.server.Message.ELEM_NAME)\n\t\t\t\tcontinue;\n\n\t\t\tElement elem = p.getElement();\n\t\t\tElement error = elem.getChildStaticStr(ELEM_NAME);\n\t\t\tif (error != null && error.getXMLNS() == XMLNS) {\n\t\t\t\t// We are removing delivery-error payload for outgoing messages\n\t\t\t\t// to other components than with jid toIgnore\n\t\t\t\tif (toIgnore == null || !toIgnore.equals(packet.getPacketTo())) {\n\t\t\t\t\telem.removeChild(error);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void filterErrorElement(Element messageElem) {\n\t\tElement error = messageElem.getChildStaticStr(ELEM_NAME);\n\t\tif (error != null && error.getXMLNS() == XMLNS) {\n\t\t\t// removing error element\n\t\t\tmessageElem.removeChild(error);\n\t\t}\n\t}\n\t\n\t/**\n\t * Filters packets before they are processed by processors to filter out delivery-error \n\t * packets sent to bare jid if other connection is available\n\t * \n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t * @return \n\t */\n\tpublic static boolean preProcess(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, \n\t\t\tQueue<Packet> results, Map<String, Object> settings, Message messageProcessor) {\n\t\tif (packet.getElemName() != tigase.server.Message.ELEM_NAME)\n\t\t\treturn false;\n\n\t\tElement deliveryError = getDeliveryError(packet);\n\t\tif (deliveryError == null)\n\t\t\treturn false;\n\t\t\n\t\ttry {\n\t\t\t// We should ignore messages sent to bare jid if message contains delivery-error \n\t\t\t// payload and other connection is currently active - this is needed to reduce\n\t\t\t// issues related to duplication of messages\n\t\t\t// This would be better if we would check if there is any active session but also\n\t\t\t// if there was any active session then message was processed!\n\t\t\tif (packet.getStanzaTo() != null && packet.getStanzaTo().getResource() == null && session != null) {\n\t\t\t\tif (packet.getElemName() != Message.ELEM_NAME)\n\t\t\t\t\treturn true;\n\t\t\t\t\n\t\t\t\tList<XMPPResourceConnection> sessionsForMessageDelivery = messageProcessor.getConnectionsForMessageDelivery(session);\n\t\t\t\t\n\t\t\t\tif (sessionsForMessageDelivery.isEmpty())\n\t\t\t\t\treturn false;\n\t\t\t\t\n\t\t\t\tString delay = deliveryError.getAttributeStaticStr(\"stamp\");\n\t\t\t\tif (delay == null)\n\t\t\t\t\treturn true;\n\t\t\t\t\n\t\t\t\t// maybe we should forward data to only active sessions which were not available at this point??\n\t\t\t\t// how to get time of error? or maybe original time of message? timestamp might be slow while \n\t\t\t\t// in other case we might get issues with servers in other timezones!\n\t\t\t\tlong time = Long.parseLong(delay);\n\t\t\t\t\n\t\t\t\tfor (XMPPResourceConnection conn : sessionsForMessageDelivery) {\n\t\t\t\t\tif (conn.getCreationTime() <= time)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\tresult.setPacketFrom(packet.getPacketTo());\n\t\t\t\t\tresult.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn false;\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"NotAuthorizedException while processing undelivered message from \"\n\t\t\t\t\t+ \"C2S, packet = \" + packet);\n\t\t\t}\n\t\t} catch (NoConnectionIdException ex) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"NotAuthorizedException while processing undelivered message from \"\n\t\t\t\t\t+ \"C2S, packet = \" + packet);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t/**\n\t * Checks if packet is delivery-error packet\n\t * \n\t * @param packet\n\t * @return true - if packet is delivery-error\n\t */\n\tpublic static boolean isDeliveryError(Packet packet) {\n\t\tElement elem = packet.getElement();\n\t\tElement error = elem.getChildStaticStr(ELEM_NAME);\n\t\treturn error != null && error.getXMLNS() == XMLNS;\n\t}\n\n\t/**\n\t * Finds delivery-error element in packet and returns it\n\t * \n\t * @param packet\n\t * @return true - if packet is delivery-error\n\t */\n\tpublic static Element getDeliveryError(Packet packet) {\n\t\tElement elem = packet.getElement();\n\t\tElement error = elem.getChildStaticStr(ELEM_NAME);\n\t\treturn (error != null && error.getXMLNS() == XMLNS) ? error : null;\n\t}\t\n\t\n\t/**\n\t * Creates delivery-error packets to send to session manager to reprocess\n\t * undelivered packets\n\t * \n\t * @param packet\n\t * @return \n\t */\n\tpublic static Packet makeDeliveryError(Packet packet, Long stamp)  {\n\t\tPacket result = packet.copyElementOnly();\n\t\tresult.setPacketFrom(packet.getPacketTo());\n\t\tElement error = new Element(ELEM_NAME, new String[] { \"xmlns\" }, new String[] { XMLNS });\n\t\tif (stamp != null) {\n\t\t\terror.setAttribute(\"stamp\", String.valueOf(stamp));\n\t\t}\n\t\tresult.getElement().addChild(error);\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/CAPS.java",
    "content": "/*\n * CAPS.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Presence;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterFactory;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.Configurable;\n\n/**\n *\n * @author andrzej\n */\npublic class CAPS\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][]     ELEMENTS = {\n\t\t{ Presence.ELEM_NAME }, Iq.IQ_QUERY_PATH\n\t};\n\tprivate static final String         ID       = \"caps\";\n\tprivate static final Logger         log = Logger.getLogger(CAPS.class\n\t\t\t.getCanonicalName());\n\tprivate static final String         XMLNS_DISCO =\n\t\t\t\"http://jabber.org/protocol/disco#info\";\n\tprivate static final String[]       XMLNSS   = { \"jabber:client\", XMLNS_DISCO };\n\tprivate static final RosterAbstract roster_impl = RosterFactory.getRosterImplementation(\n\t\t\ttrue);\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif ((session != null) && session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tif (packet.getElemName() == Presence.ELEM_NAME) {\n\t\t\t\t\tJID                to = packet.getStanzaTo();\n\t\t\t\t\tMap<JID, String[]> resources = (Map<JID, String[]>) session\n\t\t\t\t\t\t\t.getCommonSessionData(ID);\n\n\t\t\t\t\tif (resources == null) {\n\t\t\t\t\t\tresources = new ConcurrentHashMap<JID, String[]>();\n\t\t\t\t\t\tsession.putCommonSessionData(ID, resources);\n\t\t\t\t\t}\n\t\t\t\t\tif ((packet.getType() == null) || (packet.getType() == StanzaType.available)) {\n\t\t\t\t\t\tElement c = packet.getElement().getChild(\"c\");\n\n\t\t\t\t\t\tif (c == null) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString[] capsNodes    = PresenceCapabilitiesManager.processPresence(c);\n\t\t\t\t\t\tString[] capsNodesOld = resources.put(packet.getStanzaFrom(), capsNodes);\n\n\t\t\t\t\t\tif ((capsNodesOld == null) ||!Arrays.equals(capsNodes, capsNodesOld)) {\n\n\t\t\t\t\t\t\t// we shoud send pep notifications now\n\t\t\t\t\t\t\tif ((to != null) &&!roster_impl.isSubscribedFrom(session, packet\n\t\t\t\t\t\t\t\t\t.getStanzaFrom())) {\n\n\t\t\t\t\t\t\t\t// subscription is not sufficient\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (to == null) {\n\t\t\t\t\t\t\t\tto = session.getJID();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// checking for need of disco#info\n\t\t\t\t\t\t\tPresenceCapabilitiesManager.prepareCapsQueries(JID.jidInstanceNS(to\n\t\t\t\t\t\t\t\t\t.getDomain()), packet.getStanzaFrom(), capsNodes, results);\n\t\t\t\t\t\t\tif (!session.isUserId(to.getBareJID())) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tPresenceCapabilitiesManager.handlePresence(to, packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\tcapsNodes, results);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ((packet.getType() == StanzaType.unavailable) || (packet.getType() ==\n\t\t\t\t\t\t\tStanzaType.error)) {\n\t\t\t\t\t\tresources.remove(packet.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t} else if ((packet.getElemName() == Iq.ELEM_NAME) && ((packet.getType() ==\n\t\t\t\t\t\tStanzaType.error) || (packet.getType() == StanzaType.result))) {\n\t\t\t\t\t\tString nick = packet.getStanzaTo().getLocalpart();\n\n\t\t\t\t\t\tif ((nick == null) || Configurable.DEF_SM_NAME.equals(nick)) {\n\t\t\t\t\t\t\tPresenceCapabilitiesManager.processCapsQueryResponse(packet);\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tLogger.getLogger(CAPS.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tLogger.getLogger(CAPS.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t}\n\t\t} else if (((session == null) || session.isServerSession()) && (packet\n\t\t\t\t.getElemName() == Iq.ELEM_NAME) && ((packet.getType() == StanzaType.error) ||\n\t\t\t\t(packet.getType() == StanzaType.result))) {\n\t\t\tString nick = packet.getStanzaTo().getLocalpart();\n\n\t\t\tif ((nick == null) || Configurable.DEF_SM_NAME.equals(nick)) {\n\t\t\t\tPresenceCapabilitiesManager.processCapsQueryResponse(packet);\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param feature\n\t *\n\t * \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Set<JID> getJidsWithFeature(XMPPResourceConnection session,\n\t\t\tString feature) {\n\t\tSet<JID>           jids      = new HashSet<JID>();\n\t\tMap<JID, String[]> resources = (Map<JID, String[]>) session.getCommonSessionData(ID);\n\n\t\tif (resources != null) {\n\t\t\tList<JID> available = new ArrayList<JID>(resources.keySet());\n\n\t\t\tfor (JID jid : available) {\n\t\t\t\tString[] capsNodes = resources.get(jid);\n\n\t\t\t\tif (capsNodes == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (String capsNode : capsNodes) {\n\t\t\t\t\tString[] features = PresenceCapabilitiesManager.getNodeFeatures(capsNode);\n\n\t\t\t\t\tif (features == null) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (Arrays.binarySearch(features, feature) >= 0) {\n\t\t\t\t\t\tjids.add(jid);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jids;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/ClientStateIndication.java",
    "content": "package tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.annotation.*;\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created by andrzej on 25.06.2016.\n */\n@Id(ClientStateIndication.ID)\n@Handles({\n\t\t@Handle(path = {ClientStateIndication.ACTIVE_NAME}, xmlns = ClientStateIndication.XMLNS),\n\t\t@Handle(path = {ClientStateIndication.INACTIVE_NAME}, xmlns = ClientStateIndication.XMLNS)\n})\n@StreamFeatures({\n\t\t@StreamFeature(elem = \"csi\", xmlns = ClientStateIndication.XMLNS)\n})\npublic class ClientStateIndication extends AnnotatedXMPPProcessor\n\t\timplements XMPPProcessorIfc, XMPPPacketFilterIfc {\n\n\tprivate static final Logger log = Logger.getLogger(ClientStateIndication.class.getCanonicalName());\n\n\tprotected static final String XMLNS = \"urn:xmpp:csi:0\";\n\tprotected static final String ID = XMLNS;\n\n\tprotected static final String ACTIVE_NAME = \"active\";\n\tprotected static final String INACTIVE_NAME = \"inactive\";\n\n\tprivate Logic logic = new MobileV2();\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tif (settings.containsKey(\"logic\")) {\n\t\t\tString cls = (String) settings.get(\"logic\");\n\t\t\ttry {\n\t\t\t\tlogic = (Logic) ModulesManagerImpl.getInstance().forName(cls).newInstance();\n\t\t\t} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {\n\t\t\t\tlog.log(Level.SEVERE, \"Could not create instance of class\", ex);\n\t\t\t}\n\t\t}\n\n\t\tlogic.init(settings);\n\t}\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\tlogic.filter(packet, session, repo, results);\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"ignoring packet from not authorized session which is already of type error\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (packet.getElemName()) {\n\t\t\tcase ACTIVE_NAME:\n\t\t\t\tlogic.deactivate(session, results);\n\t\t\t\tbreak;\n\t\t\tcase INACTIVE_NAME:\n\t\t\t\tlogic.activate(session, results);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tresults.offer(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet, null, true));\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\tif (!session.isAuthorized())\n\t\t\treturn null;\n\t\treturn super.supStreamFeatures(session);\n\t}\n\n\tpublic interface Logic extends XMPPPacketFilterIfc {\n\n\t\tvoid activate(XMPPResourceConnection session, Queue<Packet> results);\n\n\t\tvoid deactivate(XMPPResourceConnection session, Queue<Packet> results);\n\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/DomainFilter.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\n\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.StringUtilities;\nimport tigase.vhosts.VHostItem;\nimport tigase.vhosts.filter.CustomDomainFilter;\nimport tigase.vhosts.filter.DomainFilterPolicy;\n\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Created: Dec 30, 2008 12:43:28 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class DomainFilter\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPPacketFilterIfc, XMPPPreprocessorIfc {\n\t/** constant domain key name */\n\tpublic static final String ALLOWED_DOMAINS_KEY = \"allowed-domains\";\n\n\t/** constant domain list key name */\n\tpublic static final String  ALLOWED_DOMAINS_LIST_KEY = \"allowed-domains-list\";\n\t/** id of the plugin */\n\tprivate static final String ID                       = \"domain-filter\";\n\n\t/** Private logger for class instances. */\n\tprivate static final Logger     log = Logger.getLogger(DomainFilter.class.getName());\n\t/** paths for which plugin should be enabled */\n\tprivate static final String[][] ELEMENTS = ALL_PATHS;\n\n\t/** xmlns for which plugin should be enabled */\n\tprivate static final String[]   XMLNSS   = { ALL_NAMES };\n\n\t/** default local hostname */\n\tprivate static String local_hostname;\n\t\n\tprivate static final String[] EMPTY_STRING_ARRAY = new String[0];\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Filtering (packet): {0}\", packet);\n\t\t}\n\t\tif ((session == null) || (results == null) || (results.size() == 0)) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tDomainFilterPolicy domains = getDomains(session);\n\n\t\t\t// Fast return when user is authorized to send packets to any domain\n\t\t\tif (domains == DomainFilterPolicy.ALL) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tQueue<Packet> errors = new ArrayDeque<Packet>(1);\n\n\t\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\t\tPacket res = it.next();\n\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Filtering (result): {0}\", res );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (domains == DomainFilterPolicy.BLOCK) {\n\t\t\t\t\tif ((res.getType() != StanzaType.error) && ((((res.getStanzaFrom() != null) &&\n\t\t\t\t\t\t\t!session.isUserId(res.getStanzaFrom().getBareJID())) || ((res\n\t\t\t\t\t\t\t.getStanzaTo() != null) &&!session.isUserId(res.getStanzaTo()\n\t\t\t\t\t\t\t.getBareJID()))))) {\n\t\t\t\t\t\tremovePacket(it, res, errors, \"Communication blocked.\");\n\t\t\t\t\t}\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tString outDomain = null;\n\n\t\t\t\tif (res.getStanzaTo() != null) {\n\t\t\t\t\toutDomain = res.getStanzaTo().getDomain();\n\t\t\t\t}\n\t\t\t\tswitch (domains) {\n\t\t\t\tcase LOCAL :\n\t\t\t\t\tif ((outDomain != null) &&!session.isLocalDomain(outDomain, true) && !outDomain.equals( local_hostname )) {\n\t\t\t\t\t\tremovePacket( it, res, errors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within the server local domains.\" );\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LOCAL Domains only, blocking packet (filter): {0}\", res );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LOCAL Domains only, packet not blocked (filter): {0}\", res );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OWN :\n\t\t\t\t\tif ((outDomain != null) && !outDomain.equals( local_hostname )\n\t\t\t\t\t\t\t&&!outDomain.endsWith(session.getDomain().getVhost().getDomain())) {\n\n\t\t\t\t\t\tremovePacket( it, res, errors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within your own domain.\" );\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"OWN Domain only, blocking packet (filter): {0}\", res );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"OWN Domain only, packet not blocked (filter): {0}\", res );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CUSTOM :\n\t\t\t\t\tString[] customRules = getDomainsList(session);\n\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname )\n\t\t\t\t\t\t\t || ( res.getType() != null && res.getType().equals( StanzaType.error ) )\n\t\t\t\t\t\t\t || ( res.getStanzaFrom() == null && res.getStanzaTo() != null\n\t\t\t\t\t\t\t\t\t\t&& session.isUserId( res.getStanzaTo().getBareJID() ) ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean isAlowed = CustomDomainFilter.isAllowed( res.getStanzaFrom(), res.getStanzaTo(), customRules );\n\n\t\t\t\t\tif ( !isAlowed ){\n\t\t\t\t\t\tremovePacket( it, res, errors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Your packet was blocked by server filtering rules - FORBIDDEN\" );\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"CUSTOM filtering rules for domain {0}, blocking packet (filter): {1}, rules: {2}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { outDomain, res, Arrays.asList( customRules) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"CUSTOM filtering rules for domain {0}, packet not blocked (filter): {1}, rules: {2}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { outDomain, res, Arrays.asList( customRules) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BLACKLIST :\n\t\t\t\t\tString[] blacklistedDomains = getDomainsList(session);\n\t\t\t\t\tboolean  blacklist_match          = false;\n\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfor (String domain : blacklistedDomains) {\n\n\t\t\t\t\t\t// Intentionally comparing domains by reference instead of value\n\t\t\t\t\t\t// domain is processed through the String.intern() method\n\t\t\t\t\t\tif (domain == outDomain) {\n\t\t\t\t\t\t\tblacklist_match = true;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (blacklist_match) {\n\t\t\t\t\t\tremovePacket(it, res, errors,\n\t\t\t\t\t\t\t\t\"You attempted to communicate with the blacklisted domain - FORBIDDEN\");\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"BLACKLIST domain {1}, blocking packet (filter): {0}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object [] {res,outDomain} );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"BLACKLIST domain {1], packet not blocked (filter): {0}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object [] {res,outDomain} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase LIST :\n\n\t\t\t\t\tString[] allowedDomains = getDomainsList(session);\n\t\t\t\t\tboolean  found          = false;\n\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfor (String domain : allowedDomains) {\n\n\t\t\t\t\t\t// Intentionally comparing domains by reference instead of value\n\t\t\t\t\t\t// domain is processed through the String.intern() method\n\t\t\t\t\t\tif (domain == outDomain) {\n\t\t\t\t\t\t\tfound = true;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!found) {\n\t\t\t\t\t\tremovePacket( it, res, errors,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within selected list of domains.\" );\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LIST Domain only {1}, blocking packet (filter): {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { res, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LIST Domain only {1}, packet not blocked (filter): {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { res, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tresults.addAll(errors);\n\t\t} catch (NotAuthorizedException ex) {\n\n\t\t\t// This can happen actually easily when filtering initial handshaking\n\t\t\t// packets. I am not sure what to do yet.....\n\t\t\t// Assuming this an initial, and authentication traffic, allowing for\n\t\t\t// everything, which means, just ignore.\n\t\t} catch (TigaseDBException ex) {\n\t\t\tlog.log(Level.WARNING, \"Can't access user repository.\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init( Map<String, Object> settings ) throws TigaseDBException {\n\t\tsuper.init( settings );\n\t\tlocal_hostname = DNSResolverFactory.getInstance().getDefaultHost();\n\t}\n\n\t@Override\n\tpublic boolean preProcess( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings ) {\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Processing: {0}\", packet );\n\t\t}\n\n\t\tboolean stop = false;\n\n\t\tif ( ( session == null ) || session.isServerSession() ){\n\t\t\treturn stop;\n\t\t}\n\t\ttry {\n\t\t\tDomainFilterPolicy domains = getDomains( session );\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"DOMAINS setting is: {0}\", domains.name() );\n\t\t\t}\n\n\t\t\t// Fast return when user is authorized to send packets to any domain\n\t\t\tif ( domains == DomainFilterPolicy.ALL ){\n\t\t\t\treturn stop;\n\t\t\t}\n\n\t\t\tString outDomain = ( packet.getStanzaFrom() != null )\n\t\t\t\t\t\t\t\t\t\t\t\t ? packet.getStanzaFrom().getDomain()\n\t\t\t\t\t\t\t\t\t\t\t\t : null;\n\n\t\t\ttry {\n\t\t\t\tif ( session.getConnectionId().equals( packet.getPacketFrom() ) ){\n\t\t\t\t\toutDomain = ( packet.getStanzaTo() != null )\n\t\t\t\t\t\t\t\t\t\t\t? packet.getStanzaTo().getDomain()\n\t\t\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t}\n\t\t\t} catch ( NoConnectionIdException ex ) {\n\t\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t\t \"No connection id for session, even though this is not a server \"\n\t\t\t\t\t\t\t\t + \"session: {0}, request: {1}\", new Object[] { session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket } );\n\t\t\t}\n\t\t\tswitch ( domains ) {\n\t\t\t\tcase BLOCK:\n\t\t\t\tif ((packet.getType() == StanzaType.error) || ((packet.getStanzaFrom() ==\n\t\t\t\t\t\tnull) || (session.isUserId(packet.getStanzaFrom().getBareJID())\n\t\t\t\t\t\t\t\t\t\t\t&& ((packet.getStanzaTo() == null )\n\t\t\t\t\t\t\t\t\t\t\t\t\t|| session.isUserId( packet.getStanzaTo().getBareJID() ) ) ) ) ){\n\t\t\t\t\t\treturn stop;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tremovePacket( null, packet, results, \"Communication blocked.\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t}\n\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"BLOCK, blocking packet: {0}\", packet );\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase LOCAL:\n\t\t\t\t\tif ( ( outDomain != null ) && !session.isLocalDomain( outDomain, true ) ){\n\t\t\t\t\t\tremovePacket( null, packet, results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within the server local domains.\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LOCAL Domains only {1}, blocking packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LOCAL Domains only {1}, packet not blocked: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OWN:\n\t\t\t\t\tif ( ( outDomain != null ) && !outDomain.equals( local_hostname )\n\t\t\t\t\t\t\t && !outDomain.endsWith( session.getDomain().getVhost().getDomain() ) ){\n\t\t\t\t\t\tremovePacket( null, packet, results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within your own domain.\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"OWN Domain only {1}, blocking packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"OWN Domain only {1}, packet not blocked: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CUSTOM:\n\t\t\t\t\tString[] customRules = getDomainsList( session );\n\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname )\n\t\t\t\t\t\t\t || (packet.getType() == StanzaType.error)\n\t\t\t\t\t\t\t || ( packet.getStanzaFrom() == null && packet.getStanzaTo() != null\n\t\t\t\t\t\t\t\t\t\t&& session.isUserId( packet.getStanzaTo().getBareJID() ) ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean isAlowed = CustomDomainFilter.isAllowed( packet.getStanzaFrom(), packet.getStanzaTo(), customRules );\n\n\t\t\t\t\tif ( !isAlowed ){\n\t\t\t\t\t\tremovePacket( null, packet, results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Your packet was blocked by server filtering rules - FORBIDDEN\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"CUSTOM filtering rules {0}, blocking packet (filter): {1}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { outDomain, packet } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"CUSTOM filtering rules {0}, packet not blocked (filter): {1}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { outDomain, packet } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BLACKLIST:\n\t\t\t\t\tString[] disallowedDomains = getDomainsList( session );\n\t\t\t\t\tboolean blacklist_match = false;\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor ( String domain : disallowedDomains ) {\n\n\t\t\t\t\t// Intentionally comparing domains by reference instead of value\n\t\t\t\t\t\t// domain is processed through the String.intern() method\n\t\t\t\t\t\tif ( domain == outDomain ){\n\t\t\t\t\t\t\tblacklist_match = true;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( blacklist_match ){\n\t\t\t\t\t\tremovePacket( null, packet, results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You attempted to communicate with the blacklisted domain - FORBIDDEN\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Packet to blacklisted domain {1}, blocking packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Packet NOT TO blacklisted domain {1}, NOT blocking packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase LIST:\n\t\t\t\t\tString[] allowedDomains = getDomainsList( session );\n\t\t\t\t\tboolean found = false;\n\n\t\t\t\t\tif ( ( outDomain == null ) || outDomain.equals( local_hostname ) ){\n\t\t\t\t\t\t// don't filter system packets, breaks things\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfor ( String domain : allowedDomains ) {\n\n\t\t\t\t\t// Intentionally comparing domains by reference instead of value\n\t\t\t\t\t\t// domain is processed through the String.intern() method\n\t\t\t\t\t\tif ( domain == outDomain ){\n\t\t\t\t\t\t\tfound = true;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( !found ){\n\t\t\t\t\t\tremovePacket( null, packet, results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"You can only communicate within selected list of domains.\" );\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LISTED Domains only {1}, blocking packet: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"LISTED Domain only {1}, packet not blocked: {0}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { packet, outDomain } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch ( NotAuthorizedException ex ) {\n\n\t\t\t// This can happen actually easily when filtering initial handshaking\n\t\t\t// packets. I am not sure what to do yet.....\n\t\t\t// Assuming this an initial, and authentication traffic, allowing for\n\t\t\t// everything, which means, just ignore.\n\t\t} catch ( TigaseDBException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Can't access user repository.\", ex );\n\t\t}\n\n\t\treturn stop;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t/**\n\t * Method retrieves filtering policy based on user session, from most specific to most general,\n\t * i.e.: first user session is checked, if that fails then user repository and if there is no\n\t * rules configured then domain filtering policy from VHost is being returned (if present).\n\t *\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data. It allows\n\t *                 for storing information in a permanent storage or in memory\n\t *                 only during the live of the online session. This parameter\n\t *                 can be null if there is no online user session at the time\n\t *                 of the packet processing.\n\t *\n\t * @return relevant domain filtering policy\n\t * \n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic DomainFilterPolicy getDomains(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tVHostItem domain = session.getDomain();\n\t\tDomainFilterPolicy domainFilterPolicy\n\t\t\t\t\t\t\t\t\t\t\t = (DomainFilterPolicy) session.getCommonSessionData(ALLOWED_DOMAINS_KEY );\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Domains read from user session: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {domainFilterPolicy, domain} );\n\t\t}\n\t\tif (domainFilterPolicy == null) {\n\t\t\tString dbDomains = session.getData(null, ALLOWED_DOMAINS_KEY, null);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Domains read from database: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {dbDomains, domain});\n\t\t\t}\n\t\t\tdomainFilterPolicy = DomainFilterPolicy.valueof(dbDomains);\n\t\t\tif (domainFilterPolicy == null) {\n\t\t\t\tif (session.isAnonymous()) {\n\t\t\t\t\tdomainFilterPolicy = DomainFilterPolicy.LOCAL;\n\t\t\t\t} else {\n\t\t\t\t\t// by default ALL\n\t\t\t\t\tdomainFilterPolicy = domain.getDomainFilter();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Domains read from VHost item: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew Object[] {domainFilterPolicy, domain});\n\t\t\t}\n\t\t\tsession.putCommonSessionData( ALLOWED_DOMAINS_KEY, domainFilterPolicy );\n\t\t}\n\n\t\treturn domainFilterPolicy;\n\t}\n\n\t/**\n\t * Method retrieves list of domains to be applied to {@code LIST} and\n\t * {@code BLACKLIST} filtering policies based on user session, from most\n\t * specific to most general, i.e.: first user session is checked, if that\n\t * fails then user repository and if there is no rules configured then list of\n\t * domains from VHost is being returned (if present).\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data. It allows for\n\t *                storing information in a permanent storage or in memory only\n\t *                during the live of the online session. This parameter can be\n\t *                null if there is no online user session at the time of the\n\t *                packet processing.\n\t\t *\n\t * @return list of domains to be whitelisted/blacklisted\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic String[] getDomainsList(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tVHostItem domain = session.getDomain();\n\n\t\tString[] domainsList = (String[]) session.getCommonSessionData( ALLOWED_DOMAINS_LIST_KEY );\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Getting list of domains from user session: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { domainsList != null? Arrays.asList( domainsList) : \"\", domain } );\n\t\t}\n\n\t\tif ( domainsList == null ){\n\t\t\tString dbDomains = session.getData( null, ALLOWED_DOMAINS_LIST_KEY, null );\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Domains list read from database: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { dbDomains, domain } );\n\t\t\t}\n\n\t\t\tif ( dbDomains != null ){\n\t\t\t\tdomainsList = StringUtilities.stringToArrayOfString( dbDomains, \";\" );\n\t\t\t} else {\n\t\t\t\tdomainsList = domain.getDomainFilterDomains();\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Domains list read from VHost: {0} for VHost: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { domainsList != null? Arrays.asList( domainsList) : \"\", domain } );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (domainsList == null)\n\t\t\t\tdomainsList = EMPTY_STRING_ARRAY;\n\t\t\tsession.putCommonSessionData( ALLOWED_DOMAINS_LIST_KEY, domainsList );\n\t\t}\n\n\t\treturn domainsList;\n\t}\n\n\t/**\n\t * Helper method removing packets from processing queue and generating\n\t * appropriate error packet to be send back to client\n\t *\n\t * @param it iterator over collection of packets being filtered\n\t * @param res currently processed packet\n\t * @param errors collection of outgoing errors\n\t * @param msg human readable error message\n\t */\n\tprivate void removePacket(Iterator<Packet> it, Packet res, Queue<Packet> errors, String msg) {\n\t\tif (it != null) {\n\t\t\tit.remove();\n\t\t}\n\t\ttry {\n\t\t\terrors.add(Authorization.FORBIDDEN.getResponseMessage(res, msg, true));\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tlog.log(Level.FINE, \"Already error packet, dropping it..: {0}\", res);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/EntityTime.java",
    "content": "package tigase.xmpp.impl;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimeZone;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.annotation.DiscoFeatures;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\n\n/**\n * This supports the implementation of\n * <a href='http://xmpp.org/extensions/xep-0202.html'>XEP-0202</a>: Entity Time.\n *\n */\n@Id(EntityTime.XMLNS)\n@Handles({ @Handle(path = { Iq.ELEM_NAME, EntityTime.TIME }, xmlns = EntityTime.XMLNS) })\n@DiscoFeatures({ EntityTime.XMLNS })\npublic class EntityTime extends XMPPProcessorAbstract {\n\n\tprotected static final String XMLNS = \"urn:xmpp:time\";\n\n\tprotected static final String TIME = \"time\";\n\n\tprivate final static String ID = XMLNS;\n\n\tprivate static String getUtcOffset() {\n\t\tSimpleDateFormat sdf = new SimpleDateFormat(\"Z\");\n\t\tsdf.setTimeZone(TimeZone.getDefault());\n\t\tString dateTimeString = sdf.format(new Date());\n\n\t\treturn dateTimeString.substring(0, 3) + \":\" + dateTimeString.substring(3);\n\t}\n\n\tprivate static String getUtcTime() {\n\t\tSimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\");\n\t\tsdf.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n\t\treturn sdf.format(new Date());\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserOutPacket(JID connectionId, Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t\tsuper.processFromUserOutPacket(connectionId, packet, session, repo, results, settings);\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (packet.getStanzaTo() != null && packet.getStanzaFrom() != null\n\t\t\t\t&& packet.getStanzaTo().equals(packet.getStanzaFrom())) {\n\t\t\tprocessFromUserOutPacket(connectionId, packet, session, repo, results, settings);\n\t\t} else if (packet.getType() == StanzaType.get) {\n\t\t\tsendTimeResult(packet, results);\n\t\t} else\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", true));\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (packet.getType() == StanzaType.get) {\n\t\t\tsendTimeResult(packet, results);\n\t\t} else if (packet.getType() == StanzaType.set)\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", true));\n\t\telse\n\t\t\tsuper.processNullSessionPacket(packet, repo, results, settings);\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t}\n\n\t@Override\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t\tsuper.processToUserPacket(packet, session, repo, results, settings);\n\t}\n\n\tprivate void sendTimeResult(Packet packet, Queue<Packet> results) {\n\t\tPacket resp = packet.okResult((Element) null, 0);\n\n\t\tElement time = new Element(\"time\", new String[] { \"xmlns\" }, new String[] { XMLNS });\n\n\t\tElement tzo = new Element(\"tzo\");\n\t\ttzo.setCData(getUtcOffset());\n\t\ttime.addChild(tzo);\n\n\t\tElement utc = new Element(\"utc\");\n\t\tutc.setCData(getUtcTime());\n\t\ttime.addChild(utc);\n\n\t\tresp.getElement().addChild(time);\n\t\tresults.offer(resp);\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/ErrorCounter.java",
    "content": "/*\n * ErrorCoutner.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Packet;\nimport tigase.stats.CounterValue;\nimport tigase.stats.StatisticsList;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor;\nimport tigase.xmpp.impl.annotation.HandleStanzaTypes;\nimport tigase.xmpp.impl.annotation.Id;\n\nimport java.util.Queue;\nimport java.util.logging.Level;\n\n/**\n * ErrorCounter class is implementation of XMPPProcessor responsible for counting \n * packets with type=error which value is added to Tigase XMPP Server statistics.\n * \n * @author andrzej\n */\n@Id(\"error-counter\")\n@HandleStanzaTypes(StanzaType.error)\npublic class ErrorCounter extends AnnotatedXMPPProcessor implements XMPPPacketFilterIfc {\n\n\tprivate static final String SM_COMP = \"sess-man\";\n\t\n\tprivate final ErrorStatisticsHolder holder = new ErrorStatisticsHolder();\n\t\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tholder.getStatistics(list);\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ALL_PATHS;\n\t}\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\t//process(packet, session);\n\t\tfor (Packet r : results) {\n\t\t\tprocess(r, session);\n\t\t}\n\t}\n\n\tprotected void process(Packet packet, XMPPResourceConnection session) {\n\t\tif (super.canHandle(packet, session) == Authorization.AUTHORIZED) {\n\t\t\tholder.count(packet);\n\t\t}\n\t}\n\n\tpublic static class ErrorStatisticsHolder {\n\t\t\n\t\tprivate static final String[] ERROR_NAMES;\n\t\t\n\t\tprivate final CounterValue[] counters;\n\t\t\n\t\tstatic {\n\t\t\tint counters = Authorization.values().length+1;\n\t\t\tERROR_NAMES = new String[counters];\n\t\t\tAuthorization[] vals = Authorization.values();\n\t\t\tfor (int i=0; i<vals.length; i++) {\n\t\t\t\tString name = vals[i].getCondition();\n\t\t\t\tif (name == null) name = vals[i].name().toLowerCase();\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\t\tsb.append(vals[i].getErrorCode());\n\t\t\t\tfor (String part : name.split(\"-\")) {\n\t\t\t\t\tsb.append(Character.toUpperCase(part.charAt(0)));\n\t\t\t\t\tsb.append(part.substring(1));\n\t\t\t\t}\n\t\t\t\tERROR_NAMES[i] = sb.toString();\n\t\t\t}\n\t\t\tERROR_NAMES[vals.length] = \"0Unknown\";\n\t\t}\n\t\t\n\t\tpublic static String[] getErrorNames() {\n\t\t\treturn ERROR_NAMES;\n\t\t}\n\t\t\n\t\tpublic ErrorStatisticsHolder() {\n\t\t\tcounters = new CounterValue[ERROR_NAMES.length];\n\t\t\tfor (int i=0; i<ERROR_NAMES.length; i++) {\n\t\t\t\tcounters[i] = new CounterValue(ERROR_NAMES[i], Level.FINER);\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void count(Packet packet) {\n\t\t\tString condition = packet.getErrorCondition();\n\t\t\tAuthorization val = Authorization.getByCondition(condition);\n\t\t\tif (val != null)\n\t\t\t\tcounters[val.ordinal()].inc();\n\t\t\telse\n\t\t\t\tcounters[counters.length-1].inc();\n\t\t}\n\n\t\n\t\tpublic void getStatistics(StatisticsList list) {\n\t\t\tfor (CounterValue c : counters) {\n\t\t\t\tlist.add(SM_COMP, \"ErrorStats/\" + c.getName() + \"ErrorsNumber\", c.getValue(), c.getLevel());\n\t\t\t}\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/FlexibleOfflineMessageRetrieval.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Command;\nimport tigase.server.DataForm;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.amp.AmpFeatureIfc;\nimport tigase.server.amp.MsgRepository;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.disco.XMPPService.INFO_XMLNS;\nimport static tigase.disco.XMPPService.ITEMS_XMLNS;\nimport static tigase.server.Message.ELEM_NAME;\n\npublic class FlexibleOfflineMessageRetrieval\n\t\t//\t\textends XMPPProcessor\n\t\textends XMPPProcessorAbstract\n\t\timplements XMPPProcessorIfc {\n\n\t/** Field holds the xmlns of XEP-0013: Flexible offline messages retrieval */\n\tpublic static final String FLEXIBLE_OFFLINE_XMLNS = \"http://jabber.org/protocol/offline\";\n\n\tprivate static final Logger log = Logger.getLogger( FlexibleOfflineMessageRetrieval.class.getName() );\n\n\tprivate static final String OFFLINE_ELEMENT_NAME = \"offline\";\n\tprivate static final String ITEM_ACTION_ATTRIBUTE = \"action\";\n\tpublic static final String ITEM_ELEMENT_NAME = \"item\";\n\tpublic static final String NODE_ATTRIBUTE_NAME = \"node\";\n\tprivate static final String PURGE_ELEMENT_NAME = \"purge\";\n\tprivate static final String FETCH_ELEMENT_NAME = \"fetch\";\n\tprivate static final String[] XMLNSS = { INFO_XMLNS, ITEMS_XMLNS, FLEXIBLE_OFFLINE_XMLNS };\n\tprivate static final String[] IQ_OFFLINE = { Iq.ELEM_NAME, OFFLINE_ELEMENT_NAME };\n\tprivate static final String[][] ELEMENTS = { Iq.IQ_QUERY_PATH, Iq.IQ_QUERY_PATH, IQ_OFFLINE };\n\tprivate static final String ID = FLEXIBLE_OFFLINE_XMLNS;\n\tprivate static final Element[] DISCO_FEATURES = {\n\t\tnew Element( \"feature\", new String[] { \"var\" }, new String[] { FLEXIBLE_OFFLINE_XMLNS } ) };\n\tpublic static final String[] MESSAGE_EVENT_PATH = { ELEM_NAME, \"event\" };\n\tpublic static final String[] MESSAGE_HEADER_PATH = { ELEM_NAME, \"header\" };\n\n\tprivate static final Element identity = new Element( \"identity\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"category\", \"type\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"automation\", \"message-list\" } );\n\tprivate static final Element feature = new Element( \"feature\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"var\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { FLEXIBLE_OFFLINE_XMLNS } );\n\n\tprivate static final String form_type = \"FORM_TYPE\";\n\tprivate static final String NUMBER_OF_ = \"number_of_\";\n\n\tprivate MsgRepository msg_repo = null;\n\tprivate final OfflineMessages offlineProcessor = new OfflineMessages();\n\tprivate final MsgRepository.OfflineMessagesProcessor offlineMessagesStamper = new MsgStamper();\n\n\t@Override\n\tpublic Authorization canHandle(Packet packet, XMPPResourceConnection conn) {\n\t\tif (packet.isServiceDisco()) {\n\t\t\tif (packet.getStanzaTo() == null) {\n\t\t\t\tString node = packet.getAttributeStaticStr(Iq.IQ_QUERY_PATH, \"node\");\n\t\t\t\tif (FLEXIBLE_OFFLINE_XMLNS.equals(node))\n\t\t\t\t\treturn Authorization.AUTHORIZED;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn super.canHandle(packet, conn);\n\t}\t\n\t\n\t@Override\n\tpublic void init( Map<String, Object> settings ) throws TigaseDBException {\n\n\t\tString msg_repo_uri = (String) settings.get( AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY );\n\t\tString msg_repo_cls = (String) settings.get( AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY );\n\n\t\tif ( msg_repo_uri == null ){\n\t\t\tmsg_repo_uri = System.getProperty( AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY );\n\t\t\tif ( msg_repo_uri == null ){\n\t\t\t\tmsg_repo_uri = System.getProperty( RepositoryFactory.GEN_USER_DB_URI_PROP_KEY );\n\t\t\t}\n\t\t}\n\t\tif ( msg_repo_cls == null ){\n\t\t\tmsg_repo_cls = System.getProperty( AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY );\n\t\t}\n\t\tif ( msg_repo_uri != null ){\n\t\t\tMap<String, String> db_props = new HashMap<String, String>( 4 );\n\n\t\t\tfor ( Map.Entry<String, Object> entry : settings.entrySet() ) {\n\t\t\t\tdb_props.put( entry.getKey(), entry.getValue().toString() );\n\t\t\t}\n\n\t\t\t// Initialization of repository can be done here and in Store\n\t\t\t// class so repository related parameters for JDBCMsgRepository\n\t\t\t// should be specified for AMP plugin and AMP component\n\t\t\ttry {\n\t\t\t\tmsg_repo = (MsgRepository) MsgRepository.getInstance( msg_repo_cls, msg_repo_uri );\n\t\t\t\tmsg_repo.initRepository( msg_repo_uri, db_props );\n\t\t\t} catch ( TigaseDBException ex ) {\n\t\t\t\tmsg_repo = null;\n\t\t\t\tlog.log( Level.WARNING, \"Problem initializing connection to DB: \", ex );\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate enum ACTION {\n\n\t\tview, remove\n\t};\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket( JID connectionId, Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings ) throws PacketErrorTypeException {\n\t\tElement query = packet.getElement().findChildStaticStr( Iq.IQ_QUERY_PATH );\n\t\tElement offlineElement = packet.getElement().findChildStaticStr( IQ_OFFLINE );\n\n\t\tif ( null != query ){\n\t\t\tquery = query.clone();\n\t\t\t// processing Service Discovery - info about number of elements and list of elements\n\t\t\tString queryXmlns = query.getXMLNS();\n\t\t\tfinal String node = query.getAttributeStaticStr( NODE_ATTRIBUTE_NAME );\n\n\t\t\tif ( node != null && node.equals( FLEXIBLE_OFFLINE_XMLNS ) ){\n\t\t\t\t// prevent restoring offline messags in other connections\n\t\t\t\tsession.putCommonSessionData( FLEXIBLE_OFFLINE_XMLNS, FLEXIBLE_OFFLINE_XMLNS );\n\t\t\t}\n\n\t\t\tif ( node != null && queryXmlns != null ){\n\t\t\t\tswitch ( queryXmlns ) {\n\t\t\t\t\tcase INFO_XMLNS:\n\t\t\t\t\t\taddDiscoInfo( session, query );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ITEMS_XMLNS:\n\t\t\t\t\t\taddDiscoItems( session, query );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t\t}\n\n\t\t} else if ( null != offlineElement ){\n\t\t\t// processing retrieve/remove stored message/presence query\n\t\t\tfinal List<Element> offlineElementChildren = offlineElement.getChildren();\n\t\t\tList<Element> itemChildren = new LinkedList<Element>();\n\t\t\tboolean fetch = false;\n\t\t\tboolean purge = false;\n\n\t\t\tfor ( Element child : offlineElementChildren ) {\n\t\t\t\tString name = child.getName();\n\t\t\t\tswitch ( name ) {\n\t\t\t\t\tcase ITEM_ELEMENT_NAME:\n\t\t\t\t\t\titemChildren.add( child );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PURGE_ELEMENT_NAME:\n\t\t\t\t\t\tpurge = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FETCH_ELEMENT_NAME:\n\t\t\t\t\t\tfetch = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( itemChildren.isEmpty() && ( purge || fetch ) ){\n\t\t\t\t// we don't have any items elements, only purge or fetch\n\t\t\t\ttry {\n\t\t\t\t\tif ( fetch && !purge ){\n\t\t\t\t\t\tQueue<Packet> restorePacketForOffLineUser = restorePacketForOffLineUser( null, session, msg_repo );\t\t\t\t\t\n\t\t\t\t\t\tresults.addAll( restorePacketForOffLineUser );\n\t\t\t\t\t} else if ( purge && !fetch ){\n\t\t\t\t\t\tmsg_repo.deleteMessagesToJID( null, session );\n\t\t\t\t\t}\n\t\t\t\t} catch ( UserNotFoundException | NotAuthorizedException ex ) {\n\t\t\t\t\tlog.log( Level.WARNING, \"Problem retrieving messages from repository: \", ex );\n\t\t\t\t}\n\t\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t\t} else if ( offlineElementChildren.size() == itemChildren.size() ){\n\t\t\t\t// ok, we have items elements and all of the children are items, no fetch or purge\n\n\t\t\t\t// check if all elements have same action (view/remove)\n\t\t\t\tList<String> itemsView = new LinkedList<>();\n\t\t\t\tList<String> itemsRemove = new LinkedList<>();\n\t\t\t\tfor ( Element item : itemChildren ) {\n\t\t\t\t\tString actionString = item.getAttributeStaticStr( ITEM_ACTION_ATTRIBUTE );\n\t\t\t\t\tACTION action = ACTION.valueOf( actionString.toLowerCase() );\n\t\t\t\t\tswitch ( action ) {\n\t\t\t\t\t\tcase view:\n\t\t\t\t\t\t\titemsView.add( item.getAttributeStaticStr( NODE_ATTRIBUTE_NAME ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase remove:\n\t\t\t\t\t\t\titemsRemove.add( item.getAttributeStaticStr( NODE_ATTRIBUTE_NAME ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tif ( !itemsView.isEmpty() && itemsRemove.isEmpty() ){\n\t\t\t\t\t\t// ok, all items are 'view' type\n\t\t\t\t\t\tQueue<Packet> restorePacketForOffLineUser = restorePacketForOffLineUser( itemsView, session, msg_repo );\n\t\t\t\t\t\tif ( restorePacketForOffLineUser != null & !restorePacketForOffLineUser.isEmpty() ){\n\t\t\t\t\t\t\tresults.addAll( restorePacketForOffLineUser );\n\t\t\t\t\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tPacket err = Authorization.ITEM_NOT_FOUND.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested item was not found\", true );\n\t\t\t\t\t\t\tresults.offer( err );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( itemsView.isEmpty() && !itemsRemove.isEmpty() ){\n\t\t\t\t\t\t// ok, all items are 'remove' type\n\t\t\t\t\t\tint deleteMessagesToJID = msg_repo.deleteMessagesToJID( itemsRemove, session );\n\t\t\t\t\t\tif ( deleteMessagesToJID == 0 ){\n\t\t\t\t\t\t\tPacket err = Authorization.ITEM_NOT_FOUND.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested item was not found\", true );\n\t\t\t\t\t\t\tresults.offer( err );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPacket err = Authorization.NOT_ACCEPTABLE.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"All query items should have same action\", true );\n\t\t\t\t\t\tresults.offer( err );\n\t\t\t\t\t}\n\t\t\t\t} catch ( UserNotFoundException | NotAuthorizedException ex ) {\n\t\t\t\t\tlog.log( Level.WARNING, \"Problem retrieving messages from repository: \", ex );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void addDiscoInfo( XMPPResourceConnection session, Element query ) {\n\n\t\ttry {\n\n\t\t\tMap<Enum, Long> messagesCount = msg_repo.getMessagesCount( session.getJID() );\n\n\t\t\tif ( messagesCount != null && !messagesCount.isEmpty() ){\n\t\t\t\tquery.addChild( identity );\n\t\t\t\tquery.addChild( feature );\n\n\t\t\t\tDataForm.addDataForm( query, Command.DataType.result );\n\t\t\t\tDataForm.addHiddenField( query, form_type, FLEXIBLE_OFFLINE_XMLNS );\n\n\t\t\t\tfor ( Map.Entry<Enum, Long> entrySet : messagesCount.entrySet() ) {\n\t\t\t\t\tDataForm.addFieldValue( query, NUMBER_OF_ + entrySet.getKey(), entrySet.getValue().toString() );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch ( NotAuthorizedException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Problem retrieving messages from repository: \", ex );\n\t\t} catch ( UserNotFoundException ex ) {\n\t\t\t\n\t\t}\n\t}\n\n\tprivate void addDiscoItems( XMPPResourceConnection session, Element query ) {\n\n\t\ttry {\n\t\t\tList<Element> messagesList = msg_repo.getMessagesList( session.getJID() );\n\t\t\tif ( null != messagesList && !messagesList.isEmpty() ){\n\t\t\t\tquery.addChildren( messagesList );\n\t\t\t}\n\t\t} catch ( NotAuthorizedException | UserNotFoundException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Problem retrieving messages from repository: \", ex );\n\t\t}\n\t}\n\n\tpublic Queue<Packet> restorePacketForOffLineUser( List<String> db_ids, XMPPResourceConnection conn,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMsgRepository repo )\n\t\t\tthrows UserNotFoundException, NotAuthorizedException {\n\t\tQueue<Element> elems = repo.loadMessagesToJID( db_ids, conn, false, offlineMessagesStamper );\n\n\t\tif ( elems != null ){\n\t\t\tLinkedList<Packet> pacs = new LinkedList<Packet>();\n\t\t\tElement elem = null;\n\n\t\t\twhile ( ( elem = elems.poll() ) != null ) {\n\t\t\t\ttry {\n\t\t\t\t\tfinal Packet packetInstance = Packet.packetInstance( elem );\n\t\t\t\t\tif (packetInstance.getElemName() == Iq.ELEM_NAME) {\n\t\t\t\t\t\tpacketInstance.initVars(packetInstance.getStanzaFrom(), conn.getJID());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpacketInstance.setPacketTo( conn.getConnectionId() );\n\t\t\t\t\t}\n\t\t\t\t\tpacs.offer( packetInstance );\n\t\t\t\t} catch ( TigaseStringprepException | NoConnectionIdException ex ) {\n\t\t\t\t\tlog.warning( \"Packet addressing problem, stringprep failed: \" + elem );\n\t\t\t\t}\n\t\t\t}    // end of while (elem = elems.poll() != null)\n\t\t\ttry {\n\t\t\t\tCollections.sort( pacs, offlineProcessor.new StampComparator() );\n\t\t\t} catch ( NullPointerException e ) {\n\t\t\t\ttry {\n\t\t\t\t\tlog.warning( \"Can not sort off line messages: \" + pacs + \",\\n\" + e );\n\t\t\t\t} catch ( Exception exc ) {\n\t\t\t\t\tlog.log( Level.WARNING, \"Can not print log message.\", exc );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn pacs;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket( Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings ) throws PacketErrorTypeException {\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures( final XMPPResourceConnection session ) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tprivate static class MsgStamper implements MsgRepository.OfflineMessagesProcessor {\n\n\t\tpublic static Element offlineElementIns = new Element( OFFLINE_ELEMENT_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Element[] { new Element( ITEM_ELEMENT_NAME ) },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { FLEXIBLE_OFFLINE_XMLNS } );\n\n\t\t@Override\n\t\tpublic void stamp( Element msg, String msgID ) {\n\t\t\tElement clone = offlineElementIns.clone();\n\t\t\tfinal Element item = clone.getChild( FlexibleOfflineMessageRetrieval.ITEM_ELEMENT_NAME );\n\t\t\titem.setAttribute( FlexibleOfflineMessageRetrieval.NODE_ATTRIBUTE_NAME, msgID );\n\t\t\tmsg.addChild( clone );\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/IBB.java",
    "content": "/*\n * IBB.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n/**\n * XEP-0047: In-Band Bytestreams (IBB)\n * The class is not abstract in fact. Is has been made abstract artificially\n * to prevent from loading the class.\n *\n *\n * Created: Sat Jan 13 16:37:29 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated This class has been deprecated and replaced with\n * <code>tigase.server.xmppsession.PacketFilter</code> code. The class is left\n * for educational purpose only and should not be used. It may be removed in\n * future releases.\n */\n@Deprecated\npublic abstract class IBB\n\t\t\t\textends SimpleForwarder {\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ Iq.ELEM_NAME, \"open\" }, { Iq.ELEM_NAME, \"data\" }, { Iq.ELEM_NAME, \"close\" }\n\t};\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger   log    = Logger.getLogger(IBB.class.getName());\n\tprivate static final String   XMLNS  = \"http://jabber.org/protocol/ibb\";\n\tprivate static final String   ID     = XMLNS;\n\tprivate static final String[] XMLNSS = { XMLNS, XMLNS, XMLNS };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/InvisibleCommand.java",
    "content": "/*\n * InvisibleCommand.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterFactory;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport static tigase.xmpp.StanzaType.set;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Class InvisibleCommand implements XEP-0186 Invisible Command support\n *\n * @see <a href=\"http://xmpp.org/extensions/xep-0186.html\">XEP-0186</a>\n *\n * @author andrzej\n */\npublic class InvisibleCommand\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc {\n\tprivate static final String ID = \"invisible-command\";\n\tprivate static final Logger log = Logger.getLogger(InvisibleCommand.class\n\t\t\t.getCanonicalName());\n\tprivate static final String     XMLNS          = \"urn:xmpp:invisible:0\";\n\tprivate static final String[]   VISIBLE_PATH   = { Iq.ELEM_NAME, \"visible\" };\n\tprivate static final String[]   INVISIBLE_PATH = { Iq.ELEM_NAME, \"invisible\" };\n\tprivate static final String[][] ELEMENT_PATHS  = {\n\t\tINVISIBLE_PATH, VISIBLE_PATH\n\t};\n\tprivate static final String[]   XMLNSS         = { XMLNS, XMLNS };\n\tprivate static final String     ACTIVE_KEY     = ID + \"-active\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected RosterAbstract roster_util = getRosterUtil();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\n\t\t// stop presence broadcast if invisibility is activated - only offline should be allowed to broadcast it to buddies with direct stanza sent\n\t\tif ((packet.getElemName() == \"presence\") && (packet.getStanzaTo() == null) && (packet\n\t\t\t\t.getType() != StanzaType.unavailable)) {\n\t\t\tBoolean active = (Boolean) session.getSessionData(ACTIVE_KEY);\n\n\t\t\tactive = (active != null) && active;\n\t\t\tif (active) {\n\t\t\t\tpacket.processedBy(ID);\n\t\t\t}\n\n\t\t\treturn active;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"ignoring packet from not authorized session which is already of type error\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tStanzaType type = packet.getType();\n\n\t\t\t\tswitch (type) {\n\t\t\t\tcase set :\n\n\t\t\t\t\t// @todo: need to implement handing\n\t\t\t\t\tif (packet.getElement().findChildStaticStr(INVISIBLE_PATH) != null) {\n\n\t\t\t\t\t\t// invisibility started - set flag\n\t\t\t\t\t\tsession.putSessionData(ACTIVE_KEY, Boolean.TRUE);\n\n\t\t\t\t\t\t// send offline presence\n\t\t\t\t\t\tElement presence = new Element(\"presence\", new String[] { \"from\", \"type\" },\n\t\t\t\t\t\t\t\tnew String[] { session.getJID().toString(),\n\t\t\t\t\t\t\t\t\"unavailable\" });\n\n\t\t\t\t\t\tsession.putSessionData(XMPPResourceConnection.PRESENCE_KEY, presence);\n\t\t\t\t\t\tPresenceState.broadcastOffline(session, results, settings, roster_util);\n\t\t\t\t\t\tsession.removeSessionData(PresenceState.OFFLINE_BUD_SENT);\n\n\t\t\t\t\t\t// session.removeSessionData(XMPPResourceConnection.PRESENCE_KEY);\n\t\t\t\t\t} else if (packet.getElement().findChildStaticStr(VISIBLE_PATH) != null) {\n\n\t\t\t\t\t\t// invisibility left - clear flag\n\t\t\t\t\t\tsession.removeSessionData(ACTIVE_KEY);\n\t\t\t\t\t}\n\n\t\t\t\t\t// sending result\n\t\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"InvisibleCommand processing type is incorrect\", false));\n\t\t\t\t}\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"Not authorized\", false));\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\"Error accessing database\", false));\n\t\t\t}\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tlog.log(Level.SEVERE, \"packet error type exception\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENT_PATHS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>RosterAbstract</code>\n\t */\n\tprotected RosterAbstract getRosterUtil() {\n\t\treturn RosterFactory.getRosterImplementation(true);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/09/21\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqAuth.java",
    "content": "/*\n * JabberIqAuth.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.auth.CallbackHandlerFactory;\nimport tigase.auth.callbacks.VerifyPasswordCallback;\nimport tigase.auth.MechanismSelector;\nimport tigase.auth.MechanismSelectorFactory;\nimport tigase.auth.TigaseSaslProvider;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.security.Security;\n\nimport java.util.Collection;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.Sasl;\n\n/**\n * JEP-0078: Non-SASL Authentication\n *\n *\n * Created: Thu Feb 16 17:46:16 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqAuth\n\t\t\t\textends AbstractAuthPreprocessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENT_PATHS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger   log = Logger.getLogger(JabberIqAuth.class.getName());\n\tprivate static final String   XMLNS  = \"jabber:iq:auth\";\n\tprivate static final String   ID     = XMLNS;\n\tprivate static final String[] XMLNSS = { XMLNS };\n\tprivate static final String[] IQ_QUERY_USERNAME_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME,\n\t\t\t\"username\" };\n\tprivate static final String[] IQ_QUERY_RESOURCE_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME,\n\t\t\t\"resource\" };\n\tprivate static final String[] IQ_QUERY_PASSWORD_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME,\n\t\t\t\"password\" };\n\tprivate static final String[] IQ_QUERY_DIGEST_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME,\n\t\t\t\"digest\" };\n\tprivate static final Element[] FEATURES = { new Element(\"auth\", new String[] {\n\t\t\t\"xmlns\" }, new String[] { \"http://jabber.org/features/iq-auth\" }) };\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }) };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CallbackHandlerFactory callbackHandlerFactory = new CallbackHandlerFactory();\n\tprivate MechanismSelector      mechanismSelector;\n\n\t//~--- methods --------------------------------------------------------------\n\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\n\t\t// we should remove existing tigase.sasl provider if it is not instance of TigaseSaslProvider\n\t\t// as it can be loaded from other bundle in OSGi which will cause many issues with instanceof\n\t\t// and casting and it is NOT possible to update implementation without removing it first\n\t\tif (!(Security.getProvider(\"tigase.sasl\") instanceof TigaseSaslProvider)) {\n\t\t\tSecurity.removeProvider(\"tigase.sasl\");\n\t\t}\n\t\tSecurity.insertProviderAt(new TigaseSaslProvider(settings), 1);\n\t\tsuper.init(settings);\n\n\t\tMechanismSelectorFactory mechanismSelectorFactory = new MechanismSelectorFactory();\n\n\t\ttry {\n\t\t\tmechanismSelector = mechanismSelectorFactory.create(settings);\n\t\t} catch (Exception e) {\n\t\t\tlog.severe(\"Can't create SASL Mechanism Selector\");\n\n\t\t\tthrow new RuntimeException(\"Can't create SASL Mechanism Selector\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tsynchronized (session) {\n\n\t\t\t// If authentication timeout expired, ignore the request....\n\t\t\tif (session.getSessionData(XMPPResourceConnection.AUTHENTICATION_TIMEOUT_KEY) !=\n\t\t\t\t\tnull) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.isAuthorized()) {\n\n\t\t\t\t// Multiple authentication attempts....\n\t\t\t\t// Another authentication request on already authenticated\n\t\t\t\t// connection\n\t\t\t\t// This is not allowed and must be forbidden.\n\t\t\t\tPacket res = Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"Cannot authenticate twice on the same stream.\", false);\n\n\t\t\t\t// Make sure it gets delivered before stream close\n\t\t\t\tres.setPriority(Priority.SYSTEM);\n\t\t\t\tresults.offer(res);\n\n\t\t\t\t// Optionally close the connection to make sure there is no\n\t\t\t\t// confusion about the connection state.\n\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t\t.set, session.nextStanzaId()));\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Discovered second authentication attempt: {0}, packet: {1}\",\n\t\t\t\t\t\t\tnew Object[] { session.toString(),\n\t\t\t\t\t\t\tpacket.toString() });\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tsession.logout();\n\t\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\t\tlog.log(Level.FINER, \"Unsuccessful session logout: {0}\", session.toString());\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Session after logout: {0}\", session.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tElement    request = packet.getElement();\n\t\t\tStanzaType type    = packet.getType();\n\n\t\t\tswitch (type) {\n\t\t\tcase get :\n\t\t\t\ttry {\n\t\t\t\t\tStringBuilder            response = new StringBuilder(\"<username/>\");\n\t\t\t\t\tfinal Collection<String> auth_mechs = mechanismSelector.filterMechanisms(Sasl\n\t\t\t\t\t\t\t.getSaslServerFactories(), session);\n\n\t\t\t\t\tif (auth_mechs.contains(\"PLAIN\") || auth_mechs.contains(\"DIGEST-MD5\")) {\n\t\t\t\t\t\tresponse.append(\"<password/>\");\n\t\t\t\t\t}\n\n\t\t\t\t\t// response.append(\"<digest/>\");\n\t\t\t\t\tresponse.append(\"<resource/>\");\n\t\t\t\t\tresults.offer(packet.okResult(response.toString(), 1));\n\t\t\t\t} catch (NullPointerException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE))\n\t\t\t\t\t\tlog.fine(\"Database problem, most likely misconfiguration error: \" + ex);\n\t\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase set :\n\n\t\t\t\t// Now we use loginOther() instead to make it easier to\n\t\t\t\t// customize\n\t\t\t\t// the authentication protocol without a need to replace the\n\t\t\t\t// authentication plug-in. The authentication takes place on the\n\t\t\t\t// AuthRepository\n\t\t\t\t// level so we do not really care here what the user has sent.\n\t\t\t\tString user_name = request.getChildCDataStaticStr(IQ_QUERY_USERNAME_PATH);\n\t\t\t\tString resource  = request.getChildCDataStaticStr(IQ_QUERY_RESOURCE_PATH);\n\t\t\t\tString password  = request.getChildCDataStaticStr(IQ_QUERY_PASSWORD_PATH);\n\t\t\t\tString digest    = request.getChildCDataStaticStr(IQ_QUERY_DIGEST_PATH);\n\n\t\t\t\ttry {\n\t\t\t\t\tBareJID user_id = BareJID.bareJIDInstance(user_name, session.getDomain()\n\t\t\t\t\t\t\t.getVhost().getDomain());\n\t\t\t\t\tAuthorization result = doAuth(repo, settings, session, user_id, password,\n\t\t\t\t\t\t\tdigest);\n\n\t\t\t\t\tif (result == Authorization.AUTHORIZED) {\n\n\t\t\t\t\t\t// Some clients don't send resource here, instead they\n\t\t\t\t\t\t// send it later\n\t\t\t\t\t\t// in resource bind packet.\n\t\t\t\t\t\tif ((resource != null) &&!resource.isEmpty()) {\n\t\t\t\t\t\t\tsession.setResource(resource);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Authentication successful.\", false));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Authentication failed\", false));\n\t\t\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(),\n\t\t\t\t\t\t\t\tStanzaType.set, session.nextStanzaId()));\n\t\t\t\t\t}    // end of else\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.info(\"Authentication failed: \" + user_name);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Authorization exception: \", e);\n\t\t\t\t\t}\n\n\t\t\t\t\tPacket response = Authorization.NOT_AUTHORIZED.getResponseMessage(packet, e\n\t\t\t\t\t\t\t.getMessage(), false);\n\n\t\t\t\t\tresponse.setPriority(Priority.SYSTEM);\n\t\t\t\t\tresults.offer(response);\n\n\t\t\t\t\tInteger retries = (Integer) session.getSessionData(\"auth-retries\");\n\n\t\t\t\t\tif (retries == null) {\n\t\t\t\t\t\tretries = new Integer(0);\n\t\t\t\t\t}\n\t\t\t\t\tif (retries.intValue() < 3) {\n\t\t\t\t\t\tsession.putSessionData(\"auth-retries\", new Integer(retries.intValue() + 1));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(),\n\t\t\t\t\t\t\t\tStanzaType.set, session.nextStanzaId()));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Message type is incorrect\", false));\n\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t\t.set, session.nextStanzaId()));\n\n\t\t\t\tbreak;\n\t\t\t}    // end of switch (type)\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param repo\n\t * @param settings\n\t * @param session\n\t * @param user_id\n\t * @param password\n\t * @param digest\n\t *\n\t * \n\t */\n\tprotected Authorization doAuth(NonAuthUserRepository repo, Map<String,\n\t\t\tObject> settings, XMPPResourceConnection session, BareJID user_id, String password,\n\t\t\tString digest) {\n\t\ttry {\n\t\t\tCallbackHandler cbh = callbackHandlerFactory.create(\"PLAIN\", session, repo,\n\t\t\t\t\tsettings);\n\t\t\tfinal NameCallback nc = new NameCallback(\"Authentication identity\", user_id\n\t\t\t\t\t.getLocalpart());\n\t\t\tfinal VerifyPasswordCallback vpc = new VerifyPasswordCallback(password);\n\n\t\t\tcbh.handle(new Callback[] { nc });\n\t\t\ttry {\n\t\t\t\tcbh.handle(new Callback[] { vpc });\n\t\t\t\tif (vpc.isVerified()) {\n\t\t\t\t\tsession.authorizeJID(user_id, false);\n\n\t\t\t\t\treturn Authorization.AUTHORIZED;\n\t\t\t\t}\n\t\t\t} catch (UnsupportedCallbackException e) {\n\t\t\t\tfinal PasswordCallback pc = new PasswordCallback(\"Password\", false);\n\n\t\t\t\tcbh.handle(new Callback[] { pc });\n\n\t\t\t\tchar[] p = pc.getPassword();\n\n\t\t\t\tif ((p != null) && password.equals(new String(p))) {\n\t\t\t\t\tsession.authorizeJID(user_id, false);\n\n\t\t\t\t\treturn Authorization.AUTHORIZED;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Authorization.NOT_AUTHORIZED;\n\t\t} catch (Exception e) {\n\t\t\tlog.log(Level.WARNING, \"Can't authenticate with given CallbackHandler\", e);\n\n\t\t\treturn Authorization.INTERNAL_SERVER_ERROR;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENT_PATHS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\tif ((session == null) || session.isAuthorized()) {\n\t\t\treturn null;\n\t\t} else if (session.isTlsRequired() && !session.isEncrypted()) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn FEATURES;\n\t\t} // end of if (session.isAuthorized()) else\n\t}\n}    // JabberIqAuth\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqCommand.java",
    "content": "/*\n * JabberIqCommand.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class JabberIqCommand here.\n *\n *\n * Created: Mon Jan 22 22:41:17 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqCommand\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_COMMAND_PATH\n\t};\n\tprivate static final Logger     log = Logger.getLogger(JabberIqCommand.class.getName());\n\tprivate static final String[]   XMLNSS   = { Command.XMLNS };\n\tprivate static final String     XMLNS    = Command.XMLNS;\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final Element[]  DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Authorization canHandle(Packet packet, XMPPResourceConnection conn) {\n\t\tif (conn == null)\n\t\t\treturn null;\n\t\treturn super.canHandle(packet, conn);\n\t}\n\t\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Processing only commands (that should be guaranteed by name space)\n\t\t// and only unknown commands. All known commands are processed elsewhere\n//  if (!packet.isCommand() || packet.getCommand() != Command.OTHER) {\n//    return;\n//  }\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Received packet: {0}\", packet);\n\t\t\t}\n\n\t\t\t// Not needed anymore. Packet filter does it for all stanzas.\n//    // For all messages coming from the owner of this account set\n//    // proper 'from' attribute. This is actually needed for the case\n//    // when the user sends a message to himself.\n//    if (packet.getFrom().equals(session.getConnectionId())) {\n//      packet.getElement().setAttribute(\"from\", session.getJID());\n//    } // end of if (packet.getFrom().equals(session.getConnectionId()))\n\t\t\tif (packet.getStanzaTo() == null) {\n\n\t\t\t\t// No need for that, initVars(...) takes care of that\n\t\t\t\t// packet.getElement().setAttribute(\"to\", session.getSMComponentId().toString());\n\t\t\t\tpacket.initVars(packet.getStanzaFrom(), session.getSMComponentId());\n\n\t\t\t\t// TODO: Code below prevents from executing commands sent to vhost set to\n\t\t\t\t// the same value as the machine hostname. Not sure why it was implemented\n\t\t\t\t// that way. Maybe it caused internal, infinite loop in some cases.\n\t\t\t\t// More testing is needed....\n//      } else {\n//        if (packet.getStanzaTo().equals(session.getSMComponentId())) {\n//          // This should be handled by SM, if it is not then drop it here.\n//          if (log.isLoggable(Level.FINEST)) {\n//            log.log(Level.FINEST, \"Dropping unhandled packet addressed to SM: {0}\", packet);\n//          }\n//          return;\n//        }\n\t\t\t}\n\n\t\t\tBareJID id = packet.getStanzaTo().getBareJID();\n\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\tJID    conId  = session.getConnectionId(packet.getStanzaTo());\n\n\t\t\t\tif (conId != null) {\n\t\t\t\t\tresult.setPacketTo(conId);\n\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t} else {\n\t\t\t\t\tresult = Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"The recipient is no longer available.\", true);\n\t\t\t\t\tresult.setPacketFrom(null);\n\t\t\t\t\tresult.setPacketTo(null);\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// This is message to some other client\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresults.offer(result);\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.log(Level.WARNING, \"NotAuthorizedException for packet: {0}\", packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqIq.java",
    "content": "/*\n * JabberIqIq.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.util.Base64;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class JabberIqIq here.\n *\n *\n * Created: Sun Feb 25 23:37:48 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqIq\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\tprivate static final String     LEVEL    = \"level\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(JabberIqIq.class.getName());\n\n\t/**\n\t * I don't want to have any offensive texts in my code so let's\n\t * encode them with Base64....\n\t */\n\tprivate static String[] not_so_smart_words = {\n\t\t\"ZnVjaw==\", \"c2hpdA==\", \"d2hvcmU=\", \"ZGljaw==\", \"YXNz\", \"YW51cw==\", \"YXJzZQ==\",\n\t\t\"dmFnaW5h\", \"cG9ybg==\", \"cGVuaXM=\", \"cGlzcw==\", \"c3V4\"\n\t};\n\tprivate static final String    XMLNS  = \"jabber:iq:iq\";\n\tprivate static final String    ID     = XMLNS;\n\tprivate static final String[]  XMLNSS = { XMLNS };\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * IQ range table:\n\t * Number Range   Descriptive Label\n\t * 140+   genius\n\t * 120-139  very superior\n\t * 110-119  superior\n\t * 90-109   normal\n\t * 80-89  dull\n\t * 70-79  borderline deficiency\n\t * 50-69  moron\n\t * 20-49  imbecile\n\t * 0-19   idiot\n\t *\n\t * @param iq_level\n\t *\n\t * \n\t */\n\tpublic static String calculateIQ(String iq_level) {\n\t\tdouble value = 100;\n\n\t\ttry {\n\t\t\tvalue = Double.parseDouble(iq_level);\n\t\t} catch (NumberFormatException e) {\n\t\t\tvalue = 100;\n\t\t}\n\t\tif (value >= 140) {\n\t\t\treturn \"genius\";\n\t\t}\n\t\tif ((120 <= value) && (value <= 139)) {\n\t\t\treturn \"very superior\";\n\t\t}\n\t\tif ((110 <= value) && (value <= 119)) {\n\t\t\treturn \"superior\";\n\t\t}\n\t\tif ((90 <= value) && (value <= 109)) {\n\t\t\treturn \"normal\";\n\t\t}\n\t\tif ((80 <= value) && (value <= 89)) {\n\t\t\treturn \"dull\";\n\t\t}\n\t\tif ((70 <= value) && (value <= 79)) {\n\t\t\treturn \"borderline deficiency\";\n\t\t}\n\t\tif ((50 <= value) && (value <= 69)) {\n\t\t\treturn \"moron\";\n\t\t}\n\t\tif ((20 <= value) && (value <= 49)) {\n\t\t\treturn \"imbecile\";\n\t\t}\n\t\tif ((0 <= value) && (value <= 19)) {\n\t\t\treturn \"idiot\";\n\t\t}\n\n\t\treturn \"out of range\";\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\ttry {\n\t\t\tif ((session != null) && (packet.getFrom() != null) && packet.getFrom().equals(\n\t\t\t\t\tsession.getConnectionId()) && (packet.getElemName() == tigase.server.Message\n\t\t\t\t\t.ELEM_NAME)) {\n\t\t\t\tevaluateMessage(session, packet.getElemCDataStaticStr(tigase.server.Message\n\t\t\t\t\t\t.MESSAGE_BODY_PATH));\n\t\t\t}\n\t\t} catch (Exception e) {\n\n\t\t\t// Ignore....\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif ((session == null) && (packet.getType() != null) && (packet.getType() == StanzaType\n\t\t\t\t.get)) {\n\t\t\ttry {\n\t\t\t\tString iq_level = repo.getPublicData(packet.getStanzaTo().getBareJID(), ID,\n\t\t\t\t\t\tLEVEL, null);\n\n\t\t\t\tresults.offer(getResponsePacket(packet, iq_level));\n\t\t\t} catch (UserNotFoundException e) {\n\n\t\t\t\t// Just ignore....\n\t\t\t}    // end of try-catch\n\n\t\t\treturn;\n\t\t}      // end of if (session == null)\n\t\tif (session == null) {\n\t\t\tlog.info(\"Session null, dropping packet: \" + packet.toString());\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\n\t\t\t// Not needed anymore. Packet filter does it for all stanzas.\n//    if (packet.getFrom().equals(session.getConnectionId())) {\n//      packet.getElement().setAttribute(\"from\", session.getJID());\n//    } // end of if (packet.getFrom().equals(session.getConnectionId()))\n\t\t\tBareJID id = null;\n\n\t\t\tif (packet.getStanzaTo() != null) {\n\t\t\t\tid = packet.getStanzaTo().getBareJID();\n\t\t\t}    // end of if (packet.getElemTo() != null)\n\t\t\tif ((id == null) || session.isUserId(id)) {\n\t\t\t\tStanzaType type = packet.getType();\n\n\t\t\t\tswitch (type) {\n\t\t\t\tcase get :\n\t\t\t\t\tString iq_level = session.getPublicData(ID, LEVEL, null);\n\n\t\t\t\t\tresults.offer(getResponsePacket(packet, iq_level));\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase set :\n\t\t\t\t\tif (packet.getFrom().equals(session.getConnectionId())) {\n\t\t\t\t\t\tString curr_iq = changeIq(session, -2);\n\n\t\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"You are not allowed to set own IQ, your current IQ score: \" + curr_iq,\n\t\t\t\t\t\t\t\ttrue));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"You are not authorized to set vcard data.\", true));\n\t\t\t\t\t}    // end of else\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase result :\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\t\tresults.offer(result);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (type)\n\t\t\t} else {\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresults.offer(result);\n\t\t\t}      // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"Received privacy request but user session is not authorized yet: \" +\n\t\t\t\t\tpacket.toString());\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.warning(\"Database proble, please contact admin: \" + e);\n\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tprivate String changeIq(XMPPResourceConnection session, double val)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tdouble value = getIq(session);\n\n\t\tvalue += val;\n\n\t\tString curr = new Double(value).toString();\n\n\t\tsession.setPublicData(ID, LEVEL, curr);\n\n\t\treturn curr;\n\t}\n\n\tprivate void evaluateMessage(XMPPResourceConnection session, String msg)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (msg == null) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User wrote a message, good + 0.01\n\t\tdouble val     = 0.01;\n\t\tint    msg_len = msg.trim().length();\n\n\t\tif ((msg_len > 10) && (msg_len < 100)) {\n\t\t\tval += 0.01;\n\t\t}\n\t\tif ((msg_len >= 100) && (msg_len < 200)) {\n\t\t\tval += 0.1;\n\t\t}\n\t\tif ((msg_len >= 200) && (msg_len < 500)) {\n\t\t\tval += 0.01;\n\t\t}\n\t\tif (msg_len >= 500) {\n\t\t\tval -= 0.1;\n\t\t}\n\t\tfor (String not_smart : not_so_smart_words) {\n\t\t\tif (msg.contains(new String(Base64.decode(not_smart)))) {\n\t\t\t\tval -= 0.1;\n\t\t\t}\n\t\t}\n\n\t\tdouble iq = getIq(session);\n\n\t\tval = val / iq;\n\t\tiq  += val;\n\n\t\tString curr = new Double(iq).toString();\n\n\t\tsession.setPublicData(ID, LEVEL, curr);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate double getIq(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tString iq_level = session.getPublicData(ID, LEVEL, \"100\");\n\t\tdouble iq       = 100;\n\n\t\ttry {\n\t\t\tiq = Double.parseDouble(iq_level);\n\t\t} catch (NumberFormatException e) {\n\t\t\tiq = 100;\n\t\t}\n\n\t\treturn iq;\n\t}\n\n\tprivate Packet getResponsePacket(Packet packet, String iq_level) {\n\t\tif (iq_level == null) {\n\t\t\tiq_level = \"100\";\n\t\t}\n\n\t\tElement query = new Element(\"query\", new Element[] { new Element(\"num\", iq_level),\n\t\t\t\tnew Element(\"desc\", calculateIQ(iq_level)) }, new String[] { \"xmlns\" },\n\t\t\t\t\t\tnew String[] { XMLNS });\n\n\t\treturn packet.okResult(query, 0);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqOOB.java",
    "content": "/*\n * JabberIqOOB.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n/**\n * Class JabberIqOOB.\n * The class is not abstract in fact. Is has been made abstract artificially\n * to prevent from loading the class.\n *\n * Created: Sat Jan 13 21:55:46 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated This class has been deprecated and replaced with\n * <code>tigase.server.xmppsession.PacketFilter</code> code. The class is left\n * for educational purpose only and should not be used. It may be removed in\n * future releases.\n */\n@Deprecated\npublic abstract class JabberIqOOB\n\t\t\t\textends SimpleForwarder {\n\tprivate static final Logger     log      = Logger.getLogger(JabberIqOOB.class\n\t\t\t.getName());\n\tprivate static final String     XMLNS    = \"jabber:iq:oob\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\tprivate static final String[]   XMLNSS   = { XMLNS };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqPrivacy.java",
    "content": "/*\n * JabberIqPrivacy.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.ArrayDeque;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterFactory;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport static tigase.xmpp.impl.Privacy.*;\n\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport tigase.xmpp.PacketErrorTypeException;\n\n/**\n * Describe class JabberIqPrivacy here.\n *\n *\n * Created: Mon Oct  9 18:18:11 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqPrivacy\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc, XMPPPacketFilterIfc {\n\tprotected static final String     ACTIVE_EL_NAME  = \"active\";\n\tprotected static final Element     BLOCKED_ELEM = new Element(\"blocked\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:blocking:errors\" });\n\tprotected static final String     DEFAULT_EL_NAME = \"default\";\n\tprotected static final String[][] ELEMENTS        = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\tprotected static final String     LIST_EL_NAME    = \"list\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprotected static Logger          log = Logger.getLogger(JabberIqPrivacy.class.getName());\n\tprotected static final String    ERROR_EL_NAME        = \"error\";\n\tprotected static final String    PRESENCE_EL_NAME     = \"presence\";\n\tprotected static final String    PRESENCE_IN_EL_NAME  = \"presence-in\";\n\tprotected static final String    PRESENCE_OUT_EL_NAME = \"presence-out\";\n\tprotected static final String    XMLNS                = \"jabber:iq:privacy\";\n\tprotected static final String    ID                   = XMLNS;\n\tprotected static final String[]  XMLNSS               = { XMLNS };\n\tprotected static RosterAbstract  roster_util = RosterFactory.getRosterImplementation(\n\t\t\ttrue);\n\tprotected static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }) };\n\tprotected static final Comparator<Element> compar = new Comparator<Element>() {\n\t\t@Override\n\t\tpublic int compare(Element el1, Element el2) {\n\t\t\tString or1 = el1.getAttributeStaticStr(ORDER);\n\t\t\tString or2 = el2.getAttributeStaticStr(ORDER);\n\t\t\tif (or1.length() != or2.length())\n\t\t\t\treturn Integer.compare(or1.length(), or2.length());\n\n\t\t\treturn or1.compareTo(or2);\n\t\t}\n\t};\n\n\t//~--- constant enums -------------------------------------------------------\n\n\tprotected enum ITEM_ACTION { allow, deny }\n\n\tprotected enum ITEM_SUBSCRIPTIONS {\n\t\tboth, to, from, none\n\t}\n\n\tprotected enum ITEM_TYPE {\n\t\tjid, group, subscription, all\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif ((session == null) ||!session.isAuthorized() || (results == null) || (results\n\t\t\t\t.size() == 0)) {\n\t\t\treturn;\n\t\t}\n\t\tQueue<Packet> errors = null;\n\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\tPacket res = it.next();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Checking outbound packet: {0}\", res);\n\t\t\t}\n\n\t\t\t// Always allow presence unavailable to go, privacy lists packets and\n\t\t\t// all other which are allowed by privacy rules\n\t\t\tif ((res.getType() == StanzaType.unavailable) || res.isXMLNSStaticStr(Iq\n\t\t\t\t\t.IQ_QUERY_PATH, XMLNS) || allowed(res, session)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet not allowed to go, removing: {0}\", res);\n\t\t\t}\n\t\t\tit.remove();\n\t\t\t\n\t\t\t// support for sending error responses if packet is blocked\n\t\t\tPacket error = prepareError(res, session);\n\t\t\tif (error != null) {\n\t\t\t\tif (errors == null)\n\t\t\t\t\terrors = new ArrayDeque<Packet>();\n\t\t\t\terrors.offer(error);\n\t\t\t}\n\t\t}\n\t\tif (errors != null)\n\t\t\tresults.addAll(errors);\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * <code>preProcess</code> method checks only incoming stanzas\n\t * so it doesn't check for presence-out at all.\n\t */\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tif ((session == null) ||!session.isAuthorized() || packet.isXMLNSStaticStr(Iq\n\t\t\t\t.IQ_QUERY_PATH, XMLNS)) {\n\t\t\treturn false;\n\t\t}    // end of if (session == null)\n\n\t\tboolean allowed = allowed(packet, session);\n\t\tif (!allowed) {\n\t\t\tPacket error = prepareError(packet, session);\n\t\t\tif (error != null)\n\t\t\t\tresults.offer(error);\n\t\t}\n\t\treturn !allowed;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\t\t\tStanzaType type = packet.getType();\n\n\t\t\tswitch (type) {\n\t\t\tcase get :\n\t\t\t\tprocessGetRequest(packet, session, results);\n\n\t\t\t\tbreak;\n\n\t\t\tcase set :\n\t\t\t\tprocessSetRequest(packet, session, results);\n\n\t\t\t\tbreak;\n\n\t\t\tcase result :\n\t\t\tcase error :\n\n\t\t\t\t// Ignore\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\tbreak;\n\t\t\t}    // end of switch (type)\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\"Received privacy request but user session is not authorized yet: {0}\", packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.WARNING, \"Database problem, please contact admin: {0}\", e);\n\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tprotected boolean allowed(Packet packet, XMPPResourceConnection session) {\n\t\ttry {\n\t\t\tif (allowedByDefault(packet, session))\n\t\t\t\treturn true;\n\n\t\t\tElement list = Privacy.getActiveList(session);\n\n\t\t\tif ((list == null) ) {\n\t\t\t\tlist = Privacy.getDefaultList( session );\n\t\t\t}                  // end of if (lName == null)\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Using privcy list: {0}\", list);\n\t\t\t}\n\t\t\tif (list != null) {\n\t\t\t\tList<Element> items = list.getChildren();\n\n\t\t\t\tif (items != null) {\n\t\t\t\t\tBareJID sessionUserId = session.getBareJID();\n\t\t\t\t\tJID jid = packet.getStanzaFrom();\n\t\t\t\t\tboolean packetIn = true;\n\n\t\t\t\t\tif ((jid == null) || sessionUserId.equals(jid.getBareJID())) {\n\t\t\t\t\t\tjid = packet.getStanzaTo();\n\t\t\t\t\t\tpacketIn = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tCollections.sort(items, compar);\n\t\t\t\t\tfor (Element item : items) {\n\t\t\t\t\t\tfinal ITEM_ACTION action = ITEM_ACTION.valueOf(item.getAttributeStaticStr(ACTION));\n\t\t\t\t\t\tboolean   type_matched = false;\n\t\t\t\t\t\tboolean   elem_matched = false;\n\t\t\t\t\t\tITEM_TYPE type         = ITEM_TYPE.all;\n\n\t\t\t\t\t\tif (item.getAttributeStaticStr(TYPE) != null) {\n\t\t\t\t\t\t\ttype = ITEM_TYPE.valueOf(item.getAttributeStaticStr(TYPE));\n\t\t\t\t\t\t}            // end of if (item.getAttribute(TYPE) != null)\n\n\t\t\t\t\t\tString  value         = item.getAttributeStaticStr(VALUE);\n\t\t\t\t\t\tif (jid != null) {\n\t\t\t\t\t\t\tswitch (type) {\n\t\t\t\t\t\t\tcase jid :\n\t\t\t\t\t\t\t\ttype_matched = jid.toString().contains(value);\n\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase group :\n\t\t\t\t\t\t\t\tString[] groups = roster_util.getBuddyGroups(session, jid);\n\n\t\t\t\t\t\t\t\tif (groups != null) {\n\t\t\t\t\t\t\t\t\tfor (String group : groups) {\n\t\t\t\t\t\t\t\t\t\tif (type_matched = group.equals(value)) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}    // end of if (group.equals(value))\n\t\t\t\t\t\t\t\t\t}      // end of for (String group: groups)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase subscription :\n\t\t\t\t\t\t\t\tITEM_SUBSCRIPTIONS subscr = ITEM_SUBSCRIPTIONS.valueOf(value);\n\n\t\t\t\t\t\t\t\tswitch (subscr) {\n\t\t\t\t\t\t\t\tcase to :\n\t\t\t\t\t\t\t\t\ttype_matched = roster_util.isSubscribedTo(session, jid);\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase from :\n\t\t\t\t\t\t\t\t\ttype_matched = roster_util.isSubscribedFrom(session, jid);\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase none :\n\t\t\t\t\t\t\t\t\ttype_matched = (!roster_util.isSubscribedFrom(session, jid) &&\n\t\t\t\t\t\t\t\t\t\t\t!roster_util.isSubscribedTo(session, jid));\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase both :\n\t\t\t\t\t\t\t\t\ttype_matched = (roster_util.isSubscribedFrom(session, jid) &&\n\t\t\t\t\t\t\t\t\t\t\troster_util.isSubscribedTo(session, jid));\n\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault :\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}    // end of switch (subscr)\n\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase all :\n\t\t\t\t\t\t\tdefault :\n\t\t\t\t\t\t\t\ttype_matched = true;\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}      // end of switch (type)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (type == ITEM_TYPE.all) {\n\t\t\t\t\t\t\t\ttype_matched = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}        // end of if (from != null) else\n\t\t\t\t\t\tif (!type_matched) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}        // end of if (!type_matched)\n\n\t\t\t\t\t\tList<Element> elems = item.getChildren();\n\n\t\t\t\t\t\tif ((elems == null) || (elems.size() == 0)) {\n\t\t\t\t\t\t\telem_matched = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (Element elem : elems) {\n\t\t\t\t\t\t\t\tif (matchToPrivacyListElement(packetIn, packet, elem, action)) {\n\t\t\t\t\t\t\t\t\telem_matched = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // end of else\n\t\t\t\t\t\tif (!elem_matched) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}        // end of if (!elem_matched)\n\n\t\t\t\t\t\tswitch (action) {\n\t\t\t\t\t\tcase allow :\n\t\t\t\t\t\t\treturn true;\n\n\t\t\t\t\t\tcase deny :\n\t\t\t\t\t\t\treturn false;\n\n\t\t\t\t\t\tdefault :\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}        // end of switch (action)\n\t\t\t\t\t}          // end of for (Element item: items)\n\t\t\t\t}            // end of if (items != null)\n\t\t\t}              // end of if (lName != null)\n\t\t\t// there is no active nor default list, as per XEP-0016 2.2 Business rules\n\t\t\t// such stanza should be processed normally\n\t\t\telse {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (NoConnectionIdException e) {\n\n\t\t\t// Always allow, this is server dummy session\n\t\t} catch (NotAuthorizedException e) {\n\n//    results.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n//        \"You must authorize session first.\", true));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.log(Level.WARNING, \"Database problem, please notify the admin. {0}\", e);\n\t\t}\n\n\t\treturn true;\n\t}\n\t\n\tprotected boolean allowedByDefault(Packet packet, XMPPResourceConnection session) throws NoConnectionIdException, NotAuthorizedException {\n\t\t// If this is a preprocessing phase, always allow all packets to\n\t\t// make it possible for the client to communicate with the server.\n\t\tif (session.getConnectionId().equals(packet.getPacketFrom())) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// allow packets without from attribute and packets with from attribute same as domain name\n\t\tif ((packet.getStanzaFrom() == null) || ((packet.getStanzaFrom().getLocalpart()\n\t\t\t\t== null) && session.getBareJID().getDomain().equals(packet.getStanzaFrom()\n\t\t\t\t\t\t.getDomain()))) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// allow packets without to attribute and packets with to attribute same as domain name\n\t\tif ((packet.getStanzaTo() == null) || ((packet.getStanzaTo().getLocalpart()\n\t\t\t\t== null) && session.getBareJID().getDomain().equals(packet.getStanzaTo()\n\t\t\t\t\t\t.getDomain()))) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Always allow packets sent between sessions of same user and\n\t\t// packets sent from user to his bare jid and results of this\n\t\t// packets\n\t\tif (packet.getStanzaFrom() != null && packet.getStanzaTo() != null\n\t\t\t\t&& packet.getStanzaFrom().getBareJID().equals(packet.getStanzaTo().getBareJID())) {\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tif (packet.getType() == StanzaType.error && packet.getStanzaTo() != null && session.isUserId(packet.getStanzaTo().getBareJID())) {\n\t\t\t// this may be error sent back to sender of blocked request\n\t\t\t// or even to user who sent packet to blocked user\n\t\t\tElement error = packet.getElement().findChild(e -> e.getName() == ERROR_EL_NAME);\n\t\t\tif (error != null && error.findChild(e -> e.getName() == Authorization.NOT_ACCEPTABLE.getCondition()) != null \n\t\t\t\t\t&& error.findChild(e -> e.getName() == BLOCKED_ELEM.getName() && e.getXMLNS() == BLOCKED_ELEM.getXMLNS()) != null)\n\t\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\t\n\tprotected boolean matchToPrivacyListElement(boolean packetIn, Packet packet, Element elem, ITEM_ACTION action) {\n\t\tif ((packet.getElemName() == PRESENCE_EL_NAME)\n\t\t\t\t&& ((packetIn && (elem.getName() == PRESENCE_IN_EL_NAME)) || (!packetIn && (elem.getName() == PRESENCE_OUT_EL_NAME)))\n\t\t\t\t&& ((packet.getType() == null) || (packet.getType() == StanzaType.unavailable))) {\n\t\t\treturn true;\n\t\t}\n\t\tif (packetIn && (elem.getName() == packet.getElemName())) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\tprotected Packet prepareError(Packet packet, XMPPResourceConnection session) {\n\t\tif (packet.getType() != StanzaType.error) {\n\t\t\ttry {\n\t\t\t\tPacket error = null;\n\t\t\t\tswitch (packet.getElemName()) {\n\t\t\t\t\tcase \"presence\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"message\":\n\t\t\t\t\t\tif (packet.getStanzaFrom() == null || session.isUserId(packet.getStanzaFrom().getBareJID())) {\n\t\t\t\t\t\t\t// we need this here to make sure that this error will be sent to user only once\n\t\t\t\t\t\t\t// as there might be many outgoing messages as result of sending message to single\n\t\t\t\t\t\t\t// user - ie. messages sent to message archive, etc.\n\t\t\t\t\t\t\tif (packet.getPacketTo() != null)\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\terror = Authorization.NOT_ACCEPTABLE.getResponseMessage(packet, null, true);\n\t\t\t\t\t\t\terror.getElement().getChild(\"error\").addChild(BLOCKED_ELEM.clone());\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\terror = Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn error;\n\t\t\t\t\tcase \"iq\":\n\t\t\t\t\t\tif (packet.getType() == StanzaType.get || packet.getType() == StanzaType.set) {\n\t\t\t\t\t\t\tif (packet.getStanzaFrom() == null || session.isUserId(packet.getStanzaFrom().getBareJID())) {\n\t\t\t\t\t\t\t\terror = Authorization.NOT_ACCEPTABLE.getResponseMessage(packet, null, true);\n\t\t\t\t\t\t\t\terror.getElement().getChild(\"error\").addChild(BLOCKED_ELEM.clone());\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\terror = Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn error;\n\t\t\t\t}\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tlog.log(Level.FINEST, \"Packet droped due to privacy list rules. Error could not be generated properly \"\n\t\t\t\t\t\t+ \"as session is not authorized yet, should not happen.\", ex);\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINER, \"Packet dropped due to privacy list rules. Packet is error type already: {0}\",\n\t\t\t\t\t\tpacket.toStringSecure());\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprotected void processGetRequest(final Packet packet,\n\t\t\tfinal XMPPResourceConnection session, final Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, XMPPException, TigaseDBException {\n\t\tList<Element> children = packet.getElemChildrenStaticStr(Iq.IQ_QUERY_PATH);\n\n\t\tif ((children == null) || (children.size() == 0)) {\n\t\t\tString[] lists = Privacy.getLists(session);\n\n\t\t\tif (lists != null) {\n\t\t\t\tStringBuilder sblists = new StringBuilder(100);\n\n\t\t\t\tfor (String list : lists) {\n\t\t\t\t\tsblists.append(\"<list name=\\\"\").append(list).append(\"\\\"/>\");\n\t\t\t\t}\n\n\t\t\t\tString list = Privacy.getDefaultListName(session);\n\n\t\t\t\tif (list != null) {\n\t\t\t\t\tsblists.append(\"<default name=\\\"\").append(list).append(\"\\\"/>\");\n\t\t\t\t}    // end of if (defList != null)\n\t\t\t\tlist = Privacy.getActiveListName(session);\n\t\t\t\tif (list != null) {\n\t\t\t\t\tsblists.append(\"<active name=\\\"\").append(list).append(\"\\\"/>\");\n\t\t\t\t}    // end of if (defList != null)\n\t\t\t\tresults.offer(packet.okResult(sblists.toString(), 1));\n\t\t\t} else {\n\t\t\t\tresults.offer(packet.okResult((String) null, 1));\n\t\t\t}      // end of if (buddies != null) else\n\t\t} else {\n\t\t\tif (children.size() > 1) {\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"You can retrieve only one list at a time.\", true));\n\t\t\t} else {\n\t\t\t\tElement eList = Privacy.getList(session, children.get(0).getAttributeStaticStr(\n\t\t\t\t\t\t\"name\"));\n\n\t\t\t\tif (eList != null) {\n\t\t\t\t\tresults.offer(packet.okResult(eList, 1));\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Requested list not found.\", true));\n\t\t\t\t}    // end of if (eList != null) else\n\t\t\t}      // end of else\n\t\t}        // end of else\n\t}\n\n\tprotected void processSetRequest(final Packet packet,\n\t\t\tfinal XMPPResourceConnection session, final Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, XMPPException, TigaseDBException {\n\t\tList<Element> children = packet.getElemChildrenStaticStr(Iq.IQ_QUERY_PATH);\n\n\t\tif ((children != null) && (children.size() == 1)) {\n\t\t\tElement child = children.get(0);\n\n\t\t\tif (child.getName() == LIST_EL_NAME) {\n\n\t\t\t\t// Broken privacy implementation sends list without name set\n\t\t\t\t// instead of sending BAD_REQUEST error I can just assign\n\t\t\t\t// 'default' name here.\n\t\t\t\tString name = child.getAttributeStaticStr(NAME);\n\n\t\t\t\tif ((name == null) || (name.length() == 0)) {\n\t\t\t\t\tchild.setAttribute(NAME, \"default\");\n\t\t\t\t}    // end of if (name == null || name.length() == 0)\n\n\t\t\t\tList<Element> items = child.getChildren();\n\n\t\t\t\tif ((items == null) || items.isEmpty()) {\n\t\t\t\t\t// if the list is in use then forbid changes\n\t\t\t\t\tboolean inUse = session.getCommonSessionData(PRIVACY_LIST_LOADED) != null\n\t\t\t\t\t\t\t\t\t\t\t\t\t&& session.getCommonSessionData(DEFAULT) != null;\n\n\t\t\t\t\tif (!inUse) {\n\t\t\t\t\t\tfor (XMPPResourceConnection activeSession : session.getActiveSessions()) {\n\t\t\t\t\t\t\tif (activeSession.equals( session)) {\n\t\t\t\t\t\t\t\t// don't apply to the current session\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinUse |= name.equals(Privacy.getActiveListName(activeSession));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (inUse) {\n\t\t\t\t\t\tresults.offer(Authorization.CONFLICT.getResponseMessage(packet, \"Can not modify list while being in use by other session\", true));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPrivacy.removeList(session, child);\n\t\t\t\t\t\tresults.offer(packet.okResult((String) null, 0));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tAuthorization error = validateList(session, items);\n\n\t\t\t\t\tif (error == null) {\n\t\t\t\t\t\tPrivacy.addList(session, child);\n\n\t\t\t\t\t\t// updating active list if it's name matches name of updated list\n\t\t\t\t\t\tfor (XMPPResourceConnection activeSession : session.getActiveSessions()) {\n\t\t\t\t\t\t\tif (name.equals(Privacy.getActiveListName(activeSession))) {\n\t\t\t\t\t\t\t\tPrivacy.setActiveList(activeSession, name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// update default list\n\t\t\t\t\t\tif (name.equals( Privacy.getDefaultListName( session))) {\n\t\t\t\t\t\t\tPrivacy.setDefaultList( session, child );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer(packet.okResult((String) null, 0));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.offer(error.getResponseMessage(packet, null, true));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}      // end of if (child.getName().equals(\"list))\n\t\t\tif (child.getName() == DEFAULT_EL_NAME) {\n\n\t\t\t\t// User selects a different default list\n\t\t\t\tString  listName = child.getAttributeStaticStr(NAME);\n\t\t\t\tElement list     = Privacy.getList(session, listName);\n\n\t\t\t\tif ((listName != null) && (list == null)) {\n\t\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Selected list was not found on the server\", true));\n\t\t\t\t} else {\n\t\t\t\t\t// This is either declining of default list use or setting a new default list\n\t\t\t\t\tPrivacy.setDefaultList( session, list );\n\t\t\t\t\tresults.offer(packet.okResult((String) null, 0));\n\t\t\t\t}\n\t\t\t}      // end of if (child.getName().equals(\"list))\n\t\t\tif (child.getName() == ACTIVE_EL_NAME) {\n\n\t\t\t\t// User selects a different active list\n\t\t\t\tString  listName = child.getAttributeStaticStr(NAME);\n\t\t\t\tElement list     = Privacy.getList(session, listName);\n\n\t\t\t\tif ((listName != null) && (list == null)) {\n\t\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Selected list was not found on the server\", true));\n\t\t\t\t} else {\n\n\t\t\t\t\t// This is either declining of active list use or setting a new active list\n\t\t\t\t\tPrivacy.setActiveList(session, child.getAttributeStaticStr(NAME));\n\t\t\t\t\tresults.offer(packet.okResult((String) null, 0));\n\t\t\t\t}\n\t\t\t}    // end of if (child.getName().equals(\"list))\n\t\t} else {\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\"Only 1 element is allowed in privacy set request.\", true));\n\t\t}    // end of else\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param items\n\t *\n\t * \n\t */\n\tpublic static Authorization validateList(final XMPPResourceConnection session,\n\t\t\tfinal List<Element> items) {\n\t\tAuthorization result = null;\n\n\t\ttry {\n\t\t\tHashSet<Integer> orderSet = new HashSet<Integer>();\n\n\t\t\t// creating set of all known groups in roster\n\t\t\tHashSet<String> groups = new HashSet<String>();\n\n\t\t\tif (session != null) {\n\t\t\t\tJID[] jids = roster_util.getBuddies(session);\n\n\t\t\t\tif (jids != null) {\n\t\t\t\t\tfor (JID jid : jids) {\n\t\t\t\t\t\tString[] buddyGroups = roster_util.getBuddyGroups(session, jid);\n\n\t\t\t\t\t\tif (buddyGroups != null) {\n\t\t\t\t\t\t\tfor (String group : buddyGroups) {\n\t\t\t\t\t\t\t\tgroups.add(group);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (Element item : items) {\n\t\t\t\tITEM_TYPE type = ITEM_TYPE.all;\n\n\t\t\t\tif (item.getAttributeStaticStr(TYPE) != null) {\n\t\t\t\t\ttype = ITEM_TYPE.valueOf(item.getAttributeStaticStr(TYPE));\n\t\t\t\t}    // end of if (item.getAttribute(TYPE) != null)\n\n\t\t\t\tString value = item.getAttributeStaticStr(VALUE);\n\n\t\t\t\tswitch (type) {\n\t\t\t\tcase jid :\n\n\t\t\t\t\t// if jid is not valid it will throw exception\n\t\t\t\t\tJID.jidInstance(value);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase group :\n\t\t\t\t\tboolean matched = groups.contains(value);\n\n\t\t\t\t\tif (!matched) {\n\t\t\t\t\t\tresult = Authorization.ITEM_NOT_FOUND;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase subscription :\n\n\t\t\t\t\t// if subscription is not valid it will throw exception\n\t\t\t\t\tITEM_SUBSCRIPTIONS.valueOf(value);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase all :\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (result != null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// if action is not valid it will throw exception\n\t\t\t\tITEM_ACTION.valueOf(item.getAttributeStaticStr(ACTION));\n\n\t\t\t\t// checking unique order attribute value\n\t\t\t\tInteger order = Integer.parseInt(item.getAttributeStaticStr(ORDER));\n\n\t\t\t\tif ((order == null) || (order < 0) ||!orderSet.add(order)) {\n\t\t\t\t\tresult = Authorization.BAD_REQUEST;\n\t\t\t\t}\n\t\t\t\tif (result != null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception ex) {\n\n\t\t\t// if we get exception list is not valid\n\t\t\tresult = Authorization.BAD_REQUEST;\n\t\t}\n\n\t\treturn result;\n\t}\n}    // JabberIqPrivacy\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqPrivate.java",
    "content": "/*\n * JabberIqPrivate.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class JabberIqPrivate here.\n *\n *\n * Created: Mon Apr 16 08:28:18 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqPrivate\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\n\t/**\n\t * Private logger for class instancess.\n\t */\n\tprivate static Logger             log = Logger.getLogger(JabberIqPrivate.class\n\t\t\t.getName());\n\tprivate static final String       XMLNS       = \"jabber:iq:private\";\n\tprivate static final String       PRIVATE_KEY = XMLNS;\n\tprivate static final String       ID          = XMLNS;\n\tprivate static final String[]     XMLNSS      = { XMLNS };\n\tprivate static final SimpleParser parser      = SingletonFactory.getParserInstance();\n\tprivate static final Element[]    DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\t// Don't do anything if session is null\n\t\tif (session == null) {\n\t\t\tlog.info(\"Session null, dropping packet: \" + packet.toString());\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\t\t\tif ((packet.getStanzaTo() != null) &&!session.isUserId(packet.getStanzaTo()\n\t\t\t\t\t.getBareJID())) {\n\t\t\t\tresults.offer(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\"You are not authorized to access this private storage.\", true));\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (packet.getFrom().equals(session.getConnectionId())) {\n\t\t\t\tList<Element> elems = packet.getElemChildrenStaticStr(Iq.IQ_QUERY_PATH);\n\n\t\t\t\tif ((elems != null) && (elems.size() > 0)) {\n\t\t\t\t\tElement    elem = elems.get(0);\n\t\t\t\t\tStanzaType type = packet.getType();\n\n\t\t\t\t\tswitch (type) {\n\t\t\t\t\tcase get :\n\t\t\t\t\t\tString priv = session.getData(PRIVATE_KEY, elem.getName() + elem.getXMLNS(),\n\t\t\t\t\t\t\t\tnull);\n\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Loaded private data for key: \" + elem.getName() + \": \" + priv);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (priv != null) {\n\t\t\t\t\t\t\tresults.offer(parseXMLData(priv, packet));\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer(packet.okResult((String) null, 2));\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase set :\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"Saving private data: \" + elem.toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsession.setData(PRIVATE_KEY, elem.getName() + elem.getXMLNS(), elem\n\t\t\t\t\t\t\t\t.toString());\n\t\t\t\t\t\tresults.offer(packet.okResult((String) null, 0));\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase result :\n\n\t\t\t\t\t\t// Should never happen, it is an error and should be ignored\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault :\n\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}    // end of switch (type)\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(Authorization.NOT_ACCEPTABLE.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Missing query child element\", true));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"You are not authorized to access this private storage.\", true));\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"Received privacy request but user session is not authorized yet: \" +\n\t\t\t\t\tpacket.toString());\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.warning(\"Database proble, please contact admin: \" + e);\n\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tprivate Packet parseXMLData(String data, Packet packet) {\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\tparser.parse(domHandler, data.toCharArray(), 0, data.length());\n\n\t\tQueue<Element> elems  = domHandler.getParsedElements();\n\t\tPacket         result = packet.okResult((Element) null, 1);\n\t\tElement        query  = result.getElement().findChildStaticStr(Iq.IQ_QUERY_PATH);\n\n\t\tfor (Element el : elems) {\n\t\t\tquery.addChild(el);\n\t\t}    // end of for (Element el: elems)\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqRegister.java",
    "content": "/*\n * JabberIqRegister.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.form.Field;\nimport tigase.form.Form;\nimport tigase.form.FormSignatureVerifier;\nimport tigase.form.FormSignerException;\nimport tigase.form.SignatureCalculator;\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\nimport tigase.stats.StatisticsList;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * JEP-0077: In-Band Registration\n * \n * \n * Created: Thu Feb 16 13:14:06 2006\n * \n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqRegister extends XMPPProcessor implements XMPPProcessorIfc {\n\tprivate static final int REMOTE_ADDRESS_IDX = 2;\n\tprivate static final String[][] ELEMENTS = { Iq.IQ_QUERY_PATH };\n\tpublic static final String ID = \"jabber:iq:register\";\n\n\t/**\n\t * Whitelist properties\n\t */\n\n\tpublic static final String REGISTRATION_BLACKLIST_PROP_KEY = \"registration-blacklist\";\n\n\tpublic static final String REGISTRATION_WHITELIST_PROP_KEY = \"registration-whitelist\";\n\n\tpublic static final String WHITELIST_REGISTRATION_ONLY_PROP_KEY = \"whitelist-registration-only\";\n\n\tprivate List<CIDRAddress> registrationWhitelist = new LinkedList<CIDRAddress>();\n\tprivate List<CIDRAddress> registrationBlacklist = new LinkedList<CIDRAddress>();\n\tprivate boolean whitelistRegistrationOnly = false;\n\n\t/**\n\t * OAuth details for form verifier.\n\t */\n\tpublic static final String OAUTH_CONSUMERKEY_PROP_KEY = \"oauth-consumer-key\";\n\tpublic static final String OAUTH_CONSUMERSECRET_PROP_KEY = \"oauth-consumer-secret\";\n\tpublic static final String SIGNED_FORM_REQUIRED_PROP_KEY = \"signed-form-required\";\n\n\tprivate String oauthConsumerKey;\n\tprivate String oauthConsumerSecret;\n\tprivate boolean signedFormRequired = false;\n\n\tpublic void setOAuthCredentials(String oauthConsumerKey, String oauthConsumerSecret){\n\t\tthis.oauthConsumerKey = oauthConsumerKey;\n\t\tthis.oauthConsumerSecret = oauthConsumerSecret;\n\t}\n\t\n\tpublic void setSignedFormRequired(boolean required){\n\t\tthis.signedFormRequired = required;\n\t}\n\t\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(JabberIqRegister.class.getName());\n\tprivate static final String[] XMLNSS = { \"jabber:iq:register\" };\n\tprivate static final String[] IQ_QUERY_USERNAME_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME, \"username\" };\n\tprivate static final String[] IQ_QUERY_REMOVE_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME, \"remove\" };\n\tprivate static final String[] IQ_QUERY_PASSWORD_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME, \"password\" };\n\tprivate static final String[] IQ_QUERY_EMAIL_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME, \"email\" };\n\tprivate static final Element[] FEATURES = { new Element(\"register\", new String[] { \"xmlns\" },\n\t\t\tnew String[] { \"http://jabber.org/features/iq-register\" }) };\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] { \"var\" },\n\t\t\tnew String[] { \"jabber:iq:register\" }) };\n\n\t// ~--- methods\n\t// --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t/**{@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t *             TODO: Implement registration form configurable and loading\n\t *             all the fields from the registration form TODO: rewrite the\n\t *             plugin using the XMPPProcessorAbstract API\n\t */\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) throws XMPPException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet.toString());\n\t\t}\n\t\tif (session == null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Session is null, ignoring\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t} // end of if (session == null)\n\n\t\tBareJID id = session.getDomainAsJID().getBareJID();\n\n\t\tif (packet.getStanzaTo() != null) {\n\t\t\tid = packet.getStanzaTo().getBareJID();\n\t\t}\n\t\ttry {\n\n\t\t\t// I think it does not make sense to check the 'to', just the\n\t\t\t// connection\n\t\t\t// ID\n\t\t\t// if ((id.equals(session.getDomain()) ||\n\t\t\t// id.equals(session.getUserId().toString()))\n\t\t\t// && packet.getFrom().equals(session.getConnectionId())) {\n\t\t\t// Wrong thinking. The user may send an request from his own account\n\t\t\t// to register with a transport or any other service, then the\n\t\t\t// connection\n\t\t\t// ID matches the session id but this is still not a request to the\n\t\t\t// local\n\t\t\t// server. The TO address must be checked too.....\n\t\t\t// if (packet.getPacketFrom().equals(session.getConnectionId())) {\n\t\t\tif ((packet.getPacketFrom() != null) && packet.getPacketFrom().equals(session.getConnectionId())\n\t\t\t\t\t&& (!session.isAuthorized() || (session.isUserId(id) || session.isLocalDomain(id.toString(), false)))) {\n\n\t\t\t\t// We want to allow password change but not user registration if\n\t\t\t\t// registration is disabled. The only way to tell apart\n\t\t\t\t// registration\n\t\t\t\t// from password change is to check whether the user is\n\t\t\t\t// authenticated.\n\t\t\t\t// For authenticated user the request means password change,\n\t\t\t\t// otherwise\n\t\t\t\t// registration attempt.\n\t\t\t\t// Account deregistration is also called under authenticated\n\t\t\t\t// session, so\n\t\t\t\t// it should be blocked here if registration for domain is\n\t\t\t\t// disabled.\n\t\t\t\t// Assuming if user cannot register account he cannot also\n\t\t\t\t// deregister account\n\t\t\t\tElement request = packet.getElement();\n\t\t\t\tboolean remove = request.findChildStaticStr(IQ_QUERY_REMOVE_PATH) != null;\n\n\t\t\t\tif (!session.isAuthorized() || remove) {\n\t\t\t\t\tif (!isRegistrationAllowedForConnection(packet.getFrom())) {\n\t\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Registration is not allowed for this connection.\", true));\n\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!session.getDomain().isRegisterEnabled()) {\n\t\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Registration is not allowed for this domain.\", true));\n\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tAuthorization result = Authorization.NOT_AUTHORIZED;\n\t\t\t\tStanzaType type = packet.getType();\n\n\t\t\t\tswitch (type) {\n\t\t\t\tcase set:\n\n\t\t\t\t\t// Is it registration cancel request?\n\t\t\t\t\tElement elem = request.findChildStaticStr(IQ_QUERY_REMOVE_PATH);\n\n\t\t\t\t\tif (elem != null) {\n\n\t\t\t\t\t\t// Yes this is registration cancel request\n\t\t\t\t\t\t// According to JEP-0077 there must not be any\n\t\t\t\t\t\t// more subelements apart from <remove/>\n\t\t\t\t\t\telem = request.findChildStaticStr(Iq.IQ_QUERY_PATH);\n\t\t\t\t\t\tif (elem.getChildren().size() > 1) {\n\t\t\t\t\t\t\tresult = Authorization.BAD_REQUEST;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tresult = session.unregister(packet.getStanzaFrom().toString());\n\n\t\t\t\t\t\t\t\tPacket ok_result = packet.okResult((String) null, 0);\n\n\t\t\t\t\t\t\t\t// We have to set SYSTEM priority for the packet\n\t\t\t\t\t\t\t\t// here,\n\t\t\t\t\t\t\t\t// otherwise the network connection is closed\n\t\t\t\t\t\t\t\t// before the\n\t\t\t\t\t\t\t\t// client received a response\n\t\t\t\t\t\t\t\tok_result.setPriority(Priority.SYSTEM);\n\t\t\t\t\t\t\t\tresults.offer(ok_result);\n\n\t\t\t\t\t\t\t\tPacket close_cmd = Command.CLOSE.getPacket(session.getSMComponentId(),\n\t\t\t\t\t\t\t\t\t\tsession.getConnectionId(), StanzaType.set, session.nextStanzaId());\n\n\t\t\t\t\t\t\t\tclose_cmd.setPacketTo(session.getConnectionId());\n\t\t\t\t\t\t\t\tclose_cmd.setPriority(Priority.LOWEST);\n\t\t\t\t\t\t\t\tresults.offer(close_cmd);\n\t\t\t\t\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\t\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t\t\t\t\t\t} // end of try-catch\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tString user_name;\n\t\t\t\t\t\tString password;\n\t\t\t\t\t\tString email;\n\t\t\t\t\t\tif (signedFormRequired) {\n\t\t\t\t\t\t\tfinal String expectedToken = UUID.nameUUIDFromBytes(\n\t\t\t\t\t\t\t\t\t(session.getConnectionId() + \"|\" + session.getSessionId()).getBytes()).toString();\n\n\t\t\t\t\t\t\tFormSignatureVerifier verifier = new FormSignatureVerifier(oauthConsumerKey, oauthConsumerSecret);\n\t\t\t\t\t\t\tElement queryEl = request.getChild(\"query\", \"jabber:iq:register\");\n\t\t\t\t\t\t\tElement formEl = queryEl == null ? null : queryEl.getChild(\"x\", \"jabber:x:data\");\n\t\t\t\t\t\t\tif (formEl == null) {\n\t\t\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\t\t\"Use Signed Registration Form\", true));\n\t\t\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tForm form = new Form(formEl);\n\t\t\t\t\t\t\tif (!expectedToken.equals(form.getAsString(\"oauth_token\"))) {\n\t\t\t\t\t\t\t\tlog.finest(\"Received oauth_token is different that sent one.\");\n\t\t\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Unknown oauth_token\", true));\n\t\t\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!oauthConsumerKey.equals(form.getAsString(\"oauth_consumer_key\"))) {\n\t\t\t\t\t\t\t\tlog.finest(\"Unknown oauth_consumer_key\");\n\t\t\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\t\t\"Unknown oauth_consumer_key\", true));\n\t\t\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tlong timestamp = verifier.verify(packet.getStanzaTo(), form);\n\t\t\t\t\t\t\t\tuser_name = form.getAsString(\"username\");\n\t\t\t\t\t\t\t\tpassword = form.getAsString(\"password\");\n\t\t\t\t\t\t\t\temail = form.getAsString(\"email\");\n\t\t\t\t\t\t\t} catch (FormSignerException e) {\n\t\t\t\t\t\t\t\tlog.fine(\"Form Signature Validation Problem: \" + e.getMessage());\n\t\t\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Invalid form signature\",\n\t\t\t\t\t\t\t\t\t\ttrue));\n\t\t\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No, so assuming this is registration of a new\n\t\t\t\t\t\t\t// user or change registration details for existing\n\t\t\t\t\t\t\t// user\n\t\t\t\t\t\t\tuser_name = request.getChildCDataStaticStr(IQ_QUERY_USERNAME_PATH);\n\t\t\t\t\t\t\tpassword = request.getChildCDataStaticStr(IQ_QUERY_PASSWORD_PATH);\n\t\t\t\t\t\t\temail = request.getChildCDataStaticStr(IQ_QUERY_EMAIL_PATH);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tString pass_enc = null;\n\t\t\t\t\t\tif (null != password) {\n\t\t\t\t\t\t\tpass_enc = XMLUtils.unescape(password);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tMap<String, String> reg_params = null;\n\n\t\t\t\t\t\tif ((email != null) && !email.trim().isEmpty()) {\n\t\t\t\t\t\t\treg_params = new LinkedHashMap<String, String>();\n\t\t\t\t\t\t\treg_params.put(\"email\", email);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = session.register(user_name, pass_enc, reg_params);\n\t\t\t\t\t\tif (result == Authorization.AUTHORIZED) {\n\t\t\t\t\t\t\tresults.offer(result.getResponseMessage(packet, null, false));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t++statsInvalidRegistrations;\n\t\t\t\t\t\t\tresults.offer(result.getResponseMessage(packet, \"Unsuccessful registration attempt\", true));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase get: {\n\t\t\t\t\tif (signedFormRequired) {\n\t\t\t\t\t\tresults.offer(packet.okResult(prepareRegistrationForm(session\n\t\t\t\t\t\t\t), 0));\n\t\t\t\t\t} else\n\t\t\t\t\t\tresults.offer(packet.okResult(\"<instructions>\"\n\t\t\t\t\t\t\t\t+ \"Choose a user name and password for use with this service.\"\n\t\t\t\t\t\t\t\t+ \"Please provide also your e-mail address.\" + \"</instructions>\" + \"<username/>\"\n\t\t\t\t\t\t\t\t+ \"<password/>\" + \"<email/>\", 1));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase result:\n\n\t\t\t\t\t// It might be a registration request from transport for\n\t\t\t\t\t// example...\n\t\t\t\t\tPacket pack_res = packet.copyElementOnly();\n\n\t\t\t\t\tpack_res.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(pack_res);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", true));\n\n\t\t\t\t\tbreak;\n\t\t\t\t} // end of switch (type)\n\t\t\t} else {\n\t\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t\t// It might be a registration request from transport for\n\t\t\t\t\t// example...\n\t\t\t\t\tPacket pack_res = packet.copyElementOnly();\n\n\t\t\t\t\tpack_res.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(pack_res);\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(packet.copyElementOnly());\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tresults.offer(Authorization.JID_MALFORMED.getResponseMessage(packet,\n\t\t\t\t\t\"Incorrect user name, stringprep processing failed.\", true));\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You are not authorized to change registration settings.\\n\" + e.getMessage(), true));\n\t\t} catch (TigaseDBException e) {\n\t\t\tlog.warning(\"Database problem: \" + e);\n\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t} // end of try-catch\n\t}\n\n\tprivate Element prepareRegistrationForm(final XMPPResourceConnection session) throws NoConnectionIdException {\n\t\tElement query = new Element(\"query\", new String[] { \"xmlns\" }, XMLNSS);\n\t\tquery.addChild(new Element(\"instructions\", \"Use the enclosed form to register.\"));\n\t\tForm form = new Form(SignatureCalculator.SUPPORTED_TYPE, \"Contest Registration\",\n\t\t\t\t\"Please provide the following information to sign up for our special contests!\");\n\n\t\tform.addField(Field.fieldTextSingle(\"username\", \"\", \"Username\"));\n\t\tform.addField(Field.fieldTextPrivate(\"password\", \"\", \"Password\"));\n\t\tform.addField(Field.fieldTextSingle(\"email\", \"\", \"Email\"));\n\n\t\tSignatureCalculator sc = new SignatureCalculator(oauthConsumerKey, oauthConsumerSecret);\n\t\tsc.setOauthToken(UUID.nameUUIDFromBytes((session.getConnectionId() + \"|\" + session.getSessionId()).getBytes()).toString());\n\t\tsc.addEmptyFields(form);\n\n\t\tquery.addChild(form.getElement());\n\t\treturn query;\n\t}\n\n\tprotected boolean isRegistrationAllowedForConnection(JID from) {\n\t\tString remoteAdress = parseRemoteAddressFromJid(from);\n\t\tif (whitelistRegistrationOnly) {\n\t\t\treturn contains(registrationWhitelist, remoteAdress);\n\t\t}\n\t\treturn !contains(registrationBlacklist, remoteAdress);\n\t}\n\n\tprivate static String parseRemoteAddressFromJid(JID from) {\n\t\ttry {\n\t\t\tString connectionId = from.getResource();\n\t\t\treturn connectionId.split(\"_\")[REMOTE_ADDRESS_IDX];\n\t\t} catch (ArrayIndexOutOfBoundsException e) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate long statsRegisteredUsers;\n\t\n\tprivate long statsInvalidRegistrations;\n\t\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(getComponentInfo().getName(), \"Registered users\", statsRegisteredUsers, Level.INFO);\n\t\tlist.add(getComponentInfo().getName(), \"Invalid registrations\", statsInvalidRegistrations, Level.INFO);\n\t}\n\t\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tthis.oauthConsumerKey = (String) settings.get(OAUTH_CONSUMERKEY_PROP_KEY);\n\t\tthis.oauthConsumerSecret = (String) settings.get(OAUTH_CONSUMERSECRET_PROP_KEY);\n\t\tObject verifyFormSignatureObj = settings.get(SIGNED_FORM_REQUIRED_PROP_KEY);\n\t\tif (verifyFormSignatureObj != null && verifyFormSignatureObj instanceof Boolean) {\n\t\t\tsignedFormRequired = (Boolean) verifyFormSignatureObj;\n\t\t} else if (verifyFormSignatureObj != null) {\n\t\t\tsignedFormRequired = Boolean.parseBoolean(verifyFormSignatureObj.toString());\n\t\t}\n\n\t\tString whitelistRegistrationOnlyStr = (String) settings.get(WHITELIST_REGISTRATION_ONLY_PROP_KEY);\n\t\tif (whitelistRegistrationOnlyStr != null) {\n\t\t\twhitelistRegistrationOnly = Boolean.parseBoolean(whitelistRegistrationOnlyStr);\n\t\t}\n\n\t\tString registrationWhitelistStr = (String) settings.get(REGISTRATION_WHITELIST_PROP_KEY);\n\t\tif (registrationWhitelistStr != null) {\n\t\t\tregistrationWhitelist = parseList(registrationWhitelistStr);\n\t\t}\n\n\t\tString registrationBlacklistStr = (String) settings.get(REGISTRATION_BLACKLIST_PROP_KEY);\n\t\tif (registrationBlacklistStr != null) {\n\t\t\tregistrationBlacklist = parseList(registrationBlacklistStr);\n\t\t}\n\t}\n\n\tprivate static boolean contains(List<CIDRAddress> addresses, String address) {\n\t\tif (address == null)\n\t\t\treturn false;\n\t\tfor (CIDRAddress cidrAddress : addresses) {\n\t\t\tif (cidrAddress.inRange(address)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate static List<CIDRAddress> parseList(String listStr) {\n\t\tString[] splitArray = listStr.split(\",\");\n\t\tList<CIDRAddress> splitList = new LinkedList<CIDRAddress>();\n\t\tfor (String listEl : splitArray) {\n\t\t\tsplitList.add(CIDRAddress.parse(listEl.trim()));\n\t\t}\n\t\treturn splitList;\n\t}\n\n\t/**\n\t * As in\n\t * http://commons.apache.org/proper/commons-net/jacoco/org.apache.commons\n\t * .net.util/SubnetUtils.java.html\n\t */\n\tprivate static class CIDRAddress {\n\n\t\tstatic final int NBITS = 32;\n\t\tstatic final String IP_ADDRESS_MASK = \"(\\\\d{1,3})\\\\.(\\\\d{1,3})\\\\.(\\\\d{1,3})\\\\.(\\\\d{1,3})\";\n\t\tstatic final String CIDR_ADDRESS_MASK = IP_ADDRESS_MASK + \"/(\\\\d{1,3})\";\n\n\t\tstatic final Pattern IP_PATTERN = Pattern.compile(IP_ADDRESS_MASK);\n\t\tstatic final Pattern CIDR_PATTERN = Pattern.compile(CIDR_ADDRESS_MASK);\n\n\t\tfinal int high;\n\t\tfinal int low;\n\n\t\tprivate CIDRAddress(int high, int low) {\n\t\t\tthis.high = high;\n\t\t\tthis.low = low;\n\t\t}\n\n\t\tboolean inRange(String address) {\n\t\t\tint diff = toInteger(address) - low;\n\t\t\treturn diff >= 0 && (diff <= (high - low));\n\t\t}\n\n\t\tstatic int toInteger(String address) {\n\t\t\tMatcher matcher = IP_PATTERN.matcher(address);\n\t\t\tmatcher.matches();\n\t\t\treturn matchAddress(matcher);\n\t\t}\n\n\t\tstatic int matchAddress(Matcher matcher) {\n\t\t\tint addr = 0;\n\t\t\tfor (int i = 1; i <= 4; ++i) {\n\t\t\t\tint n = Integer.parseInt(matcher.group(i));\n\t\t\t\taddr |= ((n & 0xff) << 8 * (4 - i));\n\t\t\t}\n\t\t\treturn addr;\n\t\t}\n\n\t\tstatic CIDRAddress parse(String mask) {\n\t\t\tif (!mask.contains(\"/\")) {\n\t\t\t\tmask = mask + \"/\" + NBITS;\n\t\t\t}\n\t\t\tMatcher matcher = CIDR_PATTERN.matcher(mask);\n\t\t\tmatcher.matches();\n\t\t\tint address = matchAddress(matcher);\n\n\t\t\t/* Create a binary netmask from the number of bits specification /x */\n\t\t\tint cidrPart = Integer.parseInt(matcher.group(5));\n\t\t\tint netmask = 0;\n\t\t\tint broadcast = 0;\n\t\t\tint network = 0;\n\t\t\tfor (int j = 0; j < cidrPart; ++j) {\n\t\t\t\tnetmask |= (1 << 31 - j);\n\t\t\t}\n\n\t\t\t/* Calculate base network address */\n\t\t\tnetwork = (address & netmask);\n\n\t\t\t/* Calculate broadcast address */\n\t\t\tbroadcast = network | ~(netmask);\n\t\t\treturn new CIDRAddress(broadcast, network);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(XMPPResourceConnection session) {\n\t\tif (log.isLoggable(Level.FINEST) && (session != null)) {\n\t\t\tlog.finest(\"VHostItem: \" + session.getDomain());\n\t\t}\n\t\tif ((session != null) && session.getDomain().isRegisterEnabled()) {\n\t\t\treturn DISCO_FEATURES;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\tif (log.isLoggable(Level.FINEST) && (session != null)) {\n\t\t\tlog.finest(\"VHostItem: \" + session.getDomain());\n\t\t}\n\t\tif ((session != null) && session.getDomain().isRegisterEnabled()) {\n\t\t\treturn FEATURES;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic boolean isSignedFormRequired() {\n\t\treturn signedFormRequired;\n\t}\n} // JabberIqRegister\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqRoster.java",
    "content": "/*\n * JabberIqRoster.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport java.util.*;\nimport java.util.logging.*;\nimport tigase.db.*;\nimport tigase.server.*;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport static tigase.xmpp.impl.PresenceSubscription.AUTO_AUTHORIZE_PROP_KEY;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\nimport tigase.xmpp.impl.roster.*;\n\n/**\n * Class\n * <code>JabberIqRoster</code> implements part of <em>RFC-3921</em> -\n * <em>XMPP Instant Messaging</em> specification describing roster management.\n * 7. Roster Management\n *\n *\n * Created: Tue Feb 21 17:42:53 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqRoster\n\t\textends XMPPProcessor\n\t\timplements XMPPProcessorIfc {\n\n\t/** Field description */\n\tpublic static final String ANON = \"anon\";\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ Iq.ELEM_NAME, Iq.QUERY_NAME }, { Iq.ELEM_NAME, Iq.QUERY_NAME }, { Iq.ELEM_NAME, Iq.QUERY_NAME }\n\t};\n\t/** Private logger for class instance. */\n\tprivate static final Logger log = Logger.getLogger( JabberIqRoster.class.getName() );\n\tprivate static final String[] XMLNSS = { RosterAbstract.XMLNS,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t RosterAbstract.XMLNS_DYNAMIC, RosterAbstract.XMLNS_LOAD };\n\tprivate static final String[] IQ_QUERY_ITEM_PATH = { Iq.ELEM_NAME, Iq.QUERY_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"item\" };\n\t/** unique ID of the plugin */\n\tprivate static final String ID = RosterAbstract.XMLNS;\n\t/** variable holding setting regarding auto authorisation of items added to\n\t * user roset */\n\tprivate static boolean autoAuthorize = false;\n\t//~--- fields ---------------------------------------------------------------\n\t/** instance of class implementing {@link RosterAbstract} */\n\tprotected RosterAbstract roster_util = getRosterUtil();\n\n\t//~--- methods --------------------------------------------------------------\n\t@Override\n\tpublic int concurrentQueuesNo() {\n\t\treturn super.concurrentQueuesNo() * 4;\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init( Map<String, Object> settings ) throws TigaseDBException {\n\t\tautoAuthorize = Boolean.parseBoolean( (String) settings.get( AUTO_AUTHORIZE_PROP_KEY ) );\n\t\tif ( autoAuthorize ){\n\t\t\tlog.config( \"Automatic presence subscription of new roster items enabled,\"\n\t\t\t\t\t\t\t\t\t+ \"results in less strict XMPP specs compatibility \" );\n\t\t}\n\t\tif ( roster_util != null ){\n\t\t\troster_util.setProperties( settings );\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Performs processing of <em>IQ</em> packets with <em>jabber:iq:roster</em>\n\t * xmlns with the regard whether it's roster <em>set</em> or <em>get</em>\n\t * request or possibly dynamic-roster is involved. request.\n\t */\n\t@Override\n\tpublic void process( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings )\n\t\t\tthrows XMPPException {\n\t\tif ( session == null ){\n\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\tlog.log( Level.FINE, \"Session is null, ignoring packet: {0}\", packet );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif ( !session.isAuthorized() ){\n\t\t\tif ( log.isLoggable( Level.FINE ) ){\n\t\t\t\tlog.log( Level.FINE, \"Session is not authorized, ignoring packet: {0}\", packet );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// The roster request can be between the user and the server or between the\n\t\t// user and some other entity like transport\n\t\tJID connectionId = session.getConnectionId();\n\n\t\tif ( connectionId.equals( packet.getPacketFrom() ) ){\n\n\t\t\t// Packet from the user, let's check where it should go\n\t\t\tif ( ( packet.getStanzaTo() != null ) && !session.isLocalDomain( packet.getStanzaTo()\n\t\t\t\t\t.toString(), false ) && !session.isUserId( packet.getStanzaTo().getBareJID() ) ){\n\n\t\t\t\t// This is most likely a roster reaquest sent to a transport or some other\n\t\t\t\t// roster resource.\n\t\t\t\tresults.offer( packet.copyElementOnly() );\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t\n\t\t\t// Packet probably to the user, let's check where it came from\n\t\t\tif ( session.isUserId( packet.getStanzaTo().getBareJID() ) ){\n\t\t\t\tif ( packet.getStanzaTo().getResource() != null ){\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\tresult.setPacketTo( session.getConnectionId( packet.getStanzaTo() ) );\n\t\t\t\t\tresult.setPacketFrom( packet.getTo() );\n\t\t\t\t\tresults.offer( result );\n\t\t\t\t} else {\n\t\t\t\t\tprocessRemoteRosterManagementRequest( packet, session, results, settings );\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t// Hm, I do not know what to do here, should not happen\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tif ( ( packet.getStanzaFrom() != null ) && !session.isUserId( packet.getStanzaFrom()\n\t\t\t\t\t.getBareJID() ) ){\n\n\t\t\t\t// RFC says: ignore such request\n\t\t\t\tlog.log( Level.WARNING, \"Roster request ''from'' attribute doesn't match \"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+ \"session: {0}, request: {1}\", new Object[] { session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet } );\n\t\t\t\treturn;\n\t\t\t}    // end of if (packet.getElemFrom() != null\n\t\t\tStanzaType type = packet.getType();\n\t\t\tString xmlns = packet.getElement().getXMLNSStaticStr( Iq.IQ_QUERY_PATH );\n\n\t\t\tif ( xmlns == RosterAbstract.XMLNS ){\n\t\t\t\tswitch ( type ) {\n\t\t\t\t\tcase get:\n\t\t\t\t\t\tprocessGetRequest( packet, session, results, settings );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase set:\n\t\t\t\t\t\tprocessSetRequest( packet, session, results, settings );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase result:\n\t\t\t\t\t\t// Ignore\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Request type is incorrect\", false ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (type)\n\t\t\t} else {\n\t\t\t\tif ( xmlns == RosterAbstract.XMLNS_DYNAMIC ){\n\t\t\t\t\tswitch ( type ) {\n\t\t\t\t\t\tcase get:\n\t\t\t\t\t\t\tdynamicGetRequest( packet, session, results, settings );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase set:\n\t\t\t\t\t\t\tdynamicSetRequest( packet, session, results, settings );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase result:\n\t\t\t\t\t\t\t// Ignore\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Request type is incorrect\", false ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}    // end of switch (type)\n\t\t\t\t} else if (xmlns == RosterAbstract.XMLNS_LOAD) {\n\t\t\t\t\tswitch ( type ) {\n\t\t\t\t\t\tcase set:\n\t\t\t\t\t\t\tif (!roster_util.isRosterLoaded(session)) {\n\t\t\t\t\t\t\t\t// here we do not care about result as we only trigger \n\t\t\t\t\t\t\t\t// loading of roster from database\n\t\t\t\t\t\t\t\troster_util.getRosterElement(session, session.getJID());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tElement resultEl = packet.getElement().clone();\n\t\t\t\t\t\t\tresultEl.setAttribute(\"type\", StanzaType.result.name());\n\t\t\t\t\t\t\tPacket result = Packet.packetInstance(resultEl, packet.getStanzaFrom(), packet.getStanzaTo());\n\t\t\t\t\t\t\tresult.setPacketFrom(packet.getPacketFrom());\n\t\t\t\t\t\t\tresult.setPacketTo(packet.getPacketTo());\n\t\t\t\t\t\t\tresults.add(result);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Hm, don't know what to do, unexpected name space, let's record it\n\t\t\t\t\tlog.log( Level.WARNING, \"Unknown XMLNS for the roster plugin: {0}\", packet );\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( RosterRetrievingException e ) {\n\t\t\tlog.log( Level.WARNING, \"Unknown roster retrieving exception: {0} for packet: {1}\",\n\t\t\t\t\t\t\t new Object[] { e, packet } );\n\t\t\tresults.offer( Authorization.UNDEFINED_CONDITION.getResponseMessage( packet, e\n\t\t\t\t\t.getMessage(), true ) );\n\t\t} catch ( RepositoryAccessException e ) {\n\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t \"Problem with roster repository access: {0} for packet: {1}\",\n\t\t\t\t\t\t\t new Object[] { e, packet } );\n\t\t\tresults.offer( packet.okResult( (String) null, 0 ) );\n\t\t} catch ( NotAuthorizedException e ) {\n\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t \"Received roster request but user session is not authorized yet: {0}\", packet );\n\t\t\tresults.offer( Authorization.NOT_AUTHORIZED.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"You must authorize session first.\", true ) );\n\t\t} catch ( PolicyViolationException e ) {\n\t\t\tlog.log( Level.FINE,\n\t\t\t\t\t\t\t \"Roster set request violated items number policy: {0}\", packet );\n\t\t\tresults.offer( Authorization.POLICY_VIOLATION.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.getLocalizedMessage(), true ) );\n\t\t} catch ( TigaseDBException e ) {\n\t\t\tlog.log( Level.WARNING, \"Database problem, please contact admin:\", e );\n\t\t\tresults.offer( Authorization.INTERNAL_SERVER_ERROR.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Database access problem, please contact administrator.\", true ) );\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures( final XMPPResourceConnection session ) {\n\t\treturn RosterAbstract.DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures( final XMPPResourceConnection session ) {\n\t\treturn RosterAbstract.FEATURES;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\t/**\n\t * Returns an array of group names retrieved from Element item\n\t *\n\t * @param item from which groups should be obtained\n\t * @return an array of group names retrieved from Element item\n\t */\n\tpublic static String[] getItemGroups( Element item ) {\n\t\tList<Element> elgr = item.getChildren();\n\n\t\tif ( ( elgr != null ) && ( elgr.size() > 0 ) ){\n\t\t\tArrayList<String> groups = new ArrayList<String>( 1 );\n\n\t\t\tfor ( Element grp : elgr ) {\n\t\t\t\tif ( grp.getName() == RosterAbstract.GROUP ){\n\t\t\t\t\tgroups.add( grp.getCData() );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( groups.size() > 0 ){\n\t\t\t\treturn groups.toArray( new String[ groups.size() ] );\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\t/**\n\t * Method processes roster\n\t * <code>get</code> request related to dynamic roster. Generates output packet\n\t * with data from the DynamicRoster implementation for every\n\t * <em>item</em>element from processed packet or error otherwise.\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t *\n\t * @throws NotAuthorizedException\n\t */\n\tprotected static void dynamicGetRequest( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Queue<Packet> results, Map<String, Object> settings )\n\t\t\tthrows NotAuthorizedException {\n\t\tElement request = packet.getElement();\n\t\tElement item = request.findChildStaticStr( IQ_QUERY_ITEM_PATH );\n\n\t\tif ( item != null ){\n\t\t\tElement new_item = DynamicRoster.getItemExtraData( session, settings, item );\n\n\t\t\tif ( new_item == null ){\n\t\t\t\tnew_item = item;\n\t\t\t}\n\t\t\tresults.offer( packet.okResult( new_item, 1 ) );\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Missing 'item' element, request can not be processed.\", true ) );\n\t\t\t} catch ( PacketErrorTypeException ex ) {\n\t\t\t\tlog.log( Level.SEVERE, \"Received error packet? not possible.\", ex );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method processes roster\n\t * <code>set</code> request related to dynamic roster. Sets extra data for\n\t * every\n\t * <em>item</em>element from processed packet with the DynamicRoster\n\t * implementation and generates success packet or, in case of failure\n\t * generates error.\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t */\n\tprotected static void dynamicSetRequest( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Queue<Packet> results, Map<String, Object> settings ) {\n\t\tElement request = packet.getElement();\n\t\tList<Element> items = request.getChildrenStaticStr( Iq.IQ_QUERY_PATH );\n\n\t\tif ( ( items != null ) && ( items.size() > 0 ) ){\n\t\t\tfor ( Element item : items ) {\n\t\t\t\tDynamicRoster.setItemExtraData( session, settings, item );\n\t\t\t}\n\t\t\tresults.offer( packet.okResult( (String) null, 0 ) );\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Missing 'item' element, request can not be processed.\", true ) );\n\t\t\t} catch ( PacketErrorTypeException ex ) {\n\t\t\t\tlog.log( Level.SEVERE, \"Received error packet? not possible.\", ex );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method processes roster\n\t * <code>get</code> request. Generates output result packet containing user\n\t * roster items also considering roster version attribute to minimise traffic.\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processGetRequest( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tQueue<Packet> results, Map<String, Object> settings )\n\t\t\tthrows NotAuthorizedException, TigaseDBException, RosterRetrievingException,\n\t\t\t\t\t\t RepositoryAccessException {\n\n\t\t// Retrieve all Dynamic roster elements from the roster repository\n\t\tList<Element> its = DynamicRoster.getRosterItems( session, settings );\n\n\t\t// If the dynamic roster exists, we have to always recalculate hash, as the\n\t\t// part of the roster could have changed outside of the Tigase server.\n\t\tif ( ( its != null ) && ( its.size() > 0 ) ){\n\t\t\tupdateHash( session, settings );\n\t\t}\n\n\t\t// Check roster version hash.\n\t\tString incomingHash = packet.getAttributeStaticStr( Iq.IQ_QUERY_PATH, RosterAbstract.VER_ATT );\n\t\tString storedHash = \"\";\n\n\t\t// If client provided hash and the server calculated hash are the same\n\t\t// return the success result and abort further roster processing.\n\t\t// No need to send the whole roster to the client.\n\t\tif ( incomingHash != null ){\n\t\t\tstoredHash = roster_util.getBuddiesHash( session );\n\t\t\tif ( ( storedHash == null ) || storedHash.isEmpty() ){\n\t\t\t\tupdateHash( session, settings );\n\t\t\t\tstoredHash = roster_util.getBuddiesHash( session );\n\t\t\t}\n\t\t\tif ( incomingHash.equals( storedHash ) ){\n\t\t\t\tresults.offer( packet.okResult( (String) null, 0 ) );\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Retrieve standard roster items.\n\t\tList<Element> ritems = roster_util.getRosterItems( session );\n\n\t\t// Send the user's standard roster first\n\t\tif ( ( ritems != null ) && ( ritems.size() > 0 ) ){\n\t\t\tElement query = new Element( \"query\" );\n\n\t\t\tquery.setXMLNS( RosterAbstract.XMLNS );\n\t\t\tif ( incomingHash != null ){\n\t\t\t\tquery.setAttribute( RosterAbstract.VER_ATT, storedHash );\n\t\t\t}\n\t\t\tquery.addChildren( ritems );\n\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t} else {\n\t\t\tresults.offer( packet.okResult( (String) null, 1 ) );\n\t\t}\n\n\t\t// Push the dynamic roster items now\n\t\ttry {\n\t\t\tif ( ( its != null ) && ( its.size() > 0 ) ){\n\t\t\t\tArrayDeque<Element> items = new ArrayDeque<Element>( its );\n\n\t\t\t\twhile ( items.size() > 0 ) {\n\t\t\t\t\tElement iq = new Element( \"iq\", new String[] { \"type\", \"id\", \"to\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"set\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t session.nextStanzaId(), session.getJID().toString() } );\n\n\t\t\t\t\tiq.setXMLNS( CLIENT_XMLNS );\n\n\t\t\t\t\tElement query = new Element( \"query\" );\n\n\t\t\t\t\tquery.setXMLNS( RosterAbstract.XMLNS );\n\t\t\t\t\tiq.addChild( query );\n\t\t\t\t\tquery.addChild( items.poll() );\n\t\t\t\t\twhile ( ( query.getChildren().size() < 20 ) && ( items.size() > 0 ) ) {\n\t\t\t\t\t\tquery.addChild( items.poll() );\n\t\t\t\t\t}\n\n\t\t\t\t\tPacket rost_res = Packet.packetInstance( iq, null, session.getJID() );\n\n\t\t\t\t\trost_res.setPacketTo( session.getConnectionId() );\n\t\t\t\t\trost_res.setPacketFrom( packet.getTo() );\n\t\t\t\t\tresults.offer( rost_res );\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( NoConnectionIdException ex ) {\n\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t \"Problem with roster request, no connection ID for session: {0}, request: {1}\",\n\t\t\t\t\t\t\t new Object[] { session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket } );\n\t\t}\n\t}\n\n\t/**\n\t * Method processes roster\n\t * <code>set</code> request. Performs modifications of user roster.\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t * @throws XMPPException\n\t */\n\tprotected void processSetRequest( Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tQueue<Packet> results, final Map<String, Object> settings )\n\t\t\tthrows XMPPException, NotAuthorizedException, TigaseDBException, PolicyViolationException {\n\n\t\t// Element request = packet.getElement();\n\t\tList<Element> items = packet.getElemChildrenStaticStr( Iq.IQ_QUERY_PATH );\n\n\t\tif ( items != null ){\n\t\t\ttry {\n\n\t\t\t\t// RFC-3921 draft bis-03 forbids multiple items in one request\n\t\t\t\t// This however seems to make no much sense and actually was\n\t\t\t\t// requested by many users to allow for multiple items\n\t\t\t\tfor ( Element item : items ) {\n\t\t\t\t\tJID buddy = JID.jidInstance( item.getAttributeStaticStr( \"jid\" ) );\n\n\t\t\t\t\tif ( DynamicRoster.getBuddyItem( session, settings, buddy ) != null ){\n\n\t\t\t\t\t\t// Let's return an error. Dynamic roster cannot be modified via\n\t\t\t\t\t\t// XMPP.\n\t\t\t\t\t\tresults.offer( Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(\n\t\t\t\t\t\t\t\tpacket, \"You cannot modify this contact. It is controlled by an \"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \"external service.\", true ) );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ( session.isUserId( buddy.getBareJID() ) ){\n\t\t\t\t\t\tresults.offer( Authorization.NOT_ALLOWED.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"User can't add himself to the roster, RFC says NO.\", true ) );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tString subscription = item.getAttributeStaticStr( \"subscription\" );\n\n\t\t\t\t\tif ( ( subscription != null ) && subscription.equals( \"remove\" ) ){\n\t\t\t\t\t\tSubscriptionType sub = roster_util.getBuddySubscription( session, buddy );\n\n\t\t\t\t\t\tif ( sub == null ){\n\t\t\t\t\t\t\tsub = SubscriptionType.none;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString type = item.getAttributeStaticStr( Packet.TYPE_ATT );\n\n\t\t\t\t\t\tif ( ( sub != SubscriptionType.none ) && ( ( type == null ) || !type.equals( ANON ) ) ){\n\n\t\t\t\t\t\t\t// Unavailable presence should be sent first, otherwise it will be\n\t\t\t\t\t\t\t// blocked by the server after the subscription is canceled\n\t\t\t\t\t\t\tElement pres = new Element( PresenceAbstract.PRESENCE_ELEMENT_NAME );\n\n\t\t\t\t\t\t\tpres.setXMLNS( CLIENT_XMLNS );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TO_ATT, buddy.toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.FROM_ATT, session.getJID().toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TYPE_ATT, \"unavailable\" );\n\n\t\t\t\t\t\t\tPacket pres_packet = Packet.packetInstance( pres, session.getJID(), buddy );\n\n\t\t\t\t\t\t\t// We have to set a higher priority for this particular\n\t\t\t\t\t\t\t// unavailable packet\n\t\t\t\t\t\t\t// to make sure it is delivered before subscription cancellation\n\t\t\t\t\t\t\tpres_packet.setPriority( Priority.HIGH );\n\t\t\t\t\t\t\tresults.offer( pres_packet );\n\t\t\t\t\t\t\tpres = new Element( PresenceAbstract.PRESENCE_ELEMENT_NAME );\n\t\t\t\t\t\t\tpres.setXMLNS( CLIENT_XMLNS );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TO_ATT, buddy.toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.FROM_ATT, session.getBareJID().toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TYPE_ATT, \"unsubscribe\" );\n\t\t\t\t\t\t\tresults.offer( Packet.packetInstance( pres, session.getJID()\n\t\t\t\t\t\t\t\t\t.copyWithoutResource(), buddy ) );\n\t\t\t\t\t\t\tpres = new Element( PresenceAbstract.PRESENCE_ELEMENT_NAME );\n\t\t\t\t\t\t\tpres.setXMLNS( CLIENT_XMLNS );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TO_ATT, buddy.toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.FROM_ATT, session.getBareJID().toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TYPE_ATT, \"unsubscribed\" );\n\t\t\t\t\t\t\tresults.offer( Packet.packetInstance( pres, session.getJID()\n\t\t\t\t\t\t\t\t\t.copyWithoutResource(), buddy ) );\n\t\t\t\t\t\t}    // is in the roster while he isn't. In such a case just ensure the\n\n\t\t\t\t\t\t// client that the buddy has been removed for sure\n\t\t\t\t\t\tElement it = new Element( \"item\" );\n\n\t\t\t\t\t\tit.setAttribute( \"jid\", buddy.toString() );\n\t\t\t\t\t\tit.setAttribute( \"subscription\", \"remove\" );\n\t\t\t\t\t\troster_util.removeBuddy( session, buddy );\n\t\t\t\t\t\troster_util.updateBuddyChange( session, results, it );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// We are adding a new roster element here\n\t\t\t\t\t\tString name = item.getAttributeStaticStr( \"name\" );\n\t\t\t\t\t\tList<Element> groups = item.getChildren();\n\t\t\t\t\t\tString[] gr = null;\n\n\t\t\t\t\t\tif ( ( groups != null ) && ( groups.size() > 0 ) ){\n\t\t\t\t\t\t\tgr = new String[ groups.size() ];\n\n\t\t\t\t\t\t\tint cnt = 0;\n\n\t\t\t\t\t\t\tfor ( Element group : groups ) {\n\t\t\t\t\t\t\t\tgr[cnt++] = ( ( group.getCData() == null )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: group.getCData() );\n\t\t\t\t\t\t\t}    // end of for (ElementData group : groups)\n\n\t\t\t\t\t\t\t// end of for (ElementData group : groups)\n\t\t\t\t\t\t}\n\t\t\t\t\t\troster_util.addBuddy( session, buddy, name, gr, null );\n\n\t\t\t\t\t\tString type = item.getAttributeStaticStr( Packet.TYPE_ATT );\n\n\t\t\t\t\t\tif ( ( type != null ) && type.equals( ANON ) || autoAuthorize ){\n\t\t\t\t\t\t\troster_util.setBuddySubscription( session, SubscriptionType.both, buddy );\n\n\t\t\t\t\t\t\tElement pres = (Element) session.getSessionData( XMPPResourceConnection.PRESENCE_KEY );\n\n\t\t\t\t\t\t\tif ( pres == null ){\n\t\t\t\t\t\t\t\tpres = new Element( PresenceAbstract.PRESENCE_ELEMENT_NAME );\n\t\t\t\t\t\t\t\tpres.setXMLNS( CLIENT_XMLNS );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpres = pres.clone();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpres.setAttribute( Packet.TO_ATT, buddy.toString() );\n\t\t\t\t\t\t\tpres.setAttribute( Packet.FROM_ATT, session.getJID().toString() );\n\t\t\t\t\t\t\tresults.offer( Packet.packetInstance( pres, session.getJID(), buddy ) );\n\n\t\t\t\t\t\t\tif ( autoAuthorize ){\n\t\t\t\t\t\t\t\tPresenceAbstract.sendPresence( StanzaType.subscribe, session.getJID().copyWithoutResource(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t buddy.copyWithoutResource(), results, null );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tElement new_buddy = roster_util.getBuddyItem( session, buddy );\n\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"1. New Buddy: {0}\", new_buddy.toString() );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( roster_util.getBuddySubscription( session, buddy ) == null ){\n\t\t\t\t\t\t\troster_util.setBuddySubscription( session, SubscriptionType.none, buddy );\n\t\t\t\t\t\t}    // end of if (getBuddySubscription(session, buddy) == null)\n\t\t\t\t\t\tnew_buddy = roster_util.getBuddyItem( session, buddy );\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"2. New Buddy: {0}\", new_buddy.toString() );\n\t\t\t\t\t\t}\n\t\t\t\t\t\troster_util.updateBuddyChange( session, results, new_buddy );\n\t\t\t\t\t}      // end of else\n\n\t\t\t\t\t// end of else\n\t\t\t\t}\n\t\t\t\tresults.offer( packet.okResult( (String) null, 0 ) );\n\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Buddy JID is incorrct, stringprep failed.\", true ) );\n\t\t\t}\n\t\t} else {\n\t\t\tlog.log( Level.WARNING, \"No items found in roster set request: {0}\", packet );\n\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"No items found in the roster set request\", true ) );\n\t\t}\n\t}\n\n\t/**\n\t * Calculates hash value based on the user roster items and saves it to user's\n\t * session data.\n\t *\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t * @throws TigaseDBException\n\t */\n\tprotected void updateHash( XMPPResourceConnection session, Map<String, Object> settings )\n\t\t\tthrows NotAuthorizedException, TigaseDBException, RosterRetrievingException,\n\t\t\t\t\t\t RepositoryAccessException {\n\n\t\t// Retrieve standard roster items.\n\t\tList<Element> ritems = roster_util.getRosterItems( session );\n\n\t\t// Recalculate the roster hash again with dynamic roster content\n\t\tStringBuilder roster_str = new StringBuilder( 5000 );\n\n\t\t// Retrieve all Dynamic roster elements from the roster repository\n\t\tList<Element> its = DynamicRoster.getRosterItems( session, settings );\n\n\t\t// There is always a chance that the same elements exist in a dynamic roster\n\t\t// and the standard user roster. Moreover, the items in the standard roster\n\t\t// may have a different presence subscription set.\n\t\t// Here we make sure they are both in sync, that is for each entry which\n\t\t// exists in both rosters we enforce 'both' subscription type for element in\n\t\t// standard roster and remove it from the dynamic roster list.\n\t\tif ( ( its != null ) && ( its.size() > 0 ) ){\n\t\t\tfor ( Iterator<Element> it = its.iterator() ; it.hasNext() ; ) {\n\t\t\t\tElement element = it.next();\n\n\t\t\t\ttry {\n\t\t\t\t\tJID jid = JID.jidInstance( element.getAttributeStaticStr( \"jid\" ) );\n\n\t\t\t\t\tif ( roster_util.containsBuddy( session, jid ) ){\n\t\t\t\t\t\troster_util.setBuddySubscription( session, SubscriptionType.both, jid );\n\n\t\t\t\t\t\tString[] itemGroups = getItemGroups( element );\n\n\t\t\t\t\t\tif ( itemGroups != null ){\n\t\t\t\t\t\t\troster_util.addBuddyGroup( session, jid, itemGroups );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tit.remove();\n\t\t\t\t\t}\n\t\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\t\tlog.log( Level.INFO,\n\t\t\t\t\t\t\t\t\t \"JID from dynamic roster is incorrect, stringprep failed for: {0}\", element\n\t\t\t\t\t\t\t.getAttributeStaticStr( \"jid\" ) );\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// This may seem to be redundant as this call has already been made\n\t\t\t// but the roster could have been changed during above dynamic roster\n\t\t\t// merge\n\t\t\tritems = roster_util.getRosterItems( session );\n\t\t\tfor ( Element ritem : its ) {\n\t\t\t\troster_str.append( ritem.toString() );\n\t\t\t}\n\t\t}\n\t\tfor ( Element ritem : ritems ) {\n\t\t\troster_str.append( ritem.toString() );\n\t\t}\n\t\troster_util.updateRosterHash( roster_str.toString(), session );\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\t/**\n\t * Returns shared instance of class implementing {@link RosterAbstract} -\n\t * either default one ({@link RosterFlat}) or the one configured with\n\t * <em>\"roster-implementation\"</em> property.\n\t *\n\t * @return a shared instance of class implementing {@link RosterAbstract}\n\t */\n\tprotected RosterAbstract getRosterUtil() {\n\t\treturn RosterFactory.getRosterImplementation( true );\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\t/**\n\t * Performs processing of remote roster management requests as described in <a\n\t * href=\"http://xmpp.org/extensions/xep-0321.html\">XEP-0321: Remote Roster\n\t * Management</a> for the purpose of, for example, gateways.\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t * @throws PacketErrorTypeException\n\t */\n\tprivate void processRemoteRosterManagementRequest( Packet packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Queue<Packet> results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t final Map<String, Object> settings )\n\t\t\tthrows PacketErrorTypeException {\n\t\tif ( !RemoteRosterManagement.isRemoteAllowed( packet.getStanzaFrom(), session ) ){\n\t\t\tresults.offer( Authorization.NOT_ALLOWED.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Not authorized for remote roster management\", true ) );\n\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tswitch ( packet.getType() ) {\n\t\t\t\tcase get:\n\t\t\t\t\tList<Element> ritems = roster_util.getRosterItems( session );\n\n\t\t\t\t\tif ( ( ritems != null ) && !ritems.isEmpty() ){\n\t\t\t\t\t\tElement query = new Element( \"query\" );\n\n\t\t\t\t\t\tquery.setXMLNS( RosterAbstract.XMLNS );\n\n\t\t\t\t\t\tString jidStr = \"@\" + packet.getStanzaFrom().getBareJID().toString();\n\n\t\t\t\t\t\tfor ( Element ritem : ritems ) {\n\t\t\t\t\t\t\tif ( ritem.getAttributeStaticStr( \"jid\" ).endsWith( jidStr ) ){\n\t\t\t\t\t\t\t\tquery.addChild( ritem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer( packet.okResult( query, 0 ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.offer( packet.okResult( (String) null, 1 ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase set:\n\t\t\t\t\tprocessSetRequest( packet, session, results, settings );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tresults.offer( Authorization.BAD_REQUEST.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Bad stanza type\", true ) );\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch ( PolicyViolationException e ) {\n\t\t\tlog.log( Level.WARNING,\n\t\t\t\t\t\t\t \"Roster set request violated items number policy: {0}\", packet );\n\t\t\tresults.offer( Authorization.POLICY_VIOLATION.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.getLocalizedMessage(), true ) );\n\t\t} catch ( Throwable ex ) {\n\t\t\tlog.log( Level.WARNING, \"Reflection execution exception\", ex );\n\t\t\tresults.offer( Authorization.INTERNAL_SERVER_ERROR.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"Internal server error\", true ) );\n\t\t}\n\t}\n}    // JabberIqRoster\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqSi.java",
    "content": "/*\n * JabberIqSi.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n/**\n * XEP-0096: File Transfer\n * The class is not abstract in fact. Is has been made abstract artificially\n * to prevent from loading the class.\n *\n *\n * Created: Sat Jan 13 18:45:57 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated This class has been deprecated and replaced with\n * <code>tigase.server.xmppsession.PacketFilter</code> code. The class is left\n * for educational purpose only and should not be used. It may be removed in\n * future releases.\n */\n@Deprecated\npublic abstract class JabberIqSi\n\t\t\t\textends SimpleForwarder {\n\tprivate static final Logger     log = Logger.getLogger(JabberIqSi.class.getName());\n\tprivate static final String     XMLNS    = \"http://jabber.org/protocol/si\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ Iq.ELEM_NAME, \"si\" }\n\t};\n\tprivate static final String[]   XMLNSS   = { XMLNS };\n\tprivate static final Element[]  DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { \"http://jabber.org/protocol/si\" }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] {\n\t\t\t\t\t\"http://jabber.org/protocol/si/profile/file-transfer\" }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqSocks5Bytestreams.java",
    "content": "/*\n * JabberIqSocks5Bytestreams.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.server.Iq;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\n\n/**\n * XEP-0065: SOCKS5 Bytestreams\n * The class is not abstract in fact. Is has been made abstract artificially\n * to prevent from loading the class.\n *\n *\n * Created: Fri Jan 12 21:37:05 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n * @deprecated This class has been deprecated and replaced with\n * <code>tigase.server.xmppsession.PacketFilter</code> code. The class is left\n * for educational purpose only and should not be used. It may be removed in\n * future releases.\n */\n@Deprecated\npublic abstract class JabberIqSocks5Bytestreams\n\t\t\t\textends SimpleForwarder {\n\t/**\n\t * Private logger for class instancess.\n\t */\n\tprivate static final Logger log = Logger.getLogger(JabberIqSocks5Bytestreams.class\n\t\t\t.getName());\n\tprivate static final String     XMLNS    = \"http://jabber.org/protocol/bytestreams\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\tprivate static final String[]   XMLNSS   = { XMLNS };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqStats.java",
    "content": "/*\n * JabberIqStats.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.util.ElementUtils;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * XEP-0039: Statistics Gathering.\n * http://www.xmpp.org/extensions/xep-0039.html\n *\n * Created: Sat Mar 25 06:45:00 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqStats\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH, Iq.IQ_COMMAND_PATH\n\t};\n\tprivate static final Logger     log = Logger.getLogger(JabberIqStats.class.getName());\n\tprivate static final String     XMLNS    = \"http://jabber.org/protocol/stats\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final String[]   XMLNSS   = { XMLNS, Command.XMLNS };\n\tprivate static final Element[]  DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Authorization canHandle(Packet packet, XMPPResourceConnection conn) {\n\t\tif (conn == null)\n\t\t\treturn null;\n\t\treturn super.canHandle(packet, conn);\n\t}\n\t\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Received packet: {0}\", packet);\n\t\t\t}\n\t\t\tif (packet.isCommand()) {\n\t\t\t\tif ((packet.getCommand() == Command.GETSTATS) && (packet.getType() == StanzaType\n\t\t\t\t\t\t.result)) {\n\t\t\t\t\tJID conId = session.getConnectionId(packet.getStanzaTo());\n\n\t\t\t\t\tif (conId == null) {\n\n\t\t\t\t\t\t// Drop it, user is no longer online.\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Send it back to user.\n\t\t\t\t\tElement iq = ElementUtils.createIqQuery(session.getDomainAsJID(), session\n\t\t\t\t\t\t\t.getJID(), StanzaType.result, packet.getStanzaId(), XMLNS);\n\t\t\t\t\tElement query = iq.getChild(\"query\");\n\t\t\t\t\tElement stats = Command.getData(packet, \"statistics\", null);\n\n\t\t\t\t\tquery.addChildren(stats.getChildren());\n\n\t\t\t\t\tPacket result = Packet.packetInstance(iq, session.getSMComponentId(), session\n\t\t\t\t\t\t\t.getJID());\n\n\t\t\t\t\tresult.setPacketTo(conId);\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, \"Sending result: {0}\", result);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}    // end of if (packet.isCommand()\n\n\t\t\t// Maybe it is message to admininstrator:\n\t\t\tBareJID id = (packet.getStanzaTo() != null)\n\t\t\t\t\t? packet.getStanzaTo().getBareJID()\n\t\t\t\t\t: null;\n\n\t\t\t// If ID part of user account contains only host name\n\t\t\t// and this is local domain it is message to admin\n\t\t\tif ((id == null) || session.isLocalDomain(id.toString(), false)) {\n\t\t\t\tString oldto = packet.getAttributeStaticStr(\"oldto\");\n\t\t\t\tPacket result = Command.GETSTATS.getPacket(packet.getStanzaFrom(), session\n\t\t\t\t\t\t.getDomainAsJID(), StanzaType.get, packet.getStanzaId());\n\n\t\t\t\tif (oldto != null) {\n\t\t\t\t\tresult.getElement().setAttribute(\"oldto\", oldto);\n\t\t\t\t}\n\t\t\t\tresults.offer(result);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending result: \" + result);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId(packet.getStanzaTo()));\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending result: \" + result);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// This is message to some other client so I need to\n\t\t\t\t// set proper 'from' attribute whatever it is set to now.\n\t\t\t\t// Actually processor should not modify request but in this\n\t\t\t\t// case it is absolutely safe and recommended to set 'from'\n\t\t\t\t// attribute\n\t\t\t\t// Not needed anymore. Packet filter does it for all stanzas.\n//      // According to spec we must set proper FROM attribute\n//      el_res.setAttribute(\"from\", session.getJID());\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresults.offer(result);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Sending result: \" + result);\n\t\t\t\t}\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"Received stats request but user session is not authorized yet: \" +\n\t\t\t\t\tpacket);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}    // JabberIqStats\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/JabberIqVersion.java",
    "content": "/*\n * JabberIqVersion.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.XMPPServer;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\n\n/**\n * XEP-0092: Software Version\n *\n *\n * Created: Tue Mar 21 06:45:51 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class JabberIqVersion\n\t\t\t\textends XMPPProcessorAbstract {\n\tprivate static final Logger     log = Logger.getLogger(JabberIqVersion.class.getName());\n\tprivate static final String     XMLNS    = \"jabber:iq:version\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH\n\t};\n\tprivate static final String[]   XMLNSS   = { XMLNS };\n\tprivate static final Element    SERVER_VERSION = new Element(\"query\", new Element[] {\n\t\t\tnew Element(\"name\", XMPPServer.NAME),\n\t\t\tnew Element(\"version\", XMPPServer.getImplementationVersion()), new Element(\"os\",\n\t\t\t\t\tSystem.getProperty(\"os.name\") + \"-\" + System.getProperty(\"os.arch\") + \"-\" +\n\t\t\t\t\tSystem.getProperty(\"os.version\") + \", \" + System.getProperty(\"java.vm.name\") +\n\t\t\t\t\t\"-\" + System.getProperty(\"java.vm.version\") + \"-\" + System.getProperty(\n\t\t\t\t\t\"java.vm.vendor\")) }, new String[] { \"xmlns\" }, new String[] { XMLNS });\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserPacket( JID connectionId, Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Map<String, Object> settings )\n\t\t\tthrows PacketErrorTypeException {\n\t\t\t// Check whether the packet is addressed to the server or some other, XMPP entity\n\t\t\tif ((packet.getStanzaTo() == null)\n\t\t\t\t\t|| session.isLocalDomain(packet.getStanzaTo().toString(), false)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processFromUserToServerPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessFromUserToServerPacket(connectionId, packet, session, repo, results,\n\t\t\t\t\t\tsettings);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Calling method: {0}, for packet={1}, for session={2}\",\n\t\t\t\t\t\t\tnew Object[] { \"processFromUserOutPacket\",\n\t\t\t\t\t\t\tpacket, session });\n\t\t\t\t}\n\t\t\t\tprocessFromUserOutPacket(connectionId, packet, session, repo, results, settings);\n\t\t\t}\n\t}\n\n\t@Override\n\tpublic void processFromUserOutPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) {\n\t\tresults.offer(packet.copyElementOnly());\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) {\n\t\tresults.offer(packet.okResult(SERVER_VERSION, 0));\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tresults.offer(packet.okResult(SERVER_VERSION, 0));\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}    // JabberIqVersion\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/Jingle.java",
    "content": "/*\n * Jingle.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class Jingle here.\n *\n *\n * Created: Wed Feb 21 23:05:34 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class Jingle\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String     ID          = \"http://jabber.org/protocol/jingle\";\n\tprivate static final Logger     log         = Logger.getLogger(Jingle.class.getName());\n\tprivate static final String[]   JINGLE_PATH = { Iq.ELEM_NAME, \"jingle\" };\n\tprivate static final String[][] ELEMENTS    = {\n\t\tJINGLE_PATH, JINGLE_PATH, JINGLE_PATH, { Iq.ELEM_NAME, \"session\" }\n\t};\n\tprivate static final String[]   XMLNSS = { \"http://jabber.org/protocol/jingle\",\n\t\t\t\"http://www.xmpp.org/extensions/xep-0166.html#ns\",\n\t\t\t\"http://www.xmpp.org/extensions/xep-0167.html#ns\",\n\t\t\t\t\t\"http://www.google.com/session\" };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection conn,\n\t\t\tfinal NonAuthUserRepository nonAuthUserRepo, final Queue<Packet> results,\n\t\t\tfinal Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (conn == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Received packet: \" + packet);\n\t\t\t}\n\n\t\t\t// Not needed anymore. Packet filter does it for all stanzas.\n//    // For all messages coming from the owner of this account set\n//    // proper 'from' attribute. This is actually needed for the case\n//    // when the user sends a message to himself.\n//    if (packet.getFrom().equals(conn.getConnectionId())) {\n//      packet.getElement().setAttribute(\"from\", conn.getJID());\n//    } // end of if (packet.getFrom().equals(session.getConnectionId()))\n\t\t\tBareJID id = packet.getStanzaTo().getBareJID();\n\n\t\t\tif (conn.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\t// Make sure we send it to right client connection - the connection\n\t\t\t\t// which supports jingle - this Yate specific code....\n\t\t\t\tList<XMPPResourceConnection> res = conn.getParentSession().getActiveResources();\n\t\t\t\tXMPPResourceConnection       session = conn;\n\n\t\t\t\tif ((res != null) && (res.size() > 1)) {\n\n\t\t\t\t\t// If there are more than 1 connection for this user\n\t\t\t\t\t// let's look for a connection with jingle flag set...\n\t\t\t\t\tfor (XMPPResourceConnection sess : res) {\n\t\t\t\t\t\tif (sess.getSessionData(\"jingle\") != null) {\n\t\t\t\t\t\t\tsession = sess;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t} else {\n\n\t\t\t\t// This is message to some other client\n\t\t\t\tresults.offer(packet.copyElementOnly());\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/LastActivity.java",
    "content": "/*\n * LastActivity.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Iq;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.Permissions;\nimport tigase.server.Presence;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPStopListenerIfc;\nimport tigase.xmpp.impl.annotation.DiscoFeatures;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\nimport tigase.xmpp.impl.roster.RosterElement;\nimport tigase.xmpp.impl.roster.RosterFactory;\n\nimport tigase.sys.TigaseRuntime;\nimport tigase.xml.Element;\n\nimport java.util.EnumSet;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.xmpp.impl.LastActivity.ID;\nimport static tigase.xmpp.impl.LastActivity.XMLNS;\n\n/**\n * Implementation of <a\n * href='http://xmpp.org/extensions/xep-0012.html'>XEP-0012</a>: Last Activity.\n *\n * @author bmalkow\n *\n */\n\n@Id(ID)\n@DiscoFeatures({ XMLNS })\n@Handles({ @Handle(path = { Iq.ELEM_NAME, Iq.QUERY_NAME }, xmlns = XMLNS), @Handle(path = { Presence.ELEM_NAME }, xmlns = Packet.CLIENT_XMLNS),\n\t\t@Handle(path = { Message.ELEM_NAME }, xmlns = Packet.CLIENT_XMLNS) })\npublic class LastActivity extends XMPPProcessorAbstract implements XMPPStopListenerIfc {\n\n\tenum ProtectionLevel {\n\t\tALL, BUDDIES;\n\t}\n\n\tprotected static final String XMLNS = \"jabber:iq:last\";\n\tprotected final static String ID = XMLNS;\n\tprivate final static String LAST_ACTIVITY_KEY = \"LAST_ACTIVITY_KEY\";\n\tprivate final static String LAST_STATUS_KEY = \"LAST_STATUS_KEY\";\n\tprivate static final Logger log = Logger.getLogger(LastActivity.class.getName());\n\tprivate final static String PROTECTION_LEVEL_KEY = \"protection-level\";\n\tprivate final static String[] STATUS_PATH = new String[] { Presence.ELEM_NAME, \"status\" };\n\tprivate final static EnumSet<SubscriptionType> inTypes = EnumSet.of(SubscriptionType.both, SubscriptionType.from);\n\tprivate final static EnumSet<SubscriptionType> outTypes = EnumSet.of(SubscriptionType.both, SubscriptionType.to);\n\n\tprivate ProtectionLevel protectionLevel = ProtectionLevel.ALL;\n\n\tprivate static long getLastActivity(NonAuthUserRepository repo, BareJID requestedJid) throws UserNotFoundException {\n\t\tString result = repo.getPublicData(requestedJid, ID, LAST_ACTIVITY_KEY, \"-1\");\n\t\tif (result != null)\n\t\t\treturn Long.parseLong(result);\n\t\telse\n\t\t\tthrow new UserNotFoundException(requestedJid + \" doesn't exist\");\n\t}\n\n\tprivate static long getLastActivity(XMPPResourceConnection session, boolean global) {\n\t\tLong res = null;\n\n\t\tif (global)\n\t\t\tres = (Long) session.getCommonSessionData(LAST_ACTIVITY_KEY);\n\t\telse\n\t\t\tres = (Long) session.getSessionData(LAST_ACTIVITY_KEY);\n\t\treturn res == null ? -1 : res;\n\t}\n\n\tprivate static long getLastActivity(XMPPResourceConnection session, Packet packet) {\n\t\treturn getLastActivity(session, (packet.getStanzaTo().getResource() == null || packet.getStanzaTo().getResource().length() == 0));\n\t}\n\n\tprotected static RosterAbstract getRosterUtil() {\n\t\treturn RosterFactory.getRosterImplementation(true);\n\t}\n\n\tprivate static String getStatus(NonAuthUserRepository repo, BareJID requestedJid) throws UserNotFoundException {\n\t\treturn repo.getPublicData(requestedJid, ID, LAST_STATUS_KEY, null);\n\t}\n\n\tprivate static Packet preventFromINFLoop(Packet packet) {\n\t\tpacket.setPacketTo(null);\n\t\treturn packet;\n\t}\n\n\tprivate static void setLastActivity(XMPPResourceConnection session, Long last) {\n\t\tsession.putCommonSessionData(LAST_ACTIVITY_KEY, last);\n\t\tsession.putSessionData(LAST_ACTIVITY_KEY, last);\n\t}\n\n\tprivate String getStatus(XMPPResourceConnection session) {\n\t\treturn session.getPresence() == null ? null : session.getPresence().getChildCDataStaticStr(STATUS_PATH);\n\t}\n\n\tprivate void handleLastActivityRequest(Packet packet, long last, String status, Queue<Packet> results) throws PacketErrorTypeException {\n\t\tif (last >= 0) {\n\t\t\tlong result = (System.currentTimeMillis() - last) / 1000;\n\t\t\tPacket resp = packet.okResult((Element) null, 0);\n\t\t\tElement q;\n\t\t\tif (status == null) {\n\t\t\t\tq = new Element(Iq.QUERY_NAME, new String[] { Packet.XMLNS_ATT, \"seconds\" }, new String[] { XMLNS, \"\" + result });\n\t\t\t} else {\n\t\t\t\tq = new Element(Iq.QUERY_NAME, status, new String[] { Packet.XMLNS_ATT, \"seconds\" }, new String[] { XMLNS, \"\" + result });\n\t\t\t}\n\t\t\tresp.getElement().addChild(q);\n\t\t\tresults.offer(resp);\n\t\t} else {\n\t\t\tresults.offer(preventFromINFLoop(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet, \"Unknown last activity time\", false)));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\t\tif (settings.containsKey(PROTECTION_LEVEL_KEY))\n\t\t\tprotectionLevel = ProtectionLevel.valueOf((String) settings.get(PROTECTION_LEVEL_KEY));\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\tthrows XMPPException {\n\t\tif (log.isLoggable(Level.FINEST))\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\n\t\tif (packet.getElemName() == Iq.ELEM_NAME) {\n\t\t\tsuper.process(packet, session, repo, results, settings);\n\t\t} else {\n\t\t\tif ((session != null && (packet.getStanzaFrom() != null) && session.isAuthorized() && session.getBareJID().equals(packet.getStanzaFrom().getBareJID()))) {\n\t\t\t\tfinal long time = System.currentTimeMillis();\n\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Updating last:activity of user \" + session.getUserName() + \" to \" + time);\n\t\t\t\t}\n\n\t\t\t\tsetLastActivity(session, time);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processFromUserPacket(JID connectionId, Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Process From user packet: {0}\", packet);\n\t\t}\n\n\t\tswitch (packet.getType()) {\n\t\tcase get:\n\t\t\tswitch (protectionLevel) {\n\t\t\tcase BUDDIES:\n\t\t\t\tif (getRosterUtil() == null) {\n\t\t\t\t\tlog.warning(\"Roster factory returned null\");\n\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, false)));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tRosterElement element = getRosterUtil().getRosterElement(session, packet.getStanzaTo());\n\t\t\t\t\tif (element == null || !outTypes.contains(element.getSubscription())) {\n\t\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.FORBIDDEN.getResponseMessage(packet, null, false)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsuper.processFromUserPacket(connectionId, packet, session, repo, results, settings);\n\t\t\t\t\t}\n\t\t\t\t} catch (NotAuthorizedException | TigaseDBException e) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, e.getMessage(), e);\n\t\t\t\t\t}\n\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, false)));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ALL:\n\t\t\t\tsuper.processFromUserPacket(connectionId, packet, session, repo, results, settings);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase error:\n\t\tcase result:\n\t\t\tsuper.processFromUserPacket(connectionId, packet, session, repo, results, settings);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tresults.offer(preventFromINFLoop(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", false)));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing from user to server packet: {0}\", packet);\n\t\t}\n\n\t\tpacket.processedBy(ID);\n\t\tif (packet.getPermissions() == Permissions.ADMIN) {\n\t\t\thandleLastActivityRequest(packet, TigaseRuntime.getTigaseRuntime().getUptime(), null, results);\n\t\t} else {\n\t\t\tresults.offer(preventFromINFLoop(Authorization.FORBIDDEN.getResponseMessage(packet, null, false)));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\tthrows PacketErrorTypeException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing null session packet: {0}\", packet);\n\t\t}\n\n\t\tpacket.processedBy(ID);\n\t\tswitch (packet.getType()) {\n\t\tcase get:\n\t\t\tBareJID requestedJid = packet.getStanzaTo().getBareJID();\n\t\t\ttry {\n\t\t\t\tfinal long last = getLastActivity(repo, requestedJid);\n\t\t\t\tfinal String status = getStatus(repo, requestedJid);\n\t\t\t\thandleLastActivityRequest(packet, last, status, results);\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\tresults.offer(preventFromINFLoop(Authorization.FORBIDDEN.getResponseMessage(packet, null, false)));\n\t\t\t}\n\t\tcase error:\n\t\tcase result:\n\t\t\tsuper.processNullSessionPacket(packet, repo, results, settings);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tresults.offer(preventFromINFLoop(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", false)));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing server session packet: {0}\", packet);\n\t\t}\n\t\tpacket.processedBy(ID);\n\t\thandleLastActivityRequest(packet, TigaseRuntime.getTigaseRuntime().getUptime(), null, results);\n\t}\n\n\t@Override\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) throws PacketErrorTypeException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing to user packet: {0}\", packet);\n\t\t}\n\n\t\tpacket.processedBy(ID);\n\t\tswitch (packet.getType()) {\n\t\tcase get:\n\t\t\tlong last = getLastActivity(session, packet);\n\t\t\tString status = getStatus(session);\n\n\t\t\tswitch (protectionLevel) {\n\t\t\tcase BUDDIES:\n\t\t\t\tif (getRosterUtil() == null) {\n\t\t\t\t\tlog.warning(\"Roster factory returned null\");\n\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, false)));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tRosterElement element = getRosterUtil().getRosterElement(session, packet.getStanzaFrom());\n\t\t\t\t\tif (element == null || !inTypes.contains(element.getSubscription())) {\n\t\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.FORBIDDEN.getResponseMessage(packet, null, false)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandleLastActivityRequest(packet, last, status, results);\n\t\t\t\t\t}\n\t\t\t\t} catch (NotAuthorizedException | TigaseDBException e) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, e.getMessage(), e);\n\t\t\t\t\t}\n\t\t\t\t\tresults.offer(preventFromINFLoop(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, null, false)));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ALL:\n\t\t\t\thandleLastActivityRequest(packet, last, status, results);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase error:\n\t\tcase result:\n\t\t\tsuper.processToUserPacket(packet, session, repo, results, settings);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tresults.offer(preventFromINFLoop(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Message type is incorrect\", false)));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stopped(XMPPResourceConnection session, Queue<Packet> results, Map<String, Object> settings) {\n\t\tif (session != null && session.isAuthorized()) {\n\t\t\tlong last = getLastActivity(session, false);\n\t\t\tString status = getStatus(session);\n\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\tlog.finest(\"Persiting last:activity of user \" + session.getUserName() + \" in storage (value=\" + last + \", \" + \"status=\" + status\n\t\t\t\t\t\t\t+ \").\");\n\t\t\t\tsession.setPublicData(ID, LAST_ACTIVITY_KEY, String.valueOf(last));\n\t\t\t\tsession.setPublicData(ID, LAST_STATUS_KEY, status);\n\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"session isn't authorized\" + session);\n\t\t\t\t}\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.warning(\"Tigase Db Exception\");\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/Message.java",
    "content": "/*\n * Message.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\n\nimport java.util.*;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.xmpp.impl.Message.ELEM_NAME;\nimport static tigase.xmpp.impl.Message.XMLNS;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.TimeZone;\n\n/**\n * Message forwarder class. Forwards <code>Message</code> packet to it's destination\n * address.\n *\n * Created: Tue Feb 21 15:49:08 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Id(ELEM_NAME)\n@Handles({\n\t@Handle(path={ ELEM_NAME },xmlns=XMLNS)\n})\npublic class Message\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc, XMPPPacketFilterIfc {\n\n\tprotected static final String     ELEM_NAME = tigase.server.Message.ELEM_NAME;\n\n\t/** Class logger */\n\tprivate static final Logger   log    = Logger.getLogger(Message.class.getName());\n\tprivate static final String   DELIVERY_RULES_KEY = \"delivery-rules\";\n\tprivate static final String   SILENTLY_IGNORE_ERROR_KEY = \"silently-ignore-message\";\n\tprotected static final String   XMLNS  = \"jabber:client\";\n\n\tprivate MessageDeliveryRules deliveryRules = MessageDeliveryRules.inteligent;\n\tprivate boolean silentlyIgnoreError = false;\n\t\n\tprivate final SimpleDateFormat formatter;\n\t\n\t{\n\t\tthis.formatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tthis.formatter.setTimeZone( TimeZone.getTimeZone( \"GMT+8\" ) );\n\t}\n\t\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tdeliveryRules = settings.containsKey(DELIVERY_RULES_KEY)\n\t\t\t\t? MessageDeliveryRules.valueOf((String) settings.get(DELIVERY_RULES_KEY))\n\t\t\t\t: MessageDeliveryRules.inteligent;\n\n\t\tsilentlyIgnoreError = settings.containsKey(SILENTLY_IGNORE_ERROR_KEY)\n\t\t\t\t? Boolean.valueOf((String) settings.get(SILENTLY_IGNORE_ERROR_KEY))\n\t\t\t\t: Boolean.FALSE;\n\t}\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\tC2SDeliveryErrorProcessor.filter(packet, session, repo, results, null);\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\t// For performance reasons it is better to do the check\n\t\t// before calling logging method.\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}, for session: {1}\", new Object[] {\n\t\t\t\t\tpacket,\n\t\t\t\t\tsession });\n\t\t}\n\n\t\t// You may want to skip processing completely if the user is offline.\n\t\tif (session == null) {\n\t\t\tprocessOfflineUser( packet, results );\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\n\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\tBareJID id = (packet.getStanzaTo() != null)\n\t\t\t\t\t? packet.getStanzaTo().getBareJID()\n\t\t\t\t\t: null;\n\t\t\t\n\t\t\t// 不处理客户端回执 C-110\n\t\t\tif (id.equals(id.getDomain())){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Checking if this is a packet TO the owner of the session\n\t\t\tif (session.isUserId(id)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Message 'to' this user, packet: {0}, for session: {1}\",\n\t\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\t\tsession });\n\t\t\t\t}\n\n\t\t\t\tif (packet.getStanzaFrom() != null && session.isUserId(packet.getStanzaFrom().getBareJID())) {\n\t\t\t\t\tJID connectionId = session.getConnectionId();\n\t\t\t\t\tif (connectionId.equals(packet.getPacketFrom())) {\n\t\t\t\t\t\tresults.offer(packet.copyElementOnly());\n\t\t\t\t\t\t// this would cause message packet to be stored in offline storage and will not\n\t\t\t\t\t\t// send recipient-unavailable error but it will behave the same as a message to\n\t\t\t\t\t\t// unavailable resources from other sessions or servers\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tList<XMPPResourceConnection> conns = new ArrayList<XMPPResourceConnection>(5);\n\n\t\t\t\t// This is where and how we set the address of the component\n\t\t\t\t// which should rceive the result packet for the final delivery\n\t\t\t\t// to the end-user. In most cases this is a c2s or Bosh component\n\t\t\t\t// which keep the user connection.\n\t\t\t\tString resource = packet.getStanzaTo().getResource();\n\n\t\t\t\tif (resource == null) {\n\n\t\t\t\t\t// If the message is sent to BareJID then the message is delivered to\n\t\t\t\t\t// all resources\n\t\t\t\t\tconns.addAll(getConnectionsForMessageDelivery(session));\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise only to the given resource or sent back as error.\n\t\t\t\t\tXMPPResourceConnection con = session.getParentSession().getResourceForResource(\n\t\t\t\t\t\t\tresource);\n\n\t\t\t\t\tif (con != null) {\n\t\t\t\t\t\tconns.add(con);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// MessageCarbons: message cloned to all resources? why? it should be copied only\n\t\t\t\t// to resources with non negative priority!!\n\n\t\t\t\tif (conns.size() > 0) {\n\t\t\t\t\tfor (XMPPResourceConnection con : conns) {\n\t\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\t\t// 为所有消息加上时间戳  C-101\n\t\t\t\t\t\tString stamp = null;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(result.getElement().findChild(new String[]{\"message\", \"delay\"}) == null){\n\t\t\t\t\t\t\tsynchronized ( formatter ) {\n\t\t\t\t\t\t\t\tstamp = formatter.format( new Date() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult.getElement().addChild(new Element(\"delay\", new String[] { \"xmlns\", \"stamp\" }, new String[] { \"urn:xmpp:delay\", stamp}));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresult.setPacketTo(con.getConnectionId());\n\n\t\t\t\t\t\t// In most cases this might be skept, however if there is a\n\t\t\t\t\t\t// problem during packet delivery an error might be sent back\n\t\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\n\t\t\t\t\t\t// Don't forget to add the packet to the results queue or it\n\t\t\t\t\t\t// will be lost.\n\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Delivering message, packet: {0}, to session: {1}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { packet,\n\t\t\t\t\t\t\t\t\tcon });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// if there are no user connections we should process packet\n\t\t\t\t\t// the same as with missing session (i.e. should be stored if\n\t\t\t\t\t// has type 'chat'\n\t\t\t\t\tprocessOfflineUser( packet, results );\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}    // end of else\n\n\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\tid = (packet.getStanzaFrom() != null)\n\t\t\t\t\t? packet.getStanzaFrom().getBareJID()\n\t\t\t\t\t: null;\n\n\t\t\t// Checking if this is maybe packet FROM the client\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// This is a packet FROM this client, the simplest action is\n\t\t\t\t// to forward it to is't destination:\n\t\t\t\t// Simple clone the XML element and....\n\t\t\t\t// ... putting it to results queue is enough\n\t\t\t\tresults.offer(packet.copyElementOnly());\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Can we really reach this place here?\n\t\t\t// Yes, some packets don't even have from or to address.\n\t\t\t// The best example is IQ packet which is usually a request to\n\t\t\t// the server for some data. Such packets may not have any addresses\n\t\t\t// And they usually require more complex processing\n\t\t\t// This is how you check whether this is a packet FROM the user\n\t\t\t// who is owner of the session:\n\t\t\tJID jid = packet.getFrom();\n\n\t\t\t// This test is in most cases equal to checking getElemFrom()\n\t\t\tif (session.getConnectionId().equals(jid)) {\n\n\t\t\t\t// Do some packet specific processing here, but we are dealing\n\t\t\t\t// with messages here which normally need just forwarding\n\t\t\t\tElement el_result = packet.getElement().clone();\n\n\t\t\t\t// If we are here it means FROM address was missing from the\n\t\t\t\t// packet, it is a place to set it here:\n\t\t\t\tel_result.setAttribute(\"from\", session.getJID().toString());\n\n\t\t\t\tPacket result = Packet.packetInstance(el_result, session.getJID(), packet\n\t\t\t\t\t\t.getStanzaTo());\n\n\t\t\t\t// ... putting it to results queue is enough\n\t\t\t\tresults.offer(result);\n\t\t\t}\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.log(Level.FINE, \"NotAuthorizedException for packet: \" + packet + \" for session: \" + session, e);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\tprivate void processOfflineUser( Packet packet, Queue<Packet> results ) throws PacketErrorTypeException {\n\t\tif (packet.getStanzaTo() != null && packet.getStanzaTo().getResource() != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Processing message to offline user, packet: {0}, deliveryRules: {1}\",\n\t\t\t\t\t\tnew Object[]{packet, deliveryRules});\n\t\t\t}\n\n\t\t\tif (deliveryRules != MessageDeliveryRules.strict) {\n\t\t\t\tStanzaType type = packet.getType();\n\t\t\t\tif (type == null) {\n\t\t\t\t\ttype = StanzaType.normal;\n\t\t\t\t}\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase chat:\n\t\t\t\t\t\t// try to deliver this message to all available resources so we should\n\t\t\t\t\t\t// treat it as a stanza with bare \"to\" attribute\n\t\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\t\tresult.initVars(packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket.getStanzaTo().copyWithoutResource());\n\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase error:\n\t\t\t\t\t\t// for error packet we should ignore stanza according to RFC 6121\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase headline:\n\t\t\t\t\tcase groupchat:\n\t\t\t\t\tcase normal:\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// for each of this types RFC 6121 recomends silent ignoring of stanza\n\t\t\t\t\t\t// or to return error recipient-unavailable - we will send error as\n\t\t\t\t\t\t// droping packet without response may not be a good idea\n\t\t\t\t\t\tif (!silentlyIgnoreError) {\n\t\t\t\t\t\t\tresults.offer(Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(\n\t\t\t\t\t\t\t\t\tpacket, \"The recipient is no longer available.\", true));\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif ( !silentlyIgnoreError ){\n\t\t\t\t\tresults.offer( Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage( packet,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \"The recipient is no longer available.\", true ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tboolean result = C2SDeliveryErrorProcessor.preProcess(packet, session, repo, results, settings, this);\n\t\tif (result) {\n\t\t\tpacket.processedBy(id());\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate static enum MessageDeliveryRules {\n\t\tstrict,\n\t\tinteligent\n\t}\n\n\t/**\n\t * Method returns list of XMPPResourceConnections to which message should be delivered for \n\t * session passes as parameter if message was sent to bare JID\n\t * \n\t * @param session\n\t * @return\n\t * @throws NotAuthorizedException \n\t */\n\tpublic List<XMPPResourceConnection> getConnectionsForMessageDelivery(XMPPResourceConnection session) throws NotAuthorizedException {\n\t\tList<XMPPResourceConnection> conns = new ArrayList<XMPPResourceConnection>();\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\tif (conn.getPresence() != null &&  conn.getPriority() >= 0)\n\t\t\t\tconns.add(conn);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Out of: {0} total connections, only: {1} have non-negative priority\",\n\t\t\t\t\tnew Object[]{session.getActiveSessions().size(), conns.size()});\n\t\t}\n\n\t\treturn conns;\n\t}\n\n\t/**\n\t * Method returns list of JIDs to which message should be delivered for \n\t * session passes as parameter if message was sent to bare JID\n\t * \n\t * @param session\n\t * @return\n\t * @throws NotAuthorizedException \n\t */\n\tpublic Set<JID> getJIDsForMessageDelivery(XMPPResourceConnection session) throws NotAuthorizedException {\n\t\tSet<JID> jids = new HashSet<JID>();\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\tif (conn.getPresence() != null &&  conn.getPriority() >= 0)\n\t\t\t\tjids.add(conn.getJID());\n\t\t}\n\t\treturn jids;\n\t}\t\n\t\n\t/**\n\t * Method returns true if there is at least one XMPPResourceConnection which is allowed to \n\t * receive message for XMPPResourceConnection\n\t * \n\t * @param session\n\t * @return \n\t */\n\tpublic boolean hasConnectionForMessageDelivery(XMPPResourceConnection session) {\n\t\ttry {\n\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\tif (conn.getPresence() != null && conn.getPriority() >= 0)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\t// should not happen, end even if it happend then we should return false\n\t\t}\n\t\treturn false;\n\t}\n}    // Message\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessageAll.java",
    "content": "/*\n * MessageAll.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Variant of the <code>Message</code> forwarder class. This implementation forwards\n * messages to all connected resources. <br>\n * When a message <strong>'from'</strong> the user is being processed, the plugin forwards\n * the message to the destination address and also sends the message to all other connected\n * resources.<br>\n * When a message <strong>'to'</strong> the user is being processed, the plugin forwards\n * the message to all connected resources.<br>\n * The idea behind this implementation is to keep all connected resources synchronized with\n * a complete chat content. User should be able to switch between connections and continue\n * the chat.\n *\n * Created: Feb 14, 2010 4:35:45 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MessageAll\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ \"message\" }\n\t};\n\tprivate static final String     ID       = \"message-all\";\n\n\t/** Class logger */\n\tprivate static final Logger   log    = Logger.getLogger(MessageAll.class.getName());\n\tprivate static final String   XMLNS  = \"jabber:client\";\n\tprivate static final String[] XMLNSS = { XMLNS };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\t// For performance reasons it is better to do the check\n\t\t// before calling logging method.\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.finest(\"Processing packet: \" + packet);\n\t\t}\n\n\t\t// You may want to skip processing completely if the user is offline.\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\n\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\tBareJID id = (packet.getStanzaTo() != null)\n\t\t\t\t\t? packet.getStanzaTo().getBareJID()\n\t\t\t\t\t: null;\n\n\t\t\t// Checking if this is a packet TO the owner of the session\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\t// Send the message to all connected resources:\n\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\t// This is where and how we set the address of the component\n\t\t\t\t\t// which should receive the packet for the final delivery\n\t\t\t\t\t// to the end-user. In most cases this is a c2s or Bosh component\n\t\t\t\t\t// which keep the user connection.\n\t\t\t\t\tresult.setPacketTo(conn.getConnectionId());\n\n\t\t\t\t\t// In most cases this might be skept, however if there is a\n\t\t\t\t\t// problem during packet delivery an error might be sent back\n\t\t\t\t\tresult.setPacketFrom(packet.getTo());\n\n\t\t\t\t\t// Don't forget to add the packet to the results queue or it\n\t\t\t\t\t// will be lost.\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}    // end of else\n\n\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\tid = (packet.getStanzaFrom() != null)\n\t\t\t\t\t? packet.getStanzaFrom().getBareJID()\n\t\t\t\t\t: null;\n\n\t\t\t// Checking if this is maybe packet FROM the client\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// First we have to update all the other resources with this message just send\n\t\t\t\t// from the user.\n\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\n\t\t\t\t\t// Don't send the message back to the connection from which is has been\n\t\t\t\t\t// received, only to all other connections.\n\t\t\t\t\tif (conn != session) {\n\t\t\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\t\t\t// This is where and how we set the address of the component\n\t\t\t\t\t\t// which should receive the packet for the final delivery\n\t\t\t\t\t\t// to the end-user. In most cases this is a c2s or Bosh component\n\t\t\t\t\t\t// which keep the user connection.\n\t\t\t\t\t\tresult.setPacketTo(conn.getConnectionId());\n\n\t\t\t\t\t\t// Don't forget to add the packet to the results queue or it\n\t\t\t\t\t\t// will be lost.\n\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// This is a packet FROM this client, the simplest action is\n\t\t\t\t// to forward it to is't destination:\n\t\t\t\t// Simple clone the XML element and....\n\t\t\t\t// ... putting it to results queue is enough\n\t\t\t\tresults.offer(packet.copyElementOnly());\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Can we really reach this place here?\n\t\t\t// If the point is reached then the message packet does not have either from or\n\t\t\t// to address. In such a case we ignore it.\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessageAmp.java",
    "content": "/*\n * MessageAmp.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Packet;\nimport tigase.server.amp.AmpFeatureIfc;\nimport tigase.server.amp.MsgRepository;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPPostprocessorIfc;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.DNSResolverFactory;\nimport tigase.xml.Element;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.server.amp.AmpFeatureIfc.*;\n\n/**\n * Created: Apr 29, 2010 5:00:25 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MessageAmp\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPPacketFilterIfc, XMPPPostprocessorIfc, \n\t\t\t\t\t\tXMPPPreprocessorIfc, XMPPProcessorIfc {\n\tprivate static final String     AMP_JID_PROP_KEY     = \"amp-jid\";\n\tprivate static final String     STATUS_ATTRIBUTE_NAME = \"status\";\n\tprivate static final String[][] ELEMENTS             = {\n\t\t{ \"message\" }, { \"presence\" }, { \"iq\", \"msgoffline\" }\n\t};\n\tprivate static final String     ID                   = \"amp\";\n\tprivate static final Logger     log = Logger.getLogger(MessageAmp.class.getName());\n\tprivate static final String     XMLNS                = \"http://jabber.org/protocol/amp\";\n\tprivate static final String[]   XMLNSS = { \"jabber:client\", \"jabber:client\", \"msgoffline\" };\n\tprivate static Element[]        DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"msgoffline\" }) };\n\tprivate static String defHost;\n\n//\tprivate static final String STATUS_ATTRIBUTE_NAME = \"status\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JID             ampJID           = null;\n\tprivate MsgRepositoryIfc   msg_repo         = null;\n\tprivate OfflineMessages offlineProcessor = new OfflineMessages();\n\tprivate Message         messageProcessor = new Message();\n\tprivate QuotaRule quotaExceededRule = QuotaRule.error;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tdefHost = DNSResolverFactory.getInstance().getDefaultHost();\n\n\t\tif(offlineProcessor!=null)\n\t\t\tofflineProcessor.init(settings);\n\t\t\n\t\tif(messageProcessor!=null)\n\t\t\tmessageProcessor.init(settings);\n\n\t\tString ampJIDstr = (String) settings.get(AMP_JID_PROP_KEY);\n\n\t\tif (null != ampJIDstr) {\n\t\t\tampJID = JID.jidInstanceNS(ampJIDstr);\n\t\t} else {\n\t\t\tampJID = JID.jidInstanceNS(\"amp@\" + defHost);\n\t\t}\n\t\tlog.log(Level.CONFIG, \"Loaded AMP_JID option: {0} = {1}\", new Object[] {\n\t\t\t\tAMP_JID_PROP_KEY,\n\t\t\t\tampJID });\n\n\t\tString off_val = (String) settings.get(MSG_OFFLINE_PROP_KEY);\n\n\t\tif (off_val == null) {\n\t\t\toff_val = System.getProperty(MSG_OFFLINE_PROP_KEY);\n\t\t}\n\t\tif ((off_val != null) &&!Boolean.parseBoolean(off_val)) {\n\t\t\tlog.log(Level.CONFIG, \"Offline messages storage: {0}\", new Object[] { off_val });\n\t\t\tofflineProcessor = null;\n\t\t\tDISCO_FEATURES = new Element[] { new Element(\"feature\", new String[] { \"var\" },\n\t\t\t\t\tnew String[] { XMLNS }) };\n\t\t}\n\t\t\n\t\tquotaExceededRule = QuotaRule.valueof((String) settings.get(\"quota-exceeded\"));\n\n\t\tString msg_repo_uri = (String) settings.get(AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY);\n\t\tString msg_repo_cls = (String) settings.get(AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t\n\t\tif (msg_repo_uri == null) {\n\t\t\tmsg_repo_uri = System.getProperty(AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY);\n\t\t\tif (msg_repo_uri == null) {\n\t\t\t\tmsg_repo_uri = System.getProperty(RepositoryFactory.GEN_USER_DB_URI_PROP_KEY);\n\t\t\t}\n\t\t}\n\t\tif (msg_repo_cls == null) {\n\t\t\tmsg_repo_cls = System.getProperty(AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t}\n\t\tif (msg_repo_uri != null) {\n\t\t\tMap<String, String> db_props = new HashMap<String, String>(4);\n\n\t\t\tfor (Map.Entry<String, Object> entry : settings.entrySet()) {\n\t\t\t\tdb_props.put(entry.getKey(), entry.getValue().toString());\n\t\t\t}\n\n\t\t\t// Initialization of repository can be done here and in Store\n\t\t\t// class so repository related parameters for JDBCMsgRepository\n\t\t\t// should be specified for AMP plugin and AMP component\n\t\t\ttry {\n\t\t\t\tmsg_repo = MsgRepository.getInstance(msg_repo_cls, msg_repo_uri);\n\t\t\t\tmsg_repo.initRepository(msg_repo_uri, db_props);\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tmsg_repo = null;\n\t\t\t\tlog.log(Level.WARNING, \"Problem initializing connection to DB: \", ex);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\tC2SDeliveryErrorProcessor.filter(packet, session, repo, results, ampJID);\n\t}\n\t\n\t@Override\n\tpublic void postProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tif ((offlineProcessor != null) && (session == null || !messageProcessor.hasConnectionForMessageDelivery(session))) {\n\t\t\tif (packet.getElemName() == tigase.server.Message.ELEM_NAME \n\t\t\t\t\t&& packet.getStanzaTo() != null && packet.getStanzaTo().getResource() != null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tElement amp = packet.getElement().getChild(\"amp\");\n\n\t\t\tif ((amp == null) || (amp.getXMLNS() != XMLNS)\n//\t\t\t\t\t \"Individual action definitions MAY provide their own requirements.\" regarding\n//\t\t\t\t\t\t\"status\" attribute requirement!!! applies to \"alert\" and \"notify\"\n//\t\t\t\t\t|| (amp.getAttributeStaticStr(STATUS_ATTRIBUTE_NAME) != null)\n\t\t\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\tif (session != null && packet.getStanzaTo() != null\n\t\t\t\t\t\t\t&& (packet.getStanzaTo().getLocalpart() == null || !session.isUserId(packet.getStanzaTo().getBareJID())) )\n\t\t\t\t\t\treturn;\n\t\t\t\t\t\n\t\t\t\t\tofflineProcessor.publishInPubSub(packet, session, results, settings);\n\t\t\t\t\tAuthorization saveResult = offlineProcessor.savePacketForOffLineUser(packet, msg_repo, repo);\n\t\t\t\t\tPacket result = null;\n\n\t\t\t\t\tswitch (saveResult) {\n\t\t\t\t\t\tcase SERVICE_UNAVAILABLE:\n\t\t\t\t\t\t\tswitch (quotaExceededRule) {\n\t\t\t\t\t\t\t\tcase error:\n\t\t\t\t\t\t\t\t\tresult = saveResult.getResponseMessage(packet, \"Offline messages queue is full\", true);\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tcase drop:\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (result != null) {\n\t\t\t\t\t\tresults.offer(result);\n\t\t\t\t\t}\t\t\n\t\t\t\t} catch (UserNotFoundException ex) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\t\"UserNotFoundException at trying to save packet for off-line user.\" +\n\t\t\t\t\t\t\t\tpacket);\n\t\t\t\t\t}\n\t\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log(Level.FINEST, \"NotAuthorizedException when checking if message is to this \"\n\t\t\t\t\t\t\t\t+ \"user at trying to save packet for off-line user, {0}, {1}\", new Object[]{ packet, session });\n\t\t\t\t\t}\t\n\t\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\t\tlog.log(Level.FINE, \"Could not sent error to packet sent to offline user which storage to offline \"\n\t\t\t\t\t\t\t+ \"store failed. Packet is error type already: {0}\", packet.toStringSecure());\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tboolean processed = C2SDeliveryErrorProcessor.preProcess(packet, session, repo, results, settings, messageProcessor);\n\t\tif (processed && packet.getPacketFrom() != null && packet.getPacketFrom().getLocalpart().equals(ampJID.getLocalpart())) {\n\t\t\tprocessed = false;\n\t\t}\n\t\tif (processed) {\n\t\t\tpacket.processedBy(ID);\n\t\t} else if (packet.getElemName() == Message.ELEM_NAME) {\n\t\t\tElement amp = packet.getElement().getChild(\"amp\", XMLNS);\n\t\t\tif (amp == null\n//\t\t\t\t\t \"Individual action definitions MAY provide their own requirements.\" regarding\n//\t\t\t\t\t\t\"status\" attribute requirement!!! applies to \"alert\" and \"notify\"\n\t\t\t\t\t|| (amp.getAttributeStaticStr(STATUS_ATTRIBUTE_NAME) != null)\n\t\t\t\t\t|| ampJID.equals(packet.getPacketFrom())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\ttry {\n\t\t\t\tif (session == null) {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\tresult.setPacketTo(ampJID);\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t\tresult.getElement().addAttribute(OFFLINE, \"1\");\n\t\t\t\t\tpacket.processedBy(ID);\n\t\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (session.isUserId(packet.getStanzaTo().getBareJID())\n\t\t\t\t\t\t&& session.getjid() != null && session.getjid().equals( packet.getStanzaTo())\n\t\t\t\t\t\t) {\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\tresult.setPacketTo(ampJID);\n\t\t\t\t\tif ( packet.getStanzaTo().getResource() != null ){\n\t\t\t\t\t\tresult.getElement().addAttribute( TO_RES, session.getResource() );\n\t\t\t\t\t} \n\t\t\t\t\tresults.offer(result);\n\t\t\t\t\tboolean offline = !messageProcessor.hasConnectionForMessageDelivery(session);\n\t\t\t\t\tif (offline) {\n\t\t\t\t\t\tresult.getElement().addAttribute(OFFLINE, \"1\");\n\t\t\t\t\t}\n\t\t\t\t\tpacket.processedBy(ID);\n\t\t\t\t\treturn true;\t\t\t\t\t\n//\t\t\t\t} else {\n\t\t\t\t\t// this needs to be handled in process() method so we need to allow packet \n\t\t\t\t\t// to be processed in this method\n//\t\t\t\t\tJID connectionId = session.getConnectionId();\n//\n//\t\t\t\t\tif (connectionId.equals(packet.getPacketFrom())) {\n//\t\t\t\t\t\tresult.getElement().addAttribute(FROM_CONN_ID, connectionId.toString());\n//\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} catch (XMPPException ex) {\n\t\t\t\tlog.log(Level.SEVERE, \"this should not happen\", ex);\n\t\t\t}\n\t\t}\n\t\treturn processed;\n\t}\n\t\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tswitch (packet.getElemName()) {\n\t\t\tcase \"presence\":\n\t\t\t\tif ((offlineProcessor != null) && offlineProcessor.loadOfflineMessages(packet,\n\t\t\t\t\t\tsession)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tQueue<Packet> packets = offlineProcessor.restorePacketForOffLineUser(session,\n\t\t\t\t\t\t\t\tmsg_repo);\n\n\t\t\t\t\t\tif (packets != null) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tlog.finer(\"Sending off-line messages: \" + packets.size());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults.addAll(packets);\n\t\t\t\t\t\t}    // end of if (packets != null)\n\t\t\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\t\t\tlog.info(\"Something wrong, DB problem, cannot load offline messages. \" + e);\n\t\t\t\t\t}      // end of try-catch\n\n\t\t\t\t\t// notify AMP component that user is online now\n\t\t\t\t\tif (packet.getStanzaTo() == null) {\n\t\t\t\t\t\tPacket notification = packet.copyElementOnly();\n\t\t\t\t\t\tnotification.initVars(session.getJID(), ampJID);\n\t\t\t\t\t\tresults.offer(notification);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tElement amp = packet.getElement().getChild(\"amp\", XMLNS);\n\n\t\t\t\tif ((amp == null)\n//\t\t\t\t\t \"Individual action definitions MAY provide their own requirements.\" regarding\n//\t\t\t\t\t\t\"status\" attribute requirement!!! applies to \"alert\" and \"notify\"\n\t\t\t\t\t\t|| (amp.getAttributeStaticStr(STATUS_ATTRIBUTE_NAME) != null)\n\t\t\t\t\t\t|| (packet.getPacketFrom() != null && ampJID.getLocalpart().equals(packet.getPacketFrom().getLocalpart()))) {\n\t\t\t\t\tmessageProcessor.process(packet, session, repo, results, settings);\n\t\t\t\t} else {\n\t\t\t\t\t// when packet from user with AMP is sent we need to forward it to AMP\n\t\t\t\t\t// for processing but we need to do this here and not in preProcess method\n\t\t\t\t\t// as in other case other processors would not receive this packet at all!\n\t\t\t\t\tJID connectionId = session.getConnectionId();\n\t\t\t\t\tPacket result = packet.copyElementOnly();\n\t\t\t\t\tif (connectionId.equals(packet.getPacketFrom())) {\n\t\t\t\t\t\t//if (!session.isUserId(packet.getStanzaTo().getBareJID()))\n\t\t\t\t\t\tresult.getElement().addAttribute(FROM_CONN_ID, connectionId.toString());\n\t\t\t\t\t\tif ( null != session.getBareJID() ){\n\t\t\t\t\t\t\tresult.getElement().addAttribute(SESSION_JID, session.getJID().toString() );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\tresult.setPacketTo(ampJID);\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"iq\":\n\t\t\t\tif (offlineProcessor != null) {\n\t\t\t\t\tofflineProcessor.processIq(packet, session, repo, results);\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet, ID, true));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\t\n\tprivate enum QuotaRule {\n\t\terror,\n\t\tdrop;\n\t\t\n\t\tpublic static QuotaRule valueof(String name) {\n\t\t\ttry {\n\t\t\t\tif (name != null)\n\t\t\t\t\treturn QuotaRule.valueOf(name);\n\t\t\t} catch (IllegalArgumentException ex) {\n\t\t\t}\n\t\t\treturn QuotaRule.error;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessageCarbons.java",
    "content": "/*\n * MessageCarbons.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.xmpp.impl;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.function.Function;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Iq;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPPresenceUpdateProcessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * MessageCarbons class implements XEP-0280 Message Carbons protocol extension.\n * \n * @author andrzej\n */\npublic class MessageCarbons \n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPacketFilterIfc,\n\t\t\t\tXMPPPresenceUpdateProcessorIfc\n\t\t\t\t{    \n\n\tprivate static final Logger log = Logger.getLogger(MessageCarbons.class.getCanonicalName());\n\t\n\tprivate static final String ID = \"message-carbons\";\n\t\n\tpublic static final String XMLNS = \"urn:xmpp:carbons:2\";\n\t\n\tprivate static final String[][] ELEMENTS = { { \"message\" }, { \"iq\", \"enable\" }, { \"iq\", \"disable\" } };\n\tprivate static final String[] XMLNSS = { XMPPProcessor.CLIENT_XMLNS, XMLNS, XMLNS };\n \t\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] { \"var\" }, new String[] { XMLNS }) };\n\t\n\tprivate static final String ENABLED_KEY = XMLNS + \"-enabled\";\n\t\n\tprivate static final String ENABLED_RESOURCES_KEY = XMLNS + \"-resources\";\n\t\n\tprivate static final String ENABLE_ELEM_NAME = \"enable\";\n\tprivate static final String DISABLE_ELEM_NAME = \"disable\";\n\t\n\tprivate static final String[] MESSAGE_HINTS_NO_COPY = { Message.ELEM_NAME, \"no-copy\" };\n\tprivate static final String MESSAGE_HINTS_XMLNS = \"urn:xmpp:hints\";\n\t\n\tprivate static final Function<String,Object> RESOURCES_MAP_FACTORY = (k) -> { return new ConcurrentHashMap<JID,Boolean>(); };\n\t\n\tprivate tigase.xmpp.impl.Message messageProcessor = new tigase.xmpp.impl.Message();\n\t\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, \n\t\t\tQueue<Packet> results, Map<String, Object> settings) throws XMPPException {\n\t\t\n\t\tif (session == null)\n\t\t\treturn;\n\t\t\n\t\tif (packet.getElemName() == Iq.ELEM_NAME) {\n\n\t\t\tboolean enable = packet.getElement().getChild(ENABLE_ELEM_NAME, XMLNS) != null;\n\t\t\tboolean disable = packet.getElement().getChild(DISABLE_ELEM_NAME, XMLNS) != null;\n\t\t\t\n\t\t\t// we can only enable or disable but we cannot do both\n\t\t\tif ((enable && disable) || (!enable && !disable)) {\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, null, false));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tJID sessionJid = session.getJID();\t\t\t\t\n\t\t\t\tif (packet.getStanzaFrom() != null && !sessionJid.equals(packet.getStanzaFrom())\n\t\t\t\t\t\t&& session.isUserId(packet.getStanzaFrom().getBareJID()) && packet.getStanzaFrom().getResource() != null) {\n\t\t\t\t\t\n\t\t\t\t\t// direct notification about state of MessageCarbons for other resource\n\t\t\t\t\tMap<JID,Boolean> resources = (Map<JID,Boolean>) session.getCommonSessionData(ENABLED_RESOURCES_KEY);\n\t\t\t\t\tif (resources == null) {\n\t\t\t\t\t\tsynchronized (session.getParentSession()) {\n\t\t\t\t\t\t\tresources = (Map<JID, Boolean>) session.getCommonSessionData(ENABLED_RESOURCES_KEY);\n\t\t\t\t\t\t\tif (resources == null) {\n\t\t\t\t\t\t\t\tresources = new ConcurrentHashMap<JID, Boolean>();\n\t\t\t\t\t\t\t\tsession.putCommonSessionData(ENABLED_RESOURCES_KEY, resources);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"received state notification from {0} with value = {1}\", \n\t\t\t\t\t\t\t\tnew Object[]{packet.getStanzaFrom(), enable});\n\t\t\t\t\t}\n\t\t\t\t\tBoolean oldValue = resources.put(packet.getStanzaFrom(), enable);\n\t\t\t\t\tif (oldValue == null) {\n\t\t\t\t\t\t// if it is first info about this resource then notify it about\n\t\t\t\t\t\t// state of MC for other resources\n\t\t\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\t\t\t\tnotifyStateChanged(conn.getJID(), packet.getStanzaFrom(), isEnabled(conn), results);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsetEnabled(session, enable, results);\n\t\t\t\t\t// send result of operation\n\t\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (packet.getElemName() == Message.ELEM_NAME && packet.getType() == StanzaType.chat \n\t\t\t\t&& packet.getStanzaTo() != null) {\n\n\t\t\t// ignoring if message packet was resent from c2s for redelivery\n\t\t\tif (C2SDeliveryErrorProcessor.isDeliveryError(packet))\n\t\t\t\treturn;\n\t\t\t\n\t\t\tMap<JID,Boolean> resources = (Map<JID,Boolean>) session.getCommonSessionData(ENABLED_RESOURCES_KEY);\n\t\t\tif (resources == null || resources.isEmpty()) {\n\t\t\t\t// no session has enabled message carbons\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// if this is error delivering forked message we should not fork it\n\t\t\t// but we need to fork only messsages with type chat so no need to check it\n\t\t\t//if (isErrorDeliveringForkedMessage(packet, session))\n\t\t\t//\treturn;\n\t\t\t\n\t\t\tif (packet.getType() == StanzaType.chat) {\n\t\t\t\t\n\t\t\t\t// if this is error delivering forked message we should not fork it\n\t\t\t\t// but we need to fork only messsages with type chat so no need to check it\n\t\t\t\t//if (isErrorDeliveringForkedMessage(packet, session))\n\t\t\t\t//\treturn;\n\t\t\t\tif (packet.getElement().getChild(\"received\", XMLNS) != null\n\t\t\t\t\t\t|| packet.getElement().getChild(\"sent\", XMLNS) != null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// support for XEP-0334 Message Processing Hints\n\t\t\t\tif (packet.getAttributeStaticStr(MESSAGE_HINTS_NO_COPY, \"xmlns\") == MESSAGE_HINTS_XMLNS) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// if this is private message then do not send carbon copy\n\t\t\t\tElement privateEl = packet.getElement().getChild(\"private\", XMLNS);\n\n\t\t\t\tif (privateEl != null) {\n\t\t\t\t\t// TODO: is it enought to just remove this element?\n\t\t\t\t\tpacket.getElement().removeChild(privateEl);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tString type = session.isUserId(packet.getStanzaTo().getBareJID()) ? \"received\" : \"sent\";\n\t\t\t\tJID srcJid = JID.jidInstance(session.getBareJID());\n\t\t\t\t// collections of jid to which message will be delivered by default so we need to skip them\n\t\t\t\tSet<JID> skipForkingTo = null;\n\t\t\t\t\t\t\t\n\t\t\t\tif (session.isUserId(packet.getStanzaTo().getBareJID()) && packet.getStanzaTo().getResource() == null) {\n\t\t\t\t\t// message is cloned to all resources by Message.java, it violates RFC6121 \n\t\t\t\t\t// while it should be copied only to resources with non negative priority!!\n\t\t\t\t\t// until it is not solved there is no need to fork messages\n\n\t\t\t\t\t// as we started to respect connection priority we need to implement proper \n\t\t\t\t\t// forking of messages sent to bare jid\n\t\t\t\t\t// we need to fork this message\n\t\t\t\t\tskipForkingTo = messageProcessor.getJIDsForMessageDelivery(session);\n\t\t\t\t\t\n\t\t\t\t\t// we should skip forking to JID with enabled message carbons if jid is not from local node\n\t\t\t\t\tfor (JID jid : resources.keySet()) {\n\t\t\t\t\t\tif (session.getParentSession().getResourceForJID(jid) == null)\n\t\t\t\t\t\t\tskipForkingTo.add(jid);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tskipForkingTo = Collections.singleton(session.getJID());\n\t\t\t\t}\n\n\t\t\t\tif ( log.isLoggable( Level.FINER ) ){\n\t\t\t\t\tlog.log( Level.FINER, \"Sending message carbon copy, packet: {0}, resources {1}, skipForkingTo: {2}, session: {3}\",\n\t\t\t\t\t\t\t\t\t new Object[] { packet, resources, skipForkingTo, session } );\n\t\t\t\t}\n\n\t\t\t\tfor (Map.Entry<JID, Boolean> entry : resources.entrySet()) {\n\n\t\t\t\t\tif (!entry.getValue()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tJID jid = entry.getKey();\n\n\t\t\t\t\t// do not send carbon copy to session to which it is addressed\n\t\t\t\t\t// or from which it is sent or to which it will be delivered due\n\t\t\t\t\t// to default routing\n\t\t\t\t\tif (skipForkingTo.contains(entry.getKey())) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// prepare carbon copy of message\t\t\t\t\t\n\t\t\t\t\tPacket msgClone = prepareCarbonCopy(packet, srcJid, jid, type);\n\t\t\t\t\tresults.offer(msgClone);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\t\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\t\n\t/**\n\t * Prepare packet which is carbon copy of message passed as argument\n\t * \n\t * @param packet\n\t * @param session\n\t * @param srcJid\n\t * @param jid\n\t * @param type\n\t * \n\t * @throws NoConnectionIdException \n\t */\n\tprivate static Packet prepareCarbonCopy(Packet packet, \n\t\t\tJID srcJid, JID jid, String type) { //throws NoConnectionIdException {\n\t\tPacket msgClone = Message.getMessage(srcJid, jid, packet.getType(), null, \n\t\t\t\tnull, null, packet.getStanzaId());\n\t\t\n\t\t//msgClone.setPacketTo(session.getConnectionId(jid));\n\n\t\tElement received = new Element(type);\n\t\treceived.setXMLNS(XMLNS);\n\t\tmsgClone.getElement().addChild(received);\n\n\t\tElement forwarded = new Element(\"forwarded\");\n\t\tforwarded.setXMLNS(\"urn:xmpp:forward:0\");\n\t\treceived.addChild(forwarded);\n\n\t\tforwarded.addChild(packet.getElement().clone());\n\t\t\n\t\treturn msgClone;\n\t\t\n\t}\n\t\n\t/**\n\t * Add/Remove session JID to set of JIDs with enabled carbon copy protocol\n\t * \n\t * @param session\n\t * @param value\n\t * @throws NotAuthorizedException \n\t */\n\tprivate static void setEnabled(XMPPResourceConnection session, boolean value, Queue<Packet> results) throws NotAuthorizedException {\n\t\tsession.putSessionData(ENABLED_KEY, value);\n\n\t\tMap<JID,Boolean> resources = (Map<JID,Boolean>) session.getCommonSessionData(ENABLED_RESOURCES_KEY);\n\t\t\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log(Level.FINER, \"session = {0}\" + \" enabling \" + XMLNS + \n\t\t\t\t\t\", resources to notify = {1}\", new Object[]{\n\t\t\t\t\t\tsession, resources == null ? \"null\" : resources.size()});\n\t\t}\n\t\t\n\t\tif (resources != null) {\n\t\t\tJID fromJid = session.getJID();\n\t\t\tfor (JID jid : resources.keySet()) {\n\t\t\t\t\n\t\t\t\tif (jid.equals(fromJid))\n\t\t\t\t\tcontinue;\n\t\t\t\t\n\t\t\t\tnotifyStateChanged(fromJid, jid, value, results);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * Returns true if session is enabled for receiving carbon copy messages\n\t * \n\t * @param session\n\t * \n\t * @throws NotAuthorizedException \n\t */\n\tprivate static boolean isEnabled(XMPPResourceConnection session) throws NotAuthorizedException {\n\t\tBoolean value = (Boolean) session.getSessionData(ENABLED_KEY);\n\t\treturn (value != null && value);\n\t}\n\t\n\t/**\n\t * Prepares MC state change notification\n\t * \n\t * @param from\n\t * @param to\n\t * @param value\n\t * @param results \n\t */\n\tprivate static void notifyStateChanged(JID from, JID to, boolean value, Queue<Packet> results) {\n\t\tif (from.equals(to))\n\t\t\treturn;\n\t\t\n\t\tElement iq = new Element(\"iq\", new String[]{\"xmlns\", \"type\"},\n\t\t\t\tnew String[]{Packet.CLIENT_XMLNS, StanzaType.set.name()});\n\t\tElement enable = new Element(value ? ENABLE_ELEM_NAME : DISABLE_ELEM_NAME,\n\t\t\t\tnew String[]{\"xmlns\"}, new String[]{XMLNS});\n\t\tiq.addChild(enable);\n\t\t\n\t\tPacket packet = Packet.packetInstance(iq, from, to);\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"sending state notification = {0}\", packet);\n\t\t}\n\t\tresults.offer(packet);\n\t}\n\t\n\t\n\t@Override\n\tpublic void presenceUpdate(XMPPResourceConnection session, Packet packet, Queue<Packet> results) \n\t\t\tthrows NotAuthorizedException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"session = {0} processing presence = {1}\", \n\t\t\t\t\tnew Object[]{session, packet.toString()});\n\t\t}\n\n\t\tConcurrentHashMap<JID, Boolean> resources = \n\t\t\t\t(ConcurrentHashMap<JID, Boolean>) session.computeCommonSessionDataIfAbsent(ENABLED_RESOURCES_KEY, RESOURCES_MAP_FACTORY);\n\n\t\tStanzaType type = packet.getType();\n\t\tif (type == null || type == StanzaType.available) {\n\t\t\tif (resources.putIfAbsent(packet.getStanzaFrom(), false) != null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"session = {0} adding resource = {1} to list of available resources\", \n\t\t\t\t\t\tnew Object[]{session, packet.getStanzaFrom()});\t\t\t\n\t\t\t}\n\t\t\t\n\n\t\t\tfor (XMPPResourceConnection res : session.getActiveSessions()) {\n\t\t\t\tif (res.isAuthorized()) {\n\t\t\t\t\tnotifyStateChanged(res.getJID(), packet.getStanzaFrom(), isEnabled(res), results);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (type == StanzaType.unavailable) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"session = {0} removing resource = {1} from list of available resources\", \n\t\t\t\t\t\tnew Object[]{session, packet.getStanzaFrom()});\n\t\t\t}\n\t\t\tresources.remove(packet.getStanzaFrom());\n\t\t}\n\n\t}\t\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif ((session == null) ||!session.isAuthorized() || (results == null) || (results\n\t\t\t\t.size() == 0) || packet == null) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif (packet.getElemName() != Message.ELEM_NAME)\n\t\t\treturn;\n\t\t\n\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\tPacket res = it.next();\n\t\t\t\n\t\t\tif (res.getElemName() != Message.ELEM_NAME)\n\t\t\t\tcontinue;\n\t\t\t\n\t\t\t// if it is error during delivering forked message then drop it\n\t\t\tif (isErrorDeliveringForkedMessage(packet, session)) {\n\t\t\t\tit.remove();\n\t\t\t}\n\t\t\t\n\t\t\tElement messageEl = res.getElement();\t\t\t\n\t\t\t\n\t\t\tElement privateEl = messageEl.getChild(\"private\", XMLNS);\n\n\t\t\tif (privateEl != null) {\n\t\t\t\t// TODO: is it enought to just remove this element?\n\t\t\t\tmessageEl.removeChild(privateEl);\n\t\t\t}\n\t\t}\t\t\n\t}\n\t\n\t/**\n\t * Method returns true if \n\t * \n\t * @param packet\n\t * @param session\n\t * \n\t */\n\tprivate boolean isErrorDeliveringForkedMessage(Packet packet, XMPPResourceConnection session) {\n\n\t\tif (!session.isAuthorized() || packet.getStanzaTo() == null)\n\t\t\treturn false;\n\t\t\t\n\t\t\n\t\ttry {\n\t\t\t// check if it is error from delivering forked message\n\t\t\tif (packet.getType() == StanzaType.error && packet.getStanzaTo().getResource() == null\n\t\t\t\t\t&& session.isUserId(packet.getStanzaTo().getBareJID())) {\n\n\t\t\t\tElement messageEl = packet.getElement();\n\n\t\t\t\t// it will be error if it contains sent element\n\t\t\t\tElement sentEl = messageEl.getChild(\"sent\", XMLNS);\n\t\t\t\tif (sentEl != null) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// it will also be error if it contains received element\n\t\t\t\tElement receivedEl = messageEl.getChild(\"received\", XMLNS);\n\t\t\t\tif (receivedEl != null) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (NotAuthorizedException ex) {\n\t\t\t// should not happens\n\t\t}\n\t\t\t\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessageForwarding.java",
    "content": "/*\n * MessageForwarding.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Message forwarder class. Forwards <code>Message</code> packet to it's\n * destination address.\n *\n * Created: Tue Feb 21 15:49:08 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev: 2348 $\n */\npublic class MessageForwarding\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String FORWARD_EL    = \"forward\";\n\tprivate static final String FORWARD_XMLNS = \"http://tigase.org/protocol/forward#v1\";\n\tprivate static final String ID            = \"message-vhost-forward\";\n\n\t/** Class logger */\n\tprivate static final Logger     log = Logger.getLogger(MessageForwarding.class\n\t\t\t.getName());\n\tprivate static final String     XMLNS    = \"jabber:client\";\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ tigase.server.Message.ELEM_NAME }\n\t};\n\tprivate static final String[]   XMLNSS   = { XMLNS };\n\tprivate static final String[]   MESSAGE_FORWARD_PATH = { tigase.server.Message\n\t\t\t.ELEM_NAME,\n\t\t\tFORWARD_EL };\n\tprivate static final Element forw_el = new Element(FORWARD_EL, new String[] {\n\t\t\t\"xmlns\" }, new String[] { FORWARD_XMLNS });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\t// For performance reasons it is better to do the check\n\t\t// before calling logging method.\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}\", packet);\n\t\t}\n\n\t\t// If the session is null (user offline), then we cannot forward as we\n\t\t// do not have access to user's configuration. The message should be\n\t\t// processed\n\t\t// once again when the user comes back online and his messages are read\n\t\t// from offline storage.\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\n\t\t// We only want to forward messages which contain body element\n\t\tif (packet.getElemCDataStaticStr(tigase.server.Message.MESSAGE_BODY_PATH) == null) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the message contains forward payload already we drop it to prevent\n\t\t// infinite loop due to some misconfiguration\n\t\tif (packet.isXMLNSStaticStr(MESSAGE_FORWARD_PATH, FORWARD_XMLNS)) {\n\t\t\treturn;\n\t\t}\n\n\t\tJID forwardAddr = session.getDomain().getMessageForward();\n\n\t\t// No forward address means no forwarding which means no further processing\n\t\t// is required.\n\t\tif (forwardAddr == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tJID user = null;\n\n\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\tBareJID id = (packet.getStanzaTo() != null)\n\t\t\t\t\t? packet.getStanzaTo().getBareJID()\n\t\t\t\t\t: null;\n\n\t\t\t// Checking if this is a packet TO the owner of the session\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tuser = packet.getStanzaTo();\n\t\t\t} else {\n\n\t\t\t\t// Remember to cut the resource part off before comparing JIDs\n\t\t\t\tid = (packet.getStanzaFrom() != null)\n\t\t\t\t\t\t? packet.getStanzaFrom().getBareJID()\n\t\t\t\t\t\t: null;\n\n\t\t\t\t// Checking if this is maybe packet FROM the client\n\t\t\t\tif (session.isUserId(id)) {\n\t\t\t\t\tuser = packet.getStanzaFrom();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Can we really reach this place here?\n\t\t\t// Yes, some packets don't even have from or to address.\n\t\t\t// The best example is IQ packet which is usually a request to\n\t\t\t// the server for some data. Such packets may not have any addresses\n\t\t\t// And they usually require more complex processing\n\t\t\t// This is how you check whether this is a packet FROM the user\n\t\t\t// who is owner of the session:\n\t\t\tif (user == null) {\n\t\t\t\tuser = session.getJID();\n\t\t\t}\n\n\t\t\tElement forward_payload = forw_el.clone();\n\n\t\t\tforward_payload.addAttribute(\"from\", packet.getStanzaFrom().toString());\n\t\t\tforward_payload.addAttribute(\"to\", packet.getStanzaTo().toString());\n\n\t\t\tPacket result = Packet.packetInstance(packet.getElement(), user, forwardAddr);\n\n\t\t\tresult.getElement().addChild(forward_payload);\n\t\t\tresults.offer(result);\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}    // Message\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessagePush.java",
    "content": "/*\n * Message.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport tigase.apns.APNSManager;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPPacketFilterIfc;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\nimport static tigase.xmpp.impl.MessagePush.*;\n\n/**\n * Message forwarder class. Forwards <code>Message</code> packet to it's destination\n * address.\n *\n * Created: Tue Feb 21 15:49:08 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Id(ID)\n@Handles({\n\t@Handle(path={ ELEM_NAME },xmlns=XMLNS)\n})\npublic class MessagePush\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPacketFilterIfc {\n\n\tprotected static final String     ID = \"message-push\";\n\t\n\tprotected static final String     ELEM_NAME = tigase.server.Message.ELEM_NAME;\n\n\t/** Class logger */\n\tprivate static final Logger   log    = Logger.getLogger(Message.class.getName());\n\tprotected static final String   XMLNS  = \"jabber:client\";\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\t}\n\n\t@Override\n\tpublic void filter(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results) {\n\t\tC2SDeliveryErrorProcessor.filter(packet, session, repo, results, null);\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\t// For performance reasons it is better to do the check\n\t\t// before calling logging method.\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Processing packet: {0}, for session: {1}\", new Object[] {\n\t\t\t\t\tpacket,\n\t\t\t\t\tsession });\n\t\t}\n\n\t\t// Message push via apns.. if the user is offline.\n\t\tif (session == null) {\n\t\t\tString type = packet.getElement().getAttributeStaticStr(\"type\");\n\t\t\tif(type == null || !type.equals(\"chat\")){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tElement $body = packet.getElement().findChild(new String[]{\"message\", \"body\"});\n\t\t\t\n\t\t\tif($body == null)\n\t\t\t\treturn;\n\n\t\t\t\n\t\t\ttry {\n\t\t\t\t\n\t\t\t\tJSONObject obj = new JSONObject($body.getCData());\n\t\t\t\tif (obj.getJSONObject(\"data\").get(\"chatType\").equals(\"1\") && obj.getJSONObject(\"data\").get(\"msgType\").equals(2001)){\n\t\t\t\t\t\n\t\t\t\t\tfinal String uid = obj.getJSONObject(\"data\").get(\"to\").toString();\n\t\t\t\t\t\n\t\t\t\t\tAPNSManager.pushMsg(uid, \n\t\t\t\t\t\t\tobj.getJSONObject(\"data\").getJSONObject(\"ext\").get(\"nick\") + \":\"\n\t\t\t\t\t\t\t+ obj.getJSONObject(\"data\").getJSONObject(\"body\").get(\"content\"));\n\t\t\t\t}\n\t\t\t} catch (JSONException e) {\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE, \"#APNS push error: json tanslation error!\");\n\t\t\t\t}\n\t\t\t} catch (RuntimeException e) {\n\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\tlog.log(Level.FINE, \"#APNS push error: \" + e.getMessage());\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t}\n\t}\n}    \n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MessageReceipts.java",
    "content": "/*\n * MessageAmp.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport static tigase.server.amp.AmpFeatureIfc.MSG_OFFLINE_PROP_KEY;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport tigase.apns.APNSManager;\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\nimport tigase.receipt.BufferedMessageReceiptsStore;\nimport tigase.receipt.BufferedMessageReceiptsStore.Callback;\nimport tigase.receipt.MessageReceiptsStore;\nimport tigase.server.Packet;\nimport tigase.server.amp.AmpFeatureIfc;\nimport tigase.server.amp.MsgRepository;\nimport tigase.util.DNSResolver;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Created: Apr 29, 2010 5:00:25 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class MessageReceipts\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc , Callback{\n\tprivate static final String     RECEIPT_JID_PROP_KEY     = \"receipt-jid\";\n\tpublic static final String     RECEIPT_RECEIVED     = \"received\";\n\tpublic static final String     RECEIPT_REQUEST     = \"request\";\n\tpublic static final String     DELAY     = \"delay\";\n\tprivate static String \t\t\thost = null;\n\t\n\tprivate static final String[][] ELEMENTS             = {\n\t\t{ Message.ELEM_NAME , RECEIPT_RECEIVED}, { Message.ELEM_NAME , RECEIPT_REQUEST}\n\t};\n\tprivate static final String     XMLNS                = \"urn:xmpp:receipts\";\n\tprivate static final String     ID                   = XMLNS;\n\tprivate static final Logger     log = Logger.getLogger(MessageReceipts.class.getName());\n\tprivate static final String[]   XMLNSS = { XMLNS, XMLNS };\n\tprivate static Element[]        DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"msgoffline\" }) };\n\tprivate static final String defHost = DNSResolver.getDefaultHostname();\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JID             receiptJID           = null;\n\tprivate MsgRepositoryIfc   msg_repo         = null;\n\tprivate OfflineMessages offlineProcessor = new OfflineMessages();\n\tprivate Message         messageProcessor = new Message();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tString receiptJIDstr = (String) settings.get(RECEIPT_JID_PROP_KEY);\n\n\t\tif (null != receiptJIDstr) {\n\t\t\treceiptJID = JID.jidInstanceNS(receiptJIDstr);\n\t\t} else {\n\t\t\treceiptJID = JID.jidInstanceNS(\"receipt@\" + defHost);\n\t\t}\n\t\tlog.log(Level.CONFIG, \"Loaded RECEIPT_JID option: {0} = {1}\", new Object[] {\n\t\t\t\tRECEIPT_JID_PROP_KEY,\n\t\t\t\treceiptJID });\n\n\t\tString off_val = (String) settings.get(MSG_OFFLINE_PROP_KEY);\n\n\t\tif (off_val == null) {\n\t\t\toff_val = System.getProperty(MSG_OFFLINE_PROP_KEY);\n\t\t}\n\t\tif ((off_val != null) &&!Boolean.parseBoolean(off_val)) {\n\t\t\tlog.log(Level.CONFIG, \"Offline messages storage: {0}\", new Object[] { off_val });\n\t\t\tofflineProcessor = null;\n\t\t\tDISCO_FEATURES = new Element[] { new Element(\"feature\", new String[] { \"var\" },\n\t\t\t\t\tnew String[] { XMLNS }) };\n\t\t}\n\n\t\tString msg_repo_uri = (String) settings.get(AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY);\n\t\tString msg_repo_cls = (String) settings.get(AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t\n\t\tif (msg_repo_uri == null) {\n\t\t\tmsg_repo_uri = System.getProperty(AmpFeatureIfc.AMP_MSG_REPO_URI_PROP_KEY);\n\t\t\tif (msg_repo_uri == null) {\n\t\t\t\tmsg_repo_uri = System.getProperty(RepositoryFactory.GEN_USER_DB_URI_PROP_KEY);\n\t\t\t}\n\t\t}\n\t\tif (msg_repo_cls == null) {\n\t\t\tmsg_repo_cls = System.getProperty(AmpFeatureIfc.AMP_MSG_REPO_CLASS_PROP_KEY);\n\t\t}\n\t\tif (msg_repo_uri != null) {\n\t\t\tMap<String, String> db_props = new HashMap<String, String>(4);\n\n\t\t\tfor (Map.Entry<String, Object> entry : settings.entrySet()) {\n\t\t\t\tdb_props.put(entry.getKey(), entry.getValue().toString());\n\t\t\t}\n\n\t\t\t// Initialization of repository can be done here and in Store\n\t\t\t// class so repository related parameters for JDBCMsgRepository\n\t\t\t// should be specified for AMP plugin and AMP component\n\t\t\ttry {\n\t\t\t\tmsg_repo = MsgRepository.getInstance(msg_repo_cls, msg_repo_uri);\n\t\t\t\tmsg_repo.initRepository(msg_repo_uri, db_props);\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tmsg_repo = null;\n\t\t\t\tlog.log(Level.WARNING, \"Problem initializing connection to DB: \", ex);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\n\t\tif(session == null){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif(packet.getElement().getChild(RECEIPT_REQUEST) != null){\n\t\t\t\n\t\t\tBareJID to = (packet.getStanzaTo() != null) ? packet.getStanzaTo().getBareJID() : null;\n\t\t\t\n\t\t\t// send receipt back if the receiver is offline.\n\t\t    // end of if (session == null)\n\t\t\tif (session.isUserId(to)) {\n\t\t\t\t\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t                log.log(Level.FINEST, \"Process packet: {0}\", packet);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tstore(packet.copyElementOnly(), session, repo);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tBareJID from = (packet.getStanzaFrom() != null) ? packet.getStanzaFrom().getBareJID() : null;\n\t\t\t\n\t\t\tif (session != null && session.isUserId(from)) {\n\t\t\t\tfinal Packet pac = packet.copyElementOnly();\n\t\t\t\tPacket receipt = makeReceipts(pac);\n\t\t\t\tresults.offer(receipt);\n\t\t\t\t\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t                log.log(Level.FINEST, \"Send receipt packet: {0}\", packet);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t} else {\n\t\t\t // Remember to cut the resource part off before comparing JIDs\n\t \t\tBareJID id = (packet.getStanzaTo() != null) ? packet.getStanzaTo().getBareJID() : null;\n\n\t \t\t// Checking if this is a receipt packet to server\n\t \t\tif (!session.isServerSession() && id.toString().equals(session.getBareJID().getDomain())) {\n\t \t\t\t\n\t \t\t\tif (log.isLoggable(Level.FINEST)) {\n\t \t\t\t\tlog.log(Level.FINEST, \"Received receipts: {0}\", packet);\n\t \t\t\t}\n\t \t\t\t\n\t \t\t\tfinal String packetId = packet.getElement().getChild(RECEIPT_RECEIVED).getAttributeStaticStr(\"id\");\n\t \t\t\tremove(packet.getStanzaFrom(), packetId);\n\t \t\t}\n\t \t\t\n\t\t}\n\t}\n\t\n\tprivate Packet makeReceipts(Packet packet) {\n\t\t\n\t\tPacket receipt = null;\n\t\tfinal JID fromJID =   packet.getStanzaFrom();\n\t\tElement elm = new Element(Message.ELEM_NAME, new String[] { \"to\", \"from\", \"type\", \"xmlns\"},\n\t\t\t\t\t\t\t\tnew String[]{ fromJID.toString(), fromJID.getDomain(), \"chat\", \"jabber:client\"});\n\t\t\n\t\telm.addChild(new Element(RECEIPT_RECEIVED, \n\t\t\t\t\t\t\tnew String[] { \"id\", \"xmlns\" }, \n\t\t\t\t\t\t\tnew String[] {packet.getStanzaId(), XMLNS}));\n\t\t\n\t\ttry {\n\t\t\treceipt = Packet.packetInstance(elm);\n\t\t} catch (TigaseStringprepException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\t\n\t\treturn receipt;\n\t}\n\t\n\tprotected void store(Packet packet, XMPPResourceConnection session, NonAuthUserRepository userRepo) {\n\t\tMessageReceiptsStore store = BufferedMessageReceiptsStore.getInstance();\n\t\tif (null != store) {\n\t\t\tstore.setCallback(this);\n\t\t\tstore.append(packet, session, userRepo);\n\t\t}\n\t}\n\t\n\tprivate void remove(JID stanzaFrom, String packetId) {\n\t\tMessageReceiptsStore store = BufferedMessageReceiptsStore.getInstance();\n\t\tif (null != store) {\n\t\t\tstore.remove(stanzaFrom, packetId);\n\t\t}\n\t}\n\t\n\n\t@Override\n\tpublic void messageExpired(Packet message, long arrivedTime, XMPPResourceConnection session, NonAuthUserRepository userRepo) {\n\t\ttry {\n\t\t\tofflineProcessor.savePacketForOffLineUser(message, msg_repo, userRepo);\n\t\t\tSystem.out.println(\"----------------Expired message store--------\" + message.getStanzaId() + \"-------------\");\n\t\t\tif(session != null ){\n\t\t\t\tsession.logout();\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.log(Level.FINER, \"#Receipt : Expired message store into DB error, close session : packet: {0}\", message);\n\t\t\t}\n\t\t} catch (UserNotFoundException e) {\n\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\tlog.log(Level.WARNING, \"Expired message store into DB error, packet: {0}\", message);\n\t\t\t}\n\t\t\te.printStackTrace();\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\tlog.log(Level.WARNING, \"Expired message, Close session error, packet: {0}\", message);\n\t\t\t}\n\t\t}\n\t\t\n\t\tString type = message.getElement().getAttributeStaticStr(\"type\");\n\t\tif(type == null || !type.equals(\"chat\")){\n\t\t\treturn;\n\t\t}\n\t\tElement $body = message.getElement().findChild(new String[]{\"message\", \"body\"});\n\t\t\n\t\tif($body == null)\n\t\t\treturn;\n\n\t\ttry {\n\t\t\tJSONObject obj = new JSONObject($body.getCData());\n\t\t\tif (obj.getJSONObject(\"data\").get(\"chatType\").equals(\"1\") && obj.getJSONObject(\"data\").get(\"msgType\").equals(2001)){\n\t\t\t\t\n\t\t\t\tfinal String uid = obj.getJSONObject(\"data\").get(\"to\").toString();\n\t\t\t\t\n\t\t\t\tAPNSManager.pushMsg(uid, \n\t\t\t\t\t\tobj.getJSONObject(\"data\").getJSONObject(\"ext\").get(\"nick\") + \":\"\n\t\t\t\t\t\t+ obj.getJSONObject(\"data\").getJSONObject(\"body\").get(\"content\"));\n\t\t\t}\n\t\t} catch (JSONException e) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"#APNS push error: json tanslation error!\");\n\t\t\t}\n\t\t} catch (RuntimeException e) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"#APNS push error: \" + e.getMessage());\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\n\t@Override\n\tpublic void messageDropped(JID jid, String messageId,\n\t\t\tboolean hasBuffered) {\n\t\t// TODO Auto-generated method stub\n\t\t\n\t}\n\n\t\t\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MobileV1.java",
    "content": "/*\n * MobileV1.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Presence;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\n\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n//~--- JDK imports ------------------------------------------------------------\n\n/**\n * Class responsible for queuing packets (usable in connections from mobile\n * clients - power usage optimization) version 1\n *\n * @author andrzej\n */\npublic class MobileV1\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, ClientStateIndication.Logic {\n\t// default values\n\tprivate static final int        DEF_MAX_QUEUE_SIZE_VAL = 50;\n\tprivate static final long       DEF_MAX_TIMEOUT_VAL    = 6 * 60 * 1000;\n\tprivate static final String     ID                     = \"mobile_v1\";\n\tprivate static final Logger     log = Logger.getLogger(MobileV1.class\n\t\t\t.getCanonicalName());\n\tprivate static final String     MAX_QUEUE_SIZE_KEY     = \"max-queue-size\";\n\tprivate static final String     MAX_TIMEOUT_KEY        = \"max-timeout\";\n\tprivate static final String     MOBILE_EL_NAME         = \"mobile\";\n\tprivate static final String     XMLNS = \"http://tigase.org/protocol/mobile#v1\";\n\tprivate static final String[][] ELEMENT_PATHS          = {\n\t\t{ Iq.ELEM_NAME, MOBILE_EL_NAME }\n\t};\n\tprivate static final String[]   XMLNSS                 = { XMLNS };\n\tprivate static final String     TIMEOUT_KEY            = ID + \"-timeout\";\n\tprivate static final Element[]  SUP_FEATURES = { new Element(MOBILE_EL_NAME,\n\t\t\tnew String[] { \"xmlns\" }, new String[] { XMLNS }) };\n\tprivate static final String QUEUE_KEY = ID + \"-queue\";\n\n\t// keys\n\tprivate static final String LAST_TRANSFER_KEY = ID + \"-last-transfer\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int  maxQueueSize = DEF_MAX_QUEUE_SIZE_VAL;\n\tprivate long maxTimeout   = DEF_MAX_TIMEOUT_VAL;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tInteger maxQueueSizeVal = (Integer) settings.get(MAX_QUEUE_SIZE_KEY);\n\n\t\tif (maxQueueSizeVal != null) {\n\t\t\tmaxQueueSize = maxQueueSizeVal;\n\t\t}\n\n\t\tLong maxTimeoutVal = (Long) settings.get(MAX_TIMEOUT_KEY);\n\n\t\tif (maxTimeoutVal != null) {\n\t\t\tmaxTimeout = maxTimeoutVal;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"ignoring packet from not authorized session which is already of type error\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tStanzaType type = packet.getType();\n\n\t\t\tswitch (type) {\n\t\t\tcase set :\n\t\t\t\tElement el       = packet.getElement().getChild(MOBILE_EL_NAME);\n\t\t\t\tString  valueStr = el.getAttributeStaticStr(\"enable\");\n\n\t\t\t\t// if value is true queuing will be enabled\n\t\t\t\tboolean value = (valueStr != null) && (\"true\".equals(valueStr) || \"1\".equals(\n\t\t\t\t\t\tvalueStr));\n\n\t\t\t\tif (el.getAttributeStaticStr(\"timeout\") != null) {\n\n\t\t\t\t\t// we got timeout so we should set it for this session\n\t\t\t\t\tlong timeout = Long.parseLong(el.getAttributeStaticStr(\"timeout\"));\n\n\t\t\t\t\tsetTimeout(session, timeout);\n\t\t\t\t}\n\n\t\t\t\tif (value) {\n\t\t\t\t\tactivate(session, results);\n\t\t\t\t} else {\n\t\t\t\t\tdeactivate(session, results);\n\t\t\t\t}\n\n\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Mobile processing type is incorrect\", false));\n\t\t\t}\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tLogger.getLogger(MobileV1.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENT_PATHS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\tif (session == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn SUP_FEATURES;\n\t}\n\n\t@Override\n\tpublic void activate(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tif (session.getSessionData(QUEUE_KEY) == null) {\n\t\t\tsession.putSessionDataIfAbsent(QUEUE_KEY, new LinkedBlockingQueue<Packet>());\n\t\t}\n\t\tsession.putSessionData(XMLNS, true);\n\t}\n\n\t@Override\n\tpublic void deactivate(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tsession.putSessionData(XMLNS, false);\n\n\t\tflushQueue(session, results);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void filter(Packet _packet, XMPPResourceConnection sessionFromSM,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif ((sessionFromSM == null) ||!sessionFromSM.isAuthorized() || (results == null) ||\n\t\t\t\t(results.size() == 0)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\tPacket res = it.next();\n\n\t\t\t// check if packet contains destination\n\t\t\tif ((res == null) || (res.getPacketTo() == null)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"packet without destination\");\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// get resource connection for destination\n\t\t\tXMPPResourceConnection session = sessionFromSM.getParentSession()\n\t\t\t\t\t.getResourceForConnectionId(res.getPacketTo());\n\n\t\t\tif (session == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"no session for destination {0} for packet {1}\",\n\t\t\t\t\t\t\tnew Object[] { res.getPacketTo().toString(),\n\t\t\t\t\t\t\tres.toString() });\n\t\t\t\t}\n\n\t\t\t\t// if there is no session we should not queue\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// if queue is not enabled we do nothing\n\t\t\tif (!isQueueEnabled(session)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"queue is no enabled\");\n\t\t\t\t}\n\n\t\t\t\tflushQueue(session, results);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tQueue<Packet> queue = (Queue<Packet>) session.getSessionData(QUEUE_KEY);\n\n\t\t\t// lets check if packet should be queued\n\t\t\tif (filter(session, res, queue)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"queuing packet = {0}\", res.toString());\n\t\t\t\t}\n\t\t\t\tit.remove();\n\t\t\t\tif (queue.size() > maxQueueSize) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"sending packets from queue (OVERFLOW)\");\n\t\t\t\t\t}\n\n\t\t\t\t\tPacket p;\n\n\t\t\t\t\twhile ((p = queue.poll()) != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// setting destination for packet in case if\n\t\t\t\t\t\t\t// stream was resumed and connId changed\n\t\t\t\t\t\t\tp.setPacketTo(session.getConnectionId());\n\t\t\t\t\t\t\tresults.offer(p);\n\t\t\t\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"should not happen, as connection is ready\", ex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param res\n\t * @param queue\n\t *\n\t * \n\t */\n\tpublic boolean filter(XMPPResourceConnection session, Packet res, Queue<Packet> queue) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"checking if packet should be queued {0}\", res.toString());\n\t\t}\n\t\tif (res.getElemName() != Presence.ELEM_NAME) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"ignoring packet, packet is not presence:  {0}\", res\n\t\t\t\t\t\t.toString());\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tStanzaType type = res.getType();\n\n\t\tif ((type != null) && (type != StanzaType.unavailable) && (type != StanzaType\n\t\t\t\t.available)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"queuing packet {0}\", res.toString());\n\t\t}\n\t\tqueue.offer(res);\n\n\t\treturn true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected void flushQueue(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tQueue<Packet> queue = (Queue<Packet>) session.getSessionData(QUEUE_KEY);\n\n\t\tif ((queue != null) &&!queue.isEmpty()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"sending packets from queue (DISABLED)\");\n\t\t\t}\n\t\t\tPacket p;\n\t\t\twhile ((p = queue.poll()) != null) {\n\t\t\t\ttry {\n\t\t\t\t\t// setting destination for packet in case if\n\t\t\t\t\t// stream was resumed and connId changed\n\t\t\t\t\tp.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(p);\n\t\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\t\tlog.log(Level.FINEST, \"should not happen, as connection is ready\", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check if queuing is enabled\n\t *\n\t * @param session\n\t * \n\t */\n\tprotected boolean isQueueEnabled(XMPPResourceConnection session) {\n\t\tBoolean enabled = (Boolean) session.getSessionData(XMLNS);\n\n\t\treturn (enabled != null) && enabled;\n\t}\n\n\t/**\n\t * Check timeout for queue\n\t *\n\t * @param session\n\t * \n\t */\n\tprotected boolean isTimedOut(XMPPResourceConnection session) {\n\t\tLong lastAccessTime = (Long) session.getSessionData(LAST_TRANSFER_KEY);\n\n\t\tif (lastAccessTime == null) {\n\t\t\treturn true;\n\t\t}\n\t\tif (lastAccessTime + getTimeout(session) < System.currentTimeMillis()) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Update last send time\n\t *\n\t * @param session\n\t */\n\tprotected void updateLastAccessTime(XMPPResourceConnection session) {\n\t\tsession.putSessionData(LAST_TRANSFER_KEY, System.currentTimeMillis());\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Get timeout used for session queue\n\t *\n\t * @param session\n\t * \n\t */\n\tprivate long getTimeout(XMPPResourceConnection session) {\n\t\tLong timeout = (Long) session.getSessionData(TIMEOUT_KEY);\n\n\t\tif (timeout == null) {\n\t\t\treturn maxTimeout;\n\t\t}\n\n\t\treturn timeout;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Set timeout for session queue\n\t *\n\t * @param session\n\t * @param timeout\n\t */\n\tprivate void setTimeout(XMPPResourceConnection session, long timeout) {\n\t\tif (timeout == 0) {\n\t\t\tsession.removeSessionData(TIMEOUT_KEY);\n\t\t} else {\n\t\t\tsession.putSessionData(TIMEOUT_KEY, timeout);\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MobileV2.java",
    "content": "/*\n * MobileV2.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.Iterator;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Class responsible for queuing packets (usable in connections from mobile\n * clients - power usage optimization) version 2\n *\n * @author andrzej\n */\npublic class MobileV2\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPacketFilterIfc, ClientStateIndication.Logic {\n\t// default values\n\tprivate static final int    DEF_MAX_QUEUE_SIZE_VAL = 50;\n\tprivate static final String ID                     = \"mobile_v2\";\n\tprivate static final Logger log = Logger.getLogger(MobileV2.class.getCanonicalName());\n\n\t// keys\n\tprivate static final String     MAX_QUEUE_SIZE_KEY = \"max-queue-size\";\n\tprivate static final String     MOBILE_EL_NAME     = \"mobile\";\n\tprivate static final String     XMLNS = \"http://tigase.org/protocol/mobile#v2\";\n\tprivate static final String[][] ELEMENT_PATHS      = {\n\t\t{ Iq.ELEM_NAME, MOBILE_EL_NAME }\n\t};\n\tprivate static final String[]   XMLNSS             = { XMLNS };\n\tprivate static final Element[]  SUP_FEATURES = { new Element(MOBILE_EL_NAME,\n\t\t\tnew String[] { \"xmlns\" }, new String[] { XMLNS }) };\n\tprivate static final String QUEUE_KEY = ID + \"-queue\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int maxQueueSize = DEF_MAX_QUEUE_SIZE_VAL;\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tInteger maxQueueSizeVal = (Integer) settings.get(MAX_QUEUE_SIZE_KEY);\n\n\t\tif (maxQueueSizeVal != null) {\n\t\t\tmaxQueueSize = maxQueueSizeVal;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"ignoring packet from not authorized session which is already of type error\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tStanzaType type = packet.getType();\n\n\t\t\tswitch (type) {\n\t\t\tcase set :\n\t\t\t\tElement el       = packet.getElement().getChild(MOBILE_EL_NAME);\n\t\t\t\tString  valueStr = el.getAttributeStaticStr(\"enable\");\n\n\t\t\t\t// if value is true queuing will be enabled\n\t\t\t\tboolean value = (valueStr != null) && (\"true\".equals(valueStr) || \"1\".equals(\n\t\t\t\t\t\tvalueStr));\n\n\t\t\t\tif (value) {\n\t\t\t\t\tactivate(session, results);\n\t\t\t\t} else {\n\t\t\t\t\tdeactivate(session, results);\n\t\t\t\t}\n\n\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Mobile processing type is incorrect\", false));\n\t\t\t}\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tLogger.getLogger(MobileV2.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENT_PATHS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\tif (session == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn SUP_FEATURES;\n\t}\n\n\t@Override\n\tpublic void activate(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tif (session.getSessionData(QUEUE_KEY) == null) {\n\n\t\t\t// session.putSessionData(QUEUE_KEY, new\n\t\t\t// LinkedBlockingQueue<Packet>());\n\t\t\tsession.putSessionData(QUEUE_KEY, new ConcurrentHashMap<JID, Packet>());\n\t\t}\n\t\tsession.putSessionData(XMLNS, true);\n\t}\n\n\t@Override\n\tpublic void deactivate(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tif (session.getSessionData(QUEUE_KEY) == null) {\n\n\t\t\t// session.putSessionData(QUEUE_KEY, new\n\t\t\t// LinkedBlockingQueue<Packet>());\n\t\t\tsession.putSessionData(QUEUE_KEY, new ConcurrentHashMap<JID, Packet>());\n\t\t}\n\t\tsession.putSessionData(XMLNS, false);\n\n\t\tflushQueue(session, results);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void filter(Packet _packet, XMPPResourceConnection sessionFromSM,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif ((sessionFromSM == null) ||!sessionFromSM.isAuthorized() || (results == null) ||\n\t\t\t\t(results.size() == 0)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\tPacket res = it.next();\n\n\t\t\t// check if packet contains destination\n\t\t\tif ((res == null) || (res.getPacketTo() == null)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"packet without destination\");\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// get resource connection for destination\n\t\t\tXMPPResourceConnection session = sessionFromSM.getParentSession()\n\t\t\t\t\t.getResourceForConnectionId(res.getPacketTo());\n\n\t\t\tif (session == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"no session for destination {0} for packet {1}\",\n\t\t\t\t\t\t\tnew Object[] { res.getPacketTo().toString(),\n\t\t\t\t\t\t\tres.toString() });\n\t\t\t\t}\n\n\t\t\t\t// if there is no session we should not queue\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// if queue is not enabled we do nothing\n\t\t\tif (!isQueueEnabled(session)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"queue is no enabled\");\n\t\t\t\t}\n\t\t\t\tflushQueue(session, results);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tMap<JID, Packet> queue = (Map<JID, Packet>) session.getSessionData(QUEUE_KEY);\n\n\t\t\t// lets check if packet should be queued\n\t\t\tif (filter(session, res, queue)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"queuing packet = {0}\", res.toString());\n\t\t\t\t}\n\t\t\t\tit.remove();\n\t\t\t\tif (queue.size() > maxQueueSize) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"sending packets from queue (OVERFLOW)\");\n\t\t\t\t\t}\n\t\t\t\t\tfor (Packet p : queue.values()) {\n\t\t\t\t\t\tresults.offer(res);\n\t\t\t\t\t}\n\t\t\t\t\tqueue.clear();\n\n\t\t\t\t\t// we are sending all items from map so there is no need\n\t\t\t\t\t// to filter it (fix for ConcurrentModificationException)\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param res\n\t * @param queue\n\t *\n\t * \n\t */\n\tpublic boolean filter(XMPPResourceConnection session, Packet res, Map<JID,\n\t\t\tPacket> queue) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"checking if packet should be queued {0}\", res.toString());\n\t\t}\n\t\tif (res.getElemName() != \"presence\") {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"ignoring packet, packet is not presence:  {0}\", res\n\t\t\t\t\t\t.toString());\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tStanzaType type = res.getType();\n\n\t\tif ((type != null) && (type != StanzaType.unavailable) && (type != StanzaType\n\t\t\t\t.available)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"queuing packet {0}\", res.toString());\n\t\t}\n\t\tqueue.put(res.getStanzaFrom(), res);\n\n\t\treturn true;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprotected void flushQueue(XMPPResourceConnection session, Queue<Packet> results) {\n\t\tMap<JID, Packet> queue = (Map<JID, Packet>) session.getSessionData(QUEUE_KEY);\n\n\t\tif ((queue != null) &&!queue.isEmpty()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"sending packets from queue (DISABLED)\");\n\t\t\t}\n\t\t\tfor (Packet p : queue.values()) {\n\t\t\t\ttry {\n\t\t\t\t\t// setting destination for packet in case if\n\t\t\t\t\t// stream was resumed and connId changed\n\t\t\t\t\tp.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(p);\n\t\t\t\t} catch (NoConnectionIdException ex) {\n\t\t\t\t\tlog.log(Level.FINEST, \"should not happen, as connection is ready\", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t\tqueue.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Check if queuing is enabled\n\t *\n\t * @param session\n\t * \n\t */\n\tprotected boolean isQueueEnabled(XMPPResourceConnection session) {\n\t\tBoolean enabled = (Boolean) session.getSessionData(XMLNS);\n\n\t\treturn (enabled != null) && enabled;\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MobileV3.java",
    "content": "/*\n * MobileV3.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.annotation.*;\n\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.xmpp.impl.MobileV3.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\n/**\n * Class responsible for queuing packets (usable in connections from mobile\n * clients - power usage optimization) version 3\n *\n * @author andrzej\n */\n@Id(ID)\n@Handles({\n\t@Handle(path={Iq.ELEM_NAME, MOBILE_EL_NAME},xmlns=XMLNS)\n})\n@StreamFeatures({\n\t@StreamFeature(elem=MOBILE_EL_NAME,xmlns=XMLNS)\n})\npublic class MobileV3\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPacketFilterIfc {\n\t\n\tprivate static class StateHolder { \n\t\tprivate final Map<JID,QueueState> states = new HashMap<JID,QueueState>();\n\t\tprivate final Queue<Packet> queue = new ArrayDeque<Packet>();\n\t\t\n\t\tprotected QueueState setState(JID jid, QueueState state) {\n\t\t\tQueueState oldState = getState(jid);\n\t\t\tif (oldState.value() < state.value()) {\n\t\t\t\tstates.put(jid, state);\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn oldState;\n\t\t}\n\t\t\n\t\tprotected QueueState getState(JID jid) {\n\t\t\tQueueState state = states.get(jid);\n\t\t\tif (state == null)\n\t\t\t\tstate = QueueState.none;\n\t\t\treturn state;\n\t\t}\n\t\t\n\t\tprotected void reset() {\n\t\t\tstates.clear();\n\t\t\tqueue.clear();\n\t\t}\n\t}\n\t\n\t// default values\n\tprivate static final int    DEF_MAX_QUEUE_SIZE_VAL = 50;\n\tprotected static final String ID                     = \"mobile_v3\";\n\tprivate static final Logger log = Logger.getLogger(MobileV3.class.getCanonicalName());\n\n\t// keys\n\tprivate static final String     MAX_QUEUE_SIZE_KEY = \"max-queue-size\";\n\tprotected static final String     MOBILE_EL_NAME     = \"mobile\";\n\tprotected static final String     XMLNS = \"http://tigase.org/protocol/mobile#v3\";\n\tprivate static final String PRESENCE_QUEUE_KEY = ID + \"-presence-queue\";\n\tprivate static final String PACKET_QUEUE_KEY = ID + \"-packet-queue\";\n\n\tprivate static final String DELAY_ELEM_NAME = \"delay\";\n\tprivate static final String DELAY_XMLNS = \"urn:xmpp:delay\";\n\tprivate static final String MESSAGE_ELEM_NAME = \"message\";\n\t\n\t//private static final ThreadLocal<Queue> prependResultsThreadQueue = new ThreadLocal<Queue>();\n\tprivate static final ThreadLocal<StateHolder> threadState = new ThreadLocal<StateHolder>();\n\t\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate int maxQueueSize = DEF_MAX_QUEUE_SIZE_VAL;\n\tprivate SimpleDateFormat formatter;\t\n\t{\n\t\tthis.formatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tthis.formatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\n\t\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\n\t\tInteger maxQueueSizeVal = (Integer) settings.get(MAX_QUEUE_SIZE_KEY);\n\n\t\tif (maxQueueSizeVal != null) {\n\t\t\tmaxQueueSize = maxQueueSizeVal;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\ttry {\n\t\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\t\"Session is not yet authorized.\", false));\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\"ignoring packet from not authorized session which is already of type error\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tStanzaType type = packet.getType();\n\n\t\t\tswitch (type) {\n\t\t\tcase set :\n\t\t\t\tElement el       = packet.getElement().getChild(MOBILE_EL_NAME);\n\t\t\t\tString  valueStr = el.getAttributeStaticStr(\"enable\");\n\n\t\t\t\t// if value is true queuing will be enabled\n\t\t\t\tboolean value = (valueStr != null) && (\"true\".equals(valueStr) || \"1\".equals(\n\t\t\t\t\t\tvalueStr));\n\n\t\t\t\tif (session.getSessionData(PRESENCE_QUEUE_KEY) == null) {\n\n\t\t\t\t\t// session.putSessionData(QUEUE_KEY, new\n\t\t\t\t\t// LinkedBlockingQueue<Packet>());\n\t\t\t\t\tsession.putSessionData(PRESENCE_QUEUE_KEY, new ConcurrentHashMap<JID, Packet>());\n\t\t\t\t}\n\t\t\t\tif (session.getSessionData(PACKET_QUEUE_KEY) == null) {\n\t\t\t\t\tsession.putSessionData(PACKET_QUEUE_KEY, new ArrayDeque<Packet>());\n\t\t\t\t}\n\t\t\t\tsession.putSessionData(XMLNS, value);\n\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\"Mobile processing type is incorrect\", false));\n\t\t\t}\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\tLogger.getLogger(MobileV3.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\tif (session == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!session.isAuthorized()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn super.supStreamFeatures(session);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void filter(Packet _packet, XMPPResourceConnection sessionFromSM,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results) {\n\t\tif ((sessionFromSM == null) ||!sessionFromSM.isAuthorized() || (results == null) ||\n\t\t\t\t(results.size() == 0)) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tStateHolder holder = threadState.get();\n\t\tif (holder == null) {\n\t\t\tholder = new StateHolder();\n\t\t\tthreadState.set(holder);\n\t\t}\n\t\t\n\t\tfor (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {\n\t\t\tPacket res = it.next();\n\n\t\t\t// check if packet contains destination\n\t\t\tif ((res == null) || (res.getPacketTo() == null)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"packet without destination\");\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// get resource connection for destination\n\t\t\tXMPPResourceConnection session = sessionFromSM.getParentSession()\n\t\t\t\t\t.getResourceForConnectionId(res.getPacketTo());\n\n\t\t\tif (session == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"no session for destination {0} for packet {1}\",\n\t\t\t\t\t\t\tnew Object[] { res.getPacketTo().toString(),\n\t\t\t\t\t\t\tres.toString() });\n\t\t\t\t}\n\n\t\t\t\t// if there is no session we should not queue\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tMap<JID, Packet> presenceQueue = (Map<JID, Packet>) session.getSessionData(PRESENCE_QUEUE_KEY);\n\t\t\tQueue<Packet> packetQueue = (Queue<Packet>) session.getSessionData(PACKET_QUEUE_KEY);\n\t\t\t\n\t\t\t//QueueState state = QueueState.need_flush;\n\t\t\tif (!isQueueEnabled(session)) {\n\t\t\t\tif ((presenceQueue == null && packetQueue == null)\n\t\t\t\t\t\t|| (presenceQueue.isEmpty() && packetQueue.isEmpty())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"mobile queues needs flushing - presences: {0}, packets: {1}\", \n\t\t\t\t\t\t\tnew Object[] {presenceQueue.size(), packetQueue.size() });\n\t\t\t\t}\n\t\t\t\tholder.setState(res.getPacketTo(), QueueState.need_flush);\n\t\t\t} else {\n\t\t\t\tQueueState state = filter(session, res, holder.getState(res.getPacketTo()), presenceQueue, packetQueue);\n\t\t\t\tif (state == QueueState.queued) {\n\t\t\t\t\tit.remove();\n\t\t\t\t\tif (log.isLoggable(Level.FINEST))\n\t\t\t\t\t\tlog.log(Level.FINEST, \"queue packet = {0}\", res.toString());\n\t\t\t\t\tif (presenceQueue.size() > maxQueueSize) {\n\t\t\t\t\t\tstate = QueueState.need_flush;\n\t\t\t\t\t}\n\t\t\t\t\telse if (packetQueue.size() > maxQueueSize)\n\t\t\t\t\t\tstate = QueueState.need_packet_flush;\n\t\t\t\t}\n\t\t\t\tstate = holder.setState(res.getPacketTo(), state);\n\t\t\t}\n\t\t\t\n//\t\t\tswitch (state) {\n//\t\t\t\tcase need_flush:\n//\t\t\t\t\tprependResults = prependResultsThreadQueue.get();\n//\t\t\t\t\tif (prependResults == null) {\n//\t\t\t\t\t\tprependResults = new ArrayDeque<Packet>();\n//\t\t\t\t\t\tprependResultsThreadQueue.set(prependResults);\n//\t\t\t\t\t}\n//\t\t\t\t\t\n//\t\t\t\t\ttry {\n//\t\t\t\t\t\tsynchronized (presenceQueue) {\n//\t\t\t\t\t\t\tJID connId = session.getConnectionId();\n//\t\t\t\t\t\t\tfor (Packet p : presenceQueue.values()) {\n//\t\t\t\t\t\t\t\t// we need to set packet to again in case Stream\n//\t\t\t\t\t\t\t\t// Management resumption happend in meanwhile\n//\t\t\t\t\t\t\t\tp.setPacketTo(connId);\n//\t\t\t\t\t\t\t\tprependResults.offer(p);\n//\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\tpresenceQueue.clear();\n//\t\t\t\t\t\t}\n//\t\t\t\t\t}\n//\t\t\t\t\tcatch (NoConnectionIdException ex) {\n//\t\t\t\t\t\tlog.log(Level.SEVERE, \"this should not happen\", ex);\n//\t\t\t\t\t}\n//\t\t\t\t\t\n//\t\t\t\tcase need_packet_flush:\n//\t\t\t\t\tif (prependResults == null) {\n//\t\t\t\t\t\tprependResults = prependResultsThreadQueue.get();\n//\t\t\t\t\t\tif (prependResults == null) {\n//\t\t\t\t\t\t\tprependResults = new ArrayDeque<Packet>();\n//\t\t\t\t\t\t\tprependResultsThreadQueue.set(prependResults);\n//\t\t\t\t\t\t}\n//\t\t\t\t\t}\n//\t\t\t\t\ttry {\n//\t\t\t\t\t\tsynchronized (packetQueue) {\n//\t\t\t\t\t\t\tJID connId = session.getConnectionId();\n//\t\t\t\t\t\t\tPacket p = null;\n//\t\t\t\t\t\t\twhile ((p = packetQueue.poll()) != null) {\n//\t\t\t\t\t\t\t\t// we need to set packet to again in case Stream\n//\t\t\t\t\t\t\t\t// Management resumption happend in meanwhile\n//\t\t\t\t\t\t\t\tp.setPacketTo(connId);\n//\t\t\t\t\t\t\t\tprependResults.offer(p);\n//\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\tpacketQueue.clear();\n//\t\t\t\t\t\t}\n//\t\t\t\t\t}\n//\t\t\t\t\tcatch (NoConnectionIdException ex) {\n//\t\t\t\t\t\tlog.log(Level.SEVERE, \"this should not happen\", ex);\n//\t\t\t\t\t}\t\t\t\t\n//\t\t\t\tcase queued:\t\t\t\t\t\n//\t\t\t\t\tbreak;\n//\t\t\t\t\t\n//\t\t\t\tdefault:\n//\t\t\t\t\tbreak;\n//\t\t\t}\n\t\t}\n\n\t\tfor (Map.Entry<JID,QueueState> e : holder.states.entrySet()) {\n\t\t\tXMPPResourceConnection session = null;\n\t\t\tswitch (e.getValue()) {\n\t\t\t\tcase need_flush:\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsession = sessionFromSM.getParentSession().getResourceForConnectionId(e.getKey());\n\t\t\t\t\t\tif (session != null) {\n\t\t\t\t\t\t\tMap<JID, Packet> presenceQueue = (Map<JID, Packet>) session.getSessionData(PRESENCE_QUEUE_KEY);\n\t\t\t\t\t\t\tsynchronized (presenceQueue) {\n\t\t\t\t\t\t\t\tJID connId = session.getConnectionId();\n\t\t\t\t\t\t\t\tfor (Packet p : presenceQueue.values()) {\n\t\t\t\t\t\t\t\t// we need to set packet to again in case Stream\n\t\t\t\t\t\t\t\t\t// Management resumption happend in meanwhile\n\t\t\t\t\t\t\t\t\tp.setPacketTo(connId);\n\t\t\t\t\t\t\t\t\tholder.queue.offer(p);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpresenceQueue.clear();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (NoConnectionIdException ex) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"this should not happen\", ex);\n\t\t\t\t\t}\n\t\t\t\tcase need_packet_flush:\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (session == null)\n\t\t\t\t\t\t\tsession = sessionFromSM.getParentSession().getResourceForConnectionId(e.getKey());\n\t\t\t\t\t\tif (session != null) {\n\t\t\t\t\t\t\tQueue<Packet> packetQueue = (Queue<Packet>) session.getSessionData(PACKET_QUEUE_KEY);\n\t\t\t\t\t\t\tsynchronized (packetQueue) {\n\t\t\t\t\t\t\t\tJID connId = session.getConnectionId();\n\t\t\t\t\t\t\t\tPacket p = null;\n\t\t\t\t\t\t\t\twhile ((p = packetQueue.poll()) != null) {\n\t\t\t\t\t\t\t\t// we need to set packet to again in case Stream\n\t\t\t\t\t\t\t\t\t// Management resumption happend in meanwhile\n\t\t\t\t\t\t\t\t\tp.setPacketTo(connId);\n\t\t\t\t\t\t\t\t\tholder.queue.offer(p);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpacketQueue.clear();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (NoConnectionIdException ex) {\n\t\t\t\t\t\tlog.log(Level.SEVERE, \"this should not happen\", ex);\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\tcase queued:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!holder.queue.isEmpty()) {\n\t\t\tif (log.isLoggable(Level.FINEST)) \n\t\t\t\tlog.log(Level.FINEST, \"sending queued packets = {0}\", holder.queue.size());\n\t\t\tholder.queue.addAll(results);\n\t\t\tresults.clear();\n\t\t\tresults.addAll(holder.queue);\n\t\t\t//holder.queue.clear();\n\t\t}\n\t\tholder.reset();\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param res\n\t * @param presenceQueue\n\t *\n\t * \n\t */\n\tprivate QueueState filter(XMPPResourceConnection session, Packet res, QueueState state,\n\t\t\tMap<JID,Packet> presenceQueue, Queue<Packet> packetQueue) {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"checking if packet should be queued {0}\", res.toString());\n\t\t}\n\t\t\n\t\tif (state == QueueState.need_flush)\n\t\t\treturn state;\n\n\t\tif (res.getElemName() == MESSAGE_ELEM_NAME) {\n\t\t\tif (state.value() > QueueState.queued.value())\n\t\t\t\treturn state;\n\t\t\t\n\t\t\tList<Element> children = res.getElement().getChildren();\n\t\t\tif (children != null) {\n\t\t\t\tfor (Element child : children) {\n\t\t\t\t\tif (MessageCarbons.XMLNS.equals(child.getXMLNS())) {\n\t\t\t\t\t\tElement delay = res.getElement().getChild(DELAY_ELEM_NAME, DELAY_XMLNS);\n\t\t\t\t\t\tif (delay == null) {\n\t\t\t\t\t\t\tdelay = createDelayElem(session);\n\t\t\t\t\t\t\tif (delay != null) {\n\t\t\t\t\t\t\t\tElement forward = child.getChild(\"forward\", \"urn:xmpp:forward:0\");\n\t\t\t\t\t\t\t\tif (forward != null) {\n\t\t\t\t\t\t\t\t\tElement msg = forward.getChild(MESSAGE_ELEM_NAME);\n\t\t\t\t\t\t\t\t\tif (msg != null) {\n\t\t\t\t\t\t\t\t\t\tmsg.addChild(delay);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsynchronized (packetQueue) {\n\t\t\t\t\t\t\tpacketQueue.offer(res);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn QueueState.queued;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn QueueState.need_packet_flush;\n\t\t}\n\t\t\n\t\tif (res.getElemName() != \"presence\") {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"ignoring packet, packet is not presence:  {0}\", res\n\t\t\t\t\t\t.toString());\n\t\t\t}\n\n\t\t\treturn QueueState.need_packet_flush;\n\t\t}\n\n\t\tStanzaType type = res.getType();\n\n\t\tif ((type != null) && (type != StanzaType.unavailable) && (type != StanzaType\n\t\t\t\t.available)) {\n\t\t\treturn QueueState.need_flush;\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"queuing packet {0}\", res.toString());\n\t\t}\n\t\tElement delay = res.getElement().getChild(DELAY_ELEM_NAME, DELAY_XMLNS);\n\t\tif (delay == null) {\n\t\t\tdelay = createDelayElem(session);\n\t\t\tif (delay != null) {\n\t\t\t\tres.getElement().addChild(delay);\n\t\t\t}\n\t\t}\n\t\tsynchronized (presenceQueue) {\n\t\t\tpresenceQueue.put(res.getStanzaFrom(), res);\n\t\t}\n\n\t\treturn QueueState.queued;\n\t}\n\n\tprivate Element createDelayElem(XMPPResourceConnection session) {\n\t\tString timestamp = null;\n\t\tsynchronized (formatter) {\n\t\t\ttimestamp = formatter.format(new Date());\n\t\t}\n\t\t\n\t\ttry {\n\t\t\treturn new Element(DELAY_ELEM_NAME, new String[] { \"xmlns\", \"from\", \"stamp\" }, \n\t\t\t\t\tnew String[] { DELAY_XMLNS, session.getBareJID().getDomain(), timestamp });\n\t\t}\n\t\tcatch (NotAuthorizedException ex) {\n\t\t\treturn null;\n\t\t}\n\t}\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Check if queuing is enabled\n\t *\n\t * @param session\n\t * \n\t */\n\tprotected static boolean isQueueEnabled(XMPPResourceConnection session) {\n\t\tBoolean enabled = (Boolean) session.getSessionData(XMLNS);\n\n\t\treturn (enabled != null) && enabled;\n\t}\n\t\n\tprivate static enum QueueState {\n\t\tnone(0),\n\t\tqueued(1),\n\t\tneed_flush(3),\n\t\tneed_packet_flush(2);\n\t\t\n\t\tprivate final int value;\n\t\t\n\t\tQueueState(int value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\t\n\t\tpublic int value() {\n\t\t\treturn value;\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/16\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/OfflineMessages.java",
    "content": "/*\n * OfflineMessages.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\nimport tigase.apns.APNSManager;\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.amp.MsgRepository;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.ElementMatcher;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPPostprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.osgi.ModulesManagerImpl;\nimport tigase.util.DNSResolverFactory;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimeZone;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport static tigase.server.Message.ELEM_NAME;\n\n/**\n * OfflineMessages plugin implementation which follows <a\n * href=\"http://xmpp.org/extensions/xep-0160.html\">XEP-0160: Best Practices for\n * Handling Offline Messages</a> specification. Responsible for storing messages\n * send to offline users - either as a standalone plugin or as a processor for\n * other plugins (e.g. AMP). Is registered to handle packets of type\n * {@code <presence>}.\n *\n *\n * Created: Mon Oct 16 13:28:53 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class OfflineMessages\n\t\textends XMPPProcessor\n\t\timplements XMPPPostprocessorIfc, XMPPProcessorIfc {\n\n\t/** Field holds default client namespace for stanzas. In case of\n\t * {@code msgoffline} plugin it is <em>jabber:client</em> */\n\tprotected static final String XMLNS = \"jabber:client\";\n\t/** Field holds identification string for the plugin. In case of\n\t * {@code msgoffline} plugin it is <em>msgoffline</em> */\n\tprivate static final String ID = \"msgoffline\";\n\t/** Private logger for class instances. */\n\tprivate static final Logger log = Logger.getLogger( OfflineMessages.class.getName() );\n\t/** Field holds an array for element paths for which the plugin offers\n\t * processing capabilities. In case of {@code msgoffline} plugin it is\n\t * <em>presence</em> stanza */\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ PresenceAbstract.PRESENCE_ELEMENT_NAME }, { \"iq\", \"msgoffline\" } };\n\t/** Field holds an array of name-spaces for stanzas which can be processed by\n\t * this plugin. In case of {@code msgoffline} plugin it is\n\t * <em>jabber:client</em> */\n\tprivate static final String[] XMLNSS = { XMLNS, ID };\n\t/** Field holds an array of XML Elements with service discovery features which\n\t * have to be returned to the client uppon request. In case of\n\t * {@code msgoffline} plugin it is the same as plugin name -\n\t * <em>msgoffline</em> */\n\tprivate static final Element[] DISCO_FEATURES = {\n\t\tnew Element( \"feature\", new String[] { \"var\" }, new String[] { \"msgoffline\" } ) };\n\t/** Field holds the default hostname of the machine. */\n\tprivate static String defHost;\n\t/** Field holds an array for element paths for which the plugin offers message\n\t * saving capabilities. In case of {@code msgoffline} plugin it is\n\t * <em>presence</em> stanza */\n\tpublic static final String[] MESSAGE_EVENT_PATH = { ELEM_NAME, \"event\" };\n\t/** Field holds an array for element paths for which the plugin offers\n\t * processing capabilities. In case of {@code msgoffline} plugin it is\n\t * <em>presence</em> stanza */\n\tpublic static final String[] MESSAGE_HEADER_PATH = { ELEM_NAME, \"header\" };\n\tpublic static final String[] MESSAGE_HINTS_NO_STORE = { ELEM_NAME, \"no-store\" };\n\tpublic static final String MESSAGE_HINTS_XMLNS = \"urn:xmpp:hints\";\n\tpublic static final String[] MESSAGE_RECEIVED_PATH = { ELEM_NAME, \"received\" };\n\tpublic static final String MESSAGE_RECEIVED_XMLNS = \"urn:xmpp:receipts\";\n\tprivate static final String MSG_OFFLINE_STORAGE_PATHS = \"msg-store-offline-paths\";\n\tprivate static final String MSG_REPO_CLASS_KEY = \"msg-repo-class\";\n\tprivate static final String MSG_PUBSUB_JID = \"msg-pubsub-jid\";\n\tprivate static final String MSG_PUBSUB_NODE = \"msg-pubsub-node\";\n\tprivate static final String MSG_PUBSUB_PUBLISHER = \"msg-pubsub-publisher\";\n\tpublic static final String[] PUBSUB_NODE_PATH = { Message.ELEM_NAME, \"event\", \"items\" };\n\tpublic static final String PUBSUB_NODE_KEY = \"node\";\n\n\t//~--- fields ---------------------------------------------------------------\n\t/** Field holds class for formatting and parsing dates in a locale-sensitive\n\t * manner */\n\tprivate final SimpleDateFormat formatter;\n\tprivate String msgRepoCls = null;\n\tprivate Message message = new Message();\n\tprivate String pubSubJID;\n\tprivate String pubSubNode;\n\tprivate String defaultPublisher;\n\tprivate ElementMatcher[] offlineStorageMatchers = new ElementMatcher[0];\n\t\n\t{\n\t\tthis.formatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\t//this.formatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t\tthis.formatter.setTimeZone( TimeZone.getTimeZone( \"GMT+8\" ) );\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\t\tdefHost = DNSResolverFactory.getInstance().getDefaultHost();\n\t\tmsgRepoCls = (String) settings.get(MSG_REPO_CLASS_KEY);\n\t\tif (settings.containsKey(MSG_PUBSUB_JID))\n\t\t\tthis.pubSubJID = (String) settings.get(MSG_PUBSUB_JID);\n\t\tif (settings.containsKey(MSG_PUBSUB_NODE))\n\t\t\tthis.pubSubNode = (String) settings.get(MSG_PUBSUB_NODE);\n\t\tif (settings.containsKey(MSG_PUBSUB_NODE))\n\t\t\tthis.pubSubNode = (String) settings.get(MSG_PUBSUB_NODE);\n\t\tif (settings.containsKey(MSG_PUBSUB_PUBLISHER))\n\t\t\tthis.defaultPublisher = (String) settings.get(MSG_PUBSUB_PUBLISHER);\n\t\tif (settings.containsKey(MSG_OFFLINE_STORAGE_PATHS)) {\n\t\t\tString[] matcherStrs = (String[]) settings.get(MSG_OFFLINE_STORAGE_PATHS);\n\t\t\tList<ElementMatcher> matchers = new ArrayList<>();\n\t\t\tfor (String matcherStr : matcherStrs) {\n\t\t\t\tElementMatcher matcher = ElementMatcher.create(matcherStr);\n\t\t\t\tif (matcher != null) {\n\t\t\t\t\tmatchers.add(matcher);\n\t\t\t\t}\n\t\t\t}\n\t\t\tofflineStorageMatchers = matchers.toArray(new ElementMatcher[0]);\n\t\t}\n\t}\n\t\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * OfflineMessages postprocessor simply calls {@code savePacketForOffLineUser}\n\t * method to store packet to offline repository.\n\t */\n\t@Override\n\tpublic void postProcess( final Packet packet, final XMPPResourceConnection conn,\n\t\t\t\t\t\t\t\t\t\t\t\t\t final NonAuthUserRepository repo, final Queue<Packet> queue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t Map<String, Object> settings ) {\n\t\tif ( conn == null || !message.hasConnectionForMessageDelivery(conn) ){\n\t\t\ttry {\n\t\t\t\tif (packet.getElemName() == tigase.server.Message.ELEM_NAME\n\t\t\t\t\t\t&& packet.getStanzaTo() != null && packet.getStanzaTo().getResource() != null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (conn != null && packet.getStanzaTo() != null && !conn.isUserId(packet.getStanzaTo().getBareJID()))\n\t\t\t\t\treturn;\n\t\t\t\tMsgRepositoryIfc msg_repo = getMsgRepoImpl( repo, conn );\n\n\t\t\t\tpublishInPubSub(packet, conn, queue, settings);\n\t\t\t\t\n\t\t\t\tAuthorization saveResult = savePacketForOffLineUser( packet, msg_repo, repo );\n\t\t\t\tPacket result = null;\n\t\t\t\t\n\t\t\t\tswitch (saveResult) {\n\t\t\t\t\tcase SERVICE_UNAVAILABLE:\n\t\t\t\t\t\tresult = saveResult.getResponseMessage(packet, \"Offline messages queue is full\", true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (result != null) {\n\t\t\t\t\tqueue.offer(result);\n\t\t\t\t}\n\t\t\t} catch ( UserNotFoundException e ) {\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\"UserNotFoundException at trying to save packet for off-line user.\"\n\t\t\t\t\t\t\t+ packet );\n\t\t\t\t}\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log(Level.FINEST, \"NotAuthorizedException when checking if message is to this \"\n\t\t\t\t\t\t\t+ \"user at trying to save packet for off-line user, {0}, {1}\", new Object[]{ packet, conn });\n\t\t\t\t}\n\t\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\tlog.log(Level.FINE, \"Could not sent error to packet sent to offline user which storage to offline \"\n\t\t\t\t\t\t+ \"store failed. Packet is error type already: {0}\", packet.toStringSecure());\n\t\t\t}    // end of try-catch\n\t\t}      // end of if (conn == null)\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * {@code OfflineMessages} processor is triggered by {@code <presence>}\n\t * stanza. Upon receiving it plugin tries to load messages from repository\n\t * and, if the result is not empty, sends them to the user\n\t */\n\t@Override\n\tpublic void process( final Packet packet, final XMPPResourceConnection conn,\n\t\t\t\t\t\t\t\t\t\t\t final NonAuthUserRepository repo, final Queue<Packet> results,\n\t\t\t\t\t\t\t\t\t\t\t final Map<String, Object> settings )\n\t\t\tthrows NotAuthorizedException {\n\t\tswitch (packet.getElemName()) {\n\t\t\tcase tigase.server.Presence.ELEM_NAME:\n\t\t\t\tif (loadOfflineMessages(packet, conn)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tMsgRepositoryIfc msg_repo = getMsgRepoImpl(repo, conn);\n\t\t\t\t\t\tQueue<Packet> packets = restorePacketForOffLineUser(conn, msg_repo);\n\n\t\t\t\t\t\tif (packets != null) {\n\t\t\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\t\t\tlog.finer(\"Sending off-line messages: \" + packets.size());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults.addAll(packets);\n\t\t\t\t\t\t}    // end of if (packets != null)\n\t\t\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\t\t\tlog.info(\"Something wrong, DB problem, cannot load offline messages. \" + e);\n\t\t\t\t\t}      // end of try-catch\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase Iq.ELEM_NAME:\n\t\t\t\tprocessIq(packet, conn, repo, results);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tpublic void processIq(Packet packet, XMPPResourceConnection conn, NonAuthUserRepository repo, Queue<Packet> results) throws NotAuthorizedException {\n\t\ttry {\n\t\t\tif (conn != null && packet.getFrom().equals(conn.getConnectionId())) {\n\t\t\t\tElement msgoffline = packet.getElement().getChild(\"msgoffline\");\n\t\t\t\tString limitStr = null;\n\t\t\t\tswitch (packet.getType()) {\n\t\t\t\t\tcase set:\n\t\t\t\t\t\tlimitStr = msgoffline.getAttributeStaticStr(\"limit\");\n\t\t\t\t\t\tLong limit = null;\n\t\t\t\t\t\tif (limitStr != null) {\n\t\t\t\t\t\t\tif (\"none\".equals(limitStr) || \"false\".equals(limitStr))\n\t\t\t\t\t\t\t\tlimit = (long)-1;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tlimit = Long.parseLong(limitStr);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (limit == null) {\n\t\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Value of limit attribute is incorrect\", false));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (limit >= 0) {\n\t\t\t\t\t\t\t\tconn.setPublicData(MsgRepository.OFFLINE_MSGS_KEY, MsgRepository.MSGS_STORE_LIMIT_KEY, limitStr);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconn.removePublicData(MsgRepository.OFFLINE_MSGS_KEY, MsgRepository.MSGS_STORE_LIMIT_KEY);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// following get case will return result for set as well\n\t\t\t\t\tcase get:\n\t\t\t\t\t\tif (limitStr == null)\n\t\t\t\t\t\t\tlimitStr = conn.getPublicData(MsgRepository.OFFLINE_MSGS_KEY, MsgRepository.MSGS_STORE_LIMIT_KEY, null);\n\t\t\t\t\t\tif (limitStr == null)\n\t\t\t\t\t\t\tlimitStr = \"false\";\n\t\t\t\t\t\tmsgoffline = new Element(\"msgoffline\", new String[] { \"xmlns\", \"limit\" }, new String[] { \"msgoffline\", limitStr });\n\t\t\t\t\t\tresults.offer(packet.okResult(msgoffline, 0));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \n\t\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet, \n\t\t\t\t\t\t\"You are not authorized to access this private storage.\", false));\n\t\t\t}\n\t\t} catch (TigaseDBException ex) {\n\t\t} catch (NoConnectionIdException ex) {\n\t\t} catch (PacketErrorTypeException ex) {\n\t\t\t\n\t\t}\n\t}\n\t\n\t/**\n\t * Method restores all messages from repository for the JID of the current\n\t * session. All retrieved elements are then instantiated as {@code Packet}\n\t * objects added to {@code LinkedList} collection and, if possible, sorted by\n\t * timestamp.\n\t *\n\t * @param conn user session which keeps all the user session data and also\n\t *             gives an access to the user's repository data.\n\t * @param repo an implementation of {@link MsgRepositoryIfc} interface\n\t *\n\t *\n\t * @return a {@link Queue} of {@link Packet} objects based on all stored\n\t *         payloads for the JID of the current session.\n\t *\n\t * @throws UserNotFoundException\n\t * @throws NotAuthorizedException\n\t */\n\tpublic Queue<Packet> restorePacketForOffLineUser( XMPPResourceConnection conn,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMsgRepositoryIfc repo )\n\t\t\tthrows UserNotFoundException, NotAuthorizedException {\n\t\tQueue<Element> elems = repo.loadMessagesToJID( conn, true );\n\n\t\tif ( elems != null ){\n\t\t\tLinkedList<Packet> pacs = new LinkedList<Packet>();\n\t\t\tElement elem = null;\n\n\t\t\twhile ( ( elem = elems.poll() ) != null ) {\n\t\t\t\ttry {\n\t\t\t\t\tPacket p = Packet.packetInstance( elem );\n\t\t\t\t\tif (p.getElemName() == Iq.ELEM_NAME) {\n\t\t\t\t\t\tp.initVars(p.getStanzaFrom(), conn.getJID());\n\t\t\t\t\t}\n\t\t\t\t\tpacs.offer( p );\n\t\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\t\tlog.warning( \"Packet addressing problem, stringprep failed: \" + elem );\n\t\t\t\t}\n\t\t\t}    // end of while (elem = elems.poll() != null)\n\t\t\ttry {\n\t\t\t\tCollections.sort( pacs, new StampComparator() );\n\t\t\t} catch ( NullPointerException e ) {\n\t\t\t\ttry {\n\t\t\t\t\tlog.warning( \"Can not sort off line messages: \" + pacs + \",\\n\" + e );\n\t\t\t\t} catch ( Exception exc ) {\n\t\t\t\t\tlog.log( Level.WARNING, \"Can not print log message.\", exc );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn pacs;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method stores messages to offline repository with the following rules\n\t * applied, i.e. saves only:\n\t * <ul>\n\t * <li> message stanza with either nonempty {@code <body>}, {@code <event>} or\n\t * {@code <header>} child element and only messages of type normal, chat.</li>\n\t * <li> presence stanza of type subscribe, subscribed, unsubscribe and\n\t * unsubscribed.</li>\n\t * </ul>\n\t * <br>\n\t * Processed messages are stamped with the {@code delay} element and\n\t * appropriate timestamp.\n\t * <br>\n\t *\n\t *\n\t * @param pac  a {@link Packet} object containing packet that should be\n\t *             verified and saved\n\t * @param repo a {@link MsgRepositoryIfc} repository handler responsible for\n\t *             storing messages\n\t * @param userRepo\n\t *\n\t * @return {@code true} if the packet was correctly saved to repository,\n\t *         {@code false} otherwise.\n\t *\n\t * @throws UserNotFoundException\n\t */\n\tpublic Authorization savePacketForOffLineUser( Packet pac, MsgRepositoryIfc repo, NonAuthUserRepository userRepo)\n\t\t\tthrows UserNotFoundException {\n\t\tStanzaType type = pac.getType();\n\n\t\t// save only:\n\t\t// message stanza with either {@code <body>} or {@code <event>} child element and only of type normal, chat\n\t\t// presence stanza of type subscribe, subscribed, unsubscribe and unsubscribed\n\t\tif ( isAllowedForOfflineStorage(pac) ){\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Storing packet for offline user: {0}\", pac );\n\t\t\t}\n\n\t\t\tElement elem = pac.getElement().clone();\n\n\t\t\tC2SDeliveryErrorProcessor.filterErrorElement(elem);\n\n\t\t\tString stamp = null;\n\t\t\tsynchronized ( formatter ) {\n\t\t\t\tstamp = formatter.format( new Date() );\n\t\t\t}\n\t\t\t\n\t\t\t//为所有消息加上时间戳  C-101\n\t\t\tif(elem.getChild(\"delay\") == null){\n\t\t\t\tString from = pac.getStanzaTo().getDomain();\n\t\n\t\t\t\tElement x = new Element( \"delay\", \"Offline Storage - \" + defHost, new String[] {\n\t\t\t\t\t\"from\",\n\t\t\t\t\t\"stamp\", \"xmlns\" }, new String[] { from, stamp, \"urn:xmpp:delay\" } );\n\t\t\t\telem.addChild( x );\n\t\t\t}\n\n\t\t\tpac.processedBy( ID );\n\t\t\t\n\t\t\t// 类型为5000的消息不存库 C-102\n\t\t\tElement $body = pac.getElement().findChild(new String[]{\"message\", \"body\"});\n\t\t\tif($body != null){\n\t\t\t\ttry {\n\t\t\t\t\tJSONObject obj = new JSONObject($body.getCData());\n\t\t\t\t\tif (obj.get(\"type\").equals(\"5000\")){\n\t\t\t\t\t\treturn Authorization.AUTHORIZED;\n\t\t\t\t\t}\n\t\t\t\t} catch (JSONException e) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"#5000 : json tanslation error!\");\n\t\t\t\t\t}\n\t\t\t\t} catch (RuntimeException e) {\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.log(Level.FINE, \"#5000 :  \" + e.getMessage());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (repo.storeMessage( pac.getStanzaFrom(), pac.getStanzaTo(), null, elem, userRepo) ) {\n\t\t\t\treturn Authorization.AUTHORIZED;\t\t\n\t\t\t} else {\n\t\t\t\treturn Authorization.SERVICE_UNAVAILABLE;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Packet for offline user not suitable for storing: {0}\",\n\t\t\t\t\t\t\t\t pac );\n\t\t\t}\n\t\t}\n\n\t\treturn Authorization.FEATURE_NOT_IMPLEMENTED;\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures( final XMPPResourceConnection session ) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\t/**\n\t * Method allows obtaining instance of {@link MsgRepositoryIfc} interface\n\t * implementation.\n\t *\n\t * @param conn user session which keeps all the user session data and also\n\t *             gives an access to the user's repository data.\n\t * @param repo an implementation of {@link MsgRepositoryIfc} interface\n\t *\n\t * @return instance of {@link MsgRepositoryIfc} interface implementation.\n\t */\n\tprotected MsgRepositoryIfc getMsgRepoImpl( NonAuthUserRepository repo,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t XMPPResourceConnection conn ) {\n\t\tif (msgRepoCls == null) {\n\t\t\treturn new MsgRepositoryImpl( repo, conn );\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tOfflineMsgRepositoryIfc msgRepo = (OfflineMsgRepositoryIfc) ModulesManagerImpl.getInstance().forName(msgRepoCls).newInstance();\n\t\t\t\tmsgRepo.init(repo, conn);\n\t\t\t\treturn msgRepo;\n\t\t\t} catch (Exception ex) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\t\n\t/** \n\t * Method determines whether packet sent to offline user should be stored in\n\t * offline storage or not\n\t * @param pac\n\t * @return \n\t */\n\tprotected boolean isAllowedForOfflineStorage(Packet pac) {\n\t\t// custom element matchers override default values so let's check\n\t\t// this matchers at first\n\t\tfor (ElementMatcher matcher : offlineStorageMatchers) {\n\t\t\tif (matcher.matches(pac))\n\t\t\t\treturn matcher.getValue();\n\t\t}\n\t\t\n\t\treturn isAllowedForOfflineStorageDefaults(pac);\n\t}\n\t\n\tprotected boolean isAllowedForOfflineStorageDefaults(Packet pac) {\n\t\tStanzaType type = pac.getType();\n\t\tswitch (pac.getElemName()) {\n\t\t\tcase \"message\":\n\t\t\t\tif (type == null || type == StanzaType.normal || type == StanzaType.chat) {\n\t\t\t\t\t// support for XEP-0334 Message Processing Hints\t\t\t\t\t\n\t\t\t\t\tif (pac.getAttributeStaticStr( MESSAGE_HINTS_NO_STORE, \"xmlns\") == MESSAGE_HINTS_XMLNS)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (pac.getElemCDataStaticStr( tigase.server.Message.MESSAGE_BODY_PATH ) != null)\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tif (pac.getElemChildrenStaticStr( MESSAGE_EVENT_PATH ) != null)\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tif (pac.getElemChildrenStaticStr( MESSAGE_HEADER_PATH ) != null)\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tif (pac.getElement().getXMLNSStaticStr( MESSAGE_RECEIVED_PATH ) == MESSAGE_RECEIVED_XMLNS)\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"presence\":\n\t\t\t\tif ( ( type == StanzaType.subscribe ) || ( type == StanzaType.subscribed )\n\t\t\t\t\t\t || ( type == StanzaType.unsubscribe ) || ( type == StanzaType.unsubscribed ) )\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\treturn false;\t\n\t}\n\t\n\t/**\n\t * Method determines whether offline messages should be loaded - the process\n\t * should be run only once per user session and only for available/null\n\t * presence with priority greater than 0.\n\t *\n\t *\n\t * @param packet a {@link Packet} object containing packet that should be\n\t *               verified and saved\n\t * @param conn   user session which keeps all the user session data and also\n\t *               gives an access to the user's repository data.\n\t *\n\t * @return {@code true} if the messages should be loaded, {@code false}\n\t *         otherwise.\n\t */\n\tprotected boolean loadOfflineMessages( Packet packet, XMPPResourceConnection conn ) {\n\n\t\t// If the user session is null or the user is anonymous just\n\t\t// ignore it.\n\t\tif ( ( conn == null ) || conn.isAnonymous() ){\n\t\t\treturn false;\n\t\t}    // end of if (session == null)\n\n\t\t// Try to restore the offline messages only once for the user session\n\t\tif ( conn.getSessionData( ID ) != null ){\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// make sure this is broadcast presence as only in this case we should sent offline messages\n\t\tif (packet.getStanzaTo() != null)\n\t\t\treturn false;\t\t\n\n\t\t// if we are using XEP-0013: Flexible offline messages retrieval then we skip loading\n\t\tif ( conn.getCommonSessionData(FlexibleOfflineMessageRetrieval.FLEXIBLE_OFFLINE_XMLNS) != null ){\n\t\t\treturn false;\n\t\t}\n\n\t\tStanzaType type = packet.getType();\n\n\t\tif ( ( type == null ) || ( type == StanzaType.available ) ){\n\n\t\t\t// Should we send off-line messages now?\n\t\t\t// Let's try to do it here and maybe later I find better place.\n\t\t\tString priority_str = packet.getElemCDataStaticStr( tigase.server.Presence.PRESENCE_PRIORITY_PATH );\n\t\t\tint priority = 0;\n\n\t\t\tif ( priority_str != null ){\n\t\t\t\ttry {\n\t\t\t\t\tpriority = Integer.decode( priority_str );\n\t\t\t\t} catch ( NumberFormatException e ) {\n\t\t\t\t\tpriority = 0;\n\t\t\t\t}    // end of try-catch\n\t\t\t}      // end of if (priority != null)\n\t\t\tif ( priority >= 0 ){\n\t\t\t\tconn.putSessionData( ID, ID );\n\n\t\t\t\treturn true;\n\t\t\t}      // end of if (priority >= 0)\n\t\t}        // end of if (type == null || type == StanzaType.available)\n\n\t\treturn false;\n\t}\n\n\tpublic void publishInPubSub(final Packet packet, final XMPPResourceConnection conn, final Queue<Packet> queue,\n\t\t\tMap<String, Object> settings) {\n\t\tif (pubSubJID == null || pubSubNode == null)\n\t\t\treturn;\n\t\tfinal StanzaType type = packet.getType();\n\t\tif ((packet.getElemName().equals(\"message\")\n\t\t\t\t&& ((packet.getElemCDataStaticStr(tigase.server.Message.MESSAGE_BODY_PATH) != null)\n\t\t\t\t\t\t|| (packet.getElemChildrenStaticStr(MESSAGE_EVENT_PATH) != null) || (packet.getElemChildrenStaticStr(MESSAGE_HEADER_PATH) != null)) && ((type == null)\n\t\t\t\t|| (type == StanzaType.normal) || (type == StanzaType.chat)))\n\t\t\t\t|| (packet.getElemName().equals(\"presence\") && ((type == StanzaType.subscribe)\n\t\t\t\t\t\t|| (type == StanzaType.subscribed) || (type == StanzaType.unsubscribe) || (type == StanzaType.unsubscribed)))) {\n\t\t\tString tmpNode = packet.getElement().getAttributeStaticStr(PUBSUB_NODE_PATH, PUBSUB_NODE_KEY);\n\t\t\tif (tmpNode != null && tmpNode.equals(this.pubSubNode)) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Publishing skipped to prevent loops: {0}\", packet);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Publishing packet in pubsub: {0}\", packet);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (defaultPublisher != null) {\n\t\t\t\t\tElement iq = new Element(\"iq\", new String[] { \"type\", \"id\", \"to\", \"from\" }, new String[] { \"set\",\n\t\t\t\t\t\t\t\"\" + System.nanoTime(), pubSubJID, defaultPublisher });\n\t\t\t\t\tElement pubsub = new Element(\"pubsub\", new String[] { \"xmlns\" },\n\t\t\t\t\t\t\tnew String[] { \"http://jabber.org/protocol/pubsub\" });\n\t\t\t\t\tiq.addChild(pubsub);\n\t\t\t\t\tElement publish = new Element(\"publish\", new String[] { \"node\" }, new String[] { this.pubSubNode });\n\t\t\t\t\tpubsub.addChild(publish);\n\t\t\t\t\tElement item = new Element(\"item\");\n\t\t\t\t\tpublish.addChild(item);\n\n\t\t\t\t\titem.addChild(packet.getElement());\n\n\t\t\t\t\tPacket out = Packet.packetInstance(iq);\n\t\t\t\t\tout.setXMLNS(Packet.CLIENT_XMLNS);\n\t\t\t\t\tqueue.add(out);\n\t\t\t\t} else if (log.isLoggable(Level.WARNING))\n\t\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\t\"Cannot publish message in PubSub, because cannot determine publisher. Please define default publisher JID.\",\n\t\t\t\t\t\t\tpacket);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlog.log(Level.WARNING, \"Problem during publish packet in pubsub\", e);\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static interface OfflineMsgRepositoryIfc extends MsgRepositoryIfc {\n\t\t\n\t\tvoid init( NonAuthUserRepository repo, XMPPResourceConnection conn);\n\t\t\n\t}\n\t\n\t//~--- inner classes --------------------------------------------------------\n\t/**\n\t * Implementation of {@code MsgRepositoryIfc} interface providing basic\n\t * support for storing and loading of Elements from repository.\n\t */\n\tprivate class MsgRepositoryImpl implements OfflineMsgRepositoryIfc {\n\n\t\t/** Field holds user session which keeps all the user session data and also\n\t\t * gives an access to the user's repository data. */\n\t\tprivate XMPPResourceConnection conn = null;\n\t\t/** Field holds a reference to user session which keeps all the user session\n\t\t * data and also gives an access to the user's repository data. */\n\t\tprivate SimpleParser parser = SingletonFactory.getParserInstance();\n\t\t/** Field holds reference to an implementation of {@link MsgRepositoryIfc}\n\t\t * interface */\n\t\tprivate NonAuthUserRepository repo = null;\n\n\t\t//~--- constructors -------------------------------------------------------\n\t\t/**\n\t\t * Constructs {@code MsgRepositoryImpl} object referencing user session and\n\t\t * having handle to user repository.\n\t\t *\n\t\t * @param repo an implementation of {@link MsgRepositoryIfc} interface\n\t\t * @param conn user session which keeps all the user session data and also\n\t\t *             gives an access to the user's repository data.\n\t\t */\n\t\tprivate MsgRepositoryImpl(NonAuthUserRepository repo, XMPPResourceConnection conn) {\n\t\t\tinit(repo, conn);\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void init(NonAuthUserRepository repo, XMPPResourceConnection conn) {\n\t\t\tthis.repo = repo;\n\t\t\tthis.conn = conn;\n\t\t}\n\n\t\t@Override\n\t\tpublic void initRepository(String conn_str, Map<String, String> map) {\n\t\t\t// nothing to do here as we base on UserRepository which is already initialized\n\t\t}\n\t\t\n\t\t//~--- get methods --------------------------------------------------------\n\t\t@Override\n\t\tpublic Element getMessageExpired( long time, boolean delete ) {\n\t\t\tthrow new UnsupportedOperationException( \"Not supported yet.\" );\n\t\t}\n\n\t\t//~--- methods ------------------------------------------------------------\n\t\t@Override\n\t\tpublic Queue<Element> loadMessagesToJID( XMPPResourceConnection session, boolean delete )\n\t\t\t\tthrows UserNotFoundException {\n\t\t\ttry {\n\t\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\t\t\t\tString[] msgs = conn.getOfflineDataList( ID, \"messages\" );\n\n\t\t\t\tif ( ( msgs != null ) && ( msgs.length > 0 ) ){\n\t\t\t\t\tconn.removeOfflineData( ID, \"messages\" );\n\n\t\t\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\t\t\tfor ( String msg : msgs ) {\n\t\t\t\t\t\tsb.append( msg );\n\t\t\t\t\t}\n\n\t\t\t\t\tchar[] data = sb.toString().toCharArray();\n\n\t\t\t\t\tparser.parse( domHandler, data, 0, data.length );\n\n\t\t\t\t\treturn domHandler.getParsedElements();\n\t\t\t\t}    // end of while (elem = elems.poll() != null)\n\t\t\t} catch ( NotAuthorizedException ex ) {\n\t\t\t\tlog.info( \"User not authrized to retrieve offline messages, \"\n\t\t\t\t\t\t\t\t\t+ \"this happens quite often on some installations where there\"\n\t\t\t\t\t\t\t\t\t+ \" are a very short living client connections. They can \"\n\t\t\t\t\t\t\t\t\t+ \"disconnect at any time. \" + ex );\n\t\t\t} catch ( TigaseDBException ex ) {\n\t\t\t\tlog.warning( \"Error accessing database for offline message: \" + ex );\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean storeMessage( JID from, JID to, Date expired, Element msg, NonAuthUserRepository userRepo )\n\t\t\t\tthrows UserNotFoundException {\n\t\t\trepo.addOfflineDataList( to.getBareJID(), ID, \"messages\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { msg.toString() } );\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * {@link Comparator} interface implementation for the purpose of sorting\n\t * Elements retrieved from the repository by the timestamp stored in\n\t * {@code delay} element.\n\t */\n\tpublic class StampComparator\n\t\t\timplements Comparator<Packet> {\n\n\t\t@Override\n\t\tpublic int compare( Packet p1, Packet p2 ) {\n\t\t\tString stamp1 = \"\";\n\t\t\tString stamp2 = \"\";\n\n\t\t\t// Try XEP-0203 - the new XEP...\n\t\t\tElement stamp_el1 = p1.getElement().getChild( \"delay\", \"urn:xmpp:delay\" );\n\n\t\t\tif ( stamp_el1 == null ){\n\n\t\t\t\t// XEP-0091 support - the old one...\n\t\t\t\tstamp_el1 = p1.getElement().getChild( \"x\", \"jabber:x:delay\" );\n\t\t\t\tif ( stamp_el1 != null ){\n\t\t\t\t\tstamp1 = stamp_el1.getAttributeStaticStr( \"stamp\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Try XEP-0203 - the new XEP...\n\t\t\tElement stamp_el2 = p2.getElement().getChild( \"delay\", \"urn:xmpp:delay\" );\n\n\t\t\tif ( stamp_el2 == null ){\n\n\t\t\t\t// XEP-0091 support - the old one...\n\t\t\t\tstamp_el2 = p2.getElement().getChild( \"x\", \"jabber:x:delay\" );\n\t\t\t\tif ( stamp_el2 != null ){\n\t\t\t\t\tstamp2 = stamp_el2.getAttributeStaticStr( \"stamp\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stamp1.compareTo( stamp2 );\n\t\t}\n\t}\n}    // OfflineMessages\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PepPlugin.java",
    "content": "/*\n * PepPlugin.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\nimport tigase.xmpp.impl.roster.RosterFactory;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.EnumSet;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Class description\n *\n *\n * @version 5.0.0, 2010.03.01 at 03:12:30 GMT\n * @author Artur Hefczyc\n */\npublic class PepPlugin\n\t\t\t\textends XMPPProcessorAbstract {\n\tprivate static final String    _XMLNS = \"http://jabber.org/protocol/pubsub\";\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { _XMLNS }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { _XMLNS + \"#owner\" }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { _XMLNS +\n\t\t\t\t\t\"#publish\" }),\n\t\t\tnew Element(\"identity\", new String[] { \"category\", \"type\" }, new String[] {\n\t\t\t\t\t\"pubsub\",\n\t\t\t\t\t\"pep\" }), };\n\tprivate static final String[][]                ELEMENTS             = {\n\t\tIq.IQ_PUBSUB_PATH\n\t};\n\tprivate static final String                    ID                   = \"pep-simple\";\n\tprivate static final String[]                  IQ_PUBSUB_PATH       = { \"iq\",\n\t\t\t\"pubsub\" };\n\tprivate static final Logger                    log = Logger.getLogger(\n\t\t\t\"tigase.xmpp.impl.PepPlugin\");\n\tprivate static final String                    PUBSUB_COMPONENT_URL =\n\t\t\t\"pubsub-component\";\n\tprivate static RosterAbstract                  roster = RosterFactory\n\t\t\t.getRosterImplementation(true);\n\tprivate static final EnumSet<SubscriptionType> SUBSCRITION_TYPES = EnumSet.of(\n\t\t\tSubscriptionType.both, SubscriptionType.from);\n\tprivate static final String[] XMLNSS = { _XMLNS };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate final HashSet<String> supportedNodes = new HashSet<String>();\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Constructs ...\n\t *\n\t */\n\tpublic PepPlugin() {\n\t\tthis.supportedNodes.add(\"http://jabber.org/protocol/tune\");\n\t\tthis.supportedNodes.add(\"http://jabber.org/protocol/mood\");\n\t\tthis.supportedNodes.add(\"http://jabber.org/protocol/activity\");\n\t\tthis.supportedNodes.add(\"http://jabber.org/protocol/geoloc\");\n\t\tthis.supportedNodes.add(\"urn:xmpp:avatar:data\");\n\t\tthis.supportedNodes.add(\"urn:xmpp:avatar:metadata\");\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\ttry {\n\t\t\tList<Element> x         = packet.getElemChildrenStaticStr(IQ_PUBSUB_PATH);\n\t\t\tboolean       processed = false;\n\n\t\t\tfor (Element element : x) {\n\t\t\t\tString action = element.getName();\n\t\t\t\tString node   = element.getAttributeStaticStr(\"node\");\n\n\t\t\t\tif (this.supportedNodes.contains(node)) {\n\t\t\t\t\tif (action == \"retract\") {\n\t\t\t\t\t\tElement item    = element.getChild(\"item\", null);\n\t\t\t\t\t\tElement retract = new Element(\"retract\");\n\n\t\t\t\t\t\tif (item.getAttributeStaticStr(Packet.ID_ATT) != null) {\n\t\t\t\t\t\t\tretract.addAttribute(Packet.ID_ATT, item.getAttributeStaticStr(Packet\n\t\t\t\t\t\t\t\t\t.ID_ATT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprocessed = true;\n\t\t\t\t\t\tprocessPEPPublish(packet, node, retract, session, repo, results, settings);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (action == \"publish\") {\n\t\t\t\t\t\t\tElement item = element.getChild(\"item\", null);\n\n\t\t\t\t\t\t\tprocessed = true;\n\t\t\t\t\t\t\tprocessPEPPublish(packet, node, item, session, repo, results, settings);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (processed) {\n\t\t\t\tresults.offer(packet.okResult((Element) null, 0));\n\t\t\t} else {\n\t\t\t\tresults.offer(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,\n\t\t\t\t\t\t\"The PEP node is not yet supported.\", true));\n\t\t\t}\n\t\t} catch (NotAuthorizedException ex) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t} catch (TigaseDBException ex) {\n\t\t\tLogger.getLogger(PepPlugin.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tresults.offer(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\"Service not available.\", true));\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\n\t\t// I guess we ignore such packets here, no pep support for the server\n\t\t// itself yet\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tprivate void forward(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tString pubSubComponentUrl = (settings == null)\n\t\t\t\t? null\n\t\t\t\t: (String) settings.get(PUBSUB_COMPONENT_URL);\n\n\t\tif ((session == null) || (pubSubComponentUrl == null)) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.fine(\"Packet reject. No Session or PubSub Component URL.\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\t\t\tpacket.getElement().setAttribute(\"to\", pubSubComponentUrl);\n\n\t\t\tBareJID id = packet.getStanzaTo().getBareJID();\n\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t} else {\n\n\t\t\t\t// This is message to some other client\n\t\t\t\tresults.offer(packet.copyElementOnly());\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n\n\tprivate void processPEPPublish(Packet packet, String node, Element pepItem,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tJID[]   buddies = roster.getBuddies(session, SUBSCRITION_TYPES);\n\t\tElement event = new Element(\"event\", new String[] { \"xmlns\" }, new String[] {\n\t\t\t\t\"http://jabber.org/protocol/pubsub#event\" });\n\t\tElement items = new Element(\"items\", new String[] { \"node\" }, new String[] { node });\n\n\t\tevent.addChild(items);\n\t\titems.addChild(pepItem);\n\n\t\tJID from = packet.getStanzaFrom();\n\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tElement message = new Element(\"message\", new String[] { \"from\", \"to\", \"type\",\n\t\t\t\t\t\t\"id\" }, new String[] { from.toString(), buddy.toString(), \"headline\",\n\t\t\t\t\t\tpacket.getStanzaId() });\n\n\t\t\t\tmessage.addChild(event);\n\t\t\t\tresults.offer(Packet.packetInstance(message, from, buddy));\n\t\t\t}\n\t\t}\n\n\t\tElement message = new Element(\"message\", new String[] { \"from\", \"to\", \"type\", \"id\" },\n\t\t\t\tnew String[] { from.toString(),\n\t\t\t\tfrom.toString(), \"headline\", packet.getStanzaId() });\n\n\t\tmessage.addChild(event);\n\t\tresults.offer(Packet.packetInstance(message, from, from));\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/Presence.java",
    "content": "/*\n * Presence.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\nimport tigase.server.Priority;\n\nimport tigase.stats.StatisticsList;\n\nimport tigase.sys.TigaseRuntime;\n\nimport tigase.util.TigaseStringprepException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.roster.*;\n\nimport static tigase.xmpp.impl.roster.RosterAbstract.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.server.Iq;\nimport tigase.server.PolicyViolationException;\n\nimport tigase.annotations.TigaseDeprecatedComponent;\nimport tigase.osgi.ModulesManagerImpl;\n\n/**\n * Class responsible for handling Presence packets - deprecated\n * Use PresenceState and PresenceSubscription classes\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\n@TigaseDeprecatedComponent(note = \"Please remove \\'+presence\\' from \\'--sm-plugins=\\' or switch to \\'presence-state\\' and \\'presence-subscription\\' plugins\")\npublic class Presence\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPStopListenerIfc {\n\t/**\n\t * key allowing enabling automatic authorisation.\n\t */\n\tpublic static final String AUTO_AUTHORIZE_PROP_KEY = \"auto-authorize\";\n\n\t/**\n\t * <code>DIRECT_PRESENCE</code> is a key in temporary session data for the\n\t * collection of JIDs where direct presence was sent. To all these addresses\n\t * unavailable presence must be sent when user disconnects.\n\t */\n\tpublic static final String DIRECT_PRESENCE = \"direct-presences\";\n\n\tpublic static final String DISABLE_ROSTER_LAZY_LOADING_KEY = \"disable-roster-lazy-loading\";\n\n\tpublic static final String EXTENDED_PRESENCE_PROCESSORS_KEY = \"extended-presence-processors\";\n\t\n\t/** Field description */\n\tpublic static final String OFFLINE_BUD_SENT = \"offline-bud-sent\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_RES_SENT = \"offline-res-sent\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_ROSTER_LAST_SEEN_PROP_KEY =\n\t\t\t\"offline-roster-last-seen\";\n\n\t/** Field description */\n\tpublic static final String PRESENCE_ELEMENT_NAME = \"presence\";\n\n\t/**\n\t * key allowing setting global forwarding JID address.\n\t */\n\tpublic static final String PRESENCE_GLOBAL_FORWARD = \"presence-global-forward\";\n\n\t/** Field description */\n\tpublic static final String SKIP_OFFLINE_PROP_KEY = \"skip-offline\";\n\n\t/** Field description */\n\tpublic static final String SKIP_OFFLINE_SYS_PROP_KEY = \"skip-offline-sys\";\n\n\t/** Field description */\n\tpublic static final String USERS_STATUS_CHANGES = \"Users status changes\";\n\n\t/** Field description */\n\tprotected static final String XMLNS                      = CLIENT_XMLNS;\n\tprivate static int            HIGH_PRIORITY_PRESENCES_NO = 10;\n\n\t/** Private logger for class instance. */\n\tprivate static final Logger     log = Logger.getLogger(Presence.class.getName());\n\tprivate static final long       MAX_DIRECT_PRESENCES_NO = 1000;\n\tprivate static final String[]   PRESENCE_PRIORITY_PATH  = { \"presence\", \"priority\" };\n\tprivate static final String[]   XMLNSS                  = { XMLNS, RosterAbstract.XMLNS_LOAD };\n\tprivate static boolean\t\t\trosterLazyLoading       = true;\n\tprivate static boolean          skipOfflineSys          = true;\n\tprivate static boolean          skipOffline             = false;\n\tprivate static final String[]   PRESENCE_C_PATH         = { PRESENCE_ELEMENT_NAME,\n\t\t\t\"c\" };\n\tprivate static final String     ID                      = PRESENCE_ELEMENT_NAME;\n\tprivate static final String[][] ELEMENTS                = {\n\t\t{ PRESENCE_ELEMENT_NAME }, { Iq.ELEM_NAME, Iq.QUERY_NAME }\n\t};\n\n\t/**\n\t * variable holding setting regarding auto authorisation of items added to\n\t * user roset\n\t */\n\tprivate static boolean autoAuthorize = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected RosterAbstract roster_util           = getRosterUtil();\n\tprivate String[]         offlineRosterLastSeen = null;\n\tprivate JID              presenceGLobalForward = null;\n\tprivate long             usersStatusChanges    = 0;\n\tprivate static final List<ExtendedPresenceProcessorIfc> extendedPresenceProcessors = new ArrayList<>();\n\n\t// ~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Add JID to collection of JIDs to which direct presence was sent. To all\n\t * these addresses unavailable presence must be sent when user disconnects.\n\t *\n\t * @param jid     to which direct presence was sent.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic static void addDirectPresenceJID(JID jid, XMPPResourceConnection session) {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif (direct_presences == null) {\n\t\t\tdirect_presences = new LinkedHashSet<JID>(10);\n\t\t\tsession.putSessionData(DIRECT_PRESENCE, direct_presences);\n\t\t}    // end of if (direct_presences == null)\n\t\tif (direct_presences.size() < MAX_DIRECT_PRESENCES_NO) {\n\t\t\tdirect_presences.add(jid);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Added direct presence jid: {0}\", jid);\n\t\t}\n\t}\n\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t *\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param results     this a collection with packets which have been generated\n\t *                    as input packet processing results.\n\t * @param settings    this map keeps plugin specific settings loaded from the\n\t *                    Tigase server configuration.\n\t * @param roster_util instance of class implementing {@link RosterAbstract}.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic static void broadcastOffline(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract roster_util)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Preventing sending offline notifications more than once\n\t\tif (session.getSessionData(OFFLINE_BUD_SENT) != null) {\n\t\t\treturn;\n\t\t}\n\t\tsession.putSessionData(OFFLINE_BUD_SENT, OFFLINE_BUD_SENT);\n\n\t\tElement pres = session.getPresence();\n\n\t\tif (pres != null) {\n\t\t\tsendPresenceBroadcast(StanzaType.unavailable, session, FROM_SUBSCRIBED, results,\n\t\t\t\t\tpres, settings, roster_util);\n\t\t} else {\n\t\t\tbroadcastDirectPresences(StanzaType.unavailable, session, results, pres);\n\t\t}\n\t}\n\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t * Before sending presence method calls {@code  requiresPresenceSending()},\n\t * configured to only check local environment status (if enabled) to verify\n\t * whether presence needs to be sent.\n\t *\n\t *\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic void broadcastProbe(XMPPResourceConnection session, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Broadcasting probes for: {0}\", session);\n\t\t}\n\n\t\t// Probe is always broadcasted with initial presence\n\t\tElement presInit  = session.getPresence();\n\t\tElement presProbe = prepareProbe( session );\n\n\t\tJID[] buddies = roster_util.getBuddies(session, SUB_BOTH);\n\n\t\ttry {\n\t\t\tbuddies = DynamicRoster.addBuddies(session, settings, buddies);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\n\t\t\t// Ignore, handled in the JabberIqRoster code\n\t\t}\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending presence probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presProbe);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending intial presence to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presInit);\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending initial presence and probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\n\t\tJID[] buddies_to = roster_util.getBuddies(session, SUB_TO);\n\n\t\tif (buddies_to != null) {\n\t\t\tfor (JID buddy : buddies_to) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() + \" | Sending probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presProbe);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending presence probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\n\t\t// TODO: It might be a marginal number of cases here but just make it clear\n\t\t// we send a presence here regardless\n\t\tJID[] buddies_from = roster_util.getBuddies(session, SUB_FROM);\n\n\t\tif (buddies_from != null) {\n\t\t\tfor (JID buddy : buddies_from) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending initial presence to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presInit);\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending initial presence and probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\t}\n\n\tprivate Element prepareProbe( XMPPResourceConnection session ) throws NotAuthorizedException {\n\t\tElement presProbe = new Element(PRESENCE_ELEMENT_NAME);\n\t\tpresProbe.setXMLNS(XMLNS);\n\t\tpresProbe.setAttribute(\"type\", StanzaType.probe.toString());\n\t\tpresProbe.setAttribute(\"from\", session.getBareJID().toString());\n\t\treturn presProbe;\n\t}\n\n\t@Override\n\tpublic int concurrentQueuesNo() {\n\t\treturn super.concurrentQueuesNo() * 4;\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\n\t\t// Init plugin configuration\n\t\tString tmp;\n\n\t\ttmp            = (String) settings.get(SKIP_OFFLINE_PROP_KEY);\n\t\tskipOffline    = (tmp != null)\n\t\t\t\t? Boolean.parseBoolean(tmp)\n\t\t\t\t: skipOffline;\n\t\ttmp            = (String) settings.get(SKIP_OFFLINE_SYS_PROP_KEY);\n\t\tskipOfflineSys = (tmp != null)\n\t\t\t\t? Boolean.parseBoolean(tmp)\n\t\t\t\t: skipOfflineSys;\n\t\tif (skipOffline || skipOfflineSys) {\n\t\t\tlog.config(String.format(\n\t\t\t\t\t\"Skipping sending presence to offline contacts enabled :: \" +\n\t\t\t\t\t\"skipOffline: %1$s, skipOfflineSys: %2$s\", skipOffline, skipOfflineSys));\n\t\t}\n\t\tautoAuthorize = Boolean.parseBoolean((String) settings.get(AUTO_AUTHORIZE_PROP_KEY));\n\t\tif (autoAuthorize) {\n\t\t\tlog.config(\n\t\t\t\t\t\"Automatic presence autorization enabled, results in less strict XMPP specs compatibility \");\n\t\t}\n\t\ttmp = (String) settings.get( OFFLINE_ROSTER_LAST_SEEN_PROP_KEY );\n\t\tif ( tmp != null ){\n\t\t\tif ( tmp.contains( \"off\" ) ){\n\t\t\t\tofflineRosterLastSeen = null;\n\t\t\t} else {\n\t\t\t\tofflineRosterLastSeen = tmp.split( \",\" );\n\t\t\t\tlog.log( Level.CONFIG, \"Loaded roster offline last seen config: {0}\", tmp );\n\t\t\t}\n//\t\t} else {\n//\t\t\tofflineRosterLastSeen = new String[] {\"*\"};\n//\t\t\tlog.config(\"No configuration found for Loaded roster offline last seen. - enabling for All clients\");\n\t\t}\n\t\ttmp = (String) settings.get(PRESENCE_GLOBAL_FORWARD);\n\t\tif (tmp != null) {\n\t\t\ttry {\n\t\t\t\tpresenceGLobalForward = JID.jidInstance(tmp);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tpresenceGLobalForward = null;\n\t\t\t\tlog.log(Level.WARNING, \"Presence global forward misconfiguration, cannot parse JID {0}\", tmp);\n\t\t\t}\n\t\t}\n\t\ttmp = (String) settings.get(DISABLE_ROSTER_LAZY_LOADING_KEY);\n\t\trosterLazyLoading = (tmp == null || !Boolean.parseBoolean(tmp));\n\n\t\ttmp = (String) settings.get(EXTENDED_PRESENCE_PROCESSORS_KEY);\n\n\t\tString[] extPresenceProcessorsClasses = tmp != null ? tmp.split( \",\") : null ;\n\n\t\tif ( extPresenceProcessorsClasses != null ){\n\t\t\tfor ( String clazz : extPresenceProcessorsClasses ) {\n\t\t\t\ttry {\n\t\t\t\t\tExtendedPresenceProcessorIfc processor = (ExtendedPresenceProcessorIfc) ModulesManagerImpl.getInstance().forName( clazz ).newInstance();\n\n\t\t\t\t\textendedPresenceProcessors.add( processor );\n\t\t\t\t\tlog.log(Level.CONFIG, \"Loadeded ExtendedPresenceProcessor: {0}\", processor.getClass());\n\n\t\t\t\t} catch ( ClassNotFoundException | InstantiationException | IllegalAccessException ex ) {\n\t\t\t\t\tLogger.getLogger( Presence.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Performs processing of <em>presence</em> packets and calls different\n\t * methods for particular {@link PresenceType}\n\t *\n\t */\n\t@SuppressWarnings({ \"unchecked\", \"fallthrough\" })\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is null, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (!session.isAuthorized()) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is not authorized, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\tif (packet.getElemName() == Iq.ELEM_NAME) {\n\t\t\t// here we process results of roster loading process requests\n\t\t\tboolean finishProcessing = true;\n\t\t\tswitch (packet.getType()) {\n\t\t\t\tcase result:\n\t\t\t\t\tsynchronized (session) {\n\t\t\t\t\t\tElement presEl = session.getPresence();\n\t\t\t\t\t\tif (presEl != null) {\n\t\t\t\t\t\t\tsession.removeSessionData(XMPPResourceConnection.PRESENCE_KEY);\n\t\t\t\t\t\t\tpresEl.removeAttribute(\"from\");\n\t\t\t\t\t\t\tpresEl.removeAttribute(\"to\");\n\t\t\t\t\t\t\tPacket pres = Packet.packetInstance(presEl, packet.getStanzaFrom(), packet.getStanzaTo());\n\t\t\t\t\t\t\tpres.setPacketFrom(packet.getPacketFrom());\n\t\t\t\t\t\t\tpres.setPacketTo(packet.getPacketTo());\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tprocessOutInitial(pres, session, results, settings, PresenceType.out_initial);\n\t\t\t\t\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\t\"Can not access user Roster, user session is not authorized yet: {0}\",\n\t\t\t\t\t\t\t\t\t\tpacket);\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"presence problem...\", e);\n\t\t\t\t\t\t\t} catch (TigaseDBException e) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for presence data: {0}\", e);\n\t\t\t\t\t\t\t}    // end of try-catch\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// ignore this\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (finishProcessing)\n\t\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Synchronization to avoid conflict with login/logout events\n\t\t// processed in the SessionManager asynchronously\n\t\tsynchronized (session) {\n\t\t\ttry {\n\t\t\t\tPresenceType pres_type = roster_util.getPresenceType(session, packet);\n\n\t\t\t\tif (pres_type == null) {\n\t\t\t\t\tlog.log(Level.INFO, \"Invalid presence found: {0}\", packet);\n\n\t\t\t\t\treturn;\n\t\t\t\t}    // end of if (type == null)\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0} | {1} presence found: {2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { session.getBareJID().toString(), pres_type, packet });\n\t\t\t\t}\n\n\t\t\t\t// All 'in' subscription presences must have a valid from address\n\t\t\t\tswitch (pres_type) {\n\t\t\t\tcase in_unsubscribe :\n\t\t\t\tcase in_subscribe :\n\t\t\t\tcase in_unsubscribed :\n\t\t\t\tcase in_subscribed :\n\t\t\t\t\tif (packet.getStanzaFrom() == null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.fine(\"'in' subscription presence without valid 'from' address, \" +\n\t\t\t\t\t\t\t\t\t\"dropping packet: \" + packet);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (session.isUserId(packet.getStanzaFrom().getBareJID())) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\"''in'' subscription to myself, not allowed, returning \" +\n\t\t\t\t\t\t\t\t\t\"error for packet: \" + \"{0}\", packet);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"You can not subscribe to yourself.\", false));\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// as per http://xmpp.org/rfcs/rfc6121.html#sub\n\t\t\t\t\t// Implementation Note: When a server processes or generates an outbound\n\t\t\t\t\t// presence stanza of type \"subscribe\", \"subscribed\", \"unsubscribe\",\n\t\t\t\t\t// or \"unsubscribed\", the server MUST stamp the outgoing presence\n\t\t\t\t\t// stanza with the bare JID <localpart@domainpart> of the sending entity,\n\t\t\t\t\t// not the full JID <localpart@domainpart/resourcepart>.\n\t\t\t\t\t//\n\t\t\t\t\t// we enforce this rule also for incomming presence subscirption packets\n\t\t\t\t\tpacket.initVars( packet.getStanzaFrom().copyWithoutResource(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t session.getJID().copyWithoutResource() );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_subscribe :\n\t\t\t\tcase out_unsubscribe :\n\t\t\t\tcase out_subscribed :\n\t\t\t\tcase out_unsubscribed :\n\n\t\t\t\t\t// Check wheher the destination address is correct to prevent\n\t\t\t\t\t// broken/corrupted roster entries:\n\t\t\t\t\tif ((packet.getStanzaTo() == null) || packet.getStanzaTo().toString()\n\t\t\t\t\t\t\t.isEmpty()) {\n\t\t\t\t\t\tresults.offer(Authorization.JID_MALFORMED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"The destination address is incorrect.\", false));\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// According to RFC 3921 draft bis-3, both source and destination\n\t\t\t\t\t// addresses must be BareJIDs, handled by initVars(...)\n\t\t\t\t\tpacket.initVars(session.getJID().copyWithoutResource(), packet.getStanzaTo()\n\t\t\t\t\t\t\t.copyWithoutResource());\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tswitch (pres_type) {\n\t\t\t\tcase out_initial :\n\t\t\t\t\tprocessOutInitial(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_subscribe :\n\t\t\t\tcase out_unsubscribe :\n\t\t\t\t\tprocessOutSubscribe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_subscribed :\n\t\t\t\tcase out_unsubscribed :\n\t\t\t\t\tprocessOutSubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_initial :\n\t\t\t\t\tprocessInInitial(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_subscribe :\n\t\t\t\t\tprocessInSubscribe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_unsubscribe :\n\t\t\t\t\tprocessInUnsubscribe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_subscribed :\n\t\t\t\t\tprocessInSubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_unsubscribed :\n\t\t\t\t\tprocessInUnsubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_probe :\n\t\t\t\t\tif (session.getPresence() == null) {\n\n\t\t\t\t\t\t// If the user has not yet sent initial presence then ignore the\n\t\t\t\t\t\t// probe.\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessInProbe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_probe :\n\t\t\t\t\tforwardPresence(results, packet, session.getJID());\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase error :\n\t\t\t\t\tprocessError(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (type)\n\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\"Can not access user Roster, user session is not authorized yet: {0}\",\n\t\t\t\t\t\tpacket);\n\t\t\t\tlog.log(Level.FINEST, \"presence problem...\", e);\n\t\t\t} catch ( PolicyViolationException e ) {\n\t\t\t\tlog.log( Level.FINE, \"Violation of roster items number policy: {0}\", packet );\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for presence data: {0}\", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\t/**\n\t * Remove JID from collection of JIDs to which direct presence was sent.\n\t *\n\t * @param jid     to which direct presence was sent.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic static void removeDirectPresenceJID(JID jid, XMPPResourceConnection session) {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif (direct_presences != null) {\n\t\t\tdirect_presences.remove(jid);\n\t\t}    // end of if (direct_presences == null)\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Added direct presence jid: {0}\", jid);\n\t\t}\n\t}\n\n\t/**\n\t * Sends out all pending subscription request during user log-in.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void resendPendingInRequests(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tJID[] buddies = roster_util.getBuddies(session, RosterAbstract.PENDING_IN);\n\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tElement presence = new Element(PRESENCE_ELEMENT_NAME);\n\n\t\t\t\tpresence.setAttribute(\"type\", StanzaType.subscribe.toString());\n\t\t\t\tpresence.setXMLNS(XMLNS);\n\n\t\t\t\tPacket pres = Packet.packetInstance(presence, buddy, null);\n\n\t\t\t\tupdatePresenceChange(pres, session, results);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sends Presence stanza from provided parameters without returning created\n\t * result {@link Packet} object. In case of missing {@code  pres} parameter a\n\t * Presence stanza will be created with provided {@link StanzaType} type\n\t * {@code t}, {@link JID} type {@code from} and {@link JID} type {@code to}.\n\t * Otherwise Presence stanza {@code pres} will be cloned and {@code to}\n\t * attribute will be set from parameter {@code to}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t * @param to      is a <code>JID</code> instance with stanza destination\n\t *                address.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t */\n\tpublic static void sendPresence(StanzaType t, BareJID from, BareJID to,\n\t\t\tQueue<Packet> results, Element pres) {\n\t\tsendPresence(t, JID.jidInstance(from), JID.jidInstance(to), results, pres);\n\t}\n\n\t/**\n\t * Sends Presence stanza from provided parameters as well as returns created\n\t * result {@link Packet} object. In case of missing {@code  pres} parameter a\n\t * Presence stanza will be created with provided {@link StanzaType} type\n\t * {@code t}, {@link JID} type {@code from} and {@link JID} type {@code to}.\n\t * Otherwise Presence stanza {@code pres} will be cloned and {@code to}\n\t * attribute will be set from parameter {@code to}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t * @param to      is a <code>JID</code> instance with stanza destination\n\t *                address.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t *\n\t * @return an instance of {@link Packet} holding Presence stanza created from\n\t *         provided parameters.\n\t */\n\tpublic static Packet sendPresence(StanzaType t, JID from, JID to,\n\t\t\tQueue<Packet> results, Element pres) {\n\t\tElement presence = null;\n\t\tPacket  result   = null;\n\n\t\tif (pres == null) {\n\t\t\tpresence = new Element(PRESENCE_ELEMENT_NAME);\n\t\t\tif (t != null) {\n\t\t\t\tpresence.setAttribute(\"type\", t.toString());\n\t\t\t}    // end of if (t != null)\n\t\t\t\t\telse {\n\t\t\t\tpresence.setAttribute(\"type\", StanzaType.unavailable.toString());\n\t\t\t}    // end of if (t != null) else\n\t\t\tif (null != from ) {\n\t\t\t\tpresence.setAttribute(\"from\", from.toString());\n\t\t\t}\n\t\t\tpresence.setXMLNS(XMLNS);\n\t\t} else {\n\t\t\tpresence = pres.clone();\n\t\t}      // end of if (pres == null) else\n\t\tpresence.setAttribute(\"to\", to.toString());\n\t\ttry {\n\n\t\t\t// Connection IDs are not available so let's send it a normal way\n\t\t\tresult = Packet.packetInstance(presence);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Sending presence info: {0}\", result);\n\t\t\t}\n\t\t\tresults.offer(result);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\"Packet stringprep addressing problem, skipping presence send: {0}\", presence);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t * Before sending presence method calls {@code  requiresPresenceSending()}\n\t * performing, if configured, both system and roster check to verify whether\n\t * presence needs to be sent.\n\t *\n\t * @param t           specifies type of the presence to be send.\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param results     this a collection with packets which have been generated\n\t *                    as input packet processing results.\n\t * @param subscrs     an {@code EnumSet<SubscriptionType>} holding all\n\t *                    {@link SubscriptionType} to which a Presence should be\n\t *                    broadcast.\n\t * @param pres        an Object of type {@link Element} holding Presence\n\t *                    stanza to be sent.\n\t * @param settings    this map keeps plugin specific settings loaded from the\n\t *                    Tigase server configuration.\n\t * @param roster_util instance of class implementing {@link RosterAbstract}.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic static void sendPresenceBroadcast(StanzaType t, XMPPResourceConnection session,\n\t\t\tEnumSet<SubscriptionType> subscrs, Queue<Packet> results, Element pres, Map<String,\n\t\t\tObject> settings, RosterAbstract roster_util)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Direct presence if any should be sent first\n\t\tbroadcastDirectPresences(t, session, results, pres);\n\n\t\tRosterAbstract roster = roster_util;\n\n\t\tif (roster == null) {\n\t\t\troster = RosterFactory.getRosterImplementation(true);\n\t\t}\n\n\t\tJID[] buddies = roster.getBuddies(session, subscrs);\n\n\t\ttry {\n\t\t\tbuddies = DynamicRoster.addBuddies(session, settings, buddies);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\n\t\t\t// Ignore, handled in the JabberIqRoster code\n\t\t}\n\t\tif (buddies != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, session.getBareJID() + \" | Buddies found: \" + Arrays\n\t\t\t\t\t\t.toString(buddies));\n\t\t\t}\n\n\t\t\tPriority pack_priority = Priority.PRESENCE;\n\t\t\tint      pres_cnt      = 0;\n\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tif (requiresPresenceSending(roster, buddy, session, false)) {\n\t\t\t\t\tPacket pack = sendPresence(t, session.getJID(), buddy, results, pres);\n\n\t\t\t\t\tif (pres_cnt == HIGH_PRIORITY_PRESENCES_NO) {\n\t\t\t\t\t\t++pres_cnt;\n\t\t\t\t\t\tpack_priority = Priority.LOWEST;\n\t\t\t\t\t}\n\t\t\t\t\tif (pack != null) {\n\t\t\t\t\t\tpack.setPriority(pack_priority);\n\t\t\t\t\t\troster.setPresenceSent(session, buddy, true);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Not sending presence to buddy: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No buddies found!!!!\");\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stopped(XMPPResourceConnection session, Queue<Packet> results, Map<String,\n\t\t\tObject> settings) {\n\n\t\t// Synchronization to avoid conflict with login/logout events\n\t\t// processed in the SessionManager asynchronously\n\t\tsynchronized (session) {\n\n\t\t\t// According to the spec and logic actually offline status should\n\t\t\t// not be broadcasted if initial presence was not sent by the client.\n\t\t\ttry {\n\t\t\t\tif (session.getPresence() != null) {\n\n\t\t\t\t\t// If this was called without sending unavailable presence\n\t\t\t\t\t// we have to generate it on our own.\n\t\t\t\t\tElement pres = session.getPresence();\n\n\t\t\t\t\tif (!StanzaType.unavailable.toString().equals(pres.getAttributeStaticStr(Packet\n\t\t\t\t\t\t\t.TYPE_ATT))) {\n\t\t\t\t\t\tpres.setAttribute(Packet.TYPE_ATT, StanzaType.unavailable.toString());\n\t\t\t\t\t\tsession.setPresence(pres);\n\t\t\t\t\t}\n\t\t\t\t\tbroadcastOffline(session, results, settings, roster_util);\n\t\t\t\t\tupdateOfflineChange(session, results);\n\t\t\t\t} else {\n\t\t\t\t\tbroadcastDirectPresences(StanzaType.unavailable, session, results, null);\n\t\t\t\t}\n\t\t\t\troster_util.logout(session);\n\t\t\t} catch (NotAuthorizedException e) {\n\n\t\t\t\t// Do nothing, it may happen quite often when the user disconnects\n\t\t\t\t// before it authenticates.\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for offline message: \", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\tpublic static void rebroadcastPresence(XMPPResourceConnection session, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException {\n\t\tElement presence = session.getPresence();\n\n\t\tif (presence == null ) {\n\t\t\t// user has not sent initial presence yet, ignore\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( ExtendedPresenceProcessorIfc processor : extendedPresenceProcessors ) {\n\t\t\tElement extendContent = processor.extend( session, results );\n\t\t\tif ( extendContent != null ){\n\t\t\t\t// avoid duplicate\n\t\t\t\tElement child = presence.getChild( extendContent.getName(), extendContent.getXMLNS() );\n\t\t\t\tif ( child != null ){\n\t\t\t\t\tpresence.removeChild( child );\n\t\t\t\t}\n\t\t\t\tpresence.addChild( extendContent );\n\t\t\t}\n\t\t}\n\t\t\n\t\tsendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results, presence, null, getRosterUtil());\n\n\t\tupdateUserResources(presence, session, results, false);\n\n//\t\tsendPresenceBroadcast( StanzaType.get, session, SUB_TO, results, presence, null, null );\n\t}\n\n\t/**\n\t * <code>updatePresenceChange</code> method is used to broadcast to all active\n\t * resources presence stanza received from other users, like incoming\n\t * availability presence, subscription presence and so on... Initial presences\n\t * are however sent only to those resources which already have sent initial\n\t * presence.\n\t *\n\t * @param presence an <code>Element</code> presence received from other users,\n\t *                 we have to change 'to' attribute to full resource JID.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tpublic static void updatePresenceChange(Packet presence,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tboolean initial_p = ((presence.getAttributeStaticStr(Packet.TYPE_ATT) == null) ||\n\t\t\t\t\"available\".equals(presence.getAttributeStaticStr(Packet.TYPE_ATT)) ||\n\t\t\t\t\"unavailable\".equals(presence.getAttributeStaticStr(Packet.TYPE_ATT)));\n\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\n\t\t\t// Update presence change only for online resources that is\n\t\t\t// resources which already sent initial presence.\n\t\t\tif (((conn.getPresence() == null) && initial_p)) {\n\n\t\t\t\t// Ignore....\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\"Skipping update presence change for a resource which hasn't sent \" +\n\t\t\t\t\t\t\t\"initial presence yet, or is remote connection: \" + conn);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(\"Update presence change to: \" + conn);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tPacket pres_update = presence.copyElementOnly();\n\n\t\t\t\t\tpres_update.initVars(presence.getStanzaFrom(), conn.getJID()\n\t\t\t\t\t\t\t.copyWithoutResource());\n\t\t\t\t\tpres_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pres_update);\n\t\t\t\t} catch (NotAuthorizedException | NoConnectionIdException e) {\n\n\t\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t\t// This catch is to make sure all other resources receive\n\t\t\t\t\t// notification.\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t/**\n\t * <code>updateUserResources</code> method is used to broadcast to all\n\t * <strong>other</strong> resources presence stanza from one user resource. So\n\t * if new resource connects this method updates presence information about new\n\t * resource to old resources and about old resources to new resource.\n\t *\n\t * @param presence an <code>Element</code> presence received from other users,\n\t *                 we have to change 'to' attribute to full resource JID.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param initial   specifies whether this is an initial presence or not (i.e.\n\t *                 if there is a presence data from the presence stored within\n\t *                 user session object or not)\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tpublic static void updateUserResources(Element presence,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results, boolean initial)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Update presence change to: {0}\", conn.getJID());\n\t\t\t\t}\n\n\t\t\t\t// We also do not send presence updates to any remote connections on\n\t\t\t\t// different cluster nodes. Each node takes care of delivering presence\n\t\t\t\t// locally\n\t\t\t\tif (conn.isResourceSet()) {\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tElement pres_update = presence.clone();\n\t\t\t\t\tPacket  pack_update = Packet.packetInstance(pres_update, session.getJID(), conn\n\t\t\t\t\t\t\t.getJID().copyWithoutResource());\n\n\t\t\t\t\tpack_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pack_update);\n\n\t\t\t\t\tElement presence_el = conn.getPresence();\n\n\t\t\t\t\t// Send to new resource last presence sent by the old resource\n\t\t\t\t\tif ((presence_el != null) && initial && (conn != session)) {\n\t\t\t\t\t\tpres_update = presence_el.clone();\n\t\t\t\t\t\tpack_update = Packet.packetInstance(pres_update, conn.getJID(), session\n\t\t\t\t\t\t\t\t.getJID().copyWithoutResource());\n\t\t\t\t\t\tpack_update.setPacketTo(session.getConnectionId());\n\t\t\t\t\t\tresults.offer(pack_update);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(\"Skipping presence update to: \" + conn.getJID());\n\t\t\t\t\t}\n\t\t\t\t}    // end of else\n\t\t\t} catch (NotAuthorizedException | NoConnectionIdException e) {\n\n\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t// This catch is to make sure all other resources receive notification.\n\t\t\t}\n\t\t}        // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(id(), USERS_STATUS_CHANGES, usersStatusChanges, Level.INFO);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * {@code broadcastDirectPresences} broadcast a direct Presence from provided\n\t * {@code pres} {@link Element} object to the collection of JIDs stored in\n\t * temporary session data under key {@code DIRECT_PRESENCE}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected static void broadcastDirectPresences(StanzaType t,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results, Element pres)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif ((direct_presences != null) && (t != null) && (t == StanzaType.unavailable)) {\n\t\t\tfor (JID buddy : direct_presences) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Updating direct presence for: {0}\", buddy);\n\t\t\t\t}\n\n\t\t\t\tPacket pack = sendPresence(t, session.getJID(), buddy, results, pres);\n\n\t\t\t\tpack.setPriority(Priority.LOW);\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (direct_presence != null)\n\t}\n\n\t/**\n\t * Method sends back presence to contact while it becomes online (i.e. during\n\t * processing of incoming initial presence of the contact/buddy)\n\t *\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param buddy   {@link JID} of a roster element for which an online state\n\t *                will be set\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param online  set whether given contact is online or offline\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void buddyOnline(XMPPResourceConnection session, JID buddy,\n\t\t\tQueue<Packet> results, boolean online)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\troster_util.setOnline(session, buddy, online);\n\t\tif (online && skipOffline &&!roster_util.presenceSent(session, buddy) && roster_util\n\t\t\t\t.isSubscribedFrom(session, buddy)) {\n\t\t\tElement pres = session.getPresence();\n\n\t\t\tif (pres != null) {\n\t\t\t\tsendPresence(null, null, buddy, results, pres);\n\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Simply forwards packet to the destination\n\t *\n\t *\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param packet  to forward\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t */\n\tprotected static void forwardPresence(Queue<Packet> results, Packet packet, JID from) {\n\t\tElement result = packet.getElement().clone();\n\n\t\t// Not needed anymore. Packet filter does it for all stanzas.\n\t\t// According to spec we must set proper FROM attribute\n\t\t// Yes, but packet filter puts full JID and we need a subscription\n\t\t// presence without resource here.\n\t\tresult.setAttribute(\"from\", from.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"\\n\\nFORWARD presence: {0}\", result.toString());\n\t\t}\n\t\tresults.offer(Packet.packetInstance(result, from, packet.getStanzaTo()));\n\t}\n\n\t/**\n\t * Process presence stanza of type Error. Allows errors sent from server to\n\t * user and ignore presence errors sent from the user.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processError(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType presenceType)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException {\n\n\t\t// Strategy change.\n\t\t// Now we allow all error presences sent to the user, but we just ignore\n\t\t// presence errors sent from the user\n\t\tif (session.isUserId(packet.getStanzaTo().getBareJID())) {\n\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\tresults.offer(result);\n\t\t} else {\n\n\t\t\t// Ignore....\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming initial presence (i.e. in the\n\t * receivers session manager).\n\t * <p>\n\t * It validates the packet (whether from is present or if it's a direct\n\t * presence to existing resource) and subsequently set received presence for\n\t * the contact that sent it.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInInitial(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType presenceType)\n\t\t\t\t\tthrows NoConnectionIdException, NotAuthorizedException, TigaseDBException {\n\t\tif (packet.getStanzaFrom() == null) {\n\n\t\t\t// That really happened already. It looks like a bug in tigase\n\t\t\t// let's try to catch it here....\n\t\t\tlog.log(Level.WARNING, \"Initial presence without from attribute set: {0}\", packet);\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If this is a direct presence to a resource which is already gone\n\t\t// Ignore it.\n\t\tString resource = packet.getStanzaTo().getResource();\n\n\t\tif ((resource != null) &&!resource.isEmpty()) {\n\t\t\tXMPPResourceConnection direct = session.getParentSession().getResourceForResource(\n\t\t\t\t\tresource);\n\n\t\t\tif (direct != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Received direct presence from: {0} to: {1}\",\n\t\t\t\t\t\t\tnew Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\tpacket.getStanzaTo() });\n\t\t\t\t}\n\n\t\t\t\t// Send a direct presence to correct resource, otherwise ignore\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(direct.getConnectionId());\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Ignoring direct presence from: {0} to: {1}, resource gone.\",\n\t\t\t\t\t\t\tnew Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\tpacket.getStanzaTo() });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tboolean online = StanzaType.unavailable != packet.getType();\n\n\t\tbuddyOnline(session, packet.getStanzaFrom(), results, online);\n\t\tif (session.getPresence() == null) {\n\n\t\t\t// Just ignore, this user does not want to receive presence updates\n\t\t\treturn;\n\t\t}\n\n\t\tJID presBuddy = packet.getStanzaFrom().copyWithoutResource();\n\n\t\t// If other users are in 'to' or 'both' contacts, broadcast\n\t\t// their presences to all active resources\n\t\tElement dynItem;\n\n\t\ttry {\n\t\t\tdynItem = DynamicRoster.getBuddyItem(session, settings, presBuddy);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\t\t\tdynItem = null;\n\t\t}\n\t\tif ( roster_util.isSubscribedTo( session, presBuddy ) || ( dynItem != null ) ){\n\t\t\tRosterElement rel = roster_util.getRosterElement( session, presBuddy );\n\n\t\t\tif ( rel != null ){\n\t\t\t\trel.setLastSeen( System.currentTimeMillis() );\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t \"Received initial presence, setting buddy: {0} online status to: {1}\",\n\t\t\t\t\t\t\t\t new Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonline } );\n\t\t\t}\n\t\t\tupdatePresenceChange(packet, session, results);\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming presence probe (i.e. in the\n\t * receivers session manager).\n\t * <p>\n\t * It validates whether the packet comes from a contact that has correct\n\t * subscription and responds with presence of all user's resources presences.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws PacketErrorTypeException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInProbe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType presenceType)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, PacketErrorTypeException {\n\t\tSubscriptionType buddy_subscr = null;\n\t\tElement          dynItem;\n\n\t\ttry {\n\t\t\tdynItem = DynamicRoster.getBuddyItem(session, settings, packet.getStanzaFrom());\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\t\t\tdynItem = null;\n\t\t}\n\t\tif (dynItem != null) {\n\t\t\tbuddy_subscr = SubscriptionType.both;\n\t\t} else {\n\t\t\tbuddy_subscr = roster_util.getBuddySubscription(session, packet.getStanzaFrom());\n\t\t}\n\t\tif (buddy_subscr == null) {\n\t\t\tbuddy_subscr = SubscriptionType.none;\n\t\t}    // end of if (buddy_subscr == null)\n\t\tif (roster_util.isSubscribedFrom(buddy_subscr)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Received probe, setting buddy: {0} as online.\", packet\n\t\t\t\t\t\t.getStanzaFrom());\n\t\t\t}\n\n\t\t\t// Probe is usually without resource anyway, so probably more correct approach would\n\t\t\t// be to remove below.\n\t\t\tif (packet.getStanzaFrom().getResource() != null) {\n\t\t\t\troster_util.setOnline(session, packet.getStanzaFrom(), true);\n\t\t\t}\n\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\ttry {\n\t\t\t\t\tElement pres = conn.getPresence();\n\n\t\t\t\t\tif (pres != null) {\n\t\t\t\t\t\tsendPresence(null, null, packet.getStanzaFrom().copyWithoutResource(),\n\t\t\t\t\t\t\t\tresults, pres);\n\t\t\t\t\t\troster_util.setPresenceSent(session, packet.getStanzaFrom(), true);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Received probe, sending presence response to: {0}\",\n\t\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (NotAuthorizedException | TigaseDBException e) {\n\n\t\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t\t// This catch is to make sure all other resources receive\n\t\t\t\t\t// notification.\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// acording to spec 4.3.2. Server Processing of Inbound Presence Probe\n\t\t\t// http://xmpp.org/rfcs/rfc6121.html#presence-probe-inbound\n\t\t\t// If the user's bare JID is in the contact's roster with a subscription\n\t\t\t// state other\n\t\t\t// than \"From\", \"From + Pending Out\", or \"Both\", then the contact's server\n\t\t\t// SHOULD return a presence stanza of type \"unsubscribed\"\n\t\t\tif (!isAllowedForPresenceProbe(session, packet.getStanzaFrom())) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Received probe, users bare JID: {0} is not in the roster. Responding with unsubscribed\",\n\t\t\t\t\t\t\tpacket.getStanzaFrom().getBareJID());\n\t\t\t\t}\n\t\t\t\tsendPresence(StanzaType.unsubscribed, session.getBareJID(), packet.getStanzaFrom()\n\t\t\t\t\t\t.getBareJID(), results, null);\n\t\t\t} else {\n\t\t\t\t// However, if a server receives a presence probe from a configured\n\t\t\t\t// domain of the server itself or another such trusted service, it MAY\n\t\t\t\t// provide presence information about the user to that entity.\n\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\t\tElement pres = conn.getPresence();\n\n\t\t\t\t\tif (pres != null) {\n\t\t\t\t\t\tsendPresence(null, null, packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\tresults, pres);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Received probe, sending presence response to: {0}\",\n\t\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of if (roster_util.isSubscribedFrom(session, packet.getElemFrom()))\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming subscription request (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * If the contact is already subscribed the an auto-reply with\n\t * type='subscribded' is sent, otherwise contact is added to the roster (if\n\t * it's missing/there is no current subscription), sets the subscription type\n\t * to {@code PresenceType.in_subscribe} and subsequently broadcast presence\n\t * update to all connected resources.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInSubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// If the buddy is already subscribed then auto-reply with subscribed\n\t\t// presence stanza.\n\t\tif (roster_util.isSubscribedFrom(session, packet.getStanzaFrom())) {\n\t\t\tsendPresence(StanzaType.subscribed, session.getJID().copyWithoutResource(), packet\n\t\t\t\t\t.getStanzaFrom(), results, null);\n\t\t} else {\n\t\t\tSubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t\t.getStanzaFrom());\n\n\t\t\tif (curr_sub == null) {\n\t\t\t\troster_util.addBuddy(session, packet.getStanzaFrom(), null, null, null);\n\t\t\t}    // end of if (curr_sub == null)\n\t\t\troster_util.updateBuddySubscription(session, pres_type, packet.getStanzaFrom());\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tupdatePresenceChange(packet, session, results);\n\t\t\t} else {\n\t\t\t\troster_util.setBuddySubscription(session, SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaFrom().copyWithoutResource());\n\t\t\t}\n\t\t}    // end of else\n\t\tif (autoAuthorize) {\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tpacket.getStanzaFrom().copyWithoutResource()));\n\t\t\tbroadcastProbe(session, results, settings);\n\t\t\tsendPresence(StanzaType.subscribed, session.getJID(), packet.getStanzaFrom(),\n\t\t\t\t\tresults, null);\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming subscribed presence (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * Contact is added to the roster (if it's missing/there is no current\n\t * subscription), sets the subscription type to\n\t * {@code PresenceType.in_subscribed} and subsequently, if subscription has\n\t * changed,forwards the presence to user resource connection as well as\n\t * broadcast presence update to all connected resources.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInSubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tSubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t.getStanzaFrom());\n\n\t\tif (!autoAuthorize && (curr_sub == null)) {\n\t\t\troster_util.addBuddy(session, packet.getStanzaFrom(), null, null, null);\n\t\t}    // end of if (curr_sub == null)\n\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tpacket.getStanzaFrom());\n\n\t\tif (subscr_changed) {\n\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\tresults.offer(forward_p);\n\t\t\tif (autoAuthorize) {\n\t\t\t\troster_util.setBuddySubscription(session, SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaFrom().copyWithoutResource());\n\t\t\t}\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tpacket.getStanzaFrom()));\n\n\t\t\tElement delay = packet.getElement().getChild( \"delay\", \"urn:xmpp:delay\");\n\t\t\tif (delay != null ) {\n\t\t\t\t// offline packet, lets send probe\n\t\t\t\tElement presProbe = prepareProbe( session );\n\t\t\t\tsendPresence( null, null, packet.getStanzaFrom(), results, presProbe );\n\t\t\t}\n\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming unsubscribe presence (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * First method performs update of subscription of the given contact and\n\t * subsequently the request is forwarded to the client to make sure it says in\n\t * synch with the server (in case there was actual change in subscription).\n\t * Lastly a roster push is generated to all connected resources to update them\n\t * with current state of the roster and items subscriptions.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInUnsubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tpacket.getStanzaFrom());\n\n\t\tif (subscr_changed) {\n\n\t\t\t// First forward the request to the client to make sure it stays in sync\n\t\t\t// with the server. This should be done only in the case of actual change of the state\n\t\t\t// and with auto-authorization disabled\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\t\tresults.offer(forward_p);\n\t\t\t}\n\n\t\t\tElement item = roster_util.getBuddyItem(session, packet.getStanzaFrom());\n\n\t\t\tif (item != null) {\n\t\t\t\troster_util.updateBuddyChange(session, results, item);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Received unsubscribe request from a user who is not in the roster: {0}\",\n\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (autoAuthorize) {\n\t\t\t\tbroadcastProbe(session, results, settings);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming unsubscribed presence (i.e.\n\t * in the receivers session manager).\n\t * <p>\n\t * First method checks for the current subscription of the contact and if this\n\t * verifies performs subsequent actions such as forwarding presence to the\n\t * user connection to make sure it says in synch with the server, updates\n\t * contact subscription with {@code PresenceType.in_unsubscribed} and in case\n\t * that there was a change in user subscription send out a roster push to all\n\t * connected resources to update them with current state of the roster and\n\t * items subscriptions.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInUnsubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tSubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t.getStanzaFrom());\n\n\t\tif (curr_sub != null) {\n\n\t\t\t// First forward the request to the client to make sure it stays in sync\n\t\t\t// with the server. This should be done only with auto-authorization disabled\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\t\tresults.offer(forward_p);\n\t\t\t}\n\n\t\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\t\tpacket.getStanzaFrom());\n\n\t\t\tif (subscr_changed) {\n\t\t\t\tElement item = roster_util.getBuddyItem(session, packet.getStanzaFrom());\n\n\t\t\t\t// The roster item could have been removed in the meantime....\n\t\t\t\tif (item != null) {\n\t\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(\n\t\t\t\t\t\t\tsession, packet.getStanzaFrom()));\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Received unsubscribe request from a user who is not in the roster: {0}\",\n\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (autoAuthorize) {\n\t\t\t\t\tbroadcastProbe(session, results, settings);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing outgoing initial presence (i.e. in the\n\t * sender session manager).\n\t * <p>\n\t * Process packet accordingly whether it's a direct presence (forward it, add\n\t * to proper collection of JIDs to which a direct presence has been sent) or\n\t * regular presence. THe latter causes properly address the packet, store\n\t * presence within session data for subsequent use, and for the first\n\t * availability presence (in case there is no prior presence stored in user\n\t * session data) server sends probes to all contacts and pushes out all\n\t * pending subscription request or (if there i already presence stored in\n\t * session data) broadcast presence update to contacts.\n\t * <p>\n\t * If there is a JID forwarding set up, presence is also forwarded to\n\t * configured JID.\n\t *\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t * @param type     specifies type of the presence.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutInitial(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Is it a direct presence to some entity on the network?\n\t\tif (packet.getStanzaTo() != null) {\n\n\t\t\t// Yes this is it, send direct presence\n\t\t\tresults.offer(packet.copyElementOnly());\n\n\t\t\t// If this is unavailable presence, remove jid from Set\n\t\t\t// otherwise add it to the Set\n\t\t\tif (packet.getType() == StanzaType.unavailable) {\n\t\t\t\tremoveDirectPresenceJID(packet.getStanzaTo(), session);\n\t\t\t} else {\n\t\t\t\taddDirectPresenceJID(packet.getStanzaTo(), session);\n\t\t\t}\n\t\t} else {\n\t\t\t++usersStatusChanges;\n\n\t\t\tboolean first = false;\n\n\t\t\tif (session.getPresence() == null) {\n\t\t\t\tfirst = true;\n\t\t\t}\n\t\t\tpacket.initVars(session.getJID(), packet.getStanzaTo());\n\t\t\tfinal Element presenceEl = packet.getElement();\n\n\t\t\tfor ( ExtendedPresenceProcessorIfc processor : extendedPresenceProcessors ) {\n\t\t\t\tElement extendContent = processor.extend( session, results );\n\t\t\t\tif ( extendContent != null ){\n\t\t\t\t\tpresenceEl.addChild( extendContent );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Store user presence for later time...\n\t\t\t// To send response to presence probes for example.\n\t\t\tsession.setPresence(presenceEl);\n\n\t\t\t// here we need to check if roster is loaded\n\t\t\tif (!rosterLazyLoading || roster_util.isRosterLoaded(session)) {\n\t\t\t\t// if it is already loaded then continue processing\n\t\t\t\t// Special actions on the first availability presence\n\t\t\t\tif ((packet.getType() == null) || (packet.getType() == StanzaType.available)) {\n\t\t\t\t\tsession.removeSessionData(OFFLINE_BUD_SENT);\n\t\t\t\t\tsession.removeSessionData(OFFLINE_RES_SENT);\n\t\t\t\t\tif (first) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsendRosterOfflinePresence(session, results);\n\t\t\t\t\t\t} catch (NotAuthorizedException | TigaseDBException | NoConnectionIdException ex) {\n\t\t\t\t\t\t\tlog.log(Level.INFO, \"Experimental code throws exception: \", ex);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Send presence probes to 'to' or 'both' contacts\n\t\t\t\t\t\tbroadcastProbe(session, results, settings);\n\n\t\t\t\t\t\t// Resend pending in subscription requests\n\t\t\t\t\t\tresendPendingInRequests(session, results);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Broadcast initial presence to 'from' or 'both' contacts\n\t\t\t\t\t\tsendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t results, presenceEl, settings, roster_util);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Broadcast initial presence to other available user resources\n\t\t\t\t\tupdateUserResources(presenceEl, session, results, first);\n\t\t\t\t} else {\n\t\t\t\t\tstopped(session, results, settings);\n\t\t\t\t}\n\n\t\t\t\t// Presence forwarding\n\t\t\t\tJID forwardTo = session.getDomain().getPresenceForward();\n\n\t\t\t\tif (forwardTo == null) {\n\t\t\t\t\tforwardTo = presenceGLobalForward;\n\t\t\t\t}\n\t\t\t\tif (forwardTo != null) {\n\t\t\t\t\tsendPresence(null, session.getJID(), forwardTo, results, presenceEl);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// if roster is not yet loaded we need to trigger roster load by Roster plugin\n\t\t\t\tElement iq = new Element(Iq.ELEM_NAME, new String[] { \"type\" }, new String[] { \"set\" });\n\t\t\t\tElement query = new Element(Iq.QUERY_NAME, new String[] { Iq.XMLNS_ATT }, new String[] { RosterAbstract.XMLNS_LOAD });\n\t\t\t\tiq.addChild(query);\n\t\t\t\tPacket loadCmd = Packet.packetInstance(iq, packet.getStanzaFrom(), packet.getStanzaTo());\n\t\t\t\tloadCmd.setPacketFrom(packet.getPacketFrom());\n\t\t\t\tloadCmd.setPacketTo(packet.getPacketTo());\n\t\t\t\tresults.add(loadCmd);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing outgoing subscribe and unsubscribe\n\t * presence (i.e. in the sender session manager).\n\t * <p>\n\t * Presence packet is forwarded to the destination with the JID stripped from\n\t * the resource.\n\t * <p>In case of {@code PresenceType.out_subscribe} packet type contact is\n\t * added to the roster (in case it was missing), a subscription state is being\n\t * updated and, in case there was a change, a roster push is being sent to all\n\t * user resources.\n\t * <p>\n\t * In case of {@code PresenceType.out_unsubscribe} method updates contact\n\t * subscription (and generates roster push if there was a change) and if the\n\t * resulting contact subscription is NONE then contact is removed from the\n\t * roster.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutSubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// According to RFC-3921 I must forward all these kind presence\n\t\t// requests, it allows to resynchronize\n\t\t// subscriptions in case of synchronization loss\n\t\tboolean subscr_changed = false;\n\n\t\tforwardPresence(results, packet, session.getJID().copyWithoutResource());\n\n\t\tSubscriptionType current_subscription = roster_util.getBuddySubscription(session,\n\t\t\t\tpacket.getStanzaTo());\n\n\t\tif (pres_type == PresenceType.out_subscribe) {\n\t\t\tif (current_subscription == null) {\n\t\t\t\troster_util.addBuddy(session, packet.getStanzaTo(), null, null, null);\n\t\t\t}    // end of if (current_subscription == null)\n\t\t\tsubscr_changed = roster_util.updateBuddySubscription(session, pres_type, packet\n\t\t\t\t\t.getStanzaTo());\n\t\t\tif (autoAuthorize) {\n\t\t\t\troster_util.setBuddySubscription(session, SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaTo().copyWithoutResource());\n\t\t\t}\n\t\t\tif (subscr_changed) {\n\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\t\tpacket.getStanzaTo()));\n\t\t\t}    // end of if (subscr_changed)\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"out_subscribe: current_subscription = \" +\n\t\t\t\t\t\tcurrent_subscription);\n\t\t\t}\n\t\t\tif (current_subscription != null) {\n\t\t\t\tsubscr_changed = roster_util.updateBuddySubscription(session, pres_type, packet\n\t\t\t\t\t\t.getStanzaTo());\n\t\t\t\tcurrent_subscription = roster_util.getBuddySubscription(session, packet\n\t\t\t\t\t\t.getStanzaTo());\n\t\t\t\tif (subscr_changed) {\n\t\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(\n\t\t\t\t\t\t\tsession, packet.getStanzaTo()));\n\t\t\t\t}    // end of if (subscr_changed)\n\t\t\t\tif (SUB_NONE.contains(current_subscription)) {\n\t\t\t\t\troster_util.removeBuddy(session, packet.getStanzaTo());\n\t\t\t\t}    // end of if (current_subscription == null)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing outgoing subscribed and unsubscribed\n\t * presence (i.e. in the sender session manager).\n\t * <p>\n\t * Presence packet is forwarded to the destination with the JID stripped from\n\t * the resource, a subscription state is being updated and, in case there was\n\t * a change, a roster push is being sent to all user resources. Also, in case\n\t * of presence type out_subscribed server send current presence to the user\n\t * from each of the contact's available resources. For the presence type\n\t * out_unsubscribed an unavailable presence is sent.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutSubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// According to RFC-3921 I must forward all these kind presence\n\t\t// requests, it allows to re-synchronize\n\t\t// subscriptions in case of synchronization loss\n\t\tforwardPresence(results, packet, session.getJID().copyWithoutResource());\n\n\t\tElement initial_presence = session.getPresence();\n\t\tJID     buddy            = packet.getStanzaTo().copyWithoutResource();\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tbuddy);\n\n\t\tif (autoAuthorize && (pres_type == PresenceType.out_subscribed)) {\n\t\t\troster_util.setBuddySubscription(session, SubscriptionType.both, buddy\n\t\t\t\t\t.copyWithoutResource());\n\t\t}\n\t\tif (subscr_changed) {\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tbuddy));\n\t\t\tif (initial_presence != null) {\n\t\t\t\tif (pres_type == PresenceType.out_subscribed) {\n\n\t\t\t\t\t// The contact's server MUST then also send current presence to the user\n\t\t\t\t\t// from each of the contact's available resources.\n\t\t\t\t\tList<XMPPResourceConnection> activeSessions = session.getActiveSessions();\n\n\t\t\t\t\tfor (XMPPResourceConnection userSessions : activeSessions) {\n\t\t\t\t\t\tElement presence = userSessions.getPresence();\n\n\t\t\t\t\t\tsendPresence(StanzaType.available, userSessions.getjid(), buddy, results,\n\t\t\t\t\t\t\t\tpresence);\n\t\t\t\t\t}\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tsendPresence(StanzaType.unavailable, session.getJID(), buddy, results, null);\n\t\t\t\t}\n\t\t\t}    // end of if (subscr_changed)\n\t\t}\n\t}\n\n\t/**\n\t * Method sends server generated presence unavailable for all buddies from the\n\t * roster with a custom status message.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @throws TigaseDBException\n\t * @throws NotAuthorizedException\n\t * @throws NoConnectionIdException\n\t */\n\t@SuppressWarnings(\"empty-statement\")\n\tprotected void sendRosterOfflinePresence(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException {\n\t\tif (offlineRosterLastSeen == null) {\n\t\t\tlog.finest(\"No clients specified in config, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tElement pres = session.getPresence();\n\n\t\tif (pres == null) {\n\t\t\tlog.finest(\"Presence not set yet, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tString node = pres.getAttributeStaticStr(PRESENCE_C_PATH, \"node\");\n\n\t\tif (node == null) {\n\t\t\tlog.finest(\"Presence node not set, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tboolean validClient = false;\n\t\tint     i           = 0;\n\n\t\tif ( offlineRosterLastSeen.length > 0 && !offlineRosterLastSeen[0].equals( \"*\" ) ){\n\t\t\twhile ( ( i < offlineRosterLastSeen.length ) && !( validClient |= node.contains(\n\t\t\t\t\tofflineRosterLastSeen[i++] ) ) );\n\t\t\tif ( !validClient ){\n\t\t\t\tlog.finest( \"Client does not match, skipping...\" );\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t// enabled for all clients\n\t\t}\n\n\t\tJID[] buddies = roster_util.getBuddies(session, TO_SUBSCRIBED);\n\n\t\tif (buddies != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Buddies found: {0}\", Arrays.toString(buddies));\n\t\t\t}\n\n\t\t\tPriority pack_priority = Priority.PRESENCE;\n\t\t\tint      pres_cnt      = 0;\n\n\t\t\tfor ( JID buddy : buddies ) {\n\t\t\t\tList<Element> children = roster_util.getCustomChildren( session, buddy );\n\n\t\t\t\tif ( children != null && !children.isEmpty() ){\n\t\t\t\t\tPacket pack = sendPresence( StanzaType.unavailable, buddy, session.getJID(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tresults, null );\n\t\t\t\t\t\n\t\t\t\t\tif ( pres_cnt == HIGH_PRIORITY_PRESENCES_NO ){\n\t\t\t\t\t\t++pres_cnt;\n\t\t\t\t\t\tpack_priority = Priority.LOWEST;\n\t\t\t\t\t}\n\t\t\t\t\tpack.setPriority( pack_priority );\n\t\t\t\t\tpack.setPacketTo( session.getConnectionId() );\n\t\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\t\tpack.getElement().addChild( child );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}\n\t}\n\n\t/**\n\t * <code>updateOfflineChange</code> method broadcast off-line presence to all\n\t * other user active resources.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tprotected static void updateOfflineChange(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException {\n\n\t\t// Preventing sending offline notifications more than once\n\t\tif (session.getSessionData(OFFLINE_RES_SENT) != null) {\n\t\t\treturn;\n\t\t}\n\t\tsession.putSessionData(OFFLINE_RES_SENT, OFFLINE_RES_SENT);\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Update presence change to: {0}\", conn.getJID());\n\t\t\t\t}\n\t\t\t\tif ((conn != session) && (conn.isResourceSet()) &&!conn.getResource().equals(\n\t\t\t\t\t\tsession.getResource())) {\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tElement pres_update = new Element(PRESENCE_ELEMENT_NAME);\n\n\t\t\t\t\tpres_update.setAttribute(\"type\", StanzaType.unavailable.toString());\n\t\t\t\t\tpres_update.setXMLNS(XMLNS);\n\n\t\t\t\t\t// accroding to RFC1621, 4.5.2.  Server Processing of Outbound Unavailable Presence\n\t\t\t\t\t// this presece packet should be addressed to fullJID\n\t\t\t\t\tPacket pack_update = Packet.packetInstance( pres_update, session.getJID(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconn.getJID() );\n\n\t\t\t\t\tpack_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pack_update);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Skipping presence update to: {0}\", conn.getJID());\n\t\t\t\t\t}\n\t\t\t\t}    // end of else\n\t\t\t} catch (NoConnectionIdException | NotAuthorizedException e) {\n\n\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t// This catch is to make sure all other resources receive notification.\n\t\t\t}\n\t\t}        // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t/**\n\t * Method updates resources information upon receiving initial availability\n\t * presence (type available or missing type)\n\t *\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param type    specifies type of the stanza.\n\t * @param packet  packet is which being processed.\n\t */\n\tprotected static void updateResourcesAvailable(XMPPResourceConnection session,\n\t\t\tStanzaType type, Packet packet) {\n\t\tXMPPSession parentSession = session.getParentSession();\n\n\t\tif (parentSession != null) {\n\t\t\tMap<JID, Map> resources;\n\t\t\tboolean       online = (type == null) || (type == StanzaType.available);\n\n\t\t\tsynchronized (parentSession) {\n\t\t\t\tresources = (Map<JID, Map>) parentSession.getCommonSessionData(\n\t\t\t\t\t\tXMPPResourceConnection.ALL_RESOURCES_KEY);\n\t\t\t\tif (resources == null) {\n\t\t\t\t\tif (!online) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresources = new ConcurrentHashMap<>();\n\t\t\t\t\tsession.putCommonSessionData(XMPPResourceConnection.ALL_RESOURCES_KEY,\n\t\t\t\t\t\t\tresources);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (online) {\n\t\t\t\tMap map = resources.get(packet.getStanzaFrom());\n\n\t\t\t\tif (map == null) {\n\t\t\t\t\tmap = new ConcurrentHashMap();\n\t\t\t\t\tresources.put(packet.getStanzaFrom(), map);\n\t\t\t\t}\n\n\t\t\t\tString priorityStr = packet.getElemCDataStaticStr(PRESENCE_PRIORITY_PATH);\n\n\t\t\t\tif (priorityStr != null) {\n\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY, Integer.parseInt(\n\t\t\t\t\t\t\tpriorityStr));\n\t\t\t\t} else if (!map.containsKey(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY)) {\n\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY, 0);\n\t\t\t\t}\n\n\t\t\t\tElement c = packet.getElement().getChild(\"c\", \"http://jabber.org/protocol/caps\");\n\n\t\t\t\tif (c != null) {\n\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_CAPS_KEY,\n\t\t\t\t\t\t\tPresenceCapabilitiesManager.processPresence(c));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresources.remove(packet.getStanzaFrom());\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns shared instance of class implementing {@link RosterAbstract} -\n\t * either default one ({@link RosterFlat}) or the one configured with\n\t * <em>\"roster-implementation\"</em> property.\n\t *\n\t * @return shared instance of class implementing {@link RosterAbstract}\n\t */\n\tprotected static RosterAbstract getRosterUtil() {\n\t\treturn RosterFactory.getRosterImplementation(true);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\tprivate boolean isAllowedForPresenceProbe(XMPPResourceConnection session, JID jid) {\n\t\tif (jid == null)\n\t\t\treturn false;\n\t\t\n\t\treturn session.getDomain().isTrustedJID(jid);\n\t}\n\t\n\t/**\n\t * Method checks whether a given contact requires sending presence. In case of\n\t * enabling option {@code skipOffline} and user being offline in the roster\n\t * the presence is not sent. Alternatively enabling option\n\t * {@code skipOfflineSys} would cause local environment check for user status\n\t * and omit sending presence if the local use is offline.\n\t *\n\t *\n\t * @param roster      instance of class implementing {@link RosterAbstract}.\n\t * @param buddy       JID of a contact for which a check is to be performed.\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param systemCheck indicates whether the check should be only based on\n\t *                    local environment state ({@code true}) or rooster state\n\t *                    of given user should also be taken into consideration\n\t *                    ({@code false}).\n\t *\n\t * @return {code true} if the contact requires sending presence (e.g. is not\n\t *         online and options skipOffline or skipOfflineSys are enabled)\n\t *\n\t * @throws TigaseDBException\n\t * @throws NotAuthorizedException\n\t */\n\tprivate static boolean requiresPresenceSending(RosterAbstract roster, JID buddy,\n\t\t\tXMPPResourceConnection session, boolean systemCheck)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tboolean result = true;\n\n\t\t// if non-system check is enabled during broadcast of non-first initial\n\t\t// presence or offline presence\n\t\tif (!systemCheck) {\n\t\t\tboolean isOnline = roster.isOnline( session, buddy );\n\t\t\tif ( skipOffline && !isOnline ){\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"{0} | buddy: {1} is online: {2}\",\n\t\t\t\t\t\t\t\t\t new Object[] { session.getJID(), buddy, isOnline } );\n\t\t\t\t}\n\t\t\t\tresult = result && false;\n\t\t\t}\n\t\t}\n\t\tif (skipOfflineSys) {\n\t\t\tTigaseRuntime runtime = TigaseRuntime.getTigaseRuntime();\n\t\t\tboolean isJidOnline = runtime.isJidOnline( buddy );\n\n\t\t\tif ( runtime.hasCompleteJidsInfo()\n\t\t\t\t\t && session.isLocalDomain( buddy.getDomain(), false )\n\t\t\t\t\t && !isJidOnline ){\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"{0} | buddy: {1} is online (sys): {2}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { session.getJID(), buddy, isJidOnline } );\n\t\t\t\t}\n\t\t\t\tresult = result && false;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic interface ExtendedPresenceProcessorIfc {\n\t\tElement extend( XMPPResourceConnection session, Queue<Packet> results );\n\t}\n\n} \n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PresenceAbstract.java",
    "content": "/*\n * Presence.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.*;\nimport tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor;\nimport tigase.xmpp.impl.roster.*;\n\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.*;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.xmpp.impl.roster.RosterAbstract.SUB_BOTH;\nimport static tigase.xmpp.impl.roster.RosterAbstract.SUB_FROM;\nimport static tigase.xmpp.impl.roster.RosterAbstract.SUB_TO;\n\n/**\n * Class responsible for handling Presence packets\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic abstract class PresenceAbstract\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\t\n\t/** Field description */\n\tpublic static final String PRESENCE_ELEMENT_NAME = \"presence\";\n\n\t/** Field description */\n\tpublic static final String SKIP_OFFLINE_PROP_KEY = \"skip-offline\";\n\n\tpublic static final String PRESENCE_PROBE_FULL_JID_KEY = \"probe-full-jid\";\n\n\t/** Field description */\n\tpublic static final String SKIP_OFFLINE_SYS_PROP_KEY = \"skip-offline-sys\";\n\n\t/** Field description */\n\tpublic static final String USERS_STATUS_CHANGES = \"Users status changes\";\n\n\t/** Field description */\n\tprotected static final String XMLNS                      = CLIENT_XMLNS;\n\n\t/** Private logger for class instance. */\n\tprivate static final Logger     log = Logger.getLogger(PresenceAbstract.class.getName());\n\t//private static final String[]   PRESENCE_PRIORITY_PATH  = { \"presence\", \"priority\" };\n\t//private static final String[]   XMLNSS                  = { XMLNS, RosterAbstract.XMLNS_LOAD };\n\tprivate static boolean          skipOfflineSys          = true;\n\tprotected static boolean          skipOffline             = false;\n\tprotected static boolean probeFullJID = false;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\t/** Field description */\n\tprotected RosterAbstract roster_util           = getRosterUtil();\n\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t * Before sending presence method calls {@code  requiresPresenceSending()},\n\t * configured to only check local environment status (if enabled) to verify\n\t * whether presence needs to be sent.\n\t *\n\t *\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic void broadcastProbe(XMPPResourceConnection session, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Broadcasting probes for: {0}\", session);\n\t\t}\n\n\t\t// Probe is always broadcasted with initial presence\n\t\tElement presInit  = session.getPresence();\n\t\tElement presProbe = prepareProbe( session );\n\n\t\tJID[] buddies = roster_util.getBuddies(session, SUB_BOTH);\n\n\t\ttry {\n\t\t\tbuddies = DynamicRoster.addBuddies(session, settings, buddies);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\n\t\t\t// Ignore, handled in the JabberIqRoster code\n\t\t}\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending presence probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presProbe);\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending intial presence to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presInit);\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending initial presence and probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\n\t\tJID[] buddies_to = roster_util.getBuddies(session, SUB_TO);\n\n\t\tif (buddies_to != null) {\n\t\t\tfor (JID buddy : buddies_to) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() + \" | Sending probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presProbe);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending presence probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\n\t\t// TODO: It might be a marginal number of cases here but just make it clear\n\t\t// we send a presence here regardless\n\t\tJID[] buddies_from = roster_util.getBuddies(session, SUB_FROM);\n\n\t\tif (buddies_from != null) {\n\t\t\tfor (JID buddy : buddies_from) {\n\t\t\t\tif (requiresPresenceSending(roster_util, buddy, session, true)) {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Sending initial presence to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t\tsendPresence(null, null, buddy, results, presInit);\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Skipping sending initial presence and probe to: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (buddies == null)\n\t}\n\n\tprotected static Element prepareProbe( XMPPResourceConnection session ) throws NotAuthorizedException {\n\t\tElement presProbe = new Element(PRESENCE_ELEMENT_NAME);\n\t\tpresProbe.setXMLNS(XMLNS);\n\t\tpresProbe.setAttribute(\"type\", StanzaType.probe.toString());\n\t\tif (probeFullJID) {\n\t\t\tpresProbe.setAttribute(\"from\", session.getJID().toString());\n\t\t} else {\n\t\t\tpresProbe.setAttribute(\"from\", session.getBareJID().toString());\n\t\t}\n\t\treturn presProbe;\n\t}\n\n\t@Override\n\tpublic int concurrentQueuesNo() {\n\t\treturn super.concurrentQueuesNo() * 4;\n\t}\n\n//\t@Override\n\tprotected static void initSettings(Map<String, Object> settings) throws TigaseDBException {\n\n\t\t// Init plugin configuration\n\t\tString tmp;\n\n\t\ttmp            = (String) settings.get(PRESENCE_PROBE_FULL_JID_KEY);\n\t\tprobeFullJID    = (tmp != null)\n\t\t\t\t? Boolean.parseBoolean(tmp)\n\t\t\t\t: probeFullJID;\n\t\t\tlog.log( Level.CONFIG,\n\t\t\t\t\t\t\t \"Sending probe from FullJID set to: {0}\", probeFullJID );\n\n\t\ttmp            = (String) settings.get(SKIP_OFFLINE_PROP_KEY);\n\t\tskipOffline    = (tmp != null)\n\t\t\t\t? Boolean.parseBoolean(tmp)\n\t\t\t\t: skipOffline;\n\t\ttmp            = (String) settings.get(SKIP_OFFLINE_SYS_PROP_KEY);\n\t\tskipOfflineSys = (tmp != null)\n\t\t\t\t? Boolean.parseBoolean(tmp)\n\t\t\t\t: skipOfflineSys;\n\t\tif (skipOffline || skipOfflineSys) {\n\t\t\tlog.log( Level.CONFIG,\n\t\t\t\t\t\t\t \"Skipping sending presence to offline contacts enabled :: skipOffline: {0}, skipOfflineSys: {1}\",\n\t\t\t\t\t\t\t new Object[] { skipOffline, skipOfflineSys } );\n\t\t}\n\t}\n\n\t/**\n\t * Sends Presence stanza from provided parameters without returning created\n\t * result {@link Packet} object. In case of missing {@code  pres} parameter a\n\t * Presence stanza will be created with provided {@link StanzaType} type\n\t * {@code t}, {@link JID} type {@code from} and {@link JID} type {@code to}.\n\t * Otherwise Presence stanza {@code pres} will be cloned and {@code to}\n\t * attribute will be set from parameter {@code to}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t * @param to      is a <code>JID</code> instance with stanza destination\n\t *                address.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t */\n\tpublic static void sendPresence(StanzaType t, BareJID from, BareJID to,\n\t\t\tQueue<Packet> results, Element pres) {\n\t\tsendPresence(t, JID.jidInstance(from), JID.jidInstance(to), results, pres);\n\t}\n\n\t/**\n\t * Sends Presence stanza from provided parameters as well as returns created\n\t * result {@link Packet} object. In case of missing {@code  pres} parameter a\n\t * Presence stanza will be created with provided {@link StanzaType} type\n\t * {@code t}, {@link JID} type {@code from} and {@link JID} type {@code to}.\n\t * Otherwise Presence stanza {@code pres} will be cloned and {@code to}\n\t * attribute will be set from parameter {@code to}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t * @param to      is a <code>JID</code> instance with stanza destination\n\t *                address.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t *\n\t * @return an instance of {@link Packet} holding Presence stanza created from\n\t *         provided parameters.\n\t */\n\tpublic static Packet sendPresence(StanzaType t, JID from, JID to,\n\t\t\tQueue<Packet> results, Element pres) {\n\t\tElement presence = null;\n\t\tPacket  result   = null;\n\n\t\tif (pres == null) {\n\t\t\tpresence = new Element(PRESENCE_ELEMENT_NAME);\n\t\t\tif (t != null) {\n\t\t\t\tpresence.setAttribute(\"type\", t.toString());\n\t\t\t}    // end of if (t != null)\n\t\t\t\t\telse {\n\t\t\t\tpresence.setAttribute(\"type\", StanzaType.unavailable.toString());\n\t\t\t}    // end of if (t != null) else\n\t\t\tif (null != from ) {\n\t\t\t\tpresence.setAttribute(\"from\", from.toString());\n\t\t\t}\n\t\t\tpresence.setXMLNS(XMLNS);\n\t\t} else {\n\t\t\tpresence = pres.clone();\n\t\t}      // end of if (pres == null) else\n\t\tpresence.setAttribute(\"to\", to.toString());\n\t\ttry {\n\n\t\t\t// Connection IDs are not available so let's send it a normal way\n\t\t\tresult = Packet.packetInstance(presence);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Sending presence info: {0}\", result);\n\t\t\t}\n\t\t\tresults.offer(result);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\"Packet stringprep addressing problem, skipping presence send: {0}\", presence);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * <code>updatePresenceChange</code> method is used to broadcast to all active\n\t * resources presence stanza received from other users, like incoming\n\t * availability presence, subscription presence and so on... Initial presences\n\t * are however sent only to those resources which already have sent initial\n\t * presence.\n\t *\n\t * @param presence an <code>Element</code> presence received from other users,\n\t *                 we have to change 'to' attribute to full resource JID.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tpublic static void updatePresenceChange(Packet presence,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tboolean initial_p = ((presence.getAttributeStaticStr(Packet.TYPE_ATT) == null) ||\n\t\t\t\t\"available\".equals(presence.getAttributeStaticStr(Packet.TYPE_ATT)) ||\n\t\t\t\t\"unavailable\".equals(presence.getAttributeStaticStr(Packet.TYPE_ATT)));\n\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\n\t\t\t// Update presence change only for online resources that is\n\t\t\t// resources which already sent initial presence.\n\t\t\tif (((conn.getPresence() == null) && initial_p)) {\n\n\t\t\t\t// Ignore....\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\n\t\t\t\t\t\t\t\"Skipping update presence change for a resource which hasn't sent \" +\n\t\t\t\t\t\t\t\"initial presence yet, or is remote connection: \" + conn);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(\"Update presence change to: \" + conn);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tPacket pres_update = presence.copyElementOnly();\n\n\t\t\t\t\tpres_update.initVars(presence.getStanzaFrom(), conn.getJID()\n\t\t\t\t\t\t\t.copyWithoutResource());\n\t\t\t\t\tpres_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pres_update);\n\t\t\t\t} catch (NotAuthorizedException | NoConnectionIdException e) {\n\n\t\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t\t// This catch is to make sure all other resources receive\n\t\t\t\t\t// notification.\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t/**\n\t * <code>updateUserResources</code> method is used to broadcast to all\n\t * <strong>other</strong> resources presence stanza from one user resource. So\n\t * if new resource connects this method updates presence information about new\n\t * resource to old resources and about old resources to new resource.\n\t *\n\t * @param presence an <code>Element</code> presence received from other users,\n\t *                 we have to change 'to' attribute to full resource JID.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param initial   specifies whether this is an initial presence or not (i.e.\n\t *                 if there is a presence data from the presence stored within\n\t *                 user session object or not)\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tpublic static void updateUserResources(Element presence,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results, boolean initial)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Update presence change to: {0}\", conn.getJID());\n\t\t\t\t}\n\n\t\t\t\t// We also do not send presence updates to any remote connections on\n\t\t\t\t// different cluster nodes. Each node takes care of delivering presence\n\t\t\t\t// locally\n\t\t\t\tif (conn.isResourceSet()) {\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tElement pres_update = presence.clone();\n\t\t\t\t\tPacket  pack_update = Packet.packetInstance(pres_update, session.getJID(), conn\n\t\t\t\t\t\t\t.getJID().copyWithoutResource());\n\n\t\t\t\t\tpack_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pack_update);\n\n\t\t\t\t\tElement presence_el = conn.getPresence();\n\n\t\t\t\t\t// Send to new resource last presence sent by the old resource\n\t\t\t\t\tif ((presence_el != null) && initial && (conn != session)) {\n\t\t\t\t\t\tpres_update = presence_el.clone();\n\t\t\t\t\t\tpack_update = Packet.packetInstance(pres_update, conn.getJID(), session\n\t\t\t\t\t\t\t\t.getJID().copyWithoutResource());\n\t\t\t\t\t\tpack_update.setPacketTo(session.getConnectionId());\n\t\t\t\t\t\tresults.offer(pack_update);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.finer(\"Skipping presence update to: \" + conn.getJID());\n\t\t\t\t\t}\n\t\t\t\t}    // end of else\n\t\t\t} catch (NotAuthorizedException | NoConnectionIdException e) {\n\n\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t// This catch is to make sure all other resources receive notification.\n\t\t\t}\n\t\t}        // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Simply forwards packet to the destination\n\t *\n\t *\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param packet  to forward\n\t * @param from    is a <code>JID</code> instance with stanza source address.\n\t */\n\tprotected static void forwardPresence(Queue<Packet> results, Packet packet, JID from) {\n\t\tElement result = packet.getElement().clone();\n\n\t\t// Not needed anymore. Packet filter does it for all stanzas.\n\t\t// According to spec we must set proper FROM attribute\n\t\t// Yes, but packet filter puts full JID and we need a subscription\n\t\t// presence without resource here.\n\t\tresult.setAttribute(\"from\", from.toString());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"\\n\\nFORWARD presence: {0}\", result.toString());\n\t\t}\n\t\tresults.offer(Packet.packetInstance(result, from, packet.getStanzaTo()));\n\t}\n\n//\t/**\n//\t * Method updates resources information upon receiving initial availability\n//\t * presence (type available or missing type)\n//\t *\n//\t *\n//\t * @param session user session which keeps all the user session data and also\n//\t *                gives an access to the user's repository data.\n//\t * @param type    specifies type of the stanza.\n//\t * @param packet  packet is which being processed.\n//\t */\n//\tprotected static void updateResourcesAvailable(XMPPResourceConnection session,\n//\t\t\tStanzaType type, Packet packet) {\n//\t\tXMPPSession parentSession = session.getParentSession();\n//\n//\t\tif (parentSession != null) {\n//\t\t\tMap<JID, Map> resources;\n//\t\t\tboolean       online = (type == null) || (type == StanzaType.available);\n//\n//\t\t\tsynchronized (parentSession) {\n//\t\t\t\tresources = (Map<JID, Map>) parentSession.getCommonSessionData(\n//\t\t\t\t\t\tXMPPResourceConnection.ALL_RESOURCES_KEY);\n//\t\t\t\tif (resources == null) {\n//\t\t\t\t\tif (!online) {\n//\t\t\t\t\t\treturn;\n//\t\t\t\t\t}\n//\t\t\t\t\tresources = new ConcurrentHashMap<>();\n//\t\t\t\t\tsession.putCommonSessionData(XMPPResourceConnection.ALL_RESOURCES_KEY,\n//\t\t\t\t\t\t\tresources);\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\tif (online) {\n//\t\t\t\tMap map = resources.get(packet.getStanzaFrom());\n//\n//\t\t\t\tif (map == null) {\n//\t\t\t\t\tmap = new ConcurrentHashMap();\n//\t\t\t\t\tresources.put(packet.getStanzaFrom(), map);\n//\t\t\t\t}\n//\n//\t\t\t\tString priorityStr = packet.getElemCDataStaticStr(PRESENCE_PRIORITY_PATH);\n//\n//\t\t\t\tif (priorityStr != null) {\n//\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY, Integer.parseInt(\n//\t\t\t\t\t\t\tpriorityStr));\n//\t\t\t\t} else if (!map.containsKey(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY)) {\n//\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_PRIORITY_KEY, 0);\n//\t\t\t\t}\n//\n//\t\t\t\tElement c = packet.getElement().getChild(\"c\", \"http://jabber.org/protocol/caps\");\n//\n//\t\t\t\tif (c != null) {\n//\t\t\t\t\tmap.put(XMPPResourceConnection.ALL_RESOURCES_CAPS_KEY,\n//\t\t\t\t\t\t\tPresenceCapabilitiesManager.processPresence(c));\n//\t\t\t\t}\n//\t\t\t} else {\n//\t\t\t\tresources.remove(packet.getStanzaFrom());\n//\t\t\t}\n//\t\t}\n//\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Returns shared instance of class implementing {@link RosterAbstract} -\n\t * either default one ({@link RosterFlat}) or the one configured with\n\t * <em>\"roster-implementation\"</em> property.\n\t *\n\t * @return shared instance of class implementing {@link RosterAbstract}\n\t */\n\tprotected static RosterAbstract getRosterUtil() {\n\t\treturn RosterFactory.getRosterImplementation(true);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\t\n\t/**\n\t * Method checks whether a given contact requires sending presence. In case of\n\t * enabling option {@code skipOffline} and user being offline in the roster\n\t * the presence is not sent. Alternatively enabling option\n\t * {@code skipOfflineSys} would cause local environment check for user status\n\t * and omit sending presence if the local use is offline.\n\t *\n\t *\n\t * @param roster      instance of class implementing {@link RosterAbstract}.\n\t * @param buddy       JID of a contact for which a check is to be performed.\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param systemCheck indicates whether the check should be only based on\n\t *                    local environment state ({@code true}) or rooster state\n\t *                    of given user should also be taken into consideration\n\t *                    ({@code false}).\n\t *\n\t * @return {code true} if the contact requires sending presence (e.g. is not\n\t *         online and options skipOffline or skipOfflineSys are enabled)\n\t *\n\t * @throws TigaseDBException\n\t * @throws NotAuthorizedException\n\t */\n\tprotected static boolean requiresPresenceSending(RosterAbstract roster, JID buddy,\n\t\t\tXMPPResourceConnection session, boolean systemCheck)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tboolean result = true;\n\n\t\t// if non-system check is enabled during broadcast of non-first initial\n\t\t// presence or offline presence\n\t\tif (!systemCheck) {\n\t\t\tboolean isOnline = roster.isOnline( session, buddy );\n\t\t\tif ( skipOffline && !isOnline ){\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"{0} | buddy: {1} is online: {2}\",\n\t\t\t\t\t\t\t\t\t new Object[] { session.getJID(), buddy, isOnline } );\n\t\t\t\t}\n\t\t\t\tresult = result && false;\n\t\t\t}\n\t\t}\n\t\tif (skipOfflineSys) {\n\t\t\tTigaseRuntime runtime = TigaseRuntime.getTigaseRuntime();\n\t\t\tboolean isJidOnline = runtime.isJidOnline( buddy );\n\n\t\t\tif ( runtime.hasCompleteJidsInfo()\n\t\t\t\t\t && session.isLocalDomain( buddy.getDomain(), false )\n\t\t\t\t\t && !isJidOnline ){\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"{0} | buddy: {1} is online (sys): {2}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { session.getJID(), buddy, isJidOnline } );\n\t\t\t\t}\n\t\t\t\tresult = result && false;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n} \n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PresenceCapabilitiesManager.java",
    "content": "/*\n * PresenceCapabilitiesManager.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ConcurrentSkipListSet;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.conf.Configurable;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Class description\n *\n *\n * @version        Enter version here..., 13/02/16\n * @author         Enter your name here...\n */\npublic class PresenceCapabilitiesManager {\n\tprivate static long idCounter = 0;\n\tprivate static Logger log     =\n\t\tLogger.getLogger(PresenceCapabilitiesManager.class.getName());\n\n\t// Map<capsNode,Set<feature>>\n\tprivate static final Map<String, String[]> nodeFeatures = new ConcurrentHashMap<String,String[]>(250);\n\tprivate static final ConcurrentMap<String,Set<String>> featureNodes = new ConcurrentHashMap<String,Set<String>>(250);\n\tprivate static final List<PresenceCapabilitiesListener> handlers =\n\t\tnew CopyOnWriteArrayList<PresenceCapabilitiesListener>();\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param capsNode\n\t * @param features\n\t */\n\tpublic static void setNodeFeatures(String capsNode, String[] features) {\n\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\tlog.log( Level.FINER, \"setting features for node = {0}, features = {1}\",\n\t\t\t\t\t\t\t new Object[] { capsNode, Arrays.asList( features ) } );\n\t\t}\n\t\tArrays.sort(features);\n\t\tnodeFeatures.put(capsNode, features);\n\t\tfor (String feature : features) {\n\t\t\tSet<String> caps = featureNodes.get(feature);\n\t\t\tif (caps == null) {\n\t\t\t\tSet<String> tmp = new CopyOnWriteArraySet<String>();\n\t\t\t\tcaps = featureNodes.putIfAbsent(feature, tmp);\n\t\t\t\tif (caps == null) {\n\t\t\t\t\tcaps = tmp;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcaps.add(capsNode);\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param capsNode\n\t *\n\t * \n\t */\n\tpublic static String[] getNodeFeatures(String capsNode) {\n\t\treturn nodeFeatures.get(capsNode);\n\t}\n\t\n\tpublic static Set<String> getNodesWithFeature(String feature) {\n\t\tSet<String> nodes = featureNodes.get(feature);\n\t\tif (nodes == null) {\n\t\t\treturn Collections.emptySet();\n\t\t} else {\n\t\t\treturn Collections.unmodifiableSet(nodes);\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param c\n\t *\n\t * \n\t */\n\tpublic static String[] processPresence(Element c) {\n\t\tSet<String> caps_nodes = null;\n\n\t\tif (c != null) {\n\t\t\tcaps_nodes = new HashSet<String>();\n\n\t\t\tString caps_node = c.getAttributeStaticStr(\"node\") + \"#\" +\n\t\t\t\t\t\t\t\t\t\t\t\t c.getAttributeStaticStr(\"ver\");\n\n\t\t\tcaps_nodes.add(caps_node);\n\t\t\tif ((c.getAttributeStaticStr(\"hash\") == null) &&\n\t\t\t\t\t(c.getAttributeStaticStr(\"ext\") != null)) {\n\t\t\t\tfor (String e : c.getAttributeStaticStr(\"ext\").split(\" \")) {\n\t\t\t\t\tcaps_nodes.add(c.getAttributeStaticStr(\"node\") + \"#\" + e);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn caps_nodes.toArray(new String[caps_nodes.size()]);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compJid\n\t * @param to\n\t * @param caps_nodes\n\t * @param results\n\t */\n\tpublic static void prepareCapsQueries(JID compJid, JID to, String[] caps_nodes,\n\t\t\t\t\tQueue<Packet> results) {\n\t\tif (caps_nodes != null) {\n\t\t\tfor (String caps_node : caps_nodes) {\n\t\t\t\tif (!nodeFeatures.containsKey(caps_node)) {\n\t\t\t\t\tresults.offer(prepareCapsQuery(to, compJid, caps_node));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compJid\n\t * @param to\n\t * @param caps_nodes\n\t * @param results\n\t */\n\tpublic static void prepareCapsQueriesEl(JID compJid, JID to, String[] caps_nodes,\n\t\t\t\t\tQueue<Element> results) {\n\t\tif (caps_nodes != null) {\n\t\t\tfor (String caps_node : caps_nodes) {\n\t\t\t\tif (!nodeFeatures.containsKey(caps_node)) {\n\t\t\t\t\tresults.offer(prepareCapsQueryEl(to, compJid, caps_node));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param compJid\n\t * @param p\n\t * @param results\n\t *\n\t * \n\t */\n\tpublic static String[] processPresence(JID compJid, Packet p, Queue<Packet> results) {\n\t\tElement c            = p.getElement().getChild(\"c\");\n\t\tSet<String> features = new HashSet<String>();\n\n\t\tif (c != null) {\n\t\t\tString caps_node = c.getAttributeStaticStr(\"node\") + \"#\" +\n\t\t\t\t\t\t\t\t\t\t\t\t c.getAttributeStaticStr(\"ver\");\n\n\t\t\t// String[] nFeatures = nodeFeatures.get(caps_node);\n\t\t\tif (!nodeFeatures.containsKey(caps_node)) {\n\t\t\t\tSet<String> caps_nodes = new HashSet<String>();\n\n\t\t\t\tcaps_nodes.add(caps_node);\n\t\t\t\tif ((c.getAttributeStaticStr(\"hash\") == null) &&\n\t\t\t\t\t\t(c.getAttributeStaticStr(\"ext\") != null)) {\n\t\t\t\t\tfor (String e : c.getAttributeStaticStr(\"ext\").split(\" \")) {\n\t\t\t\t\t\tcaps_nodes.add(c.getAttributeStaticStr(\"node\") + \"#\" + e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (String node : caps_nodes) {\n\t\t\t\t\tif (!nodeFeatures.containsKey(node)) {\n\t\t\t\t\t\tresults.offer(prepareCapsQuery(p.getFrom(), compJid, node));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn features.toArray(new String[features.size()]);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param to\n\t * @param from\n\t * @param node\n\t *\n\t * \n\t */\n\tpublic static Packet prepareCapsQuery(JID to, JID from, String node) {\n\t\tElement iq = prepareCapsQueryEl(to, from, node);\n\t\tfinal Iq iqPacket = new Iq(iq, from, to);\n\t\tiqPacket.setXMLNS( Packet.CLIENT_XMLNS);\n\n\t\treturn iqPacket;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param to\n\t * @param from\n\t * @param node\n\t *\n\t * \n\t */\n\tpublic static Element prepareCapsQueryEl(JID to, JID from, String node) {\n\t\tString id  = String.valueOf(idCounter++);\n\t\tElement iq = new Element(\"iq\", new String[] { \"from\", \"to\", \"id\", \"type\", Packet.XMLNS_ATT },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { from.toString(),\n\t\t\t\t\t\tto.toString(), id, \"get\", Packet.CLIENT_XMLNS });\n\t\tElement query = new Element(\"query\", new String[] { \"xmlns\", \"node\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"http://jabber.org/protocol/disco#info\",\n\t\t\t\t\t\tnode });\n\n\t\tiq.addChild(query);\n\n\t\treturn iq;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t */\n\tpublic static void processCapsQueryResponse(Packet packet) {\n\n\t\t// No need for checking to domain - processors and components should do this\n//  if (VHostManager.isLocalDomainOrComponent(packet.getStanzaTo().getDomain())) {\n\t\t\tElement query = packet.getElement().getChild(\"query\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"http://jabber.org/protocol/disco#info\");\n\n\t\t\tif (query != null) {\n\t\t\t\tif (packet.getType() == StanzaType.result) {\n\t\t\t\t\tif (query.getAttributeStaticStr(\"node\") == null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.finest(\"disco#info query without node attribute!\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tList<Element> ch = query.getChildren();\n\n\t\t\t\t\tif (ch != null) {\n\t\t\t\t\t\tSet<String> features = new ConcurrentSkipListSet<String>();\n\n\t\t\t\t\t\tfor (Element item : ch) {\n\t\t\t\t\t\t\tif (!\"feature\".equals(item.getName())) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfeatures.add(item.getAttributeStaticStr(\"var\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsetNodeFeatures(query.getAttributeStaticStr(\"node\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfeatures.toArray(new String[features.size()]));\n\t\t\t\t\t}\n\t\t\t\t}\n\n//      else if (packet.getType() == StanzaType.error && manager.getNodeFeatures(query.getAttribute(\"node\")) == null) {\n//          getInstance().setNodeFeatures(query.getAttribute(\"node\"), NULL_NODES);\n//      }\n//      return;\n\t\t}\n\n//  }\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param owner\n\t * @param from\n\t * @param capsNodes\n\t * @param results\n\t */\n\tpublic static void handlePresence(JID owner, JID from, String[] capsNodes,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tQueue<Packet> results) {\n\t\tif (capsNodes == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tList<PresenceCapabilitiesListener> handlers = PresenceCapabilitiesManager.handlers;\n\n\t\tfor (PresenceCapabilitiesListener handler : handlers) {\n\t\t\thandler.handlePresence(owner, from, capsNodes, results);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param handler\n\t */\n\tpublic static void registerPresenceHandler(PresenceCapabilitiesListener handler) {\n\t\thandlers.add(handler);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param handler\n\t */\n\tpublic static void unregisterPresenceHandler(PresenceCapabilitiesListener handler) {\n\t\thandlers.remove(handler);\n\t}\n\n\t//~--- inner interfaces -----------------------------------------------------\n\n\t/**\n\t * Interface description\n\t *\n\t *\n\t * @version        Enter version here..., 13/02/16\n\t * @author         Enter your name here...\n\t */\n\tpublic static interface PresenceCapabilitiesListener {\n\t\t/**\n\t\t * Method description\n\t\t *\n\t\t *\n\t\t * @param owner\n\t\t * @param sender\n\t\t * @param capsNodes\n\t\t * @param results\n\t\t */\n\t\tvoid handlePresence(JID owner, JID sender, String[] capsNodes, Queue<Packet> results);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PresenceOffline.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\nimport tigase.db.DBInitException;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPStopListenerIfc;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterElement;\nimport tigase.xmpp.impl.roster.RosterFlat;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventBusFactory;\nimport tigase.disteventbus.EventHandler;\nimport tigase.sys.TigaseRuntime;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.TimeZone;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport static tigase.xmpp.impl.roster.RosterAbstract.ROSTER;\n\n@Id(PresenceOffline.ID)\n@Handles({\n\t@Handle(path = { PresenceAbstract.PRESENCE_ELEMENT_NAME }, xmlns = PresenceAbstract.CLIENT_XMLNS),\n\t@Handle(path = { Iq.ELEM_NAME, Iq.QUERY_NAME }, xmlns = RosterAbstract.XMLNS)\n})\npublic class PresenceOffline extends PresenceAbstract implements XMPPStopListenerIfc {\n\n\tpublic static final String PRESENCE_REPO_CLASS_PROP_KEY = \"presence-repo-class\";\n\tpublic static final String PRESENCE_REPO_URI_PROP_KEY = \"presence-repo-uri\";\n\tpublic static final String CACHE_SIZE_PROP_KEY = \"cache-size\";\n\n\tprivate final int cacheSizeDef = 1000;\n\n\tprivate static final Logger log = Logger.getLogger( PresenceOffline.class.getCanonicalName() );\n\n\tprotected static final String ID = \"presence-offline\";\n\n\tprivate final SimpleParser parser = SingletonFactory.getParserInstance();\n\n\tprivate static final EnumSet<StanzaType> PRESENCE_SUB_CHANGE_TYPES = EnumSet.of( StanzaType.subscribed, StanzaType.unsubscribe, StanzaType.unsubscribed );\n\n\tprivate final String presenceSessionEventName = \"start-stop\";\n\n\tprivate UserRepository userRepository = null;\n\n\tprivate LRUConcurrentCache<BareJID, Element> presenceCache = null;\n\tprivate LRUConcurrentCache<BareJID, Map<BareJID, RosterElement>> rosterCache = null;\n\n\tprivate final static String LAST_OFFLINE_PRESENCE_KEY = \"last-offline-presence\";\n\tprivate final static String DELAY_STAMP_KEY = \"delay-stamp\";\n\n\tprivate final static String EVENTBUS_PRESENCE_SESSION_XMLNS = \"tigase:user:presence-session\";\n\n\tprivate final EventBus eventBus = EventBusFactory.getInstance();\n\tprivate final UserPresenceSessionEventHandler userPresenceSessionEventHandler = new UserPresenceSessionEventHandler();\n\n\tprivate final SimpleDateFormat formatter;\n\n\tboolean delayStamp = true;\n\n\t{\n\t\tthis.formatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tthis.formatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\n\n\t@Override\n\tpublic void init( Map<String, Object> settings ) throws TigaseDBException {\n\t\t// configuring static settings in common methods\n\n\t\tPresenceAbstract.initSettings( settings );\n\n\t\tString tmp;\n\n\t\ttmp = (String) settings.get( DELAY_STAMP_KEY );\n\t\tdelayStamp = ( tmp != null )\n\t\t\t\t\t\t\t\t ? Boolean.parseBoolean( tmp )\n\t\t\t\t\t\t\t\t : delayStamp;\n\t\tlog.log( Level.CONFIG,\n\t\t\t\t\t\t \"Adding offline presence delay stamp to: {0}\", delayStamp );\n\n\t\tpresenceCache = new LRUConcurrentCache<>( 10000 );\n\t\trosterCache = new LRUConcurrentCache<>( 10000 );\n\n\t\tString repo_uri = (String) settings.get( PRESENCE_REPO_URI_PROP_KEY );\n\t\tString repo_cls = (String) settings.get( PRESENCE_REPO_CLASS_PROP_KEY );\n\n\t\tif ( repo_uri == null ){\n\t\t\trepo_uri = System.getProperty( PRESENCE_REPO_URI_PROP_KEY );\n\t\t\tif ( repo_uri == null ){\n\t\t\t\trepo_uri = System.getProperty( RepositoryFactory.GEN_USER_DB_URI_PROP_KEY );\n\t\t\t}\n\t\t}\n\t\tif ( repo_cls == null ){\n\t\t\trepo_cls = System.getProperty( PRESENCE_REPO_CLASS_PROP_KEY );\n\t\t}\n\t\tif ( repo_uri != null ){\n\t\t\tMap<String, String> db_props = new HashMap<String, String>( 4 );\n\n\t\t\tfor ( Map.Entry<String, Object> entry : settings.entrySet() ) {\n\t\t\t\tdb_props.put( entry.getKey(), entry.getValue().toString() );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tuserRepository = RepositoryFactory.getUserRepository( repo_cls, repo_uri, db_props );\n\t\t\t} catch ( ClassNotFoundException | InstantiationException | IllegalAccessException | DBInitException ex ) {\n\t\t\t\tlog.log( Level.WARNING, \"Problem initializing connection to DB: \", ex );\n\t\t\t}\n\n\t\t}\n\n\t\tint cacheSize = cacheSizeDef;\n\n\t\tString cacheSizeStr = (String) settings.get( CACHE_SIZE_PROP_KEY );\n\t\tif ( cacheSizeStr != null ){\n\t\t\ttry {\n\t\t\t\tcacheSize = Integer.parseInt( cacheSizeStr );\n\t\t\t} catch ( NumberFormatException e ) {\n\t\t\t\tlog.log( Level.WARNING, \"Using default cache value: \" + cacheSize, e );\n\t\t\t}\n\t\t}\n\n\t\tpresenceCache = new LRUConcurrentCache<>( cacheSize );\n\t\trosterCache = new LRUConcurrentCache<>( cacheSize );\n\n\t\teventBus.addHandler( presenceSessionEventName, EVENTBUS_PRESENCE_SESSION_XMLNS, userPresenceSessionEventHandler );\n\t}\n\n\t@SuppressWarnings({ \"unchecked\", \"fallthrough\" })\n\t@Override\n\tpublic void process( final Packet packet, final XMPPResourceConnection session, final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String, Object> settings ) throws XMPPException {\n\n\t\t// if presence probe & user is offline -> send last offline presence\n\t\t// if presence unavailable - from that user - store presence & invalidate cache\n\t\t// if presence sub change or roster change -- invalidate roster cache\n\t\tif ( \"presence\".equals( packet.getElemName() ) ){\n\n\t\t\tif ( session == null\n\t\t\t\t\t && packet.getType() == StanzaType.probe\n\t\t\t\t\t && packet.getStanzaFrom() != null && packet.getStanzaTo() != null && !packet.getStanzaFrom().equals( packet.getStanzaTo() ) ){\n\n\t\t\t\tBareJID stanzaTo = packet.getStanzaTo() != null ? packet.getStanzaTo().getBareJID() : null;\n\t\t\t\tBareJID stanzaFrom = packet.getStanzaFrom() != null ? packet.getStanzaFrom().getBareJID() : null;\n\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Processing presence probe {0} to offline user: {1}\", new Object[] { packet, packet.getStanzaTo() } );\n\t\t\t\t}\n\n\t\t\t\tif ( stanzaTo != null && stanzaFrom != null ){\n\n\t\t\t\t\tif ( isSubscriptionValid( stanzaTo, stanzaFrom ) ){\n\n\t\t\t\t\t\tElement presence = presenceCache.get( stanzaTo );\n\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Retrieved presence from cache: {0}\", presence );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( presence == null ){\n\t\t\t\t\t\t\tpresence = loadPresenceFromRepo( stanzaTo );\n\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Retrieved presence from respository: {0}\", presence );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( presence != null ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tPacket p = Packet.packetInstance( presence.clone() );\n\t\t\t\t\t\t\t\tp.initVars( p.getStanzaFrom(), packet.getStanzaFrom() );\n\n\t\t\t\t\t\t\t\tresults.offer( p );\n\t\t\t\t\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\t\t\t\t\tlog.log( Level.WARNING, \"Error creating packet instance from presence: \" + presence, ex );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else if ( session != null && packet.getStanzaFrom() != null ){\n\n\t\t\t\tif ( PRESENCE_SUB_CHANGE_TYPES.contains( packet.getType() ) ){\n\n\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"Presence sub change - sending event to cleare cache {0}\", packet.getElement() );\n\t\t\t\t\t}\n\n\t\t\t\t\tsendEvent( \"roster\",\n\t\t\t\t\t\t\t\t\t\t packet.getStanzaFrom() != null ? packet.getStanzaFrom().getBareJID() : null,\n\t\t\t\t\t\t\t\t\t\t packet.getStanzaTo() != null ? packet.getStanzaTo().getBareJID() : null\n\t\t\t\t\t);\n\n\t\t\t\t} else if ( session.isUserId( packet.getStanzaFrom().getBareJID() )\n\t\t\t\t\t\t\t\t\t\t&& ( ( packet.getType() == null )\n\t\t\t\t\t\t\t\t\t\t\t\t || ( packet.getType() == StanzaType.available ) ) //\t\t\t\t\t\t\t\t\t\t&& !isNotOnlySession( session )\n\t\t\t\t\t\t){\n\n\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\tlog.log( Level.FINEST, \"Presence session: {0} started - sending event and removing data from repository, packet: \",\n\t\t\t\t\t\t\t\t\t\t new Object[] { session, packet }\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tsendEvent( \"presence\", session.getJID().getBareJID() );\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tuserRepository.removeData( packet.getStanzaFrom().getBareJID(), LAST_OFFLINE_PRESENCE_KEY );\n\t\t\t\t\t} catch ( TigaseDBException ex ) {\n\t\t\t\t\t\tlog.log( Level.WARNING, \"Error removing data from repository while starting new presence session\", ex );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t} else if ( packet.getType() == StanzaType.set\n\t\t\t\t\t\t\t\t&& packet.getElement().getXMLNSStaticStr( Iq.IQ_QUERY_PATH ) == RosterAbstract.XMLNS ){\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Roster change - updated roster cache, packet: {0}\", packet );\n\t\t\t}\n\n\t\t\tif ( packet.getStanzaFrom() != null ){\n\t\t\t\tfinal BareJID user = packet.getStanzaFrom().getBareJID();\n\t\t\t\tsendEvent( \"roster\", user );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stopped( XMPPResourceConnection session, Queue<Packet> results, Map<String, Object> settings ) {\n\n//\t\tif ( isNotOnlySession( session ) ){\n//\t\t\treturn;\n//\t\t}\n\t\t// Synchronization to avoid conflict with login/logout events\n\t\t// processed in the SessionManager asynchronously\n\t\tif ( session == null || !session.isAuthorized() ){\n\t\t\treturn;\n\t\t}\n\n\t\tsynchronized ( session ) {\n\n\t\t\tsendEvent( \"presence\", session.getjid().getBareJID() );\n\n\t\t\tfinal Element lastPresence = session.getPresence() != null ? session.getPresence().clone() : null;\n\t\t\tif ( lastPresence != null ){\n\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Session: {0} stopped, storing to repository last presence: {1}\", new Object[] { session, lastPresence } );\n\t\t\t\t}\n\n\t\t\t\tif ( delayStamp ){\n\t\t\t\t\tString stamp = null;\n\n\t\t\t\t\tsynchronized ( formatter ) {\n\t\t\t\t\t\tstamp = formatter.format( new Date() );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( stamp != null ){\n\t\t\t\t\t\tElement x = new Element( \"delay\", new String[] { \"stamp\", \"xmlns\" }, new String[] { stamp, \"urn:xmpp:delay\" } );\n\t\t\t\t\t\tlastPresence.addChild( x );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( !StanzaType.unavailable.toString().equals( lastPresence.getAttributeStaticStr( Packet.TYPE_ATT ) ) ){\n\t\t\t\t\tlastPresence.setAttribute( Packet.TYPE_ATT, StanzaType.unavailable.toString() );\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tuserRepository.setData( session.getjid().getBareJID(), LAST_OFFLINE_PRESENCE_KEY, lastPresence.toString() );\n\t\t\t\t} catch ( TigaseDBException ex ) {\n\t\t\t\t\tlog.log( Level.WARNING, \"Error storing last offline presence to repository: \" + lastPresence, ex );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected boolean isNotOnlySession( XMPPResourceConnection session ) {\n\t\tif ( TigaseRuntime.getTigaseRuntime().hasCompleteJidsInfo() && session != null ){\n\t\t\tfinal JID userJID = session.getjid();\n\t\t\tif ( TigaseRuntime.getTigaseRuntime().isJidOnline( userJID ) ){\n\t\t\t\t// ok, this use is still connected - don't update the repository just yet\n\t\t\t\tJID[] connectionIdsForJid = TigaseRuntime.getTigaseRuntime().getConnectionIdsForJid( userJID );\n\t\t\t\tif ( connectionIdsForJid != null && connectionIdsForJid.length > 0 ){\n\t\t\t\t\tif ( connectionIdsForJid.length != 1 || !connectionIdsForJid[0].equals( userJID ) ){\n\n\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\tlog.log( Level.FINEST, \"There are other user {0} sessions still active: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t new Object[] { session.getjid(), Arrays.asList( connectionIdsForJid ) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprotected boolean isSubscriptionValid( BareJID owner, BareJID contact ) {\n\t\tRosterAbstract.SubscriptionType buddy_subscr = null;\n\t\tMap<BareJID, RosterElement> roster = null;\n\n\t\tboolean result = false;\n\n\t\troster = rosterCache.get( owner );\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Checking user {0} subscription of {1}, present in cache: {2}\",\n\t\t\t\t\t\t\t new Object[] { owner, contact, roster != null } );\n\t\t}\n\n\t\tif ( roster == null ){\n\t\t\tString rosterString = null;\n\t\t\ttry {\n\t\t\t\trosterString = userRepository.getData( owner, ROSTER );\n\t\t\t} catch ( TigaseDBException ex ) {\n\t\t\t\tlog.log( Level.WARNING, \"Problem reading roster from DB: \", ex );\n\t\t\t}\n\n\t\t\tif ( rosterString != null ){\n\t\t\t\troster = new ConcurrentHashMap<BareJID, RosterElement>( 100, 0.25f, 1 );\n\t\t\t\tRosterFlat.parseRosterUtil( rosterString, roster, null );\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Loaded roster from DB: {0}\", roster );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( roster != null ){\n\t\t\tRosterElement rosterElement = roster.get( contact );\n\t\t\tbuddy_subscr = rosterElement.getSubscription();\n\t\t\tif ( buddy_subscr == null ){\n\t\t\t\tbuddy_subscr = RosterAbstract.SubscriptionType.none;\n\t\t\t}\n\t\t\tresult = roster_util.isSubscribedFrom( buddy_subscr );\n\t\t}\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"isSubscriptionValid, owner: {0}, contact: {1}, result: {2}\", new Object[] { owner, contact, result } );\n\t\t}\n\t\treturn result;\n\t}\n\n\tprotected Element loadPresenceFromRepo( BareJID stanzaTo ) {\n\t\tElement presence = null;\n\t\ttry {\n\t\t\tString presString = userRepository.getData( stanzaTo, LAST_OFFLINE_PRESENCE_KEY );\n\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\t\tQueue<Element> parsedElements = null;\n\t\t\tif ( presString != null ){\n\n\t\t\t\tchar[] data = presString.toCharArray();\n\t\t\t\tparser.parse( domHandler, data, 0, data.length );\n\t\t\t\tparsedElements = domHandler.getParsedElements();\n\t\t\t}\n\n\t\t\tif ( parsedElements != null && parsedElements.size() > 0 ){\n\t\t\t\tpresence = parsedElements.poll();\n\t\t\t\tpresenceCache.put( stanzaTo, presence );\n\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\tlog.log( Level.FINEST, \"Loaded presence: {0} and stored it in cache\", presence );\n\t\t\t\t}\n\t\t\t}\n\t\t} catch ( TigaseDBException ex ) {\n\t\t\tlog.log( Level.WARNING, \"Loading presence from repository failed!\", ex );\n\t\t}\n\t\treturn presence;\n\t}\n\n\tprivate class UserPresenceSessionEventHandler implements EventHandler {\n\n\t\tprivate final String[] JID_PATH = { presenceSessionEventName };\n\n\t\t@Override\n\t\tpublic void onEvent( String name, String xmlns, Element event ) {\n\n\t\t\tif ( !( presenceSessionEventName.equals( name ) && EVENTBUS_PRESENCE_SESSION_XMLNS.equals( xmlns ) ) ){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tList<Element> jidElements = event.getChildrenStaticStr( JID_PATH );\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Procesing userPresence event: {0} with following jids: {1}\", new Object[] { event, jidElements } );\n\t\t\t}\n\n\t\t\tif ( jidElements != null && !jidElements.isEmpty() ){\n\t\t\t\tfor ( Element jidElement : jidElements ) {\n\n\t\t\t\t\tString jidStr = jidElement != null ? jidElement.getCData() : null;\n\t\t\t\t\tif ( jidStr != null && jidElement != null ){\n\t\t\t\t\t\tBareJID jid = BareJID.bareJIDInstanceNS( jidStr );\n\n\t\t\t\t\t\tString actionStr = jidElement.getAttributeStaticStr( \"action\" );\n\t\t\t\t\t\tif ( actionStr != null ){\n\n\t\t\t\t\t\t\tswitch ( actionStr ) {\n\t\t\t\t\t\t\t\tcase \"presence\":\n\t\t\t\t\t\t\t\t\tpresenceCache.remove( jid );\n\t\t\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Clearing presence cache: {0}, remaining items: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { jidStr, presenceCache.size() } );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"roster\":\n\t\t\t\t\t\t\t\t\trosterCache.remove( jid );\n\t\t\t\t\t\t\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\t\t\t\t\t\t\tlog.log( Level.FINEST, \"Clearing roster cache: {0}, remaining items: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t new Object[] { jidStr, rosterCache.size() } );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void sendEvent( String action, BareJID... user ) {\n\t\tif ( user != null && user.length > 0 ){\n\n\t\t\tElement event = new Element( presenceSessionEventName, new String[] { \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t new String[] { EVENTBUS_PRESENCE_SESSION_XMLNS } );\n\t\t\tfor ( BareJID bareJID : user ) {\n\t\t\t\tif ( bareJID != null ){\n\t\t\t\t\tElement jidElement = new Element( \"jid\", bareJID.toString() );\n\t\t\t\t\tjidElement.addAttribute( \"action\", action );\n\t\t\t\t\tevent.addChild( jidElement );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST, \"Sending event: \" + event );\n\t\t\t}\n\n\t\t\teventBus.fire( event );\n\t\t}\n\n\t}\n\n\tprivate class LRUConcurrentCache<K, V> {\n\n\t\tprivate final Map<K, V> cache;\n\n\t\tpublic LRUConcurrentCache( final int maxEntries ) {\n\t\t\tthis.cache = new LinkedHashMap<K, V>( maxEntries, 0.75F, true ) {\n\t\t\t\tprivate static final long serialVersionUID = -1236481390177598762L;\n\n\t\t\t\t@Override\n\t\t\t\tprotected boolean removeEldestEntry( Map.Entry<K, V> eldest ) {\n\t\t\t\t\treturn size() > maxEntries;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tpublic void put( K key, V value ) {\n\t\t\tsynchronized ( cache ) {\n\t\t\t\tcache.put( key, value );\n\t\t\t}\n\t\t}\n\n\t\tpublic V get( K key ) {\n\t\t\tsynchronized ( cache ) {\n\t\t\t\treturn cache.get( key );\n\t\t\t}\n\t\t}\n\n\t\tpublic V remove( K key ) {\n\t\t\tsynchronized ( cache ) {\n\t\t\t\treturn cache.remove( key );\n\t\t\t}\n\t\t}\n\n\t\tpublic int size() {\n\t\t\treturn cache.size();\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"LRUConcurrentCache{\" + \"cache=\" + cache + '}';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PresenceState.java",
    "content": "/*\n * PresenceState.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.EnumSet;\nimport java.util.HashSet;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.osgi.ModulesManagerImpl;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\n\nimport tigase.stats.StatisticsList;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPStopListenerIfc;\n\nimport static tigase.xmpp.impl.PresenceAbstract.forwardPresence;\n\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\nimport tigase.xmpp.impl.roster.DynamicRoster;\nimport tigase.xmpp.impl.roster.RepositoryAccessException;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterAbstract.PresenceType;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\n\nimport static tigase.xmpp.impl.roster.RosterAbstract.FROM_SUBSCRIBED;\nimport static tigase.xmpp.impl.roster.RosterAbstract.TO_SUBSCRIBED;\n\nimport tigase.xmpp.impl.roster.RosterElement;\nimport tigase.xmpp.impl.roster.RosterFactory;\nimport tigase.xmpp.impl.roster.RosterRetrievingException;\n\n/**\n *\n * @author andrzej\n */\n@Id(PresenceState.ID)\n@Handles({\n\t@Handle(path = { PresenceAbstract.PRESENCE_ELEMENT_NAME }, xmlns = PresenceAbstract.CLIENT_XMLNS),\n\t@Handle(path = { Iq.ELEM_NAME, Iq.QUERY_NAME }, xmlns = RosterAbstract.XMLNS_LOAD)\n})\npublic class PresenceState extends PresenceAbstract implements XMPPStopListenerIfc {\n\n\t/**\n\t * <code>DIRECT_PRESENCE</code> is a key in temporary session data for the\n\t * collection of JIDs where direct presence was sent. To all these addresses\n\t * unavailable presence must be sent when user disconnects.\n\t */\n\tpublic static final String DIRECT_PRESENCE = \"direct-presences\";\n\n\tpublic static final String DISABLE_ROSTER_LAZY_LOADING_KEY = \"disable-roster-lazy-loading\";\n\t\n\tpublic static final String EXTENDED_PRESENCE_PROCESSORS_KEY = \"extended-presence-processors\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_BUD_SENT = \"offline-bud-sent\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_RES_SENT = \"offline-res-sent\";\n\n\t/** Field description */\n\tpublic static final String OFFLINE_ROSTER_LAST_SEEN_PROP_KEY =\n\t\t\t\"offline-roster-last-seen\";\n\t\n\t/**\n\t * key allowing setting global forwarding JID address.\n\t */\n\tpublic static final String PRESENCE_GLOBAL_FORWARD = \"presence-global-forward\";\n\t\n\tprivate static final Logger log = Logger.getLogger(PresenceState.class.getCanonicalName());\n\t\n\tprotected static final String   ID = \"presence-state\";\n\tprotected static int            HIGH_PRIORITY_PRESENCES_NO = 10;\n\tprivate static final long       MAX_DIRECT_PRESENCES_NO = 1000;\t\n\tprivate static final String[]   PRESENCE_C_PATH         = { PRESENCE_ELEMENT_NAME, \"c\" };\n\tprivate static final Set<StanzaType> TYPES = new HashSet<>(Arrays.asList(StanzaType.available, StanzaType.unavailable, StanzaType.probe, StanzaType.error, StanzaType.result, null));\n\t\t\n\t\n\tprivate String[]         offlineRosterLastSeen = null;\n\tprivate JID              presenceGLobalForward = null;\n\tprivate static boolean\t rosterLazyLoading       = true;\n\tprivate long             usersStatusChanges    = 0;\n\tprivate static final List<ExtendedPresenceProcessorIfc> extendedPresenceProcessors = new ArrayList<>();\n\n\t// ~--- methods --------------------------------------------------------------\n\t\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\t// configuring static settings in common methods\n\t\tPresenceAbstract.initSettings(settings);\n\t\t\n\t\tString tmp = null;\n\n\t\ttmp = (String) settings.get( OFFLINE_ROSTER_LAST_SEEN_PROP_KEY );\n\t\tif ( tmp != null ){\n\t\t\tif ( tmp.contains( \"off\" ) ){\n\t\t\t\tofflineRosterLastSeen = null;\n\t\t\t} else {\n\t\t\t\tofflineRosterLastSeen = tmp.split( \",\" );\n\t\t\t\tlog.log( Level.CONFIG, \"Loaded roster offline last seen config: {0}\", tmp );\n\t\t\t}\n//\t\t} else {\n//\t\t\tofflineRosterLastSeen = new String[] {\"*\"};\n//\t\t\tlog.config(\"No configuration found for Loaded roster offline last seen. - enabling for All clients\");\n\t\t}\n\t\t\n\t\ttmp = (String) settings.get(PRESENCE_GLOBAL_FORWARD);\n\t\tif (tmp != null) {\n\t\t\ttry {\n\t\t\t\tpresenceGLobalForward = JID.jidInstance(tmp);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tpresenceGLobalForward = null;\n\t\t\t\tlog.log(Level.WARNING, \"Presence global forward misconfiguration, cannot parse JID {0}\", tmp);\n\t\t\t}\n\t\t}\n\t\t\n\t\ttmp = (String) settings.get(DISABLE_ROSTER_LAZY_LOADING_KEY);\n\t\trosterLazyLoading = (tmp == null || !Boolean.parseBoolean(tmp));\n\n\t\ttmp = (String) settings.get(EXTENDED_PRESENCE_PROCESSORS_KEY);\n\n\t\tString[] extPresenceProcessorsClasses = tmp != null ? tmp.split( \",\") : null ;\n\n\t\tif ( extPresenceProcessorsClasses != null ){\n\t\t\tfor ( String clazz : extPresenceProcessorsClasses ) {\n\t\t\t\ttry {\n\t\t\t\t\tExtendedPresenceProcessorIfc processor = (ExtendedPresenceProcessorIfc) ModulesManagerImpl.getInstance().forName( clazz ).newInstance();\n\n\t\t\t\t\textendedPresenceProcessors.add( processor );\n\t\t\t\t\tlog.log(Level.CONFIG, \"Loadeded ExtendedPresenceProcessor: {0}\", processor.getClass());\n\n\t\t\t\t} catch ( ClassNotFoundException | InstantiationException | IllegalAccessException ex ) {\n\t\t\t\t\tLogger.getLogger(PresenceAbstract.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\t@Override\n\tpublic Set<StanzaType> supTypes() {\n\t\treturn TYPES;\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Performs processing of <em>presence</em> packets and calls different\n\t * methods for particular {@link PresenceType}\n\t *\n\t */\n\t@SuppressWarnings({ \"unchecked\", \"fallthrough\" })\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session, final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String, Object> settings) throws XMPPException {\n\t\tif (session == null) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is null, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (!session.isAuthorized()) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is not authorized, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\t\t\n\n\tif (packet.getElemName() == Iq.ELEM_NAME) {\n\t\t\t// here we process results of roster loading process requests\n\t\t\tboolean finishProcessing = true;\n\t\t\tswitch (packet.getType()) {\n\t\t\t\tcase result:\n\t\t\t\t\tsynchronized (session) {\n\t\t\t\t\t\tElement presEl = session.getPresence();\n\t\t\t\t\t\tif (presEl != null) {\n\t\t\t\t\t\t\tsession.removeSessionData(XMPPResourceConnection.PRESENCE_KEY);\n\t\t\t\t\t\t\tpresEl.removeAttribute(\"from\");\n\t\t\t\t\t\t\tpresEl.removeAttribute(\"to\");\n\t\t\t\t\t\t\tPacket pres = Packet.packetInstance(presEl, packet.getStanzaFrom(), packet.getStanzaTo());\n\t\t\t\t\t\t\tpres.setPacketFrom(packet.getPacketFrom());\n\t\t\t\t\t\t\tpres.setPacketTo(packet.getPacketTo());\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tprocessOutInitial(pres, session, results, settings, RosterAbstract.PresenceType.out_initial);\n\t\t\t\t\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\t\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\t\t\t\t\"Can not access user Roster, user session is not authorized yet: {0}\",\n\t\t\t\t\t\t\t\t\t\tpacket);\n\t\t\t\t\t\t\t\tlog.log(Level.FINEST, \"presence problem...\", e);\n\t\t\t\t\t\t\t} catch (TigaseDBException e) {\n\t\t\t\t\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for presence data: {0}\", e);\n\t\t\t\t\t\t\t}    // end of try-catch\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// ignore this\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (finishProcessing)\n\t\t\t\treturn;\n\t\t}\n\t\t\n\t\t\n\t\tsynchronized (session) {\n\t\t\ttry {\n\t\t\t\tRosterAbstract.PresenceType pres_type = roster_util.getPresenceType(session, packet);\n\n\t\t\t\tif (pres_type == null) {\n\t\t\t\t\tlog.log(Level.INFO, \"Invalid presence found: {0}\", packet);\n\n\t\t\t\t\treturn;\n\t\t\t\t}    // end of if (type == null)\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0} | {1} presence found: {2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { session.getBareJID().toString(), pres_type, packet });\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch (pres_type) {\n\t\t\t\tcase out_initial :\n\t\t\t\t\tprocessOutInitial(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase in_initial :\n\t\t\t\t\tprocessInInitial(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase in_probe :\n\t\t\t\t\tif (session.getPresence() == null) {\n\n\t\t\t\t\t\t// If the user has not yet sent initial presence then ignore the\n\t\t\t\t\t\t// probe.\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessInProbe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_probe :\n\t\t\t\t\tforwardPresence(results, packet, session.getJID());\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase error :\n\t\t\t\t\tprocessError(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (type)\n\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\"Can not access user Roster, user session is not authorized yet: {0}\",\n\t\t\t\t\t\tpacket);\n\t\t\t\tlog.log(Level.FINEST, \"presence problem...\", e);\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for presence data: {0}\", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stopped(XMPPResourceConnection session, Queue<Packet> results, Map<String,\n\t\t\tObject> settings) {\n\n\t\t// Synchronization to avoid conflict with login/logout events\n\t\t// processed in the SessionManager asynchronously\n\t\tsynchronized (session) {\n\n\t\t\t// According to the spec and logic actually offline status should\n\t\t\t// not be broadcasted if initial presence was not sent by the client.\n\t\t\ttry {\n\t\t\t\tif (session.getPresence() != null) {\n\n\t\t\t\t\t// If this was called without sending unavailable presence\n\t\t\t\t\t// we have to generate it on our own.\n\t\t\t\t\tElement pres = session.getPresence();\n\n\t\t\t\t\tif (!StanzaType.unavailable.toString().equals(pres.getAttributeStaticStr(Packet\n\t\t\t\t\t\t\t.TYPE_ATT))) {\n\t\t\t\t\t\tpres.setAttribute(Packet.TYPE_ATT, StanzaType.unavailable.toString());\n\t\t\t\t\t\tsession.setPresence(pres);\n\t\t\t\t\t}\n\t\t\t\t\tbroadcastOffline(session, results, settings, roster_util);\n\t\t\t\t\tupdateOfflineChange(session, results);\n\t\t\t\t} else {\n\t\t\t\t\tbroadcastDirectPresences(StanzaType.unavailable, session, results, null);\n\t\t\t\t}\n\t\t\t\troster_util.logout(session);\n\t\t\t} catch (NotAuthorizedException e) {\n\n\t\t\t\t// Do nothing, it may happen quite often when the user disconnects\n\t\t\t\t// before it authenticates.\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for offline message: \", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\t}\t\n\t\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void getStatistics(StatisticsList list) {\n\t\tsuper.getStatistics(list);\n\t\tlist.add(id(), USERS_STATUS_CHANGES, usersStatusChanges, Level.INFO);\n\t}\n\t\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t *\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param results     this a collection with packets which have been generated\n\t *                    as input packet processing results.\n\t * @param settings    this map keeps plugin specific settings loaded from the\n\t *                    Tigase server configuration.\n\t * @param roster_util instance of class implementing {@link RosterAbstract}.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic static void broadcastOffline(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract roster_util)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Preventing sending offline notifications more than once\n\t\tif (session.getSessionData(OFFLINE_BUD_SENT) != null) {\n\t\t\treturn;\n\t\t}\n\t\tsession.putSessionData(OFFLINE_BUD_SENT, OFFLINE_BUD_SENT);\n\n\t\tElement pres = session.getPresence();\n\n\t\tif (pres != null) {\n\t\t\tsendPresenceBroadcast(StanzaType.unavailable, session, FROM_SUBSCRIBED, results,\n\t\t\t\t\tpres, settings, roster_util);\n\t\t} else {\n\t\t\tbroadcastDirectPresences(StanzaType.unavailable, session, results, pres);\n\t\t}\n\t}\n\n\t/**\n\t * Add JID to collection of JIDs to which direct presence was sent. To all\n\t * these addresses unavailable presence must be sent when user disconnects.\n\t *\n\t * @param jid     to which direct presence was sent.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic static void addDirectPresenceJID(JID jid, XMPPResourceConnection session) {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif (direct_presences == null) {\n\t\t\tdirect_presences = new LinkedHashSet<JID>(10);\n\t\t\tsession.putSessionData(DIRECT_PRESENCE, direct_presences);\n\t\t}    // end of if (direct_presences == null)\n\t\tif (direct_presences.size() < MAX_DIRECT_PRESENCES_NO) {\n\t\t\tdirect_presences.add(jid);\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Added direct presence jid: {0}\", jid);\n\t\t}\n\t}\n\t\n\t/**\n\t * Remove JID from collection of JIDs to which direct presence was sent.\n\t *\n\t * @param jid     to which direct presence was sent.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tpublic static void removeDirectPresenceJID(JID jid, XMPPResourceConnection session) {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif (direct_presences != null) {\n\t\t\tdirect_presences.remove(jid);\n\t\t}    // end of if (direct_presences == null)\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Added direct presence jid: {0}\", jid);\n\t\t}\n\t}\t\n\t\n\t/**\n\t * {@code broadcastDirectPresences} broadcast a direct Presence from provided\n\t * {@code pres} {@link Element} object to the collection of JIDs stored in\n\t * temporary session data under key {@code DIRECT_PRESENCE}.\n\t *\n\t *\n\t * @param t       specifies type of the presence to be send.\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param pres    an Object of type {@link Element} holding Presence stanza to\n\t *                be sent.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected static void broadcastDirectPresences(StanzaType t,\n\t\t\tXMPPResourceConnection session, Queue<Packet> results, Element pres)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSet<JID> direct_presences = (Set<JID>) session.getSessionData(DIRECT_PRESENCE);\n\n\t\tif ((direct_presences != null) && (t != null) && (t == StanzaType.unavailable)) {\n\t\t\tfor (JID buddy : direct_presences) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Updating direct presence for: {0}\", buddy);\n\t\t\t\t}\n\n\t\t\t\tPacket pack = sendPresence(t, session.getJID(), buddy, results, pres);\n\n\t\t\t\tpack.setPriority(Priority.LOW);\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}      // end of if (direct_presence != null)\n\t}\n\t\n\tpublic static void rebroadcastPresence(XMPPResourceConnection session, Queue<Packet> results) throws NotAuthorizedException, TigaseDBException {\n\t\tElement presence = session.getPresence();\n\n\t\tif (presence == null ) {\n\t\t\t// user has not sent initial presence yet, ignore\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( ExtendedPresenceProcessorIfc processor : extendedPresenceProcessors ) {\n\t\t\tElement extendContent = processor.extend( session, results );\n\t\t\tif ( extendContent != null ){\n\t\t\t\t// avoid duplicate\n\t\t\t\tElement child = presence.getChild( extendContent.getName(), extendContent.getXMLNS() );\n\t\t\t\tif ( child != null ){\n\t\t\t\t\tpresence.removeChild( child );\n\t\t\t\t}\n\t\t\t\tpresence.addChild( extendContent );\n\t\t\t}\n\t\t}\n\t\t\n\t\tsendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results, presence, null, getRosterUtil());\n\n\t\tupdateUserResources(presence, session, results, false);\n\n//\t\tsendPresenceBroadcast( StanzaType.get, session, SUB_TO, results, presence, null, null );\n\t}\t\n\t\n\t/**\n\t * Process presence stanza of type Error. Allows errors sent from server to\n\t * user and ignore presence errors sent from the user.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processError(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType presenceType)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException {\n\n\t\t// Strategy change.\n\t\t// Now we allow all error presences sent to the user, but we just ignore\n\t\t// presence errors sent from the user\n\t\tif (session.isUserId(packet.getStanzaTo().getBareJID())) {\n\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\tresults.offer(result);\n\t\t} else {\n\n\t\t\t// Ignore....\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming initial presence (i.e. in the\n\t * receivers session manager).\n\t * <p>\n\t * It validates the packet (whether from is present or if it's a direct\n\t * presence to existing resource) and subsequently set received presence for\n\t * the contact that sent it.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInInitial(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType presenceType)\n\t\t\t\t\tthrows NoConnectionIdException, NotAuthorizedException, TigaseDBException {\n\t\tif (packet.getStanzaFrom() == null) {\n\n\t\t\t// That really happened already. It looks like a bug in tigase\n\t\t\t// let's try to catch it here....\n\t\t\tlog.log(Level.WARNING, \"Initial presence without from attribute set: {0}\", packet);\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If this is a direct presence to a resource which is already gone\n\t\t// Ignore it.\n\t\tString resource = packet.getStanzaTo().getResource();\n\n\t\tif ((resource != null) &&!resource.isEmpty()) {\n\t\t\tXMPPResourceConnection direct = session.getParentSession().getResourceForResource(\n\t\t\t\t\tresource);\n\n\t\t\tif (direct != null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Received direct presence from: {0} to: {1}\",\n\t\t\t\t\t\t\tnew Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\tpacket.getStanzaTo() });\n\t\t\t\t}\n\n\t\t\t\t// Send a direct presence to correct resource, otherwise ignore\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(direct.getConnectionId());\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Ignoring direct presence from: {0} to: {1}, resource gone.\",\n\t\t\t\t\t\t\tnew Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\tpacket.getStanzaTo() });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tboolean online = StanzaType.unavailable != packet.getType();\n\n\t\tbuddyOnline(session, packet.getStanzaFrom(), results, online);\n\t\tif (session.getPresence() == null) {\n\n\t\t\t// Just ignore, this user does not want to receive presence updates\n\t\t\treturn;\n\t\t}\n\n\t\tJID presBuddy = packet.getStanzaFrom().copyWithoutResource();\n\n\t\t// If other users are in 'to' or 'both' contacts, broadcast\n\t\t// their presences to all active resources\n\t\tElement dynItem;\n\n\t\ttry {\n\t\t\tdynItem = DynamicRoster.getBuddyItem(session, settings, presBuddy);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\t\t\tdynItem = null;\n\t\t}\n\t\tif ( roster_util.isSubscribedTo( session, presBuddy ) || ( dynItem != null ) ){\n\t\t\tRosterElement rel = roster_util.getRosterElement( session, presBuddy );\n\n\t\t\tif ( rel != null ){\n\t\t\t\trel.setLastSeen( System.currentTimeMillis() );\n\t\t\t}\n\t\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\t\tlog.log( Level.FINEST,\n\t\t\t\t\t\t\t\t \"Received initial presence, setting buddy: {0} online status to: {1}\",\n\t\t\t\t\t\t\t\t new Object[] { packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonline } );\n\t\t\t}\n\t\t}\n\t\tupdatePresenceChange(packet, session, results);\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming presence probe (i.e. in the\n\t * receivers session manager).\n\t * <p>\n\t * It validates whether the packet comes from a contact that has correct\n\t * subscription and responds with presence of all user's resources presences.\n\t *\n\t *\n\t * @param packet       packet is which being processed.\n\t * @param session      user session which keeps all the user session data and\n\t *                     also gives an access to the user's repository data.\n\t * @param results      this a collection with packets which have been\n\t *                     generated as input packet processing results.\n\t * @param settings     this map keeps plugin specific settings loaded from the\n\t *                     Tigase server configuration.\n\t * @param presenceType specifies type of the presence.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws PacketErrorTypeException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInProbe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType presenceType)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, PacketErrorTypeException {\n\t\tRosterAbstract.SubscriptionType buddy_subscr = null;\n\t\tElement          dynItem;\n\n\t\ttry {\n\t\t\tdynItem = DynamicRoster.getBuddyItem(session, settings, packet.getStanzaFrom());\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\t\t\tdynItem = null;\n\t\t}\n\t\tif (dynItem != null) {\n\t\t\tbuddy_subscr = RosterAbstract.SubscriptionType.both;\n\t\t} else {\n\t\t\tbuddy_subscr = roster_util.getBuddySubscription(session, packet.getStanzaFrom());\n\t\t}\n\t\tif (buddy_subscr == null) {\n\t\t\tbuddy_subscr = RosterAbstract.SubscriptionType.none;\n\t\t}    // end of if (buddy_subscr == null)\n\t\tif (roster_util.isSubscribedFrom(buddy_subscr)) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Received probe, setting buddy: {0} as online.\", packet\n\t\t\t\t\t\t.getStanzaFrom());\n\t\t\t}\n\n\t\t\t// Probe is usually without resource anyway, so probably more correct approach would\n\t\t\t// be to remove below.\n\t\t\tif (packet.getStanzaFrom().getResource() != null) {\n\t\t\t\troster_util.setOnline(session, packet.getStanzaFrom(), true);\n\t\t\t}\n\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\ttry {\n\t\t\t\t\tElement pres = conn.getPresence();\n\n\t\t\t\t\tif (pres != null) {\n\t\t\t\t\t\tJID to;\n\t\t\t\t\t\tif ( probeFullJID ){\n\t\t\t\t\t\t\tto = packet.getStanzaFrom();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tto = packet.getStanzaFrom().copyWithoutResource();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsendPresence( null, null, to, results, pres );\n\t\t\t\t\t\troster_util.setPresenceSent(session, packet.getStanzaFrom(), true);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Received probe, sending presence response to: {0}\",\n\t\t\t\t\t\t\t\t\tto);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (NotAuthorizedException | TigaseDBException e) {\n\n\t\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t\t// This catch is to make sure all other resources receive\n\t\t\t\t\t// notification.\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// acording to spec 4.3.2. Server Processing of Inbound Presence Probe\n\t\t\t// http://xmpp.org/rfcs/rfc6121.html#presence-probe-inbound\n\t\t\t// If the user's bare JID is in the contact's roster with a subscription\n\t\t\t// state other\n\t\t\t// than \"From\", \"From + Pending Out\", or \"Both\", then the contact's server\n\t\t\t// SHOULD return a presence stanza of type \"unsubscribed\"\n\t\t\tif (!isAllowedForPresenceProbe(session, packet.getStanzaFrom())) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Received probe, users bare JID: {0} is not in the roster. Responding with unsubscribed\",\n\t\t\t\t\t\t\tpacket.getStanzaFrom().getBareJID());\n\t\t\t\t}\n\t\t\t\tsendPresence(StanzaType.unsubscribed, session.getBareJID(), packet.getStanzaFrom()\n\t\t\t\t\t\t.getBareJID(), results, null);\n\t\t\t} else {\n\t\t\t\t// However, if a server receives a presence probe from a configured\n\t\t\t\t// domain of the server itself or another such trusted service, it MAY\n\t\t\t\t// provide presence information about the user to that entity.\n\t\t\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\t\t\tElement pres = conn.getPresence();\n\n\t\t\t\t\tif (pres != null) {\n\t\t\t\t\t\tsendPresence(null, null, packet.getStanzaFrom(),\n\t\t\t\t\t\t\t\tresults, pres);\n\t\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\t\tlog.log(Level.FINEST, \"Received probe, sending presence response to: {0}\",\n\t\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}    // end of if (roster_util.isSubscribedFrom(session, packet.getElemFrom()))\n\t}\n\n\n\t/**\n\t * Method is responsible for processing outgoing initial presence (i.e. in the\n\t * sender session manager).\n\t * <p>\n\t * Process packet accordingly whether it's a direct presence (forward it, add\n\t * to proper collection of JIDs to which a direct presence has been sent) or\n\t * regular presence. THe latter causes properly address the packet, store\n\t * presence within session data for subsequent use, and for the first\n\t * availability presence (in case there is no prior presence stored in user\n\t * session data) server sends probes to all contacts and pushes out all\n\t * pending subscription request or (if there i already presence stored in\n\t * session data) broadcast presence update to contacts.\n\t * <p>\n\t * If there is a JID forwarding set up, presence is also forwarded to\n\t * configured JID.\n\t *\n\t *\n\t * @param packet   packet is which being processed.\n\t * @param session  user session which keeps all the user session data and also\n\t *                 gives an access to the user's repository data.\n\t * @param results  this a collection with packets which have been generated as\n\t *                 input packet processing results.\n\t * @param settings this map keeps plugin specific settings loaded from the\n\t *                 Tigase server configuration.\n\t * @param type     specifies type of the presence.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutInitial(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Is it a direct presence to some entity on the network?\n\t\tif (packet.getStanzaTo() != null) {\n\n\t\t\t// Yes this is it, send direct presence\n\t\t\tresults.offer(packet.copyElementOnly());\n\n\t\t\t// If this is unavailable presence, remove jid from Set\n\t\t\t// otherwise add it to the Set\n\t\t\tif (packet.getType() == StanzaType.unavailable) {\n\t\t\t\tremoveDirectPresenceJID(packet.getStanzaTo(), session);\n\t\t\t} else {\n\t\t\t\taddDirectPresenceJID(packet.getStanzaTo(), session);\n\t\t\t}\n\t\t} else {\n\t\t\t++usersStatusChanges;\n\n\t\t\tboolean first = false;\n\n\t\t\tif (session.getPresence() == null) {\n\t\t\t\tfirst = true;\n\t\t\t}\n\t\t\tpacket.initVars(session.getJID(), packet.getStanzaTo());\n\t\t\tfinal Element presenceEl = packet.getElement();\n\n\t\t\tfor ( ExtendedPresenceProcessorIfc processor : extendedPresenceProcessors ) {\n\t\t\t\tElement extendContent = processor.extend( session, results );\n\t\t\t\tif ( extendContent != null ){\n\t\t\t\t\tpresenceEl.addChild( extendContent );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Store user presence for later time...\n\t\t\t// To send response to presence probes for example.\n\t\t\tsession.setPresence(presenceEl);\n\n\t\t\t// here we need to check if roster is loaded\n\t\t\tif (!rosterLazyLoading || roster_util.isRosterLoaded(session)) {\n\t\t\t\t// if it is already loaded then continue processing\n\t\t\t\t// Special actions on the first availability presence\n\t\t\t\tif ((packet.getType() == null) || (packet.getType() == StanzaType.available)) {\n\t\t\t\t\tsession.removeSessionData(OFFLINE_BUD_SENT);\n\t\t\t\t\tsession.removeSessionData(OFFLINE_RES_SENT);\n\t\t\t\t\tif (first) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsendRosterOfflinePresence(session, results);\n\t\t\t\t\t\t} catch (NotAuthorizedException | TigaseDBException | NoConnectionIdException ex) {\n\t\t\t\t\t\t\tlog.log(Level.INFO, \"Experimental code throws exception: \", ex);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Send presence probes to 'to' or 'both' contacts\n\t\t\t\t\t\tbroadcastProbe(session, results, settings);\n\n\t\t\t\t\t\t// Resend pending in subscription requests\n\t\t\t\t\t\tresendPendingInRequests(session, results);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Broadcast initial presence to 'from' or 'both' contacts\n\t\t\t\t\t\tsendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t results, presenceEl, settings, roster_util);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Broadcast initial presence to other available user resources\n\t\t\t\t\tupdateUserResources(presenceEl, session, results, first);\n\t\t\t\t} else {\n\t\t\t\t\tstopped(session, results, settings);\n\t\t\t\t}\n\n\t\t\t\t// Presence forwarding\n\t\t\t\tJID forwardTo = session.getDomain().getPresenceForward();\n\n\t\t\t\tif (forwardTo == null) {\n\t\t\t\t\tforwardTo = presenceGLobalForward;\n\t\t\t\t}\n\t\t\t\tif (forwardTo != null) {\n\t\t\t\t\tsendPresence(null, session.getJID(), forwardTo, results, presenceEl);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// if roster is not yet loaded we need to trigger roster load by Roster plugin\n\t\t\t\tElement iq = new Element(Iq.ELEM_NAME, new String[] { \"type\" }, new String[] { \"set\" });\n\t\t\t\tElement query = new Element(Iq.QUERY_NAME, new String[] { Iq.XMLNS_ATT }, new String[] { RosterAbstract.XMLNS_LOAD });\n\t\t\t\tiq.addChild(query);\n\t\t\t\tPacket loadCmd = Packet.packetInstance(iq, packet.getStanzaFrom(), packet.getStanzaTo());\n\t\t\t\tloadCmd.setPacketFrom(packet.getPacketFrom());\n\t\t\t\tloadCmd.setPacketTo(packet.getPacketTo());\n\t\t\t\tresults.add(loadCmd);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * Method sends back presence to contact while it becomes online (i.e. during\n\t * processing of incoming initial presence of the contact/buddy)\n\t *\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param buddy   {@link JID} of a roster element for which an online state\n\t *                will be set\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t * @param online  set whether given contact is online or offline\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void buddyOnline(XMPPResourceConnection session, JID buddy,\n\t\t\tQueue<Packet> results, boolean online)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\troster_util.setOnline(session, buddy, online);\n\t\tif (online && skipOffline &&!roster_util.presenceSent(session, buddy) && roster_util\n\t\t\t\t.isSubscribedFrom(session, buddy)) {\n\t\t\tElement pres = session.getPresence();\n\n\t\t\tif (pres != null) {\n\t\t\t\tsendPresence(null, null, buddy, results, pres);\n\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * <code>sendPresenceBroadcast</code> method broadcasts given presence to all\n\t * buddies from roster and to all users to which direct presence was sent.\n\t * Before sending presence method calls {@code  requiresPresenceSending()}\n\t * performing, if configured, both system and roster check to verify whether\n\t * presence needs to be sent.\n\t *\n\t * @param t           specifies type of the presence to be send.\n\t * @param session     user session which keeps all the user session data and\n\t *                    also gives an access to the user's repository data.\n\t * @param results     this a collection with packets which have been generated\n\t *                    as input packet processing results.\n\t * @param subscrs     an {@code EnumSet<SubscriptionType>} holding all\n\t *                    {@link SubscriptionType} to which a Presence should be\n\t *                    broadcast.\n\t * @param pres        an Object of type {@link Element} holding Presence\n\t *                    stanza to be sent.\n\t * @param settings    this map keeps plugin specific settings loaded from the\n\t *                    Tigase server configuration.\n\t * @param roster_util instance of class implementing {@link RosterAbstract}.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t * @throws TigaseDBException\n\t */\n\tpublic static void sendPresenceBroadcast(StanzaType t, XMPPResourceConnection session,\n\t\t\tEnumSet<RosterAbstract.SubscriptionType> subscrs, Queue<Packet> results, Element pres, Map<String,\n\t\t\tObject> settings, RosterAbstract roster_util)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Direct presence if any should be sent first\n\t\tbroadcastDirectPresences(t, session, results, pres);\n\n\t\tRosterAbstract roster = roster_util;\n\n\t\tif (roster == null) {\n\t\t\troster = RosterFactory.getRosterImplementation(true);\n\t\t}\n\n\t\tJID[] buddies = roster.getBuddies(session, subscrs);\n\n\t\ttry {\n\t\t\tbuddies = DynamicRoster.addBuddies(session, settings, buddies);\n\t\t} catch (RosterRetrievingException | RepositoryAccessException ex) {\n\n\t\t\t// Ignore, handled in the JabberIqRoster code\n\t\t}\n\t\tif (buddies != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, session.getBareJID() + \" | Buddies found: \" + Arrays\n\t\t\t\t\t\t.toString(buddies));\n\t\t\t}\n\n\t\t\tPriority pack_priority = Priority.PRESENCE;\n\t\t\tint      pres_cnt      = 0;\n\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tif (requiresPresenceSending(roster, buddy, session, false)) {\n\t\t\t\t\tPacket pack = sendPresence(t, session.getJID(), buddy, results, pres);\n\n\t\t\t\t\tif (pres_cnt == HIGH_PRIORITY_PRESENCES_NO) {\n\t\t\t\t\t\t++pres_cnt;\n\t\t\t\t\t\tpack_priority = Priority.LOWEST;\n\t\t\t\t\t}\n\t\t\t\t\tif (pack != null) {\n\t\t\t\t\t\tpack.setPriority(pack_priority);\n\t\t\t\t\t\troster.setPresenceSent(session, buddy, true);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST, session.getBareJID() +\n\t\t\t\t\t\t\t\t\" | Not sending presence to buddy: \" + buddy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"No buddies found!!!!\");\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * Method sends server generated presence unavailable for all buddies from the\n\t * roster with a custom status message.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @throws TigaseDBException\n\t * @throws NotAuthorizedException\n\t * @throws NoConnectionIdException\n\t */\n\t@SuppressWarnings(\"empty-statement\")\n\tprotected void sendRosterOfflinePresence(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException {\n\t\tif (offlineRosterLastSeen == null) {\n\t\t\tlog.finest(\"No clients specified in config, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tElement pres = session.getPresence();\n\n\t\tif (pres == null) {\n\t\t\tlog.finest(\"Presence not set yet, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tString node = pres.getAttributeStaticStr(PRESENCE_C_PATH, \"node\");\n\n\t\tif (node == null) {\n\t\t\tlog.finest(\"Presence node not set, skipping...\");\n\n\t\t\treturn;\n\t\t}\n\n\t\tboolean validClient = false;\n\t\tint     i           = 0;\n\n\t\tif ( offlineRosterLastSeen.length > 0 && !offlineRosterLastSeen[0].equals( \"*\" ) ){\n\t\t\twhile ( ( i < offlineRosterLastSeen.length ) && !( validClient |= node.contains(\n\t\t\t\t\tofflineRosterLastSeen[i++] ) ) );\n\t\t\tif ( !validClient ){\n\t\t\t\tlog.finest( \"Client does not match, skipping...\" );\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t// enabled for all clients\n\t\t}\n\n\t\tJID[] buddies = roster_util.getBuddies(session, TO_SUBSCRIBED);\n\n\t\tif (buddies != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Buddies found: {0}\", Arrays.toString(buddies));\n\t\t\t}\n\n\t\t\tPriority pack_priority = Priority.PRESENCE;\n\t\t\tint      pres_cnt      = 0;\n\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tList<Element> children = roster_util.getCustomChildren( session, buddy );\n\n\t\t\t\tif ( children != null && !children.isEmpty() ){\n\t\t\t\t\tPacket pack = sendPresence( StanzaType.unavailable, buddy, session.getJID(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tresults, null );\n\t\t\t\t\t\n\t\t\t\t\tif ( pres_cnt == HIGH_PRIORITY_PRESENCES_NO ){\n\t\t\t\t\t\t++pres_cnt;\n\t\t\t\t\t\tpack_priority = Priority.LOWEST;\n\t\t\t\t\t}\n\t\t\t\t\tpack.setPriority( pack_priority );\n\t\t\t\t\tpack.setPacketTo( session.getConnectionId() );\n\t\t\t\t\tfor ( Element child : children ) {\n\t\t\t\t\t\tpack.getElement().addChild( child );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}    // end of for (String buddy: buddies)\n\t\t}\n\t}\n\t\n\t/**\n\t * <code>updateOfflineChange</code> method broadcast off-line presence to all\n\t * other user active resources.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @exception NotAuthorizedException if an error occurs\n\t */\n\tprotected static void updateOfflineChange(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException {\n\n\t\t// Preventing sending offline notifications more than once\n\t\tif (session.getSessionData(OFFLINE_RES_SENT) != null) {\n\t\t\treturn;\n\t\t}\n\t\tsession.putSessionData(OFFLINE_RES_SENT, OFFLINE_RES_SENT);\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\ttry {\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"Update presence change to: {0}\", conn.getJID());\n\t\t\t\t}\n\t\t\t\tif ((conn != session) && (conn.isResourceSet()) &&!conn.getResource().equals(\n\t\t\t\t\t\tsession.getResource())) {\n\n\t\t\t\t\t// Send to old resource presence about new resource\n\t\t\t\t\tElement pres_update = new Element(PRESENCE_ELEMENT_NAME);\n\n\t\t\t\t\tpres_update.setAttribute(\"type\", StanzaType.unavailable.toString());\n\t\t\t\t\tpres_update.setXMLNS(XMLNS);\n\n\t\t\t\t\t// accroding to RFC1621, 4.5.2.  Server Processing of Outbound Unavailable Presence\n\t\t\t\t\t// this presece packet should be addressed to fullJID\n\t\t\t\t\tPacket pack_update = Packet.packetInstance( pres_update, session.getJID(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconn.getJID() );\n\n\t\t\t\t\tpack_update.setPacketTo(conn.getConnectionId());\n\t\t\t\t\tresults.offer(pack_update);\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\t\tlog.log(Level.FINER, \"Skipping presence update to: {0}\", conn.getJID());\n\t\t\t\t\t}\n\t\t\t\t}    // end of else\n\t\t\t} catch (NoConnectionIdException | NotAuthorizedException e) {\n\n\t\t\t\t// It might be quite possible that one of the user connections\n\t\t\t\t// is in state not allowed for sending presence, in such a case\n\t\t\t\t// none of user connections would receive presence.\n\t\t\t\t// This catch is to make sure all other resources receive notification.\n\t\t\t}\n\t\t}        // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\t/**\n\t * Sends out all pending subscription request during user log-in.\n\t *\n\t * @param session user session which keeps all the user session data and also\n\t *                gives an access to the user's repository data.\n\t * @param results this a collection with packets which have been generated as\n\t *                input packet processing results.\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic void resendPendingInRequests(XMPPResourceConnection session,\n\t\t\tQueue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tJID[] buddies = roster_util.getBuddies(session, RosterAbstract.PENDING_IN);\n\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tElement presence = new Element(PRESENCE_ELEMENT_NAME);\n\n\t\t\t\tpresence.setAttribute(\"type\", StanzaType.subscribe.toString());\n\t\t\t\tpresence.setXMLNS(XMLNS);\n\n\t\t\t\tPacket pres = Packet.packetInstance(presence, buddy, null);\n\n\t\t\t\tupdatePresenceChange(pres, session, results);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tprivate boolean isAllowedForPresenceProbe(XMPPResourceConnection session, JID jid) {\n\t\tif (jid == null)\n\t\t\treturn false;\n\t\t\n\t\treturn session.getDomain().isTrustedJID(jid);\n\t}\n\t\n\tpublic interface ExtendedPresenceProcessorIfc {\n\t\tElement extend( XMPPResourceConnection session, Queue<Packet> results );\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/PresenceSubscription.java",
    "content": "/*\n * PresenceSubscription.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\npackage tigase.xmpp.impl;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Packet;\nimport tigase.server.PolicyViolationException;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport static tigase.xmpp.impl.PresenceAbstract.forwardPresence;\n\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Id;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterAbstract.PresenceType;\n\nimport static tigase.xmpp.impl.roster.RosterAbstract.SUB_NONE;\n\n\n/**\n *\n * @author andrzej\n */\n@Id(PresenceSubscription.ID)\n@Handle(path = { PresenceAbstract.PRESENCE_ELEMENT_NAME }, xmlns = PresenceAbstract.CLIENT_XMLNS)\npublic class PresenceSubscription extends PresenceAbstract {\n\t\n\t/**\n\t * key allowing enabling automatic authorisation.\n\t */\n\tpublic static final String AUTO_AUTHORIZE_PROP_KEY = \"auto-authorize\";\n\t\n\tprivate static final Logger log = Logger.getLogger(PresenceSubscription.class.getCanonicalName());\n\tprivate static final Set<StanzaType> TYPES = new HashSet<>(Arrays.asList(StanzaType.subscribe, StanzaType.subscribed, StanzaType.unsubscribe, StanzaType.unsubscribed));\n\t\n\tprotected static final String ID = \"presence-subscription\";\n\t\n\t/**\n\t * variable holding setting regarding auto authorisation of items added to\n\t * user roset\n\t */\n\tprivate static boolean autoAuthorize = false;\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tautoAuthorize = Boolean.parseBoolean((String) settings.get(AUTO_AUTHORIZE_PROP_KEY));\n\t\tif (autoAuthorize) {\n\t\t\tlog.config(\n\t\t\t\t\t\"Automatic presence autorization enabled, results in less strict XMPP specs compatibility \");\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic Set<StanzaType> supTypes() {\n\t\treturn TYPES;\n\t}\n\t\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * <br><br>\n\t *\n\t * Performs processing of <em>presence</em> packets and calls different\n\t * methods for particular {@link PresenceType}\n\t *\n\t */\n\t@SuppressWarnings({ \"unchecked\", \"fallthrough\" })\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session, final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String, Object> settings) throws XMPPException {\n\t\tif (session == null) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is null, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (!session.isAuthorized()) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is not authorized, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Synchronization to avoid conflict with login/logout events\n\t\t// processed in the SessionManager asynchronously\n\t\tsynchronized (session) {\n\t\t\ttry {\n\t\t\t\tRosterAbstract.PresenceType pres_type = roster_util.getPresenceType(session, packet);\n\n\t\t\t\tif (pres_type == null) {\n\t\t\t\t\tlog.log(Level.INFO, \"Invalid presence found: {0}\", packet);\n\n\t\t\t\t\treturn;\n\t\t\t\t}    // end of if (type == null)\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"{0} | {1} presence found: {2}\",\n\t\t\t\t\t\t\t\t\tnew Object[] { session.getBareJID().toString(), pres_type, packet });\n\t\t\t\t}\n\n\t\t\t\t// All 'in' subscription presences must have a valid from address\n\t\t\t\tswitch (pres_type) {\n\t\t\t\tcase in_unsubscribe :\n\t\t\t\tcase in_subscribe :\n\t\t\t\tcase in_unsubscribed :\n\t\t\t\tcase in_subscribed :\n\t\t\t\t\tif (packet.getStanzaFrom() == null) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.fine(\"'in' subscription presence without valid 'from' address, \" +\n\t\t\t\t\t\t\t\t\t\"dropping packet: \" + packet);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (session.isUserId(packet.getStanzaFrom().getBareJID())) {\n\t\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\t\tlog.log(Level.FINE,\n\t\t\t\t\t\t\t\t\t\"''in'' subscription to myself, not allowed, returning \" +\n\t\t\t\t\t\t\t\t\t\"error for packet: \" + \"{0}\", packet);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"You can not subscribe to yourself.\", false));\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// as per http://xmpp.org/rfcs/rfc6121.html#sub\n\t\t\t\t\t// Implementation Note: When a server processes or generates an outbound\n\t\t\t\t\t// presence stanza of type \"subscribe\", \"subscribed\", \"unsubscribe\",\n\t\t\t\t\t// or \"unsubscribed\", the server MUST stamp the outgoing presence\n\t\t\t\t\t// stanza with the bare JID <localpart@domainpart> of the sending entity,\n\t\t\t\t\t// not the full JID <localpart@domainpart/resourcepart>.\n\t\t\t\t\t//\n\t\t\t\t\t// we enforce this rule also for incomming presence subscirption packets\n\t\t\t\t\tpacket.initVars( packet.getStanzaFrom().copyWithoutResource(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t session.getJID().copyWithoutResource() );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_subscribe :\n\t\t\t\tcase out_unsubscribe :\n\t\t\t\tcase out_subscribed :\n\t\t\t\tcase out_unsubscribed :\n\n\t\t\t\t\t// Check wheher the destination address is correct to prevent\n\t\t\t\t\t// broken/corrupted roster entries:\n\t\t\t\t\tif ((packet.getStanzaTo() == null) || packet.getStanzaTo().toString()\n\t\t\t\t\t\t\t.isEmpty()) {\n\t\t\t\t\t\tresults.offer(Authorization.JID_MALFORMED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"The destination address is incorrect.\", false));\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// According to RFC 3921 draft bis-3, both source and destination\n\t\t\t\t\t// addresses must be BareJIDs, handled by initVars(...)\n\t\t\t\t\tpacket.initVars(session.getJID().copyWithoutResource(), packet.getStanzaTo()\n\t\t\t\t\t\t\t.copyWithoutResource());\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tswitch (pres_type) {\n\t\t\t\tcase out_subscribe :\n\t\t\t\tcase out_unsubscribe :\n\t\t\t\t\tprocessOutSubscribe(packet, session, results, settings, pres_type);\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase out_subscribed :\n\t\t\t\tcase out_unsubscribed :\n\t\t\t\t\tprocessOutSubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_subscribe :\n\t\t\t\t\tprocessInSubscribe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_unsubscribe :\n\t\t\t\t\tprocessInUnsubscribe(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_subscribed :\n\t\t\t\t\tprocessInSubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase in_unsubscribed :\n\t\t\t\t\tprocessInUnsubscribed(packet, session, results, settings, pres_type);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Request type is incorrect\", false));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}    // end of switch (type)\n\t\t\t} catch (NotAuthorizedException e) {\n\t\t\t\tlog.log(Level.INFO,\n\t\t\t\t\t\t\"Can not access user Roster, user session is not authorized yet: {0}\",\n\t\t\t\t\t\tpacket);\n\t\t\t\tlog.log(Level.FINEST, \"presence problem...\", e);\n\t\t\t} catch ( PolicyViolationException e ) {\n\t\t\t\tlog.log( Level.FINE, \"Violation of roster items number policy: {0}\", packet );\n\t\t\t} catch (TigaseDBException e) {\n\t\t\t\tlog.log(Level.WARNING, \"Error accessing database for presence data: {0}\", e);\n\t\t\t}    // end of try-catch\n\t\t}\n\n\t}\n\t\n\t/**\n\t * Method is responsible for processing incoming subscription request (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * If the contact is already subscribed the an auto-reply with\n\t * type='subscribded' is sent, otherwise contact is added to the roster (if\n\t * it's missing/there is no current subscription), sets the subscription type\n\t * to {@code PresenceType.in_subscribe} and subsequently broadcast presence\n\t * update to all connected resources.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInSubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// If the buddy is already subscribed then auto-reply with subscribed\n\t\t// presence stanza.\n\t\tif (roster_util.isSubscribedFrom(session, packet.getStanzaFrom())) {\n\t\t\tsendPresence(StanzaType.subscribed, session.getJID().copyWithoutResource(), packet\n\t\t\t\t\t.getStanzaFrom(), results, null);\n\t\t} else {\n\t\t\tRosterAbstract.SubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t\t.getStanzaFrom());\n\n\t\t\tif (curr_sub == null) {\n\t\t\t\troster_util.addBuddy(session, packet.getStanzaFrom(), null, null, null);\n\t\t\t}    // end of if (curr_sub == null)\n\t\t\troster_util.updateBuddySubscription(session, pres_type, packet.getStanzaFrom());\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tupdatePresenceChange(packet, session, results);\n\t\t\t} else {\n\t\t\t\troster_util.setBuddySubscription(session, RosterAbstract.SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaFrom().copyWithoutResource());\n\t\t\t}\n\t\t}    // end of else\n\t\tif (autoAuthorize) {\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tpacket.getStanzaFrom().copyWithoutResource()));\n\t\t\tbroadcastProbe(session, results, settings);\n\t\t\tsendPresence(StanzaType.subscribed, session.getJID(), packet.getStanzaFrom(),\n\t\t\t\t\tresults, null);\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming subscribed presence (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * Contact is added to the roster (if it's missing/there is no current\n\t * subscription), sets the subscription type to\n\t * {@code PresenceType.in_subscribed} and subsequently, if subscription has\n\t * changed,forwards the presence to user resource connection as well as\n\t * broadcast presence update to all connected resources.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInSubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tRosterAbstract.SubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t.getStanzaFrom());\n\n\t\tif (!autoAuthorize && (curr_sub == null)) {\n\t\t\troster_util.addBuddy(session, packet.getStanzaFrom(), null, null, null);\n\t\t}    // end of if (curr_sub == null)\n\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tpacket.getStanzaFrom());\n\n\t\tif (subscr_changed) {\n\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\tresults.offer(forward_p);\n\t\t\tif (autoAuthorize) {\n\t\t\t\troster_util.setBuddySubscription(session, RosterAbstract.SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaFrom().copyWithoutResource());\n\t\t\t}\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tpacket.getStanzaFrom()));\n\n\t\t\tElement delay = packet.getElement().getChild( \"delay\", \"urn:xmpp:delay\");\n\t\t\tif (delay != null ) {\n\t\t\t\t// offline packet, lets send probe\n\t\t\t\tElement presProbe = prepareProbe( session );\n\t\t\t\tsendPresence( null, null, packet.getStanzaFrom(), results, presProbe );\n\t\t\t}\n\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming unsubscribe presence (i.e. in\n\t * the receivers session manager).\n\t * <p>\n\t * First method performs update of subscription of the given contact and\n\t * subsequently the request is forwarded to the client to make sure it says in\n\t * synch with the server (in case there was actual change in subscription).\n\t * Lastly a roster push is generated to all connected resources to update them\n\t * with current state of the roster and items subscriptions.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInUnsubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tpacket.getStanzaFrom());\n\n\t\tif (subscr_changed) {\n\n\t\t\t// First forward the request to the client to make sure it stays in sync\n\t\t\t// with the server. This should be done only in the case of actual change of the state\n\t\t\t// and with auto-authorization disabled\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\t\tresults.offer(forward_p);\n\t\t\t}\n\n\t\t\tElement item = roster_util.getBuddyItem(session, packet.getStanzaFrom());\n\n\t\t\tif (item != null) {\n\t\t\t\troster_util.updateBuddyChange(session, results, item);\n\t\t\t} else {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Received unsubscribe request from a user who is not in the roster: {0}\",\n\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (autoAuthorize) {\n\t\t\t\tbroadcastProbe(session, results, settings);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing incoming unsubscribed presence (i.e.\n\t * in the receivers session manager).\n\t * <p>\n\t * First method checks for the current subscription of the contact and if this\n\t * verifies performs subsequent actions such as forwarding presence to the\n\t * user connection to make sure it says in synch with the server, updates\n\t * contact subscription with {@code PresenceType.in_unsubscribed} and in case\n\t * that there was a change in user subscription send out a roster push to all\n\t * connected resources to update them with current state of the roster and\n\t * items subscriptions.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processInUnsubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\t\tRosterAbstract.SubscriptionType curr_sub = roster_util.getBuddySubscription(session, packet\n\t\t\t\t.getStanzaFrom());\n\n\t\tif (curr_sub != null) {\n\n\t\t\t// First forward the request to the client to make sure it stays in sync\n\t\t\t// with the server. This should be done only with auto-authorization disabled\n\t\t\tif (!autoAuthorize) {\n\t\t\t\tPacket forward_p = packet.copyElementOnly();\n\n\t\t\t\tforward_p.setPacketTo(session.getConnectionId());\n\t\t\t\tresults.offer(forward_p);\n\t\t\t}\n\n\t\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\t\tpacket.getStanzaFrom());\n\n\t\t\tif (subscr_changed) {\n\t\t\t\tElement item = roster_util.getBuddyItem(session, packet.getStanzaFrom());\n\n\t\t\t\t// The roster item could have been removed in the meantime....\n\t\t\t\tif (item != null) {\n\t\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(\n\t\t\t\t\t\t\tsession, packet.getStanzaFrom()));\n\t\t\t\t} else {\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\t\"Received unsubscribe request from a user who is not in the roster: {0}\",\n\t\t\t\t\t\t\t\tpacket.getStanzaFrom());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (autoAuthorize) {\n\t\t\t\t\tbroadcastProbe(session, results, settings);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * Method is responsible for processing outgoing subscribe and unsubscribe\n\t * presence (i.e. in the sender session manager).\n\t * <p>\n\t * Presence packet is forwarded to the destination with the JID stripped from\n\t * the resource.\n\t * <p>In case of {@code PresenceType.out_subscribe} packet type contact is\n\t * added to the roster (in case it was missing), a subscription state is being\n\t * updated and, in case there was a change, a roster push is being sent to all\n\t * user resources.\n\t * <p>\n\t * In case of {@code PresenceType.out_unsubscribe} method updates contact\n\t * subscription (and generates roster push if there was a change) and if the\n\t * resulting contact subscription is NONE then contact is removed from the\n\t * roster.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutSubscribe(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// According to RFC-3921 I must forward all these kind presence\n\t\t// requests, it allows to resynchronize\n\t\t// subscriptions in case of synchronization loss\n\t\tboolean subscr_changed = false;\n\n\t\tforwardPresence(results, packet, session.getJID().copyWithoutResource());\n\n\t\tRosterAbstract.SubscriptionType current_subscription = roster_util.getBuddySubscription(session,\n\t\t\t\tpacket.getStanzaTo());\n\n\t\tif (pres_type == RosterAbstract.PresenceType.out_subscribe) {\n\t\t\tif (current_subscription == null) {\n\t\t\t\troster_util.addBuddy(session, packet.getStanzaTo(), null, null, null);\n\t\t\t}    // end of if (current_subscription == null)\n\t\t\tsubscr_changed = roster_util.updateBuddySubscription(session, pres_type, packet\n\t\t\t\t\t.getStanzaTo());\n\t\t\tif (autoAuthorize) {\n\t\t\t\troster_util.setBuddySubscription(session, RosterAbstract.SubscriptionType.both, packet\n\t\t\t\t\t\t.getStanzaTo().copyWithoutResource());\n\t\t\t}\n\t\t\tif (subscr_changed) {\n\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\t\tpacket.getStanzaTo()));\n\t\t\t}    // end of if (subscr_changed)\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"out_subscribe: current_subscription = \" +\n\t\t\t\t\t\tcurrent_subscription);\n\t\t\t}\n\t\t\tif (current_subscription != null) {\n\t\t\t\tsubscr_changed = roster_util.updateBuddySubscription(session, pres_type, packet\n\t\t\t\t\t\t.getStanzaTo());\n\t\t\t\tcurrent_subscription = roster_util.getBuddySubscription(session, packet\n\t\t\t\t\t\t.getStanzaTo());\n\t\t\t\tif (subscr_changed) {\n\t\t\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(\n\t\t\t\t\t\t\tsession, packet.getStanzaTo()));\n\t\t\t\t}    // end of if (subscr_changed)\n\t\t\t\tif (SUB_NONE.contains(current_subscription)) {\n\t\t\t\t\troster_util.removeBuddy(session, packet.getStanzaTo());\n\t\t\t\t}    // end of if (current_subscription == null)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method is responsible for processing outgoing subscribed and unsubscribed\n\t * presence (i.e. in the sender session manager).\n\t * <p>\n\t * Presence packet is forwarded to the destination with the JID stripped from\n\t * the resource, a subscription state is being updated and, in case there was\n\t * a change, a roster push is being sent to all user resources. Also, in case\n\t * of presence type out_subscribed server send current presence to the user\n\t * from each of the contact's available resources. For the presence type\n\t * out_unsubscribed an unavailable presence is sent.\n\t *\n\t *\n\t * @param packet    packet is which being processed.\n\t * @param session   user session which keeps all the user session data and\n\t *                  also gives an access to the user's repository data.\n\t * @param results   this a collection with packets which have been generated\n\t *                  as input packet processing results.\n\t * @param settings  this map keeps plugin specific settings loaded from the\n\t *                  Tigase server configuration.\n\t * @param pres_type specifies type of the presence.\n\t *\n\t * @throws NoConnectionIdException\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tprotected void processOutSubscribed(Packet packet, XMPPResourceConnection session,\n\t\t\tQueue<Packet> results, Map<String, Object> settings, RosterAbstract.PresenceType pres_type)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException, PolicyViolationException {\n\n\t\t// According to RFC-3921 I must forward all these kind presence\n\t\t// requests, it allows to re-synchronize\n\t\t// subscriptions in case of synchronization loss\n\t\tforwardPresence(results, packet, session.getJID().copyWithoutResource());\n\n\t\tElement initial_presence = session.getPresence();\n\t\tJID     buddy            = packet.getStanzaTo().copyWithoutResource();\n\t\tboolean subscr_changed = roster_util.updateBuddySubscription(session, pres_type,\n\t\t\t\tbuddy);\n\n\t\tif (autoAuthorize && (pres_type == RosterAbstract.PresenceType.out_subscribed)) {\n\t\t\troster_util.setBuddySubscription(session, RosterAbstract.SubscriptionType.both, buddy\n\t\t\t\t\t.copyWithoutResource());\n\t\t}\n\t\tif (subscr_changed) {\n\t\t\troster_util.updateBuddyChange(session, results, roster_util.getBuddyItem(session,\n\t\t\t\t\tbuddy));\n\t\t\tif (initial_presence != null) {\n\t\t\t\tif (pres_type == RosterAbstract.PresenceType.out_subscribed) {\n\n\t\t\t\t\t// The contact's server MUST then also send current presence to the user\n\t\t\t\t\t// from each of the contact's available resources.\n\t\t\t\t\tList<XMPPResourceConnection> activeSessions = session.getActiveSessions();\n\n\t\t\t\t\tfor (XMPPResourceConnection userSessions : activeSessions) {\n\t\t\t\t\t\tElement presence = userSessions.getPresence();\n\n\t\t\t\t\t\tsendPresence(StanzaType.available, userSessions.getjid(), buddy, results,\n\t\t\t\t\t\t\t\tpresence);\n\t\t\t\t\t}\n\t\t\t\t\troster_util.setPresenceSent(session, buddy, true);\n\t\t\t\t} else {\n\t\t\t\t\tsendPresence(StanzaType.unavailable, session.getJID(), buddy, results, null);\n\t\t\t\t}\n\t\t\t}    // end of if (subscr_changed)\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/Privacy.java",
    "content": "/*\n * Privacy.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport tigase.db.TigaseDBException;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Queue;\n\n/**\n * Class defining data structure for privacy lists.\n * Sample data storage:\n * {@code\n * <node name=\"privacy\">\n *  <map>\n *   <entry value=\"private\" type=\"String\" key=\"default\"/>\n *  </map>\n *  List name:\n *  <node name=\"private\">\n *   <map/>\n *    Item order:\n *    <node name=\"1\">\n *     <map>\n *      <entry value=\"jid\" type=\"String\" key=\"type\"/>\n *      <entry value=\"user%40domain.com/res\" type=\"String\" key=\"value\"/>\n *      <entry value=\"deny\" type=\"String\" key=\"action\"/>\n *      <entry type=\"String[]\" key=\"stanzas\">\n *       <item value=\"message\"/>\n *       <item value=\"iq\"/>\n *      </entry>\n *     </map>\n *   </node>\n * </node>\n * }\n *\n * Created: Mon Oct  9 20:50:09 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class Privacy {\n\t/** Field description */\n\tpublic static final String ACTION = \"action\";\n\n\t/** Field description */\n\tpublic static final String ACTIVE = \"active-list\";\n\n\t/** Field description */\n\tpublic static final String DEFAULT = \"default-list\";\n\n\t/** Field description */\n\tpublic static final String ITEM = \"item\";\n\n\t/** Field description */\n\tpublic static final String LIST = \"list\";\n\n\t/** Field description */\n\tpublic static final String NAME = \"name\";\n\n\t/** Field description */\n\tpublic static final String ORDER = \"order\";\n\n\t/** Field description */\n\tpublic static final String PRIVACY = \"privacy\";\n\n\t/** Field description */\n\tpublic static final String PRIVACY_LIST = \"privacy-list\";\n\n\t/** Field description */\n\tpublic static final String STANZAS = \"stanzas\";\n\n\t/** Field description */\n\tpublic static final String TYPE = \"type\";\n\n\t/** Field description */\n\tpublic static final String VALUE = \"value\";\n\n\tpublic static final String PRIVACY_LIST_LOADED = \"privacy-lists-loaded\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(Privacy.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static void addList(XMPPResourceConnection session, Element list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Saving privacy list: {0}\", list);\n\t\t}\n\n\t\tString lNode = listNode(list.getAttributeStaticStr(NAME));\n\n\t\tsession.setData(lNode, PRIVACY_LIST, list.toString());\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static void removeList(XMPPResourceConnection session, Element list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Removing privacy list: {0}\", list);\n\t\t}\n\n\t\tString lNode = listNode(list.getAttributeStaticStr(NAME));\n\n\t\tsession.removeData(lNode, PRIVACY_LIST);\n\t\tsession.removeDataGroup(lNode);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t */\n\tpublic static Element getActiveList(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\treturn (Element) session.getSessionData(ACTIVE);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t */\n\tpublic static String getActiveListName(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tElement list = getActiveList(session);\n\n\t\tif (list != null) {\n\t\t\treturn list.getAttributeStaticStr(NAME);\n\t\t} else {\n\t\t\treturn null;\n\t\t}    // end of if (list != null) else\n\t}\n\n\t/**\n\t *\n\t * @param session\n\t * @return\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static Element getDefaultList(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tElement sessionDefaultList = (Element) session.getCommonSessionData( DEFAULT );\n\t\tif (session.getCommonSessionData(PRIVACY_LIST_LOADED) == null) {\n\t\t\tif ( sessionDefaultList == null ){\n\t\t\t\tString defaultListName = getDefaultListName( session );\n\t\t\t\tif ( defaultListName != null ){\n\t\t\t\t\tsessionDefaultList = Privacy.getList( session, defaultListName);\n\t\t\t\t\tif ( null != sessionDefaultList ){\n\t\t\t\t\t\tsession.putCommonSessionData( DEFAULT, sessionDefaultList );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsession.putCommonSessionData(PRIVACY_LIST_LOADED, PRIVACY_LIST_LOADED);\n\t\t}\n\t\treturn sessionDefaultList;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static String getDefaultListName(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn session.getData(PRIVACY, DEFAULT, null);\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param list\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static Element getList(XMPPResourceConnection session, String list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Loading privacy list: {0}\", list);\n\t\t}\n\n\t\tString lNode    = listNode(list);\n\t\tString list_str = session.getData(lNode, PRIVACY_LIST, null);\n\n\t\tif ((list_str != null) &&!list_str.isEmpty()) {\n\t\t\tSimpleParser parser          = SingletonFactory.getParserInstance();\n\t\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\t\tparser.parse(domHandler, list_str.toCharArray(), 0, list_str.length());\n\n\t\t\tQueue<Element> elems = domHandler.getParsedElements();\n\t\t\tElement result       = elems.poll();\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Loaded privacy list: {0}\", result);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\treturn getListOld(session, list);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param list\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static Element getListOld(XMPPResourceConnection session, String list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tString lNode   = listNode(list);\n\t\tString[] items = session.getDataGroups(lNode);\n\n\t\tif ( items != null && list != null ){\n\t\t\tElement eList = new Element( LIST, new String[] { NAME }, new String[] { list } );\n\n\t\t\tfor (String item : items) {\n\t\t\t\tString iNode     = lNode + \"/\" + item;\n\t\t\t\tString type      = session.getData(iNode, TYPE, null);\n\t\t\t\tString value     = session.getData(iNode, VALUE, null);\n\t\t\t\tString action    = session.getData(iNode, ACTION, null);\n\t\t\t\tString[] stanzas = session.getDataList(iNode, STANZAS);\n\n\t\t\t\tif ((item == null) || (action == null)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tElement eItem = new Element(ITEM, new String[] { ORDER, ACTION },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { item,\n\t\t\t\t\t\t\t\taction });\n\n\t\t\t\tif (type != null) {\n\t\t\t\t\teItem.addAttribute(TYPE, type);\n\t\t\t\t}      // end of if (type != null)\n\t\t\t\tif (value != null) {\n\t\t\t\t\teItem.addAttribute(VALUE, value);\n\t\t\t\t}      // end of if (value != null)\n\t\t\t\tif (stanzas != null) {\n\t\t\t\t\tfor (String stanza : stanzas) {\n\t\t\t\t\t\teItem.addChild(new Element(stanza));\n\t\t\t\t\t}    // end of for (String stanza: stanzas)\n\t\t\t\t}      // end of if (stanzas != null)\n\t\t\t\teList.addChild(eItem);\n\t\t\t}        // end of for (String item: items)\n\n\t\t\treturn eList;\n\t\t}          // end of if (items != null)\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t *\n\t *\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static String[] getLists(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn session.getDataGroups(PRIVACY);\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param list\n\t *\n\t *\n\t */\n\tpublic static String listNode(final String list) {\n\t\treturn PRIVACY + \"/\" + list;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param lName\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static void setActiveList(XMPPResourceConnection session, String lName)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif (lName == null) {\n\n\t\t\t// User declines to use current actiev list\n\t\t\tsession.removeSessionData( ACTIVE );\n\t\t} else {\n\n\t\t\t// User selects a different active list\n\t\t\tElement list = getList(session, lName);\n\n\t\t\tif (list != null) {\n\t\t\t\tsession.putSessionData(ACTIVE, list);\n\t\t\t} else {\n\t\t\t\tlog.log(\n\t\t\t\t\t\tLevel.INFO,\n\t\t\t\t\t\t\"Setting active list to null, do something better than that, perhaps notify user.\");\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param list\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static void setDefaultList(XMPPResourceConnection session, Element list)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tif ((list != null) && (list.getAttributeStaticStr(NAME) != null)) {\n\t\t\tsession.setData(PRIVACY, DEFAULT, list.getAttributeStaticStr(NAME));\n\t\t\tsession.putCommonSessionData( DEFAULT, list);\n\t\t} else {\n\t\t\tsession.removeData(PRIVACY, DEFAULT);\n\t\t\tsession.removeCommonSessionData( DEFAULT );\n\t\t}\n\t}\n\n\tpublic static List<String> getBlocked(XMPPResourceConnection session) throws NotAuthorizedException, TigaseDBException {\n\t\tElement list = getDefaultList(session);\n\t\tList<String> ulist = null;\n\t\tif(list != null) {\n\t\t\tulist = list.mapChildren(item -> isBlockItem(item), item -> item.getAttributeStaticStr(VALUE));\n\t\t}\n\t\treturn ulist;\t\t\t\t\n\t}\n\t\n\tpublic static boolean block(XMPPResourceConnection session, String jid) throws NotAuthorizedException, TigaseDBException {\n\t\tString name = getDefaultListName(session);\n\t\tif(name == null) {\n\t\t\tname = \"default\";\n\t\t}\n\t\tElement list = getList(session,name);\t\t\t\n\t\tif(list != null) {\n\t\t\tif (list.findChild(item -> jid.equals(item.getAttributeStaticStr(VALUE)) && isBlockItem(item)) != null)\n\t\t\t\treturn false;\n\t\t}\n\t\tElement list_new = new Element(LIST,new String[]{NAME},new String[]{name});\t\t\n\t\tlist_new.addChild(new Element(ITEM,new String[]{TYPE,ACTION,VALUE,ORDER},new String[]{\"jid\",\"deny\",jid,\"0\"}));\n\t\tif (list != null) {\n\t\t\tList<Element> items = list.getChildren();\n\t\t\tif (items != null) {\n\t\t\t\tCollections.sort(items, JabberIqPrivacy.compar);\n\t\t\t\tfor (int i = 0; i < items.size(); i++) {\n\t\t\t\t\titems.get(i).setAttribute(ORDER, \"\" + (i + 1));\n\t\t\t\t}\n\t\t\t\tlist_new.addChildren(items);\n\t\t\t}\n\t\t}\n\t\tupdateList(session, name, list_new);\n\t\treturn true;\n\t}\n\t\n\tpublic static boolean unblock(XMPPResourceConnection session, String jid) throws NotAuthorizedException, TigaseDBException {\n\t\tString name = getDefaultListName(session);\n\t\tElement list = getList(session,name);\n\t\tif(list == null)\n\t\t\treturn false;\n\t\t\n\t\tElement list_new = new Element(LIST,new String[]{NAME},new String[]{name});\t\n\t\tList<Element> items = list.findChildren(item -> !jid.equals(item.getAttributeStaticStr(VALUE)) || !isBlockItem(item));\n\t\tif (items != null) {\n\t\t\tCollections.sort(items, JabberIqPrivacy.compar);\n\t\t\tfor (int i = 0; i < items.size(); i++) {\n\t\t\t\titems.get(i).setAttribute(ORDER, \"\" + (i + 1));\n\t\t\t}\n\t\t\tlist_new.addChildren(items);\n\t\t}\n\t\n\t\tupdateList(session, name, list_new);\n\t\t\n\t\treturn false;\t\t\n\t}\n\n\tpublic static List<String> unblockAll(XMPPResourceConnection session) throws NotAuthorizedException, TigaseDBException {\n\t\tString name = getDefaultListName(session);\n\t\tElement list = getList(session,name);\n\t\tif(list == null)\n\t\t\treturn null;\n\n\t\tList<String> ulist = list.mapChildren(item -> isBlockItem(item), item -> item.getAttributeStaticStr(VALUE));\n\t\t\n\t\tElement list_new = new Element(LIST,new String[]{NAME},new String[]{name});\t\t\t\n\t\tList<Element> items = list.findChildren(item -> !isBlockItem(item));\n\t\tif (items != null) {\n\t\t\tCollections.sort(items, JabberIqPrivacy.compar);\n\t\t\tfor (int i = 0; i < items.size(); i++) {\n\t\t\t\titems.get(i).setAttribute(ORDER, \"\" + (i + 1));\n\t\t\t}\n\t\t\tlist_new.addChildren(items);\n\t\t}\n\t\n\t\tupdateList(session, name, list_new);\n\t\t\n\t\treturn ulist;\t\t\t\t\n\t}\t\n\t\n\tprivate static void updateList(XMPPResourceConnection session, String name, Element list_new) throws NotAuthorizedException, TigaseDBException {\n\t\taddList(session,list_new);\n\t\tPrivacy.setDefaultList(session, list_new);\n\t\tif(getDefaultList(session) == null) {\n\t\t\tPrivacy.setActiveList(session, name);\n\t\t}\n\t\telse if(name.equals(getActiveListName(session))) {\n\t\t\tsession.putCommonSessionData(ACTIVE, list_new);\n\t\t\tsession.putSessionData(ACTIVE, list_new);\n\t\t}\t\t\n\t}\n\t\n\tprivate static boolean isBlockItem(Element item) {\n\t\treturn \"jid\".equals(item.getAttributeStaticStr(TYPE)) && \"deny\".equals(item.getAttributeStaticStr(ACTION)) && item.getChildren() == null;\n\t}\n\t\n}    // Privacy\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/RemoteRosterManagement.java",
    "content": "/*\n * RemoteRosterManagement.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.form.*;\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Set;\n\n/**\n *\n * @author andrzej\n */\npublic class RemoteRosterManagement\n\t\t\t\textends XMPPProcessorAbstract {\n\tprivate static final String[][] ELEMENT_PATHS = {{ \"iq\", \"query\" }, { \"message\", \"x\" }};\n\tprivate static final String ID                = \"remote-roster-management\";\n\tprivate static final Logger log               =\n\t\tLogger.getLogger(\"eu.hilow.xtigase.server.xmpp.RemoteRosterManagement\");\n\tprivate static final String XMLNS             = \"http://spectrum.im/protocol/remote-roster\";\n\tprivate static final String[] XMLNSS          = { XMLNS, \"jabber:x:data\" };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo,\n\t\t\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getElemName() == \"message\") {\n\t\t\ttry {\n\t\t\t\tprocessMessageFormResponse(packet, session, repo, results);\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tresults.offer(Authorization.FORBIDDEN.getResponseMessage(packet, null, false));\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\t\tnull, true));\n\t\t\t}\n\t\t} else {\n\t\t\tresults.offer(packet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {}\n\n\t@Override\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getElemName() == \"iq\") {\n\t\t\tprocessIq(packet, session, repo, results, settings);\n\t\t} else {\n\t\t\tsuper.processToUserPacket(packet, session, repo, results, settings);\n\t\t}\n\t}\n\n\tprivate void processIq(Packet packet, XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\t\t\t\t\t\t\t\t\t\t Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tElement query = packet.getElement().getChild(\"query\",\n\t\t\t\t\t\t\t\t\t\t\t\"http://spectrum.im/protocol/remote-roster\");\n\n\t\tif (query == null) {\n\t\t\tsuper.processToUserPacket(packet, session, repo, results, settings);\n\n\t\t\t// log.warn(\"processing IQ with bad query = {}\", packet.toString());\n\t\t\treturn;\n\t\t}\n\t\tswitch (packet.getType()) {\n\t\tcase set :\n\t\t\tif (\"request\".equals(query.getAttributeStaticStr(Packet.TYPE_ATT))) {\n\t\t\t\tJID from    = JID.jidInstanceNS(packet.getStanzaTo().getDomain());\n\t\t\t\tElement msg = new Element(tigase.server.Message.ELEM_NAME);\n\n\t\t\t\tmsg.setAttribute(Packet.FROM_ATT, from.toString());\n\t\t\t\tmsg.setAttribute(Packet.TO_ATT, packet.getStanzaTo().toString());\n\n\t\t\t\tForm form = new Form(Packet.FROM_ATT, \"Roster change permission\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t packet.getStanzaFrom().getBareJID().toString() +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \" wants to edit your roster with following reason: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t query.getAttributeStaticStr(\"reason\") +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \". Do you want to allow it?\");\n\n\t\t\t\tform.addField(Field.fieldHidden(\"FORM_TYPE\", XMLNS));\n\t\t\t\tform.addField(Field.fieldHidden(\"jid\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpacket.getStanzaFrom().getBareJID().toString()));\n\t\t\t\tform.addField(Field.fieldBoolean(\"answer\", true, \"Allow roster edit\"));\n\t\t\t\tmsg.addChildren(Collections.singletonList(form.getElement()));\n\n\t\t\t\tPacket resp = Packet.packetInstance(msg, from, packet.getStanzaTo());\n\n\t\t\t\tresults.offer(resp);\n\t\t\t} else {\n\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Unknown request type\", false));\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, \"Bad request\",\n\t\t\t\t\t\t\ttrue));\n\t\t}\n\t}\n\n\tprivate void processMessageFormResponse(Packet packet, XMPPResourceConnection session,\n\t\t\t\t\tNonAuthUserRepository repo, Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tElement x = packet.getElement().getChild(\"x\");\n\n\t\tif (x != null) {\n\t\t\tForm form        = new Form(x);\n\t\t\tif (!XMLNS.equals(form.getAsString(\"FORM_TYPE\")) \n\t\t\t\t\t&& !session.isLocalDomain(packet.getStanzaTo().toString(), false)) {\t\t\t\t\n\t\t\t\tresults.offer(packet);\n\t\t\t}\n\t\t\tJID jid          = JID.jidInstanceNS(form.get(\"jid\").getValue());\n\t\t\tBoolean answer   = false;\n\t\t\tString answerStr = form.get(\"answer\").getValue();\n\n\t\t\tif (\"true\".equals(answerStr) || \"1\".equals(answerStr)) {\n\t\t\t\tanswer = true;\n\t\t\t}\n\t\t\tsynchronized (session) {\n\t\t\t\tSet<JID> allowed = getAllowed(session);\n\n\t\t\t\t// Apply result of form\n\t\t\t\tif (answer) {\n\t\t\t\t\tallowed.add(jid);\n\t\t\t\t} else {\n\t\t\t\t\tallowed.remove(jid);\n\t\t\t\t}\n\t\t\t\tsetAllowed(session, allowed);\n\t\t\t}\n\n\t\t\t// Notify remote jid about answer\n\t\t\tElement iq = new Element(\"iq\");\n\n\t\t\tiq.setAttribute(\"from\", packet.getStanzaFrom().getBareJID().toString());\n\t\t\tiq.setAttribute(\"to\", jid.toString());\n\n\t\t\tElement query = new Element(\"query\");\n\n\t\t\tquery.setAttribute(\"xmlns\", XMLNS);\n\t\t\tquery.setAttribute(\"type\", answer\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ? \"allowed\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t : \"rejected\");\n\t\t\tiq.addChildren(Collections.singletonList(query));\n\t\t\tresults.offer(Packet.packetInstance(iq,\n\t\t\t\t\t\t\tpacket.getStanzaFrom().copyWithoutResource(), jid));\n\t\t} else {\n\t\t\tresults.offer(packet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENT_PATHS;\n\t}\n\t\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate static Set<JID> getAllowed(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Get set of allowed jids\n\t\tsynchronized (session) {\n\t\t\tSet<JID> allowed = (Set<JID>) session.getCommonSessionData(\"remote-roster-allowed\");\n\n\t\t\tif (allowed == null) {\n\t\t\t\tString data = session.getData(\"remote-roster-management\", \"allowed\", null);\n\n\t\t\t\tallowed = new HashSet<JID>();\n\t\t\t\tif (data != null) {\n\t\t\t\t\tif (data.contains(\"/\")) {\n\t\t\t\t\t\tString[] jidsStr = data.split(\"/\");\n\n\t\t\t\t\t\tfor (String jidStr : jidsStr) {\n\t\t\t\t\t\t\tif (jidStr.length() > 0) {\n\t\t\t\t\t\t\t\tallowed.add(JID.jidInstanceNS(jidStr));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tallowed.add(JID.jidInstanceNS(data));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsession.putCommonSessionData(\"remote-roster-allowed\", allowed);\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"read list of jids allowed to modify roster = {0}\",\n\t\t\t\t\t\t\t\t\tallowed);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn allowed;\n\t\t}\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\tprivate static void setAllowed(XMPPResourceConnection session, Set<JID> allowed)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// Save set of allowed jids\n\t\tStringBuilder buf = new StringBuilder(1024);\n\n\t\tsession.putCommonSessionData(\"remote-roster-allowed\", allowed);\n\n\t\tboolean first = true;\n\n\t\tfor (JID jid : allowed) {\n\t\t\tif (!first) {\n\t\t\t\tbuf.append(\"/\");\n\t\t\t} else {\n\t\t\t\tfirst = false;\n\t\t\t}\n\t\t\tbuf.append(jid.toString());\n\t\t}\n\t\tsession.setData(\"remote-roster-management\", \"allowed\", buf.toString());\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param jid\n\t * @param session\n\t *\n\t * \n\t */\n\tpublic static boolean isRemoteAllowed(JID jid, XMPPResourceConnection session) {\n\t\ttry {\n\t\t\tif (session == null) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"no session to check if {0} is allowed\", jid.toString());\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tSet<JID> allowed = getAllowed(session);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"checking if sender jid = {0} is in allowed set = {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { jid,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t allowed });\n\t\t\t}\n\n\t\t\treturn allowed.contains(jid);\n\t\t} catch (Exception ex) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param item\n\t * @param update\n\t * @param results\n\t *\n\t * @throws NotAuthorizedException\n\t * @throws TigaseDBException\n\t */\n\tpublic static void updateBuddyChange(XMPPResourceConnection session, Element item,\n\t\t\t\t\tElement update, Queue<Packet> results)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tJID jid = JID.jidInstanceNS(item.getAttributeStaticStr(\"jid\"));\n\n\t\tif (jid.getLocalpart() == null) {\n\t\t\treturn;\n\t\t}\n\t\tjid = JID.jidInstanceNS(jid.getDomain());\n\t\tif (isRemoteAllowed(jid, session)) {\n\t\t\tElement iq = update.clone();\n\n\t\t\tiq.setAttribute(\"from\", session.getBareJID().toString());\n\t\t\tiq.setAttribute(\"to\", jid.getDomain());\n\t\t\tiq.setAttribute(\"id\", \"rst\" + session.nextStanzaId());\n\t\t\tresults.offer(Packet.packetInstance(iq, JID.jidInstance(session.getBareJID()),\n\t\t\t\t\t\t\tjid));\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/RosterPresence.java",
    "content": "/*\n * RosterPresence.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterFactory;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPStopListenerIfc;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class RosterPresence here.\n *\n *\n * Created: Wed Jan 30 19:25:25 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Deprecated\npublic class RosterPresence\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPStopListenerIfc {\n\tprivate static final String ID = \"roster-presence\";\n\n\t/**\n\t * Private logger for class instance.\n\t */\n\tprivate static Logger           log = Logger.getLogger(RosterPresence.class.getName());\n\tprivate static final String     PRESENCE = \"presence\";\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ PRESENCE }, Iq.IQ_QUERY_PATH, Iq.IQ_QUERY_PATH\n\t};\n\tprivate static final String[]   XMLNSS = { PresenceAbstract.XMLNS, RosterAbstract.XMLNS,\n\t\t\tRosterAbstract.XMLNS_DYNAMIC };\n\tprivate static final RosterAbstract roster_util = RosterFactory.getRosterImplementation(\n\t\t\ttrue);\n\tprivate static final Element[] FEATURES       = RosterAbstract.FEATURES;\n\tprivate static final Element[] DISCO_FEATURES = RosterAbstract.DISCO_FEATURES;\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate JabberIqRoster rosterProc   = new JabberIqRoster();\n\tprivate PresenceState       presenceProc = new PresenceState();\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int concurrentQueuesNo() {\n\t\treturn super.concurrentQueuesNo() * 2;\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\n\t\tif (!session.isAuthorized()) {\n\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\tlog.log(Level.FINE, \"Session is not authorized, ignoring packet: {0}\", packet);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tif (packet.getElemName().equals(PRESENCE)) {\n\t\t\tpresenceProc.process(packet, session, repo, results, settings);\n\t\t} else {\n\t\t\tif ((packet.getStanzaTo() != null) && (packet.getStanzaFrom() != null) && session\n\t\t\t\t\t.isUserId(packet.getStanzaTo().getBareJID()) &&!session.isUserId(packet\n\t\t\t\t\t.getStanzaFrom().getBareJID())) {\n\t\t\t\tif (!RemoteRosterManagement.isRemoteAllowed(packet.getStanzaFrom(), session)) {\n\t\t\t\t\tresults.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Not authorized for remote roster management\", true));\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tswitch (packet.getType()) {\n\t\t\t\t\tcase get :\n\t\t\t\t\t\tList<Element> ritems = roster_util.getRosterItems(session);\n\n\t\t\t\t\t\tif ((ritems != null) &&!ritems.isEmpty()) {\n\t\t\t\t\t\t\tElement query = new Element(\"query\");\n\n\t\t\t\t\t\t\tquery.setXMLNS(RosterAbstract.XMLNS);\n\n\t\t\t\t\t\t\tString jidStr = \"@\" + packet.getStanzaFrom().getBareJID().toString();\n\n\t\t\t\t\t\t\tfor (Element ritem : ritems) {\n\t\t\t\t\t\t\t\tif (ritem.getAttributeStaticStr(\"jid\").endsWith(jidStr)) {\n\t\t\t\t\t\t\t\t\tquery.addChild(ritem);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults.offer(packet.okResult(query, 0));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresults.offer(packet.okResult((String) null, 1));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase set :\n\n//          processSetMethod.invoke(rosterProc, new Object[]{\n//                          packet, session, results, settings\n//                  });\n//          List<Element> nitems = packet.getElemChildren(\"/iq/query\");\n//          if (nitems != null) {\n//                  for (Element nitem : nitems) {\n//                          JID buddy = JID.jidInstanceNS(nitem.getAttribute(\"jid\"));\n//                          String name = nitem.getAttribute(\"name\");\n//                          String subscrStr = nitem.getAttribute(\"subscription\");\n//                          RosterAbstract.SubscriptionType subscr = subscrStr == null ? null : RosterAbstract.SubscriptionType.valueOf(subscrStr);\n//                          String[] groups = null;\n//                          List<Element> ngroups = nitem.getChildren();\n//                          if (ngroups != null && !ngroups.isEmpty()) {\n//                                  int i = 0;\n//                                  groups = new String[ngroups.size()];\n//                                  for (Element group : nitem.getChildren()) {\n//                                          groups[i++] = group.getCData() == null ? \"\" : group.getCData();\n//                                  }\n//                          }\n//                          roster_util.addBuddy(session, buddy, name, groups, null);\n//                          roster_util.setBuddySubscription(session, subscr, buddy);\n//\n//                          Element item = roster_util.getBuddyItem(session, buddy);\n//                          roster_util.updateBuddyChange(session, results, item);\n//                  }\n//          }\n//\n//          results.offer(packet.okResult((String) null, 0));\n\t\t\t\t\t\trosterProc.processSetRequest(packet, session, results, settings);\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault :\n\t\t\t\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\t\t\t\"Bad stanza type\", true));\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (Throwable ex) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Reflection execution exception\", ex);\n\t\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\t\"Internal server error\", true));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trosterProc.process(packet, session, repo, results, settings);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stopped(final XMPPResourceConnection session, final Queue<Packet> results,\n\t\t\tfinal Map<String, Object> settings) {\n\t\tpresenceProc.stopped(session, results, settings);\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\treturn FEATURES;\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/SaslAuth.java",
    "content": "/*\n * SaslAuth.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.auth.CallbackHandlerFactory;\nimport tigase.auth.mechanisms.SaslANONYMOUS;\nimport tigase.auth.MechanismSelector;\nimport tigase.auth.MechanismSelectorFactory;\nimport tigase.auth.TigaseSaslProvider;\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.XmppSaslException.SaslError;\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\n\nimport tigase.util.Base64;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.security.Security;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.sasl.Sasl;\nimport javax.security.sasl.SaslException;\nimport javax.security.sasl.SaslServer;\n\n/**\n * Describe class SaslAuth here.\n *\n *\n * Created: Mon Feb 20 16:28:13 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class SaslAuth\n\t\t\t\textends AbstractAuthPreprocessor\n\t\t\t\timplements XMPPProcessorIfc {\n\t/** Field description */\n\tpublic static final String     ID = \"urn:ietf:params:xml:ns:xmpp-sasl\";\n\tprivate static final String    _XMLNS = \"urn:ietf:params:xml:ns:xmpp-sasl\";\n\tprivate final static String    ALLOWED_SASL_MECHANISMS_KEY = \"allowed-sasl-mechanisms\";\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { _XMLNS }) };\n\tprivate static final String[][] ELEMENTS        = {\n\t\t{ \"auth\" }, { \"response\" }, { \"challenge\" }, { \"failure\" }, { \"success\" }, { \"abort\" }\n\t};\n\tprivate static final Logger     log = Logger.getLogger(SaslAuth.class.getName());\n\tprivate final static String     SASL_SERVER_KEY = \"SASL_SERVER_KEY\";\n\tprivate static final String[]   XMLNSS          = {\n\t\t_XMLNS, _XMLNS, _XMLNS, _XMLNS, _XMLNS, _XMLNS\n\t};\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate CallbackHandlerFactory    callbackHandlerFactory = new CallbackHandlerFactory();\n\tprivate final Map<String, Object> props                  = new HashMap<String,\n\t\t\tObject>();\n\tprivate MechanismSelector         mechanismSelector;\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum ElementType {\n\t\tabort, auth, challenge, failure, response, success;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic int concurrentQueuesNo() {\n\t\treturn super.concurrentQueuesNo() * 4;\n\t}\n\n\tprivate Element createReply(final ElementType type, final String cdata) {\n\t\tElement reply = new Element(type.toString());\n\n\t\treply.setXMLNS(_XMLNS);\n\t\tif (cdata != null) {\n\t\t\treply.setCData(cdata);\n\t\t}\n\n\t\treturn reply;\n\t}\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tif (settings != null) {\n\t\t\tprops.putAll(settings);\n\t\t}\n\t\tsuper.init(settings);\n\n\t\t// we should remove existing tigase.sasl provider if it is not instance of TigaseSaslProvider\n\t\t// as it can be loaded from other bundle in OSGi which will cause many issues with instanceof\n\t\t// and casting and it is NOT possible to update implementation without removing it first\n\t\tif (!(Security.getProvider(\"tigase.sasl\") instanceof TigaseSaslProvider)) {\n\t\t\tSecurity.removeProvider(\"tigase.sasl\");\n\t\t}\n\t\tSecurity.insertProviderAt(new TigaseSaslProvider(settings), 1);\n\n\t\tMechanismSelectorFactory mechanismSelectorFactory = new MechanismSelectorFactory();\n\n\t\ttry {\n\t\t\tmechanismSelector = mechanismSelectorFactory.create(settings);\n\t\t} catch (Exception e) {\n\t\t\tlog.severe(\"Can't create SASL Mechanism Selector\");\n\n\t\t\tthrow new RuntimeException(\"Can't create SASL Mechanism Selector\", e);\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t */\n\tprotected void onAuthFail(final XMPPResourceConnection session) {\n\t\tsession.removeSessionData(SASL_SERVER_KEY);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}\n\t\tsynchronized (session) {\n\n\t\t\t// If authentication timeout expired, ignore the request....\n\t\t\tif (session.getSessionData(XMPPResourceConnection.AUTHENTICATION_TIMEOUT_KEY) !=\n\t\t\t\t\tnull) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.isAuthorized()) {\n\n\t\t\t\t// Multiple authentication attempts....\n\t\t\t\t// Another authentication request on already authenticated\n\t\t\t\t// connection\n\t\t\t\t// This is not allowed and must be forbidden.\n\t\t\t\tPacket res = packet.swapFromTo(createReply(ElementType.failure,\n\t\t\t\t\t\t\"<not-authorized/>\"), null, null);\n\n\t\t\t\t// Make sure it gets delivered before stream close\n\t\t\t\tres.setPriority(Priority.SYSTEM);\n\t\t\t\tresults.offer(res);\n\n\t\t\t\t// Optionally close the connection to make sure there is no\n\t\t\t\t// confusion about the connection state.\n\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t\t.set, session.nextStanzaId()));\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST,\n\t\t\t\t\t\t\t\"Discovered second authentication attempt: {0}, packet: {1}\",\n\t\t\t\t\t\t\tnew Object[] { session.toString(),\n\t\t\t\t\t\t\tpacket.toString() });\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tsession.logout();\n\t\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\t\tlog.log(Level.FINER, \"Unsuccessful session logout: {0}\", session.toString());\n\t\t\t\t}\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.log(Level.FINEST, \"Session after logout: {0}\", session.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tElement request = packet.getElement();\n\n\t\t\ttry {\n\t\t\t\tSaslServer ss;\n\n\t\t\t\tif (\"auth\" == request.getName()) {\n\t\t\t\t\tfinal String mechanismName = request.getAttributeStaticStr(\"mechanism\");\n\n\t\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\t\tlog.finest(\"Start SASL auth. mechanism=\" + mechanismName);\n\t\t\t\t\t}\n\n\t\t\t\t\tCollection<String> allowedMechanisms = (Collection<String>) session\n\t\t\t\t\t\t\t.getSessionData(ALLOWED_SASL_MECHANISMS_KEY);\n\t\t\t\t\tsession.removeSessionData(ALLOWED_SASL_MECHANISMS_KEY);\n\n\t\t\t\t\tif (allowedMechanisms == null) {\n\t\t\t\t\t\tallowedMechanisms = mechanismSelector.filterMechanisms(Sasl.getSaslServerFactories(), session);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif ((mechanismName == null) || allowedMechanisms == null || !allowedMechanisms.contains(mechanismName)) {\n\t\t\t\t\t\tthrow new XmppSaslException(SaslError.invalid_mechanism, \"Mechanism '\" + mechanismName\n\t\t\t\t\t\t\t\t+ \"' is not allowed\");\n\t\t\t\t\t}\n\n\t\t\t\t\tCallbackHandler cbh = callbackHandlerFactory.create(mechanismName, session,\n\t\t\t\t\t\t\trepo, settings);\n\n\t\t\t\t\tss = Sasl.createSaslServer(mechanismName, \"xmpp\", session.getDomain().getVhost()\n\t\t\t\t\t\t\t.getDomain(), props, cbh);\n\t\t\t\t\tif (ss == null) {\n\t\t\t\t\t\tthrow new XmppSaslException(SaslError.invalid_mechanism, \"Mechanism '\" +\n\t\t\t\t\t\t\t\tmechanismName + \"' is not allowed\");\n\t\t\t\t\t}\n\t\t\t\t\tsession.putSessionData(SASL_SERVER_KEY, ss);\n\t\t\t\t} else if (\"response\" == request.getName()) {\n\t\t\t\t\tss = (SaslServer) session.getSessionData(SASL_SERVER_KEY);\n\t\t\t\t\tif (ss == null) {\n\t\t\t\t\t\tthrow new XmppSaslException(SaslError.malformed_request);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new XmppSaslException(SaslError.malformed_request,\n\t\t\t\t\t\t\t\"Unrecognized element \" + request.getName());\n\t\t\t\t}\n\n\t\t\t\tbyte[] data;\n\t\t\t\tString cdata = request.getCData();\n\n\t\t\t\tif ((cdata != null) && (cdata.length() == 1) && cdata.equals(\"=\")) {\n\t\t\t\t\tdata = new byte[] {};\n\t\t\t\t} else if ((cdata != null) && (cdata.length() > 0)) {\n\t\t\t\t\tdata = Base64.decode(cdata);\n\t\t\t\t} else {\n\t\t\t\t\tdata = new byte[] {};\n\t\t\t\t}\n\n\t\t\t\tbyte[] challenge = ss.evaluateResponse(data);\n\t\t\t\tString challengeData;\n\n\t\t\t\tif (challenge != null) {\n\t\t\t\t\tchallengeData = Base64.encode(challenge);\n\t\t\t\t} else {\n\t\t\t\t\tchallengeData = null;\n\t\t\t\t}\n\t\t\t\tif (ss.isComplete() && (ss.getAuthorizationID() != null)) {\n\t\t\t\t\tBareJID jid;\n\n\t\t\t\t\tif (ss.getAuthorizationID().contains(\"@\")) {\n\t\t\t\t\t\tjid = BareJID.bareJIDInstance(ss.getAuthorizationID());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjid = BareJID.bareJIDInstance(ss.getAuthorizationID(), session.getDomain()\n\t\t\t\t\t\t\t\t.getVhost().getDomain());\n\t\t\t\t\t}\n\t\t\t\t\tif (log.isLoggable(Level.FINE)) {\n\t\t\t\t\t\tlog.finest(\"Authorized as \" + jid);\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean anonymous;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tBoolean x = (Boolean) ss.getNegotiatedProperty(SaslANONYMOUS\n\t\t\t\t\t\t\t\t.IS_ANONYMOUS_PROPERTY);\n\n\t\t\t\t\t\tanonymous = (x == null)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: x.booleanValue();\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tanonymous = false;\n\t\t\t\t\t}\n\t\t\t\t\tsession.removeSessionData(SASL_SERVER_KEY);\n\t\t\t\t\tsession.authorizeJID(jid, anonymous);\n\t\t\t\t\tresults.offer(packet.swapFromTo(createReply(ElementType.success,\n\t\t\t\t\t\t\tchallengeData), null, null));\n\t\t\t\t} else if (!ss.isComplete()) {\n\t\t\t\t\tresults.offer(packet.swapFromTo(createReply(ElementType.challenge,\n\t\t\t\t\t\t\tchallengeData), null, null));\n\t\t\t\t} else {\n\t\t\t\t\tthrow new XmppSaslException(SaslError.malformed_request);\n\t\t\t\t}\n\t\t\t} catch (XmppSaslException e) {\n\t\t\t\tonAuthFail(session);\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"SASL unsuccessful\", e);\n\t\t\t\t}\n\n\t\t\t\tString el;\n\n\t\t\t\tif (e.getSaslErrorElementName() != null) {\n\t\t\t\t\tel = \"<\" + e.getSaslErrorElementName() + \"/>\";\n\t\t\t\t} else {\n\t\t\t\t\tel = \"<not-authorized/>\";\n\t\t\t\t}\n\t\t\t\tif (e.getMessage() != null) {\n\t\t\t\t\tel += \"<text xml:lang='en'>\" + e.getMessage() + \"</text>\";\n\t\t\t\t}\n\n\t\t\t\tPacket response = packet.swapFromTo(createReply(ElementType.failure, el), null,\n\t\t\t\t\t\tnull);\n\n\t\t\t\tresponse.setPriority(Priority.SYSTEM);\n\t\t\t\tresults.offer(response);\n\t\t\t} catch (SaslException e) {\n\t\t\t\tonAuthFail(session);\n\t\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\t\tlog.log(Level.FINER, \"SASL unsuccessful\", e);\n\t\t\t\t}\n\n\t\t\t\tPacket response = packet.swapFromTo(createReply(ElementType.failure,\n\t\t\t\t\t\t\"<not-authorized/>\"), null, null);\n\n\t\t\t\tresponse.setPriority(Priority.SYSTEM);\n\t\t\t\tresults.offer(response);\n\t\t\t} catch (Exception e) {\n\t\t\t\tonAuthFail(session);\n\t\t\t\tif (log.isLoggable(Level.WARNING)) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Problem with SASL\", e);\n\t\t\t\t}\n\n\t\t\t\tPacket response = packet.swapFromTo(createReply(ElementType.failure,\n\t\t\t\t\t\t\"<temporary-auth-failure/>\"), null, null);\n\n\t\t\t\tresponse.setPriority(Priority.SYSTEM);\n\t\t\t\tresults.offer(response);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\tif ((session == null) || session.isAuthorized()) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tCollection<String> auth_mechs = mechanismSelector.filterMechanisms(Sasl\n\t\t\t\t\t.getSaslServerFactories(), session);\n\t\t\tElement[] mechs = new Element[auth_mechs.size()];\n\t\t\tint       idx   = 0;\n\n\t\t\tsession.putSessionData(ALLOWED_SASL_MECHANISMS_KEY, auth_mechs);\n\t\t\tfor (String mech : auth_mechs) {\n\t\t\t\tmechs[idx++] = new Element(\"mechanism\", mech);\n\t\t\t}\n\n\t\t\treturn new Element[] { new Element(\"mechanisms\", mechs, new String[] { \"xmlns\" },\n\t\t\t\t\tnew String[] { _XMLNS }) };\n\t\t}\n\t}\n\t\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/ServiceDiscovery.java",
    "content": "/*\n * ServiceDiscovery.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.disco.XMPPServiceCollector;\n\nimport tigase.server.Command;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\n\n/**\n * Implementation of JEP-030.\n *\n *\n * Created: Mon Mar 27 20:45:36 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class ServiceDiscovery\n\t\t\t\textends XMPPProcessorAbstract {\n\tprivate static final String     ID       = \"disco\";\n\tprivate static final Logger     log = Logger.getLogger(ServiceDiscovery.class\n\t\t\t.getName());\n\tprivate static final String[][] ELEMENTS = {\n\t\tIq.IQ_QUERY_PATH, Iq.IQ_QUERY_PATH, Iq.IQ_QUERY_PATH\n\t};\n\tprivate static final String[]   XMLNSS = { XMPPServiceCollector.INFO_XMLNS,\n\t\t\tXMPPServiceCollector.ITEMS_XMLNS, Command.XMLNS };\n\tprivate static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMPPServiceCollector.INFO_XMLNS }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { XMPPServiceCollector\n\t\t\t\t\t.ITEMS_XMLNS }) };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic Authorization canHandle(Packet packet, XMPPResourceConnection conn) {\n\t\tif (packet.isServiceDisco()) {\n\t\t\ttry {\n\t\t\t\tif (packet.getStanzaTo() != null && packet.getStanzaTo().getLocalpart() != null \n\t\t\t\t\t\t&& packet.getStanzaTo().getResource() == null\n\t\t\t\t\t\t&& (conn == null || conn.isUserId(packet.getStanzaTo().getBareJID())))\n\t\t\t\t\treturn null;\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t}\n\t\t}\n\t\treturn super.canHandle(packet, conn);\n\t}\t\n\t\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\n\t\t// Handled elsewhere (in MessageRouter)\n\t\tif ( packet.getStanzaTo() != null ){\n\t\t\tlog.log( Level.FINEST, \"forwarding packet to MR\" + packet.toString() );\n\t\t\tresults.offer( packet.copyElementOnly() );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tresults.offer(Authorization.RECIPIENT_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\"The target is unavailable at this time.\", true));\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\n\t\t// Handled elsewhere (in MessageRouter)\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}    // ServiceDiscovery\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/SessionBind.java",
    "content": "/*\n * SessionBind.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\nimport tigase.xmpp.impl.annotation.*;\n\nimport static tigase.xmpp.impl.SessionBind.*;\n/**\n * Describe class SessionBind here.\n *\n *\n * Created: Mon Feb 20 22:43:59 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Id(XMLNS)\n@Handle(path={ Iq.ELEM_NAME, \"session\" }, xmlns=XMLNS)\n@StreamFeatures(\n\t@StreamFeature(elem=\"session\", xmlns=XMLNS)\n)\n@DiscoFeatures({ XMLNS })\npublic class SessionBind\n\t\t\t\textends AnnotatedXMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String     SESSION_KEY = \"Session-Set\";\n\tprotected static final String     XMLNS       = \"urn:ietf:params:xml:ns:xmpp-session\";\n\tprivate static final Logger     log = Logger.getLogger(SessionBind.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (!session.isAuthorized()) {\n\t\t\tresults.offer(session.getAuthState().getResponseMessage(packet,\n\t\t\t\t\t\"Session is not yet authorized.\", false));\n\n\t\t\treturn;\n\t\t}    // end of if (!session.isAuthorized())\n\n\t\t// Element request = packet.getElement();\n\t\tStanzaType type = packet.getType();\n\n\t\tswitch (type) {\n\t\tcase set :\n\t\t\tsession.putSessionData(SESSION_KEY, \"true\");\n\t\t\tresults.offer(packet.okResult((String) null, 0));\n\n\t\t\tbreak;\n\n\t\tdefault :\n\t\t\tresults.offer(Authorization.BAD_REQUEST.getResponseMessage(packet,\n\t\t\t\t\t\"Session type is incorrect\", false));\n\n\t\t\tbreak;\n\t\t}    // end of switch (type)\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\t\tif ((session != null) && (session.getSessionData(SESSION_KEY) == null) && session\n\t\t\t\t.isAuthorized()) {\n\t\t\treturn super.supStreamFeatures(session);\n\t\t} else {\n\t\t\treturn null;\n\t\t}    // end of if (session.isAuthorized()) else\n\t}\n}    // SessionBind\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/SimpleForwarder.java",
    "content": "/*\n * SimpleForwarder.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class SimpleForwarder here.\n *\n *\n * Created: Sat Jan 13 16:58:41 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class SimpleForwarder\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(SimpleForwarder.class.getName());\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\ttry {\n\t\t\tBareJID id = packet.getStanzaTo().getBareJID();\n\n\t\t\tif (session.isUserId(id)) {\n\n\t\t\t\t// Yes this is message to 'this' client\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId(packet.getStanzaTo()));\n\t\t\t\tresult.setPacketFrom(packet.getTo());\n\t\t\t\tresults.offer(result);\n\t\t\t} else {\n\n\t\t\t\t// This is message to some other client\n\t\t\t\tresults.offer(packet.copyElementOnly());\n\t\t\t}    // end of else\n\t\t} catch (NotAuthorizedException e) {\n\t\t\tlog.warning(\"NotAuthorizedException for packet: \" + packet);\n\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t}    // end of try-catch\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/StartTLS.java",
    "content": "/*\n * StartTLS.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.server.Command;\nimport tigase.server.Packet;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPPreprocessorIfc;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class StartTLS here.\n *\n *\n * Created: Fri Mar 24 07:22:57 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StartTLS\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc, XMPPPreprocessorIfc {\n\t// private static final String TLS_STARTED_KEY = \"TLS-Started\";\n\n\t/** Field description */\n\tpublic static final String EL_NAME = \"starttls\";\n\n\t/** Field description */\n\tprotected static final String   ID       = EL_NAME;\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ EL_NAME }, { \"proceed\" }, { \"failure\" }\n\t};\n\tprivate static final Logger     log      = Logger.getLogger(StartTLS.class.getName());\n\tprivate static final String     XMLNS    = \"urn:ietf:params:xml:ns:xmpp-tls\";\n\tprivate static final String[]   XMLNSS   = { XMLNS, XMLNS, XMLNS };\n\tprivate static final Element[]  F_REQUIRED = { new Element(\"starttls\", new Element[] {\n\t\t\tnew Element(\"required\") }, new String[] { Packet.XMLNS_ATT }, new String[] {\n\t\t\tXMLNS }) };\n\tprivate static final Element[] F_NOT_REQUIRED = { new Element(EL_NAME, new String[] {\n\t\t\tPacket.XMLNS_ATT }, new String[] { XMLNS }) };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Element proceed = new Element(\"proceed\", new String[] { Packet.XMLNS_ATT },\n\t\t\tnew String[] { XMLNS });\n\tprivate Element failure = new Element(\"failure\", new String[] { Packet.XMLNS_ATT },\n\t\t\tnew String[] { XMLNS });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(final Packet packet, final XMPPResourceConnection session,\n\t\t\tfinal NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,\n\t\t\tObject> settings) {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (packet.isElement(\"starttls\", XMLNS)) {\n\t\t\tif (session.getSessionData(ID) != null) {\n\n\t\t\t\t// Somebody tries to activate multiple TLS layers.\n\t\t\t\t// This is possible and can even work but this can also be\n\t\t\t\t// a DOS attack. Blocking it now, unless someone requests he wants\n\t\t\t\t// to have multiple layers of TLS for his connection\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"Multiple TLS requests, possible DOS attack, closing connection: {0}\",\n\t\t\t\t\t\tpacket);\n\t\t\t\tresults.offer(packet.swapFromTo(failure, null, null));\n\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t\t.set, session.nextStanzaId()));\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsession.putSessionData(ID, \"true\");\n\n\t\t\tPacket result = Command.STARTTLS.getPacket(packet.getTo(), packet.getFrom(),\n\t\t\t\t\tStanzaType.set, session.nextStanzaId(), Command.DataType.submit);\n\n\t\t\tCommand.setData(result, proceed);\n\t\t\tresults.offer(result);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Unknown TLS element: {0}\", packet);\n\t\t\tresults.offer(packet.swapFromTo(failure, null, null));\n\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t.set, session.nextStanzaId()));\n\t\t}    // end of if (packet.getElement().getName().equals(\"starttls\")) else\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\n\t\t// If session does not exist, just return null, we don't provide features\n\t\t// for non-existen stream, the second condition means that the TLS\n\t\t// has not been yet completed for the user connection.\n\t\tif ((session != null) && (session.getSessionData(ID) == null)) {\n\t\t\tVHostItem vhost = session.getDomain();\n\n\t\t\tif ((vhost != null) && session.isTlsRequired()) {\n\t\t\t\treturn F_REQUIRED;\n\t\t\t} else {\n\t\t\t\treturn F_NOT_REQUIRED;\n\t\t\t}\n\t\t} else {\n\t\t\treturn null;\n\t\t}    // end of if (session.isAuthorized()) else\n\t}\n\t\n\t@Override\n\tpublic boolean preProcess(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tboolean stop = false;\n\n\t\tif ((session == null) || session.isServerSession()) {\n\t\t\treturn stop;\n\t\t}\n\n\t\tVHostItem vhost = session.getDomain();\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"VHost: {0}\", new Object[] { vhost });\n\t\t}\n\n\t\t// Check whether the TLS has been completed\n\t\t// and the packet is allowed to be processed.\n\t\tif ((vhost != null) && session.isTlsRequired() && (session.getSessionData(ID) == null)\n\t\t\t\t&& !packet.isElement(EL_NAME, XMLNS)) {\n\t\t\tstop = true;\n\t\t}\n\n\t\treturn stop;\n\t}\n}    // StartTLS\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/StartZLib.java",
    "content": "/*\n * StartZLib.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Command;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Created: Jul 29, 2009 4:03:44 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class StartZLib\n\t\t\t\textends XMPPProcessor\n\t\t\t\timplements XMPPProcessorIfc {\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ \"compress\" }, { \"compressed\" }, { \"failure\" }\n\t};\n\tprivate static final String     ID       = \"zlib\";\n\tprivate static Logger           log      = Logger.getLogger(StartZLib.class.getName());\n\tprivate static final String     XMLNS    = \"http://jabber.org/protocol/compress\";\n\tprivate static final String[]   XMLNSS   = { XMLNS, XMLNS, XMLNS };\n\tprivate static final Element[]  FEATURES = { new Element(\"compression\", new Element[] {\n\t\t\tnew Element(\"method\", \"zlib\") }, new String[] { \"xmlns\" }, new String[] {\n\t\t\t\"http://jabber.org/features/compress\" }) };\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Element compressed = new Element(\"compressed\", new String[] { \"xmlns\" },\n\t\t\tnew String[] { XMLNS });\n\tprivate Element failure = new Element(\"failure\", new String[] { \"xmlns\" },\n\t\t\tnew String[] { XMLNS });\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void process(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows XMPPException {\n\t\tif (session == null) {\n\t\t\treturn;\n\t\t}    // end of if (session == null)\n\t\tif (packet.isElement(\"compress\", XMLNS)) {\n\t\t\tif (session.getSessionData(ID) != null) {\n\n\t\t\t\t// Somebody tries to activate multiple TLS layers.\n\t\t\t\t// This is possible and can even work but this can also be\n\t\t\t\t// a DOS attack. Blocking it now, unless someone requests he wants\n\t\t\t\t// to have multiple layers of TLS for his connection\n\t\t\t\tlog.log(Level.WARNING,\n\t\t\t\t\t\t\"Multiple ZLib requests, possible DOS attack, closing connection: {0}\",\n\t\t\t\t\t\tpacket);\n\t\t\t\tresults.offer(packet.swapFromTo(failure, null, null));\n\t\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t\t.set, session.nextStanzaId()));\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsession.putSessionData(ID, \"true\");\n\n\t\t\tPacket result = Command.STARTZLIB.getPacket(packet.getTo(), packet.getFrom(),\n\t\t\t\t\tStanzaType.set, session.nextStanzaId(), Command.DataType.submit);\n\n\t\t\tCommand.setData(result, compressed);\n\t\t\tresults.offer(result);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Unknown ZLIB element: {0}\", packet);\n\t\t\tresults.offer(packet.swapFromTo(failure, null, null));\n\t\t\tresults.offer(Command.CLOSE.getPacket(packet.getTo(), packet.getFrom(), StanzaType\n\t\t\t\t\t.set, session.nextStanzaId()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(final XMPPResourceConnection session) {\n\n\t\t// If session does not exist, just return null, we don't provide features\n\t\t// for non-existen stream\n\t\t// We also do not want to provide compression if it is already started\n\t\t// and the compression has to be available after TLS has been completed.\n\t\tif ((session != null) && (session.getSessionData(ID) == null)) {\n\n//    && session.getSessionData(StartTLS.ID) != null) {\n\t\t\treturn FEATURES;\n\t\t} else {\n\t\t\treturn null;\n\t\t}    // end of if (session.isAuthorized()) else\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/03/12\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/UrnXmppPing.java",
    "content": "/*\n * UrnXmppPing.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * XEP-0199: XMPP Ping\n *\n *\n * @author <a href=\"mailto:bmalkow@tigase.org\">Bartosz Małkowski</a>\n * @version $Rev$\n */\npublic class UrnXmppPing\n\t\t\t\textends XMPPProcessorAbstract {\n\tprivate static final Logger     log = Logger.getLogger(UrnXmppPing.class.getName());\n\tprivate static final String[][] ELEMENTS = {\n\t\t{ Iq.ELEM_NAME, \"ping\" }\n\t};\n\tprivate static final String     XMLNS    = \"urn:xmpp:ping\";\n\tprivate static final String     ID       = XMLNS;\n\tprivate static final Element[]  DISCO_FEATURES = { new Element(\"feature\",\n\t\t\tnew String[] { \"var\" }, new String[] { XMLNS }) };\n\tprivate static final String[] XMLNSS = { XMLNS };\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings) {\n\t\tresults.offer(packet.okResult((Element) null, 0));\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tresults.offer(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,\n\t\t\t\t\"Service not available.\", true));\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\t\tresults.offer(packet.okResult((Element) null, 0));\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(final XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/VCard4.java",
    "content": "/*\n * VCard4.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl;\n\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\nimport static tigase.xmpp.impl.VCard4.*;\nimport tigase.xmpp.impl.annotation.DiscoFeatures;\nimport tigase.xmpp.impl.annotation.Handle;\nimport tigase.xmpp.impl.annotation.Handles;\nimport tigase.xmpp.impl.annotation.Id;\n\n/**\n *\n * @author andrzej\n */\n@Id(ID)\n@Handles({\n\t@Handle(path={ Iq.ELEM_NAME, VCARD_EL },xmlns=XMLNS)\n})\n@DiscoFeatures({\n\tXMLNS\n})\npublic class VCard4 extends VCardXMPPProcessorAbstract {\n\t\n\tprivate static final Logger log = Logger.getLogger(VCard4.class.getCanonicalName());\n\t\n\t// private varibles reused in public variables\n\tstatic final String ID = \"vcard-xep-0292\";\n\tprotected static final String VCARD_EL = \"vcard\";\n\tprotected static final String XMLNS = \"urn:ietf:params:xml:ns:vcard-4.0\";\n\t\n\t// public variables used in other places which depends on private variables above\n\tpublic static final String REPO_NODE = ID;\n\t\n\t// private variables used only by this processor\n\tstatic final String VCARD_KEY = ID;\n\t\t\n\tprivate static final SimpleParser parser   = SingletonFactory.getParserInstance();\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param connectionId\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t *\n\t * @throws PacketErrorTypeException\n\t */\n\t@Override\n\tpublic void processFromUserOutPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (session.isLocalDomain(packet.getStanzaTo().getDomain(), false)) {\n\n\t\t\t// This is a local user so we can quickly get his vCard from the database\n\t\t\ttry {\n\t\t\t\tString strvCard = repo.getPublicData(packet.getStanzaTo().getBareJID(), ID,\n\t\t\t\t\t\tVCARD_KEY, null);\n\t\t\t\tPacket result = null;\n\n\t\t\t\tif (strvCard != null) {\n\t\t\t\t\tresult = parseXMLData(strvCard, packet);\n\t\t\t\t} else {\n\t\t\t\t\tresult = packet.okResult((String) null, 1);\n\t\t\t\t}    // end of if (vcard != null)\n\t\t\t\tresult.setPacketTo(connectionId);\n\t\t\t\tresults.offer(result);\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\"User not found\", true));\n\t\t\t}    // end of try-catch\n\t\t} else {\n\n\t\t\t// Else forward the packet to a remote server\n\t\t\tresults.offer(packet.copyElementOnly());\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param connectionId\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t *\n\t * @throws PacketErrorTypeException\n\t */\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getType() != null) {\n\t\t\ttry {\n\t\t\t\tPacket result = null;\n\n\t\t\t\tswitch (packet.getType()) {\n\t\t\t\tcase get :\n\t\t\t\t\tString strvCard = session.getPublicData(ID, VCARD_KEY, null);\n\n\t\t\t\t\tif (strvCard != null) {\n\t\t\t\t\t\tresult = parseXMLData(strvCard, packet);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = packet.okResult((String) null, 1);\n\t\t\t\t\t}    // end of if (vcard != null) else\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase set :\n\t\t\t\t\tElement elvCard = packet.getElement().getChild(VCARD_EL, XMLNS);\n\n\t\t\t\t\tsetVCard(session, elvCard);\n\t\t\t\t\tresult = packet.okResult((String) null, 0);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\n\t\t\t\t// Ignore all others...\n\t\t\t\t}\n\t\t\t\tif (result != null) {\n\t\t\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// This should not happen unless somebody sends a result vcard packet\n\t\t\t\t// to the server itself\n\t\t\t\tlog.warning(\"This should not happen, unless this is a vcard result packet \" +\n\t\t\t\t\t\t\"sent to the server, which should not happen: \" + packet);\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tlog.warning(\"Received vCard request but user session is not authorized yet: \" +\n\t\t\t\t\t\tpacket);\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tlog.log(Level.WARNING, \"Database problem, please contact admin: \" + ex, ex);\n\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t\t}\n\t\t} else {\n\n\t\t\t// TODO: if this really happen that this is clearly protocol error, as\n\t\t\t// that would be\n\t\t\t// vCard packet with no type set, do we really need to handle such an\n\t\t\t// erro? Let's\n\t\t\t// ignore it for now.\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t *\n\t * @throws PacketErrorTypeException\n\t */\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getType() == StanzaType.get) {\n\t\t\ttry {\n\t\t\t\tString strvCard = repo.getPublicData(packet.getStanzaTo().getBareJID(), ID,\n\t\t\t\t\t\tVCARD_KEY, null);\n\n\t\t\t\tif (strvCard != null) {\n\t\t\t\t\tresults.offer(parseXMLData(strvCard, packet));\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(packet.okResult((String) null, 1));\n\t\t\t\t}    // end of if (vcard != null)\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\"User not found\", true));\n\t\t\t}    // end of try-catch\n\t\t} else {\n\n\t\t\t// This is most likely a response to the user from the remote\n\t\t\t// entity with vCard request results.\n\t\t\t// Processed in processToUserPacket() method.\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t */\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\n\t\t// TODO: Hm, the server vCard should be sent here, not yet implemented....\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param packet\n\t * @param session\n\t * @param repo\n\t * @param results\n\t * @param settings\n\t *\n\t * @throws PacketErrorTypeException\n\t */\n\t@Override\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tprocessNullSessionPacket(packet, repo, results, settings);\n\t\tif ((session != null) && session.isAuthorized() && (packet.getType() != StanzaType\n\t\t\t\t.get)) {\n\t\t\ttry {\n\t\t\t\tJID conId = session.getConnectionId(packet.getStanzaTo());\n\n\t\t\t\tif (conId == null) {\n\n\t\t\t\t\t// Drop it, user is no longer online.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId(packet.getStanzaTo()));\n\t\t\t\tresults.offer(result);\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// This should not happen unless somebody sends a result vcard packet\n\t\t\t\t// to the server itself\n\t\t\t\tlog.warning(\"This should not happen, unless this is a vcard result packet \" +\n\t\t\t\t\t\t\"sent to the server, which should not happen: \" + packet);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected String getVCardXMLNS() {\n\t\treturn XMLNS;\n\t}\t\n\t\n\t@Override\n\tprotected void storeVCard(XMPPResourceConnection session, Element elvCard) throws TigaseDBException, NotAuthorizedException {\n\t\tif (elvCard != null && elvCard.getChildren() != null) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Adding vCard: \" + elvCard);\n\t\t\t}\n\t\t\tsession.setPublicData(ID, VCARD_KEY, elvCard.toString());\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Removing vCard\");\n\t\t\t}\n\t\t\tsession.removePublicData(ID, VCARD_KEY);\n\t\t}    // end of else\t\t\n\t}\t\n\t\n\tprivate Packet parseXMLData(String data, Packet packet) {\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\tparser.parse(domHandler, data.toCharArray(), 0, data.length());\n\n\t\tQueue<Element> elems  = domHandler.getParsedElements();\n\t\tPacket         result = packet.okResult((Element) null, 0);\n\n\t\tresult.setPacketFrom(null);\n\t\tresult.setPacketTo(null);\n\t\tfor (Element el : elems) {\n\t\t\tresult.getElement().addChild(el);\n\t\t}    // end of for (Element el: elems)\n\n\t\treturn result;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/VCardTemp.java",
    "content": "/*\n * VCardTemp.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserNotFoundException;\n\nimport tigase.server.Iq;\nimport tigase.server.Packet;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.PacketErrorTypeException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.xmpp.impl.annotation.*;\nimport static tigase.xmpp.impl.VCardTemp.*;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class VCardTemp here.\n *\n *\n * Created: Thu Oct 19 23:37:23 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\n@Id(XMLNS)\n@Handles({\n\t@Handle(path={ Iq.ELEM_NAME, vCard },xmlns=XMLNS),\n\t@Handle(path={ Iq.ELEM_NAME, VCARD },xmlns=XMLNS)\n})\n@DiscoFeatures({\n\tXMLNS\n})\npublic class VCardTemp\n\t\t\t\textends VCardXMPPProcessorAbstract {\n\t/** Field description */\n\tpublic static final String VCARD_KEY = \"vCard\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(VCardTemp.class.getName());\n\n\t// VCARD element is added to support old vCard protocol where element\n\t// name was all upper cases. Now the plugin should catch both cases.\n\tprotected static final String       vCard    = \"vCard\";\n\tprotected static final String       VCARD    = \"VCARD\";\n\tprotected static final String       XMLNS    = \"vcard-temp\";\n\tprotected static final String       ID       = XMLNS;\n\tprivate static final SimpleParser parser   = SingletonFactory.getParserInstance();\n\t\n\tpublic void processFromUserOutPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (session.isLocalDomain(packet.getStanzaTo().getDomain(), false)) {\n\n\t\t\t// This is a local user so we can quickly get his vCard from the database\n\t\t\ttry {\n\t\t\t\tString strvCard = repo.getPublicData(packet.getStanzaTo().getBareJID(), ID,\n\t\t\t\t\t\tVCARD_KEY, null);\n\t\t\t\tPacket result = null;\n\n\t\t\t\tif (strvCard != null) {\n\t\t\t\t\tresult = parseXMLData(strvCard, packet);\n\t\t\t\t} else {\n\t\t\t\t\tresult = packet.okResult((String) null, 1);\n\t\t\t\t}    // end of if (vcard != null)\n\t\t\t\tresult.setPacketTo(connectionId);\n\t\t\t\tresults.offer(result);\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\"User not found\", true));\n\t\t\t}    // end of try-catch\n\t\t} else {\n\n\t\t\t// Else forward the packet to a remote server\n\t\t\tresults.offer(packet.copyElementOnly());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processFromUserToServerPacket(JID connectionId, Packet packet,\n\t\t\tXMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,\n\t\t\tMap<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getType() != null) {\n\t\t\ttry {\n\t\t\t\tPacket result = null;\n\n\t\t\t\tswitch (packet.getType()) {\n\t\t\t\tcase get :\n\t\t\t\t\tString strvCard = session.getPublicData(ID, VCARD_KEY, null);\n\n\t\t\t\t\tif (strvCard != null) {\n\t\t\t\t\t\tresult = parseXMLData(strvCard, packet);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = packet.okResult((String) null, 1);\n\t\t\t\t\t}    // end of if (vcard != null) else\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase set :\n\t\t\t\t\tElement elvCard = packet.getElement().getChild(vCard);\n\n\t\t\t\t\t// This is added to support old vCard protocol where element\n\t\t\t\t\t// name was all upper cases. So here I am checking both\n\t\t\t\t\t// possibilities\n\t\t\t\t\tif (elvCard == null) {\n\t\t\t\t\t\telvCard = packet.getElement().getChild(VCARD);\n\t\t\t\t\t}\n\t\t\t\t\tsetVCard(session, elvCard);\n\t\t\t\t\tresult = packet.okResult((String) null, 0);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault :\n\n\t\t\t\t// Ignore all others...\n\t\t\t\t}\n\t\t\t\tif (result != null) {\n\t\t\t\t\tresult.setPacketTo(session.getConnectionId());\n\t\t\t\t\tresults.offer(result);\n\t\t\t\t}\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// This should not happen unless somebody sends a result vcard packet\n\t\t\t\t// to the server itself\n\t\t\t\tlog.warning(\"This should not happen, unless this is a vcard result packet \" +\n\t\t\t\t\t\t\"sent to the server, which should not happen: \" + packet);\n\t\t\t} catch (NotAuthorizedException ex) {\n\t\t\t\tlog.warning(\"Received vCard request but user session is not authorized yet: \" +\n\t\t\t\t\t\tpacket);\n\t\t\t\tresults.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet,\n\t\t\t\t\t\t\"You must authorize session first.\", true));\n\t\t\t} catch (TigaseDBException ex) {\n\t\t\t\tlog.warning(\"Database problem, please contact admin: \" + ex);\n\t\t\t\tresults.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet,\n\t\t\t\t\t\t\"Database access problem, please contact administrator.\", true));\n\t\t\t}\n\t\t} else {\n\n\t\t\t// TODO: if this really happen that this is clearly protocol error, as\n\t\t\t// that would be\n\t\t\t// vCard packet with no type set, do we really need to handle such an\n\t\t\t// erro? Let's\n\t\t\t// ignore it for now.\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processNullSessionPacket(Packet packet, NonAuthUserRepository repo,\n\t\t\tQueue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tif (packet.getType() == StanzaType.get) {\n\t\t\ttry {\n\t\t\t\tString strvCard = repo.getPublicData(packet.getStanzaTo().getBareJID(), ID,\n\t\t\t\t\t\tVCARD_KEY, null);\n\n\t\t\t\tif (strvCard != null) {\n\t\t\t\t\tresults.offer(parseXMLData(strvCard, packet));\n\t\t\t\t} else {\n\t\t\t\t\tresults.offer(packet.okResult((String) null, 1));\n\t\t\t\t}    // end of if (vcard != null)\n\t\t\t} catch (UserNotFoundException e) {\n\t\t\t\tresults.offer(Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,\n\t\t\t\t\t\t\"User not found\", true));\n\t\t\t}    // end of try-catch\n\t\t} else {\n\n\t\t\t// This is most likely a response to the user from the remote\n\t\t\t// entity with vCard request results.\n\t\t\t// Processed in processToUserPacket() method.\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processServerSessionPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) {\n\n\t\t// TODO: Hm, the server vCard should be sent here, not yet implemented....\n\t}\n\n\t@Override\n\tpublic void processToUserPacket(Packet packet, XMPPResourceConnection session,\n\t\t\tNonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings)\n\t\t\t\t\tthrows PacketErrorTypeException {\n\t\tprocessNullSessionPacket(packet, repo, results, settings);\n\t\tif ((session != null) && session.isAuthorized() && (packet.getType() != StanzaType\n\t\t\t\t.get)) {\n\t\t\ttry {\n\t\t\t\tJID conId = session.getConnectionId(packet.getStanzaTo());\n\n\t\t\t\tif (conId == null) {\n\n\t\t\t\t\t// Drop it, user is no longer online.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tPacket result = packet.copyElementOnly();\n\n\t\t\t\tresult.setPacketTo(session.getConnectionId(packet.getStanzaTo()));\n\t\t\t\tresults.offer(result);\n\t\t\t} catch (NoConnectionIdException ex) {\n\n\t\t\t\t// This should not happen unless somebody sends a result vcard packet\n\t\t\t\t// to the server itself\n\t\t\t\tlog.warning(\"This should not happen, unless this is a vcard result packet \" +\n\t\t\t\t\t\t\"sent to the server, which should not happen: \" + packet);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t@Override\n\tprotected String getVCardXMLNS() {\n\t\treturn XMLNS;\n\t}\n\t\n\t@Override\n\tprotected void storeVCard(XMPPResourceConnection session, Element elvCard) throws TigaseDBException, NotAuthorizedException {\n\t\tif (elvCard != null) {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Adding vCard: \" + elvCard);\n\t\t\t}\n\t\t\tsession.setPublicData(ID, VCARD_KEY, elvCard.toString());\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINER)) {\n\t\t\t\tlog.finer(\"Removing vCard\");\n\t\t\t}\n\t\t\tsession.removePublicData(ID, VCARD_KEY);\n\t\t}    // end of else\n\t}\n\t\n\tprivate Packet parseXMLData(String data, Packet packet) {\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\tparser.parse(domHandler, data.toCharArray(), 0, data.length());\n\n\t\tQueue<Element> elems  = domHandler.getParsedElements();\n\t\tPacket         result = packet.okResult((Element) null, 0);\n\n\t\tresult.setPacketFrom(null);\n\t\tresult.setPacketTo(null);\n\t\tfor (Element el : elems) {\n\t\t\tresult.getElement().addChild(el);\n\t\t}    // end of for (Element el: elems)\n\n\t\treturn result;\n\t}\n}    // VCardTemp\n\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/VCardXMPPProcessorAbstract.java",
    "content": "/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport tigase.db.TigaseDBException;\nimport tigase.xml.Element;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPProcessorAbstract;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic abstract class VCardXMPPProcessorAbstract extends XMPPProcessorAbstract {\n\t\n\tprivate static final Pattern DATA_URI_PATTERN = Pattern.compile(\"data:(.+);base64,(.+)\");\n\tprivate static final Pattern TEL_URI_PATTERN = Pattern.compile(\"tel:(.+)\");\n\tprivate static final Pattern XMPP_URI_PATTERN = Pattern.compile(\"xmpp:(.+)\");\n\tprivate static final Pattern GEO_URI_PATTERN = Pattern.compile(\"geo:([\\\\-0-9\\\\.]+),([\\\\-0-9\\\\.]+)\");\n\t\n\tprivate static Map<String, VCardXMPPProcessorAbstract> PROCESSORS = new ConcurrentHashMap<>();\n\tprivate static Map<String, Converter> CONVERTERS = new ConcurrentHashMap<>();\n\t\n\t@Override\n\tpublic void init(Map<String, Object> settings) throws TigaseDBException {\n\t\tsuper.init(settings);\n\t\tPROCESSORS.put(this.id(), this);\n\t}\n\t\n\tprotected abstract String getVCardXMLNS();\n\t\n\tprotected void setVCard(XMPPResourceConnection session, Element vcard) throws TigaseDBException, NotAuthorizedException {\n\t\tfor (VCardXMPPProcessorAbstract processor : PROCESSORS.values()) {\n\t\t\tConverter conv = CONVERTERS.get(getVCardXMLNS() + \"|\" + processor.getVCardXMLNS());\n\t\t\tElement vcardEl = conv == null ? vcard : conv.convert(vcard);\n\t\t\tprocessor.storeVCard(session, vcardEl);\n\t\t}\n\t}\n\t\n\tprotected abstract void storeVCard(XMPPResourceConnection session, Element vcard) throws TigaseDBException, NotAuthorizedException;\n\t\n\tprivate interface Converter {\n\t\t\n\t\tElement convert(Element vcard);\n\t\t\n\t}\n\t\n\tstatic {\n\t\tCONVERTERS.put(VCardTemp.XMLNS + \"|\" + VCard4.XMLNS, (Element vcardTemp) -> {\n\t\tif (vcardTemp == null)\n\t\t\treturn null;\n\t\t\n\t\tElement vcard4= new Element(VCard4.VCARD_EL, new String[] { \"xmlns\" }, new String[] { VCard4.XMLNS });\n\t\t\n\t\tvcardTemp.forEachChild((Element c) -> {\n\t\t\tElement r = null;\n\t\t\tList<Element> list = null;\n\t\t\tElement parameters = null;\n\t\t\tElement type = null;\n\n\t\t\tswitch (c.getName()) {\n\t\t\t\tcase \"FN\":\n\t\t\t\tcase \"NICKNAME\":\n\t\t\t\tcase \"TZ\":\n\t\t\t\tcase \"TITLE\":\n\t\t\t\tcase \"ROLE\":\n\t\t\t\tcase \"CATEGORIES\":\n\t\t\t\tcase \"NOTE\":\n\t\t\t\tcase \"PRODID\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tr.addChild(new Element(\"text\", c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"N\":\n\t\t\t\t\tr = new Element(\"n\");\n\t\t\t\t\tlist = c.mapChildren((Element c1) -> {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"GIVEN\":\n\t\t\t\t\t\t\t\treturn new Element(\"given\", c1.getCData());\n\t\t\t\t\t\t\tcase \"FAMILY\":\n\t\t\t\t\t\t\t\treturn new Element(\"surname\", c1.getCData());\n\t\t\t\t\t\t\tcase \"MIDDLE\":\n\t\t\t\t\t\t\t\treturn new Element(\"additional\", c1.getCData());\n\t\t\t\t\t\t\tcase \"PREFIX\":\n\t\t\t\t\t\t\t\treturn new Element(\"prefix\", c1.getCData());\n\t\t\t\t\t\t\tcase \"SUFFIX\":\n\t\t\t\t\t\t\t\treturn new Element(\"suffix\", c1.getCData());\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\tlist.removeIf((Element c1) -> c1 == null);\n\t\t\t\t\t\tr.addChildren(list);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"PHOTO\":\n\t\t\t\tcase \"LOGO\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tElement extVal = c.findChild((Element c1) -> c1.getName() == \"EXTVAL\");\n\t\t\t\t\tif (extVal != null) {\n\t\t\t\t\t\tr.addChild(new Element(\"uri\", extVal.getCData()));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr.addChild(new Element(\"uri\", \"data:\" + c.getChildCData((Element c1) -> c1.getName() == \"TYPE\")  + \";base64,\" + c.getChildCData((Element c1) -> c1.getName() == \"BINVAL\")));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"BDAY\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tr.addChild(new Element(\"date\", c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ADR\":\n\t\t\t\t\tr = new Element(\"adr\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"POBOX\":\n\t\t\t\t\t\t\tcase \"STREET\":\n\t\t\t\t\t\t\tcase \"LOCALITY\":\n\t\t\t\t\t\t\tcase \"REGION\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(c1.getName().toLowerCase(), c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"EXTADD\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"ext\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase \"PCODE\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"code\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase \"CTRY\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"country\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"HOME\":\n\t\t\t\t\t\t\tcase \"WORK\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (type == null) {\n\t\t\t\t\t\t\t\t\ttype = new Element(\"type\");\n\t\t\t\t\t\t\t\t\tparameters.addChild(type);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttype.addChild(new Element(\"text\", c1.getName().toLowerCase()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"PREF\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tElement pref = new Element(\"pref\");\n\t\t\t\t\t\t\t\tpref.addChild(new Element(\"integer\", \"1\"));\n\t\t\t\t\t\t\t\tparameters.addChild(pref);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"TEL\":\n\t\t\t\t\tr = new Element(\"tel\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"HOME\":\n\t\t\t\t\t\t\tcase \"WORK\":\n\t\t\t\t\t\t\tcase \"TEXT\":\n\t\t\t\t\t\t\tcase \"FAX\":\n\t\t\t\t\t\t\tcase \"CELL\":\n\t\t\t\t\t\t\tcase \"VOICE\":\n\t\t\t\t\t\t\tcase \"VIDEO\":\n\t\t\t\t\t\t\tcase \"PAGER\":\n\t\t\t\t\t\t\tcase \"TEXTPHONE\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (type == null) {\n\t\t\t\t\t\t\t\t\ttype = new Element(\"type\");\n\t\t\t\t\t\t\t\t\tparameters.addChild(type);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttype.addChild(new Element(\"text\", c1.getName().toLowerCase()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"PREF\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tElement pref = new Element(\"pref\");\n\t\t\t\t\t\t\t\tpref.addChild(new Element(\"integer\", \"1\"));\n\t\t\t\t\t\t\t\tparameters.addChild(pref);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"NUMBER\":\n\t\t\t\t\t\t\t\tElement uri = new Element(\"uri\", \"tel:\" + c1.getCData());\n\t\t\t\t\t\t\t\tr.addChild(uri);\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"EMAIL\":\n\t\t\t\t\tr = new Element(\"email\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"HOME\":\n\t\t\t\t\t\t\tcase \"WORK\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (type == null) {\n\t\t\t\t\t\t\t\t\ttype = new Element(\"type\");\n\t\t\t\t\t\t\t\t\tparameters.addChild(type);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttype.addChild(new Element(\"text\", c1.getName().toLowerCase()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"PREF\":\n\t\t\t\t\t\t\t\tif (parameters == null) {\n\t\t\t\t\t\t\t\t\tparameters = new Element(\"parameters\");\n\t\t\t\t\t\t\t\t\tr.addChild(parameters);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tElement pref = new Element(\"pref\");\n\t\t\t\t\t\t\t\tpref.addChild(new Element(\"integer\", \"1\"));\n\t\t\t\t\t\t\t\tparameters.addChild(pref);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"USERID\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"text\", c1.getCData()));\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"JABBERID\":\n\t\t\t\t\tr = new Element(\"impp\");\n\t\t\t\t\tr.addChild(new Element(\"uri\", \"xmpp:\" + c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"GEO\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tr.addChild(new Element(\"uri\", \"geo:\" + c.getChildCData((Element c1) -> c1.getName() == \"LAT\") + \",\" + c.getChildCData((Element c1) -> c1.getName() == \"LON\")));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"AGENT\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\t\n\t\t\t\t\tr.addChild(new Element(\"uri\", c.getChildCData((Element c1) -> c1.getName() == \"EXTVAL\")));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ORG\":\n\t\t\t\t\tc = c.findChild((Element c1) -> c1.getName() == \"ORGNAME\");\n\t\t\t\t\tif (c != null) {\n\t\t\t\t\t\tr = new Element(\"org\");\n\t\t\t\t\t\tr.addChild(new Element(\"text\", c.getCData()));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"REV\":\n\t\t\t\t\tr = new Element(\"rev\");\n\t\t\t\t\tr.addChild(new Element(\"timestamp\", c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"SORT-STRING\":\n\t\t\t\t\tr = new Element(\"sort-as\", c.getCData());\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"SOUND\":\n\t\t\t\t\tr = new Element(\"sound\");\n\t\t\t\t\textVal = c.findChildStaticStr(new String[] { \"EXTVAL\" });\n\t\t\t\t\tif (extVal != null) {\n\t\t\t\t\t\tr.addChild(new Element(\"uri\", extVal.getCData()));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr.addChild(new Element(\"uri\", \"data:audio/basic;base64,\" + c.getChildCData((Element c1) -> c1.getName() == \"BINVAL\")));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"UID\":\n\t\t\t\tcase \"URL\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tr.addChild(new Element(\"uri\", c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"KEY\":\n\t\t\t\t\tr = new Element(c.getName().toLowerCase());\n\t\t\t\t\tr.addChild(new Element(\"text\", c.getChildCData((Element c1) -> c1.getName() == \"CRED\")));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"DESC\":\n\t\t\t\t\tr = new Element(\"note\");\n\t\t\t\t\tr.addChild(new Element(\"text\", c.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (r != null)\n\t\t\t\tvcard4.addChild(r);\n\t\t});\n\t\t\n\t\treturn vcard4;\n\t\t});\n\t\n\t\tCONVERTERS.put(VCard4.XMLNS + \"|\" + VCardTemp.XMLNS, (Element vcard4) -> {\n\t\tElement vcardTemp = new Element(VCardTemp.vCard, new String[] { \"xmlns\" }, new String[] { VCardTemp.XMLNS });\n\t\t\n\t\tvcard4.forEachChild((Element c) -> {\n\t\t\tElement r = null;\n\t\t\tElement text = null;\n\t\t\tElement uri = null;\t\n\t\t\tList<Element> list = null;\n\t\t\t\n\t\t\tElement parameters = null;\n\t\t\tElement type = null;\n\n\t\t\tswitch (c.getName()) {\n\t\t\t\tcase \"fn\":\n\t\t\t\tcase \"nickname\":\n\t\t\t\tcase \"tz\":\n\t\t\t\tcase \"title\":\n\t\t\t\tcase \"role\":\n\t\t\t\tcase \"categories\":\n\t\t\t\tcase \"note\":\n\t\t\t\tcase \"prodid\":\n\t\t\t\t\ttext = c.findChild((Element c1) -> c1.getName() == \"text\");\n\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\tr = new Element(c.getName().toUpperCase(), text.getCData());\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"n\":\n\t\t\t\t\tr = new Element(\"N\");\n\t\t\t\t\tlist = c.mapChildren((Element c1) -> {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"given\":\n\t\t\t\t\t\t\t\treturn new Element(\"GIVEN\", c1.getCData());\n\t\t\t\t\t\t\tcase \"surname\":\n\t\t\t\t\t\t\t\treturn new Element(\"FAMILY\", c1.getCData());\n\t\t\t\t\t\t\tcase \"additional\":\n\t\t\t\t\t\t\t\treturn new Element(\"MIDDLE\", c1.getCData());\n\t\t\t\t\t\t\tcase \"prefix\":\n\t\t\t\t\t\t\t\treturn new Element(\"PREFIX\", c1.getCData());\n\t\t\t\t\t\t\tcase \"suffix\":\n\t\t\t\t\t\t\t\treturn new Element(\"SUFFIX\", c1.getCData());\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\tlist.removeIf((Element c1) -> c1 == null);\n\t\t\t\t\t\tr.addChildren(list);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"photo\":\n\t\t\t\tcase \"logo\":\n\t\t\t\t\turi = c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tif (uri != null) {\n\t\t\t\t\t\tr = new Element(c.getName().toUpperCase());\n\t\t\t\t\t\tString uriStr = uri.getCData();\n\t\t\t\t\t\tMatcher matcher = DATA_URI_PATTERN.matcher(uriStr);\n\t\t\t\t\t\tif (matcher.matches()) {\n\t\t\t\t\t\t\tr.addChild(new Element(\"TYPE\", matcher.group(1)));\n\t\t\t\t\t\t\tr.addChild(new Element(\"BINVAL\", matcher.group(2)));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tr.addChild(new Element(\"EXTVAL\", uriStr));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"bday\":\n\t\t\t\t\tElement date = c.findChild((Element c1) -> c1.getName() == \"date\");\n\t\t\t\t\tif (date != null) {\n\t\t\t\t\t\tr = new Element(c.getName().toUpperCase(), date.getCData());\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"adr\":\n\t\t\t\t\tr = new Element(\"ADR\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"pobox\":\n\t\t\t\t\t\t\tcase \"street\":\n\t\t\t\t\t\t\tcase \"locality\":\n\t\t\t\t\t\t\tcase \"region\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(c1.getName().toUpperCase(), c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"ext\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"EXTADD\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase \"code\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"PCODE\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase \"country\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"CTRY\", c1.getCData()));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"parameters\":\n\t\t\t\t\t\t\t\tfor (Element c2 : c1.getChildren()) {\n\t\t\t\t\t\t\t\t\tswitch (c2.getName()) {\n\t\t\t\t\t\t\t\t\t\tcase \"type\":\n\t\t\t\t\t\t\t\t\t\t\tlist = c2.findChildren((Element c3) -> c3.getName() == \"text\");\n\t\t\t\t\t\t\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tfor (Element c3 : list) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(c3.getCData().toUpperCase()));\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tcase \"pref\":\n\t\t\t\t\t\t\t\t\t\t\ttext = c2.findChild((Element c3) -> c3.getName() == \"integer\");\n\t\t\t\t\t\t\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(\"PREF\"));\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tel\":\n\t\t\t\t\tr = new Element(\"TEL\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"parameters\":\n\t\t\t\t\t\t\t\tfor (Element c2 : c1.getChildren()) {\n\t\t\t\t\t\t\t\t\tswitch (c2.getName()) {\n\t\t\t\t\t\t\t\t\t\tcase \"type\":\n\t\t\t\t\t\t\t\t\t\t\tlist = c2.findChildren((Element c3) -> c3.getName() == \"text\");\n\t\t\t\t\t\t\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tfor (Element c3 : list) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(c3.getCData().toUpperCase()));\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tcase \"pref\":\n\t\t\t\t\t\t\t\t\t\t\ttext = c2.findChild((Element c3) -> c3.getName() == \"integer\");\n\t\t\t\t\t\t\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(\"PREF\"));\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"uri\":\n\t\t\t\t\t\t\t\tString uriStr = c1.getCData();\n\t\t\t\t\t\t\t\tMatcher matcher = TEL_URI_PATTERN.matcher(uriStr);\n\t\t\t\t\t\t\t\tif (matcher.matches()) {\n\t\t\t\t\t\t\t\t\tr.addChild(new Element(\"NUMBER\", matcher.group(1)));\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"email\":\n\t\t\t\t\tr = new Element(\"EMAIL\");\n\t\t\t\t\tfor (Element c1 : c.getChildren()) {\n\t\t\t\t\t\tswitch (c1.getName()) {\n\t\t\t\t\t\t\tcase \"parameters\":\n\t\t\t\t\t\t\t\tfor (Element c2 : c1.getChildren()) {\n\t\t\t\t\t\t\t\t\tswitch (c2.getName()) {\n\t\t\t\t\t\t\t\t\t\tcase \"type\":\n\t\t\t\t\t\t\t\t\t\t\tlist = c2.findChildren((Element c3) -> c3.getName() == \"text\");\n\t\t\t\t\t\t\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tfor (Element c3 : list) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(c3.getCData().toUpperCase()));\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tcase \"pref\":\n\t\t\t\t\t\t\t\t\t\t\ttext = c2.findChild((Element c3) -> c3.getName() == \"integer\");\n\t\t\t\t\t\t\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\t\t\t\t\t\t\tr.addChild(new Element(\"PREF\"));\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\t\t\tr.addChild(new Element(\"USERID\", c1.getCData()));\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"impp\":\n\t\t\t\t\turi = c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tif (uri != null) {\n\t\t\t\t\t\tMatcher matcher = XMPP_URI_PATTERN.matcher(uri.getCData());\n\t\t\t\t\t\tif (matcher.matches()) {\n\t\t\t\t\t\t\tr = new Element(\"JABBERID\", matcher.group(1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tcase \"geo\":\n\t\t\t\t\turi = c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tif (uri != null) {\n\t\t\t\t\t\tMatcher matcher = GEO_URI_PATTERN.matcher(uri.getCData());\n\t\t\t\t\t\tif (matcher.matches()) {\n\t\t\t\t\t\t\tr = new Element(\"GEO\");\n\t\t\t\t\t\t\tr.addChild(new Element(\"LAT\", matcher.group(1)));\n\t\t\t\t\t\t\tr.addChild(new Element(\"LON\", matcher.group(2)));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"agent\":\n\t\t\t\t\tr = new Element(c.getName().toUpperCase());\t\n\t\t\t\t\turi = c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tr.addChild(new Element(\"EXTVAL\", uri.getCData()));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"org\":\n\t\t\t\t\ttext = c.findChild((Element c1) -> c1.getName() == \"text\");\n\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\tr = new Element(\"ORG\");\n\t\t\t\t\t\tr.addChild(new Element(\"ORGNAME\", text.getCData()));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"rev\":\n\t\t\t\t\ttext = c.findChild((Element c2) -> c2.getName() == \"timestamp\");\n\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\tr = new Element(\"REV\", text.getCData());\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sort-as\":\n\t\t\t\t\tr = new Element(\"SORT-STRING\", c.getCData());\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sound\":\n\t\t\t\t\tr = new Element(\"SOUND\");\n\t\t\t\t\turi =  c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tif (uri != null) {\n\t\t\t\t\t\tMatcher matcher = DATA_URI_PATTERN.matcher(uri.getCData());\n\t\t\t\t\t\tif (matcher.matches()) {\n\t\t\t\t\t\t\tr.addChild(new Element(\"BINVAL\", matcher.group(2)));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tr.addChild(new Element(\"EXTVAL\", uri.getCData()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"uid\":\n\t\t\t\tcase \"url\":\n\t\t\t\t\turi =  c.findChild((Element c1) -> c1.getName() == \"uri\");\n\t\t\t\t\tif (uri != null) {\n\t\t\t\t\t\tr = new Element(c.getName().toUpperCase(), uri.getCData());\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"key\":\n\t\t\t\t\ttext = c.findChild((Element c1) -> c1.getName() == \"text\");\n\t\t\t\t\tif (text != null) {\n\t\t\t\t\t\tr = new Element(c.getName().toUpperCase());\n\t\t\t\t\t\tr.addChild(new Element(\"CRED\", text.getCData()));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (r != null)\n\t\t\t\tvcardTemp.addChild(r);\n\t\t});\t\t\n\t\t\n\t\treturn vcardTemp;\n\t\t});\n\t}\n\n\tpublic static Element convertVCardTempToVCard4(Element vcardTemp) {\n\t\treturn CONVERTERS.get(VCardTemp.XMLNS + \"|\" + VCard4.XMLNS).convert(vcardTemp);\n\t}\n\t\n\tpublic static Element convertVCard4ToVCardTemp(Element vcard4) {\n\t\treturn CONVERTERS.get(VCard4.XMLNS + \"|\" + VCardTemp.XMLNS).convert(vcard4);\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/AnnotatedXMPPProcessor.java",
    "content": "/*\n * AnnotatedXMPPProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Set;\nimport tigase.xml.Element;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPProcessor;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * This class is extension of {@link tigase.xmpp.XMPPProcessor XMPPProcessor}\n * which provides support for defining processor Id, supported paths and XMLNSs\n * and more using annotations\n *\n * @author andrzej\n */\npublic abstract class AnnotatedXMPPProcessor extends XMPPProcessor {\n\n\tprivate String[][] ELEMENTS;\n\tprivate String[] XMLNSS;\n\tprivate Element[] DISCO_FEATURES;\n\tprivate Element[] STREAM_FEATURES;\n\tprivate Set<StanzaType> STANZA_TYPES;\n\t\n\tprivate String ID;\n\t\n\tprotected AnnotatedXMPPProcessor() {\n\t\tClass cls = this.getClass();\n\t\t\n\t\tcmpInfo = null;\n\t\t// support for id\n\t\tId id = (Id) cls.getAnnotation(Id.class);\n\t\tif (id != null) {\n\t\t\tID = id.value();\n\t\t}\n\t\t\n\t\t// support for supported elements paths and xmlnss\n\t\tprocessHandleAnnotation(cls);\n\t\t\n\t\t// support for supported type of stanzas\n\t\tprocessHandleStazaTypesAnnotation(cls);\t\t\n\t\t\n\t\t// support for stream features\n\t\tprocessStreamFeaturesAnnotation(cls);\n\t\t\n\t\t// support for disco features\n\t\tprocessDiscoFeaturesAnnotation(cls);\n\t\t\n\t\tcmpInfo = null;\n\t}\n\t\n\t@Override\n\tpublic String id() {\n\t\treturn ID;\n\t}\n\t\n\t@Override\n\tpublic String[][] supElementNamePaths() {\n\t\treturn ELEMENTS;\n\t}\n\t\n\t@Override\n\tpublic String[] supNamespaces() {\n\t\treturn XMLNSS;\n\t}\n\n\t@Override\n\tpublic Element[] supDiscoFeatures(XMPPResourceConnection session) {\n\t\treturn DISCO_FEATURES;\n\t}\n\n\t@Override\n\tpublic Element[] supStreamFeatures(XMPPResourceConnection session) {\n\t\treturn STREAM_FEATURES;\n\t}\n\n\t@Override\n\tpublic Set<StanzaType> supTypes() {\n\t\treturn STANZA_TYPES;\n\t}\n\t\n\tprivate void processHandleAnnotation(Class cls) {\n\t\tList<String[]> elems = new ArrayList<String[]>();\n\t\tList<String> xmlnss = new ArrayList<String>();\n\t\t\n\t\tHandles handles = (Handles) cls.getAnnotation(Handles.class);\n\t\tif (handles != null) {\n\t\t\tfor (Handle handle : handles.value()) {\n\t\t\t\tprocessHandle(handle, elems, xmlnss);\n\t\t\t}\n\t\t}\n\t\tHandle handle = (Handle) cls.getAnnotation(Handle.class);\n\t\tprocessHandle(handle, elems, xmlnss);\t\t\t\n\t\t\n\t\tif (!elems.isEmpty()) {\n\t\t\tELEMENTS = elems.toArray(new String[elems.size()][]);\n\t\t\tXMLNSS = xmlnss.toArray(new String[xmlnss.size()]);\t\t\n\t\t}\n\t}\n\t\n\tprivate static void processHandle(Handle handle, List<String[]> elems, List<String> xmlnss) {\n\t\tif (handle != null) {\n\t\t\tString[] path = null;\n\t\t\tif (handle.path().length > 0) {\n\t\t\t\tpath = handle.path();\n\t\t\t} else {\n\t\t\t\tpath = handle.pathStr().split(\"/\");\n\t\t\t}\n\t\t\tfor (int i=0; i<path.length; i++) {\n\t\t\t\tpath[i] = path[i].intern();\n\t\t\t}\n\t\t\telems.add(path);\n\t\t\txmlnss.add(handle.xmlns().intern());\n\t\t}\n\t}\n\t\n\tprivate void processStreamFeaturesAnnotation(Class cls) {\n\t\tStreamFeatures streamFeatures = (StreamFeatures) cls.getAnnotation(StreamFeatures.class);\n\t\tif (streamFeatures != null) {\n\t\t\tList<Element> values = new ArrayList<Element>();\n\t\t\tfor (StreamFeature feature : streamFeatures.value()) {\n\t\t\t\tvalues.add(new Element(feature.elem(), new String[] { \"xmlns\" }, new String[] { feature.xmlns() }));\n\t\t\t}\n\t\t\tSTREAM_FEATURES = values.toArray(new Element[values.size()]);\n\t\t}\t\t\n\t}\n\t\n\tprivate void processDiscoFeaturesAnnotation(Class cls) {\n\t\tDiscoFeatures discoFeatures = (DiscoFeatures) cls.getAnnotation(DiscoFeatures.class);\n\t\tif (discoFeatures != null) {\n\t\t\tList<Element> values = new ArrayList<Element>();\n\t\t\tfor (String feature : discoFeatures.value()) {\n\t\t\t\tvalues.add(new Element(\"feature\", new String[] { \"var\" }, new String[] { feature }));\n\t\t\t}\n\t\t\tDISCO_FEATURES = values.toArray(new Element[values.size()]);\n\t\t}\t\t\n\t}\n\n\tprivate void processHandleStazaTypesAnnotation(Class cls) {\n\t\tHandleStanzaTypes handleStanzaTypes = (HandleStanzaTypes) cls.getAnnotation(HandleStanzaTypes.class);\n\t\tif (handleStanzaTypes != null) {\n\t\t\tStanzaType[] types = handleStanzaTypes.value();\n\t\t\tEnumSet<StanzaType> tmp = EnumSet.noneOf(StanzaType.class);\n\t\t\ttmp.addAll(Arrays.asList(types));\n\t\t\tSTANZA_TYPES = tmp;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/DiscoFeatures.java",
    "content": "/*\n * DiscoFeatures.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define discovery features provided by processor\n *\n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface DiscoFeatures {\n\tString[] value();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/Handle.java",
    "content": "/*\n * Handle.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define path and XMLNSS supported by implemented processor\n * \n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface Handle {\n\tString[] path() default {};\n\tString pathStr() default \"\";\n\tString xmlns();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/HandleStanzaTypes.java",
    "content": "/*\n * HandleStanzaTypes.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport tigase.xmpp.StanzaType;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define which stanza types are supported by implemented processor\n * \n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface HandleStanzaTypes {\n\tStanzaType[] value();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/Handles.java",
    "content": "/*\n * Handles.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define paths and corresponding XMLNSs supported by processor\n * \n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface Handles {\n\tHandle[] value();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/Id.java",
    "content": "/*\n * Id.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define of processor implementation\n * \n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface Id {\n\tString value();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/StreamFeature.java",
    "content": "/*\n * StreamFeature.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define supported stream features provided by processor\n *\n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface StreamFeature {\n\tString elem();\n\tString xmlns();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/annotation/StreamFeatures.java",
    "content": "/*\n * StreamFeatures.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation which placed on {@link tigase.xmpp.impl.annotation.AnnotatedXMPPProcessor AnnotatedXMPPProcessor}\n * can define supported stream features provided by processor\n *\n * @author andrzej\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface StreamFeatures {\n\tStreamFeature[] value();\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/package-info.java",
    "content": "/**\n * Package containing implementation of all Session Manager plugins\n */\npackage tigase.xmpp.impl;\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/AnonymousRoster.java",
    "content": "/*  Tigase Jabber/XMPP Server\n *  Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp.impl.roster;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.PresenceAbstract;\nimport tigase.xmpp.impl.PresenceState;\n//import tigase.xmpp.impl.Roster;\n//import tigase.xmpp.impl.Presence;\n\n\n/**\n * Describe class AnonymousRoster here.\n *\n *\n * Created: Tue Apr 22 21:41:46 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class AnonymousRoster implements DynamicRosterIfc {\n\n\t@Override\n\tpublic void init(Map<String, Object> props) {}\n\n\t@Override\n\tpublic void init(String par) {}\n\n\t@SuppressWarnings({\"unchecked\"})\n\t@Override\n\tpublic JID[] getBuddies(XMPPResourceConnection session)\n\t\tthrows NotAuthorizedException {\n\t\tif (session.isAnonymous()) {\n\t\t\tSet<JID> direct_presences =\n\t\t\t    (Set<JID>)session.getSessionData(PresenceState.DIRECT_PRESENCE);\n\t\t\tif (direct_presences != null) {\n\t\t\t\tJID[] result = new JID[direct_presences.size()];\n\t\t\t\tint i = 0;\n\t\t\t\tfor (JID peer: direct_presences) {\n\t\t\t\t\tresult[i++] = peer;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Element getBuddyItem(XMPPResourceConnection session, JID buddy)\n\t\tthrows NotAuthorizedException {\n\t\tif (session.isAnonymous()) {\n\t\t\tJID[] anon_peers = getBuddies(session);\n\t\t\tif (anon_peers != null) {\n\t\t\t\tfor (JID peer: anon_peers) {\n\t\t\t\t\tif (peer.getBareJID().equals(buddy.getBareJID())) {\n\t\t\t\t\t\tElement item = new Element(\"item\", new Element[] {\n\t\t\t\t\t\t\t\tnew Element(\"group\", \"Anonymous peers\")},\n\t\t\t\t\t\t\tnew String[] {\"jid\", \"subscription\", \"name\"},\n\t\t\t\t\t\t\tnew String[] {peer.toString(), \"both\", peer.getLocalpart()});\n\t\t\t\t\t\treturn item;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<Element> getRosterItems(XMPPResourceConnection session)\n\t\tthrows NotAuthorizedException {\n\t\tif (session.isAnonymous()) {\n\t\t\tJID[] anon_peers = getBuddies(session);\n\t\t\tif (anon_peers != null) {\n\t\t\t\tArrayList<Element> al = new ArrayList<Element>();\n\t\t\t\tfor (JID peer: anon_peers) {\n\t\t\t\t\tElement item = new Element(\"item\", new Element[] {\n\t\t\t\t\t\t\tnew Element(\"group\", \"Anonymous peers\")},\n\t\t\t\t\t\tnew String[] {\"jid\", \"subscription\", \"name\"},\n\t\t\t\t\t\tnew String[] {peer.toString(), \"both\", peer.getLocalpart()});\n\t\t\t\t\tal.add(item);\n\t\t\t\t}\n\t\t\t\treturn al;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void setItemExtraData(Element item) { }\n\n\t@Override\n\tpublic Element getItemExtraData(Element item) { return null; }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/DynamicRoster.java",
    "content": "/*\n * DynamicRoster.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Describe class DynamicRoster here.\n *\n *\n * Created: Tue Nov 6 11:28:10 2007\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class DynamicRoster {\n\tprivate static final String DYNAMIC_ROSTERS         = \"dynamic-rosters\";\n\tprivate static final String DYNAMIC_ROSTERS_CLASSES = \"dynamic-roster-classes\";\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(\"tigase.xmpp.impl.DynamicRoster\");\n\n\t//~--- methods --------------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t * @param buddies\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID[]</code>\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t */\n\tpublic static JID[] addBuddies(final XMPPResourceConnection session, final Map<String,\n\t\t\tObject> settings, JID[] buddies)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException {\n\t\tList<JID> result = getBuddiesList(session, settings);\n\n\t\tif (buddies != null) {\n\t\t\tif (result == null) {\n\t\t\t\tresult = new ArrayList<JID>();\n\t\t\t}\n\t\t\taddBuddiesToList(result, buddies);\n\n\t\t\t// result.addAll(Arrays.asList(buddies));\n\t\t}\n\t\tif ((result != null) && (result.size() > 0)) {\n\t\t\treturn result.toArray(new JID[result.size()]);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param list\n\t * @param buddies\n\t */\n\tpublic static void addBuddiesToList(List<JID> list, JID[] buddies) {\n\t\tfor (JID buddy : buddies) {\n\t\t\tif (!list.contains(buddy)) {\n\t\t\t\tlist.add(buddy);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param settings\n\t */\n\tpublic static void init_settings(final Map<String, Object> settings) {\n\t\tDynamicRosterIfc[] dynr = (DynamicRosterIfc[]) settings.get(DYNAMIC_ROSTERS);\n\n\t\tif (dynr == null) {\n\t\t\tlog.finer(\"Initializing dynamic rosters...\");\n\n\t\t\tString dynclss = (String) settings.get(DYNAMIC_ROSTERS_CLASSES);\n\n\t\t\tif (dynclss != null) {\n\t\t\t\tString[]                    dyncls = dynclss.split(\",\");\n\t\t\t\tArrayList<DynamicRosterIfc> al     = new ArrayList<DynamicRosterIfc>(50);\n\n\t\t\t\tfor (String cls : dyncls) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tDynamicRosterIfc dri = (DynamicRosterIfc) Class.forName(cls).newInstance();\n\n\t\t\t\t\t\tif (settings.get(cls + \".init\") != null) {\n\t\t\t\t\t\t\tdri.init((String) settings.get(cls + \".init\"));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdri.init(settings);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tal.add(dri);\n\t\t\t\t\t\tlog.log(Level.INFO, \"Initialized dynamic roster: {0}\", cls);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlog.log(Level.WARNING, \"Problem initializing dynmic roster class: {0}, {1}\",\n\t\t\t\t\t\t\t\tnew Object[] { cls,\n\t\t\t\t\t\t\t\te });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (al.size() > 0) {\n\t\t\t\t\tsettings.put(DYNAMIC_ROSTERS, al.toArray(new DynamicRosterIfc[al.size()]));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>JID[]</code>\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t */\n\tpublic static JID[] getBuddies(final XMPPResourceConnection session, final Map<String,\n\t\t\tObject> settings)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException {\n\t\tList<JID> result = getBuddiesList(session, settings);\n\n\t\tif ((result != null) && (result.size() > 0)) {\n\t\t\treturn result.toArray(new JID[result.size()]);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<JID>}\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t */\n\tpublic static List<JID> getBuddiesList(final XMPPResourceConnection session,\n\t\t\tfinal Map<String, Object> settings)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException {\n\t\tDynamicRosterIfc[] dynr = getDynamicRosters(settings);\n\n\t\tif (dynr != null) {\n\t\t\tArrayList<JID> result = new ArrayList<JID>();\n\n\t\t\tfor (DynamicRosterIfc dri : dynr) {\n\t\t\t\tJID[] buddies = dri.getBuddies(session);\n\n\t\t\t\tif (buddies != null) {\n\t\t\t\t\taddBuddiesToList(result, buddies);\n\n\t\t\t\t\t// result.addAll(Arrays.asList(buddies));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.size() > 0) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t * @param buddy\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of <code>Element</code>\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t */\n\tpublic static Element getBuddyItem(final XMPPResourceConnection session,\n\t\t\tfinal Map<String, Object> settings, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException {\n\t\tDynamicRosterIfc[] dynr = getDynamicRosters(settings);\n\n\t\tif (dynr != null) {\n\t\t\tfor (DynamicRosterIfc dri : dynr) {\n\t\t\t\tElement item = dri.getBuddyItem(session, buddy);\n\n\t\t\t\tif (item != null) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param settings\n\t *\n\t *\n\t *\n\t * @return a value of <code>DynamicRosterIfc[]</code>\n\t */\n\tpublic static DynamicRosterIfc[] getDynamicRosters(final Map<String, Object> settings) {\n\t\tDynamicRosterIfc[] dynr = null;\n\n\t\tif (settings != null) {\n\t\t\tsynchronized (settings) {\n\t\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\t\tlog.finest(\"Initializing settings.\");\n\t\t\t\t}\n\t\t\t\tinit_settings(settings);\n\t\t\t}\n\t\t\tdynr = (DynamicRosterIfc[]) settings.get(DYNAMIC_ROSTERS);\n\t\t} else {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"Settings parameter is NULL\");\n\t\t\t}\n\t\t}\n\n\t\treturn dynr;\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t * @param item\n\t *\n\t *\n\t *\n\t * @return a value of <code>Element</code>\n\t */\n\tpublic static Element getItemExtraData(XMPPResourceConnection session, Map<String,\n\t\t\tObject> settings, Element item) {\n\t\tDynamicRosterIfc[] dynr = getDynamicRosters(settings);\n\n\t\tif (dynr != null) {\n\t\t\tElement result = null;\n\n\t\t\tfor (DynamicRosterIfc dri : dynr) {\n\t\t\t\tif ((result = dri.getItemExtraData(item)) != null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t *\n\t *\n\t *\n\t *\n\t * @return a value of {@code List<Element>}\n\t * @throws NotAuthorizedException\n\t * @throws RepositoryAccessException\n\t * @throws RosterRetrievingException\n\t */\n\tpublic static List<Element> getRosterItems(final XMPPResourceConnection session,\n\t\t\tfinal Map<String, Object> settings)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException {\n\t\tDynamicRosterIfc[] dynr = getDynamicRosters(settings);\n\n\t\tif (dynr != null) {\n\t\t\tArrayList<Element> result = new ArrayList<Element>();\n\n\t\t\tfor (DynamicRosterIfc dri : dynr) {\n\t\t\t\tList<Element> items = dri.getRosterItems(session);\n\n\t\t\t\tif (items != null) {\n\t\t\t\t\tresult.addAll(items);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.size() > 0) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param session\n\t * @param settings\n\t * @param item\n\t */\n\tpublic static void setItemExtraData(XMPPResourceConnection session, Map<String,\n\t\t\tObject> settings, Element item) {\n\t\tDynamicRosterIfc[] dynr = getDynamicRosters(settings);\n\n\t\tif (dynr != null) {\n\t\t\tfor (DynamicRosterIfc dri : dynr) {\n\t\t\t\tdri.setItemExtraData(item);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/DynamicRosterIfc.java",
    "content": "/*\n * DynamicRosterIfc.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Interface <code>DynamicRosterIfc</code> is to dynamically generate user roster\n * entries when the user requests the roster content. The dynamic roster\n * feature doesn't replace the normal roster with entries added by the\n * user. It just allows you to inject extra contacts lists to the user roster.\n * <br>\n * There is a very simple example implementing this interface which creates\n * roster entries for anonymous users - <code>tigase.xmpp.impl.AnonymousRoster</code>.\n * You can use it as a starting point for your code.\n * <br>\n * You can have as many implementations of this interface loaded at the same\n * time as you need and all of them are called for each user roster request.\n * <br>\n * To load your implementations you have to specify them in the configuration\n * file. The simplest way is to use <code>init.properties</code> file. Have a look\n * at the example file available in the repository. Following line added to\n * the end of the file tell the server to load the dynamic roster implementation:\n * <pre>sess-man/plugins-conf/dynamic-roster-classes=tigase.xmpp.impl.AnonymousRoster</pre>\n * If you want to load more implementations you just put a comma separated list\n * of classes instead. If your implementation needs to connect to a database\n * or any other resource or just needs extra configuration parameters you can\n * also specify them in the properties file:\n * <pre>sess-man/plugins-conf/dynamic-roster-classes=tigase.xmpp.impl.AnonymousRoster\n * sess-man/plugins-conf/dbinit=jdbc:jtds:mysql://localhost/roster-db;user=user-name;password=db-passwd\n * sess-man/plugins-conf/max-buddies=1000\n * </pre>\n * Basically all parameters starting with string:\n * <code>sess-man/plugins-conf/</code> will be provided at\n * initialization time in the <code>init(....)</code> method.\n * <br>\n * There is also a simplified form for providing configuration parameters. It is\n * used if you want to provide just one parameter to the object (like database\n * connection string):\n * <pre>sess-man/plugins-conf/tigase.xmpp.impl.AnonymousRoster.init=configuration-string</pre>\n * <br>\n * Created: Mon Oct 29 08:52:22 2007\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic interface DynamicRosterIfc {\n\t/**\n\t * <code>init</code> method is used to provide configuration parameters\n\t * and initialize the object. Please have a look at the interface description\n\t * for more details about configuration parameters. The object is never used\n\t * before it's <code>init(...)</code> method is called but it might be\n\t * used straight away after the method has finished.\n\t *\n\t * @param props a {@code Map<String, Object> props} is a configuration\n\t * parameters map in the form: key:value exactly as they were specified\n\t * in the configuration file.\n\t */\n\tvoid init(Map<String, Object> props);\n\n\t/**\n\t * <code>init</code> method is called at the initialization time when simple\n\t * form of startup parameters are used:\n\t * <pre>sess-man/plugins-conf/class-name.init=configuration-string</pre>\n\t * The <code>configuration-string</code> is passed to this <code>init(...)</code>\n\t * method in exact form as it was found in the configuration file.\n\t *\n\t * @param par a <code>String</code> value of the configuration string.\n\t */\n\tvoid init(String par);\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t/**\n\t * <code>getBuddies</code> method returns <code>String</code> array with\n\t * all roster buddies JIDs. Normally they are bare JIDs (without resource part).\n\t * This method is normally used by presence plugin to send probe and initial\n\t * presence to all contacts in the dynamic roster.\n\t *\n\t * @param session a <code>XMPPResourceConnection</code> value of the connection\n\t * session object.\n\t * @return a <code>String[]</code> array of bare JIDs for the dynamic part\n\t * of the user roster.\n\t * @exception NotAuthorizedException may be thrown if the connection session\n\t * is not yet authenticated but authorization is required to access roster data.\n\t * @exception RosterRetrievingException may be thrown when an unknown error in the\n\t * custom roster retrieving logic occurs. A message from the exception must be sent\n\t * back to a user as an error message.\n\t * @exception RepositoryAccessException may be thrown when there is an error accessing\n\t * the roster data repository, even though the user is correctly authenticated. No\n\t * error is sent back to a user, only an empty roster but the repository exception is\n\t * logged to the log file.\n\t */\n\tJID[] getBuddies(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException;\n\n\t/**\n\t * <code>getBuddyItem</code> method returns buddy item element for a given JID\n\t * or <code>null</code> if the buddy doesn't exist on the user roster list.\n\t *\n\t * @param session a <code>XMPPResourceConnection</code> value of the connection\n\t * session object.\n\t * @param buddy a <code>String</code> value of the buddy JID. It may be bare JID\n\t * or full JID.\n\t * @return an <code>Element</code> value of the XML element with all the roster\n\t * item data - JID, subscription, nick name and groups. Sample code for creating\n\t * the buddy element could look like this:\n\t * <pre>Element item = new Element(\"item\", new Element[] {\n\t *     new Element(\"group\", \"Tigase devs\")},\n\t *  new String[] {\"jid\", \"subscription\", \"name\"},\n\t *  new String[] {peer, \"both\", JIDUtils.getNodeNick(peer)});</pre>\n\t * @exception NotAuthorizedException may be thrown if the connection session\n\t * is not yet authenticated but authorization is required to access roster data.\n\t * @exception RosterRetrievingException may be thrown when an unknown error in the\n\t * custom roster retrieving logic occurs. A message from the exception must be sent\n\t * back to a user as an error message.\n\t * @exception RepositoryAccessException may be thrown when there is an error accessing\n\t * the roster data repository, even though the user is correctly authenticated. No\n\t * error is sent back to a user, only an empty roster but the repository exception is\n\t * logged to the log file.\n\t */\n\tElement getBuddyItem(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException;\n\n\t/**\n\t * Returns a new roster Item element with additional, non-standard information\n\t * for a given item. This is a way to associate custom roster information with\n\t * a contact.\n\t *\n\t *\n\t * @param item is a <code>Element</code>\n\t *\n\t * @return a value of <code>Element</code>\n\t */\n\tElement getItemExtraData(Element item);\n\n\t/**\n\t * <code>getRosterItems</code> method returns a full list with all buddies\n\t * generated by this dynamic roster implementation. The list contains all\n\t * contacts for the roster with all contacts details - buddy JID, nick name,\n\t * subscription (typically always both) and groups. Please have a look at\n\t * <code>getBuddyItem(...)</code> description for details how to create\n\t * an Element entry for the roster item.\n\t * <br>\n\t * In theory you could here\n\t * call the <code>getBuddies(...)</code> method and then for each entry from\n\t * the array call the <code>getBuddyItem(...)</code>. I strongly advice to\n\t * not do it. This is a server with thousands of connected users and possibly\n\t * thousands of packets going through the server. Think of a performance and\n\t * execute database query once if possible rather then many times.\n\t *\n\t * @param session a <code>XMPPResourceConnection</code> value of the connection\n\t * session object.\n\t * @return a {@code List<Element>} value\n\t * @exception NotAuthorizedException may be thrown if the connection session\n\t * is not yet authenticated but authorization is required to access roster data.\n\t * @exception RosterRetrievingException may be thrown when an unknown error in the\n\t * custom roster retrieving logic occurs. A message from the exception must be sent\n\t * back to a user as an error message.\n\t * @exception RepositoryAccessException may be thrown when there is an error accessing\n\t * the roster data repository, even though the user is correctly authenticated. No\n\t * error is sent back to a user, only an empty roster but the repository exception is\n\t * logged to the log file.\n\t */\n\tList<Element> getRosterItems(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, RosterRetrievingException,\n\t\t\t\t\t\t\tRepositoryAccessException;\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t/**\n\t * Method description\n\t *\n\t *\n\t * @param item is a <code>Element</code>\n\t */\n\tvoid setItemExtraData(Element item);\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/29\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/DynamicRosterTest.java",
    "content": "/*\n * DynamicRosterTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\n\n/**\n * Created: Nov 28, 2008 10:27:55 PM\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic class DynamicRosterTest\n\t\t\t\timplements DynamicRosterIfc {\n\tprivate static Logger log = Logger.getLogger(DynamicRosterTest.class.getName());\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate Map<String, Element> memStorage = new LinkedHashMap<String, Element>();\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic JID[] getBuddies(XMPPResourceConnection session) throws NotAuthorizedException {\n\t\treturn new JID[] { JID.jidInstanceNS(\"dynrost@test-d\") };\n\t}\n\n\t@Override\n\tpublic Element getBuddyItem(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tif (\"dynrost@test-d\".equals(buddy.getBareJID().toString())) {\n\t\t\treturn getBuddy();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic Element getItemExtraData(Element item) {\n\t\tString jid     = item.getAttributeStaticStr(\"jid\");\n\t\tElement result = memStorage.get(jid);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Retrieving item: {0}, for jid={1}\", new Object[] { result,\n\t\t\t\t\t\t\tjid });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic List<Element> getRosterItems(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\treturn new ArrayList<Element>(Arrays.asList(getBuddy()));\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void init(Map<String, Object> props) {}\n\n\t@Override\n\tpublic void init(String par) {}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setItemExtraData(Element item) {\n\t\tString jid = item.getAttributeStaticStr(\"jid\");\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Storing item: {0}, for jid={1}\", new Object[] { item, jid });\n\t\t}\n\t\tmemStorage.put(jid, item);\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\tprivate Element getBuddy() {\n\t\treturn new Element(\"item\", new Element[] { new Element(\"group\", \"test group\") },\n\t\t\t\t\t\t\t\t\t\t\t new String[] { \"jid\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"name\", \"subscription\" }, new String[] {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dynrost@test-d\", \"dynrost\", \"both\" });\n\t}\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/DynamicRosterTest123.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: 2411 $\n * Last modified by $Author: kobit $\n * $Date: 2010-10-27 20:27:58 -0600 (Wed, 27 Oct 2010) $\n * \n */\npackage tigase.xmpp.impl.roster;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * @author Artur Hefczyc Created Apr 1, 2011\n */\npublic class DynamicRosterTest123 implements DynamicRosterIfc {\n\n\tprivate static final String[] buddy_names = { \"test1\", \"test2\", \"test3\" };\n\n\t@Override\n\tpublic void setItemExtraData(Element item) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic Element getItemExtraData(Element item) {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void init(Map<String, Object> props) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic void init(String par) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic JID[] getBuddies(XMPPResourceConnection session) throws NotAuthorizedException {\n\t\tString domain = session.getDomain().getVhost().getDomain();\n\t\tArrayList<JID> result = new ArrayList<JID>(buddy_names.length);\n\t\tfor (String name : buddy_names) {\n\t\t\tif (!name.equals(session.getUserName())) {\n\t\t\t\tresult.add(JID.jidInstanceNS(name, domain, null));\n\t\t\t}\n\t\t}\n\t\treturn result.toArray(new JID[result.size()]);\n\t}\n\n\t@Override\n\tpublic Element getBuddyItem(XMPPResourceConnection session, JID buddy)\n\t\t\tthrows NotAuthorizedException {\n\t\treturn new Element(\"item\", new Element[] { new Element(\"group\", \"test group\") },\n\t\t\t\tnew String[] { \"jid\", \"name\", \"subscription\" }, new String[] {\n\t\t\t\t\t\tbuddy.getBareJID().toString(), buddy.getLocalpart(), \"both\" });\n\t}\n\n\t@Override\n\tpublic List<Element> getRosterItems(XMPPResourceConnection session)\n\t\t\tthrows NotAuthorizedException {\n\t\tArrayList<Element> result = new ArrayList<Element>(buddy_names.length);\n\t\tfor (JID buddy : getBuddies(session)) {\n\t\t\t\tresult.add(getBuddyItem(session, buddy));\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RepositoryAccessException.java",
    "content": "/*\n * RepositoryAccessException.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPException;\n\n/**\n *\n * @author kobit\n */\npublic class RepositoryAccessException\n\t\t\t\textends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>PacketErrorTypeException</code> instance.\n\t *\n\t * @param message\n\t */\n\tpublic RepositoryAccessException(String message) {\n\t\tsuper(message);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param message\n\t * @param cause\n\t */\n\tpublic RepositoryAccessException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/27\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/Roster.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.logging.Logger;\n\n//~--- classes ----------------------------------------------------------------\n\n/**\n * Describe class Roster here.\n *\n *\n * Created: Tue Feb 21 18:05:53 2006\n *\n * @deprecated RosterFlat should be used instead\n *\n */\n@Deprecated\npublic class Roster extends RosterAbstract {\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static Logger log = Logger.getLogger(\"tigase.xmpp.impl.Roster\");\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic void addBuddy(XMPPResourceConnection session, JID jid, String name, String[] groups,\n\t\t\tString otherData)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tString nick = name;\n\n\t\tif ((nick == null) || nick.trim().isEmpty()) {\n\t\t\tnick = jid.getLocalpart();\n\n\t\t\tif ((nick == null) || nick.trim().isEmpty()) {\n\t\t\t\tnick = jid.toString();\n\t\t\t}\n\t\t}\n\n\t\tsession.setData(groupNode(jid), NAME, nick);\n\t\tsession.setData(groupNode(jid), SUBSCRIPTION, SubscriptionType.none.toString());\n\t\tsession.setDataList(groupNode(jid), GROUPS, groups);\n\t}\n\n\t@Override\n\tpublic boolean addBuddyGroup(XMPPResourceConnection session, JID buddy, String[] groups)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t@Override\n\tpublic boolean containsBuddy(XMPPResourceConnection session, JID buddy)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tthrow new UnsupportedOperationException(\"Not supported yet.\");\n\t}\n\n\t//~--- get methods ----------------------------------------------------------\n\n\t@Override\n\tpublic JID[] getBuddies(final XMPPResourceConnection session)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tString[] jids = session.getDataGroups(ROSTER);\n\n\t\tif ((jids != null) && (jids.length > 0)) {\n\t\t\tJID[] result = new JID[jids.length];\n\t\t\tint idx = 0;\n\n\t\t\tfor (String jid : jids) {\n\t\t\t\ttry {\n\t\t\t\t\tresult[idx++] = JID.jidInstance(jid);\n\t\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\t\tlog.warning(\"Can't load user jid from database, stringprep problem: \" + jid);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String[] getBuddyGroups(final XMPPResourceConnection session, JID buddy)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn session.getDataList(groupNode(buddy), GROUPS);\n\t}\n\n\t@Override\n\tpublic String getBuddyName(final XMPPResourceConnection session, JID buddy)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn session.getData(groupNode(buddy), NAME, null);\n\t}\n\n\t@Override\n\tpublic SubscriptionType getBuddySubscription(final XMPPResourceConnection session, JID buddy)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// return SubscriptionType.both;\n\t\tString subscr = session.getData(groupNode(buddy), SUBSCRIPTION, null);\n\n\t\tif (subscr != null) {\n\t\t\treturn SubscriptionType.valueOf(subscr);\n\t\t}\n\n\t\treturn null;\n\t}\n\t\n\t@Override\n\tpublic boolean isRosterLoaded(XMPPResourceConnection session) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isOnline(XMPPResourceConnection session, JID jid)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn true;\n\t}\n\n\t//~--- methods --------------------------------------------------------------\n\n\t@Override\n\tpublic boolean presenceSent(XMPPResourceConnection session, JID jid)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean removeBuddy(final XMPPResourceConnection session, JID jid)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsession.removeDataGroup(groupNode(jid));\n\n\t\treturn true;\n\t}\n\n\t//~--- set methods ----------------------------------------------------------\n\n\t@Override\n\tpublic void setBuddyName(final XMPPResourceConnection session, JID buddy, final String name)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsession.setData(groupNode(buddy), NAME, name);\n\t}\n\n\t@Override\n\tpublic void setBuddySubscription(final XMPPResourceConnection session,\n\t\t\tfinal SubscriptionType subscription, JID buddy)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tsession.setData(groupNode(buddy), SUBSCRIPTION, subscription.toString());\n\t}\n\n\t@Override\n\tpublic void setOnline(XMPPResourceConnection session, JID jid, boolean online)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {}\n\n\t@Override\n\tpublic void setPresenceSent(XMPPResourceConnection session, JID jid, boolean sent)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {}\n\n\t@Override\n\tpublic RosterElement getRosterElement(XMPPResourceConnection session, JID jid)\n\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void logout(XMPPResourceConnection session) {\n\t}\n\t\n\t@Override\n\tpublic Element getCustomChild(XMPPResourceConnection session, JID buddy) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RosterAbstract.java",
    "content": "/*\n * RosterAbstract.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserRepository;\n\nimport tigase.server.Packet;\nimport tigase.server.PolicyViolationException;\n\nimport tigase.util.Algorithms;\n\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport java.util.Map;\nimport java.util.Queue;\n\n/**\n * Describe class RosterAbstract here.\n *\n *\n * Created: Thu Sep 4 18:09:52 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic abstract class RosterAbstract {\n\t/** Field description */\n\tpublic static final String CLIENT_XMLNS = \"jabber:client\";\n\n\t/** Field description */\n\tpublic static final String GROUP = \"group\";\n\n\t/** Field description */\n\tpublic static final String GROUPS = \"groups\";\n\n\t/** Field description */\n\tpublic static final String NAME = \"name\";\n\n\t/** Field description */\n\tpublic static final String ROSTER = \"roster\";\n\n\t/** Field description */\n\tpublic static final String ROSTER_XMLNS = \"jabber:iq:roster\";\n\n\t/** Field description */\n\tpublic static final String ROSTERHASH = \"rosterhash\";\n\n\t/** Field description */\n\tpublic static final String SUBSCRIPTION = \"subscription\";\n\n\t/** Field description */\n\tpublic static final String VER_ATT = \"ver\";\n\n\t/** Field description */\n\tpublic static final String XMLNS = \"jabber:iq:roster\";\n\t\n\t/** Field description */\n\tpublic static final String XMLNS_DYNAMIC = \"jabber:iq:roster-dynamic\";\n\n\t/** Field description */\n\tpublic static final String XMLNS_LOAD = XMLNS + \"-load\";\n\t\n\t// ~--- static fields --------------------------------------------------------\n\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log = Logger.getLogger(RosterAbstract.class.getName());\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> TO_SUBSCRIBED = EnumSet.of(\n\t\t\tSubscriptionType.to, SubscriptionType.to_pending_in, SubscriptionType.both);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> SUB_TO = EnumSet.of(SubscriptionType.to,\n\t\t\tSubscriptionType.to_pending_in);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> SUB_NONE = EnumSet.of(SubscriptionType\n\t\t\t.none, SubscriptionType.none_pending_out, SubscriptionType.none_pending_in,\n\t\t\tSubscriptionType.none_pending_out_in);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> SUB_FROM = EnumSet.of(SubscriptionType\n\t\t\t.from, SubscriptionType.from_pending_out);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> SUB_BOTH = EnumSet.of(SubscriptionType\n\t\t\t.both);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> PENDING_OUT = EnumSet.of(SubscriptionType\n\t\t\t.none_pending_out, SubscriptionType.none_pending_out_in, SubscriptionType\n\t\t\t.from_pending_out);\n\n\t/** Field description */\n\tpublic static final EnumSet<SubscriptionType> PENDING_IN = EnumSet.of(SubscriptionType\n\t\t\t.none_pending_in, SubscriptionType.none_pending_out_in, SubscriptionType\n\t\t\t.to_pending_in);\n\n\t/** Field description */\n\tpublic static final EnumSet<StanzaType> INITIAL_PRESENCES = EnumSet.of(StanzaType\n\t\t\t.available, StanzaType.unavailable);\n\n\t/** Holds all {link @SubscriptionType} elements that can be perceived as <em>FROM</em> subscription */\n\tpublic static final EnumSet<SubscriptionType> FROM_SUBSCRIBED = EnumSet.of(\n\t\t\tSubscriptionType.from, SubscriptionType.from_pending_out, SubscriptionType.both);\n\n\t/** Field description */\n\tpublic static final Element[] FEATURES = { new Element(\"ver\", new String[] { \"xmlns\" },\n\t\t\tnew String[] { \"urn:xmpp:features:rosterver\" }) };\n\n\t/** Field description */\n\tpublic static final Element[] DISCO_FEATURES = { new Element(\"feature\", new String[] {\n\t\t\t\"var\" }, new String[] { XMLNS }),\n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { XMLNS_DYNAMIC }) };\n\tprivate static EnumMap<SubscriptionType, StateTransition> subsToStateMap =\n\t\t\tnew EnumMap<SubscriptionType, StateTransition>(SubscriptionType.class);\n\n\tprotected static boolean emptyNameAllowed = false;\n\tprotected static int maxRosterSize         = new Long(Runtime.getRuntime().maxMemory() / 250000L).intValue();\n\n\t//~--- static initializers --------------------------------------------------\n\n\t// ~--- static initializers --------------------------------------------------\n\tstatic {\n\t\tsubsToStateMap.put(SubscriptionType.none, StateTransition.none);\n\t\tsubsToStateMap.put(SubscriptionType.none_pending_out, StateTransition\n\t\t\t\t.none_pending_out);\n\t\tsubsToStateMap.put(SubscriptionType.none_pending_in, StateTransition.none_pending_in);\n\t\tsubsToStateMap.put(SubscriptionType.none_pending_out_in, StateTransition\n\t\t\t\t.none_pending_out_in);\n\t\tsubsToStateMap.put(SubscriptionType.to, StateTransition.to);\n\t\tsubsToStateMap.put(SubscriptionType.to_pending_in, StateTransition.to_pending_in);\n\t\tsubsToStateMap.put(SubscriptionType.from, StateTransition.from);\n\t\tsubsToStateMap.put(SubscriptionType.from_pending_out, StateTransition\n\t\t\t\t.from_pending_out);\n\t\tsubsToStateMap.put(SubscriptionType.both, StateTransition.both);\n\t}\n\n\t//~--- constant enums -------------------------------------------------------\n\n\t// ~--- constant enums -------------------------------------------------------\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum PresenceType {\n\t\tout_initial, out_subscribe, out_unsubscribe, out_subscribed, out_unsubscribed,\n\t\t\t\tout_probe, in_initial, in_subscribe, in_unsubscribe, in_subscribed,\n\t\t\t\tin_unsubscribed, in_probe, error;\n\t}\n\n\t//~--- enums ----------------------------------------------------------------\n\n\t// Below StateTransition enum is implementation of all below tables\n\t// coming from RFC-3921\n\t// Table 1: Recommended handling of outbound \"subscribed\" stanzas\n\t// +----------------------------------------------------------------+\n\t// | EXISTING STATE | ROUTE? | NEW STATE |\n\t// +----------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | no | no state change |\n\t// | \"None + Pending In\" | yes | \"From\" |\n\t// | \"None + Pending Out/In\" | yes | \"From + Pending Out\" |\n\t// | \"To\" | no | no state change |\n\t// | \"To + Pending In\" | yes | \"Both\" |\n\t// | \"From\" | no | no state change |\n\t// | \"From + Pending Out\" | no | no state change |\n\t// | \"Both\" | no | no state change |\n\t// +----------------------------------------------------------------+\n\t// Table 2: Recommended handling of outbound \"unsubscribed\" stanzas\n\t// +----------------------------------------------------------------+\n\t// | EXISTING STATE | ROUTE? | NEW STATE |\n\t// +----------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | no | no state change |\n\t// | \"None + Pending In\" | yes | \"None\" |\n\t// | \"None + Pending Out/In\" | yes | \"None + Pending Out\" |\n\t// | \"To\" | no | no state change |\n\t// | \"To + Pending In\" | yes | \"To\" |\n\t// | \"From\" | yes | \"None\" |\n\t// | \"From + Pending Out\" | yes | \"None + Pending Out\" |\n\t// | \"Both\" | yes | \"To\" |\n\t// +----------------------------------------------------------------+\n\t// Table 3: Recommended handling of inbound \"subscribe\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | DELIVER? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | yes | \"None + Pending In\" |\n\t// | \"None + Pending Out\" | yes | \"None + Pending Out/In\" |\n\t// | \"None + Pending In\" | no | no state change |\n\t// | \"None + Pending Out/In\" | no | no state change |\n\t// | \"To\" | yes | \"To + Pending In\" |\n\t// | \"To + Pending In\" | no | no state change |\n\t// | \"From\" | no * | no state change |\n\t// | \"From + Pending Out\" | no * | no state change |\n\t// | \"Both\" | no * | no state change |\n\t// +------------------------------------------------------------------+\n\t// Table 4: Recommended handling of inbound \"unsubscribe\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | DELIVER? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | no | no state change |\n\t// | \"None + Pending In\" | yes * | \"None\" |\n\t// | \"None + Pending Out/In\" | yes * | \"None + Pending Out\" |\n\t// | \"To\" | no | no state change |\n\t// | \"To + Pending In\" | yes * | \"To\" |\n\t// | \"From\" | yes * | \"None\" |\n\t// | \"From + Pending Out\" | yes * | \"None + Pending Out\" |\n\t// | \"Both\" | yes * | \"To\" |\n\t// +------------------------------------------------------------------+\n\t// Table 5: Recommended handling of inbound \"subscribed\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | DELIVER? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | yes | \"To\" |\n\t// | \"None + Pending In\" | no | no state change |\n\t// | \"None + Pending Out/In\" | yes | \"To + Pending In\" |\n\t// | \"To\" | no | no state change |\n\t// | \"To + Pending In\" | no | no state change |\n\t// | \"From\" | no | no state change |\n\t// | \"From + Pending Out\" | yes | \"Both\" |\n\t// | \"Both\" | no | no state change |\n\t// +------------------------------------------------------------------+\n\t// Table 6: Recommended handling of inbound \"unsubscribed\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | DELIVER? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | yes | \"None\" |\n\t// | \"None + Pending In\" | no | no state change |\n\t// | \"None + Pending Out/In\" | yes | \"None + Pending In\" |\n\t// | \"To\" | yes | \"None\" |\n\t// | \"To + Pending In\" | yes | \"None + Pending In\" |\n\t// | \"From\" | no | no state change |\n\t// | \"From + Pending Out\" | yes | \"From\" |\n\t// | \"Both\" | yes | \"From\" |\n\t// +------------------------------------------------------------------+\n\t// There are 2 tables missing I think in RFC-3921:\n\t// Table 7: Recommended handling of outbound \"subscribe\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | ROUTE? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | yes | \"None + Pending Out\" |\n\t// | \"None + Pending Out\" | no | no state change |\n\t// | \"None + Pending In\" | yes | \"None + Pending Out/In\" |\n\t// | \"None + Pending Out/In\" | no | no state change |\n\t// | \"To\" | no | no state change |\n\t// | \"To + Pending In\" | no | no state change |\n\t// | \"From\" | yes | \"From + Pending Out\" |\n\t// | \"From + Pending Out\" | no | no state change |\n\t// | \"Both\" | no | no state change |\n\t// +------------------------------------------------------------------+\n\t// Table 8: Recommended handling of outbound \"unsubscribe\" stanzas\n\t// +------------------------------------------------------------------+\n\t// | EXISTING STATE | ROUTE? | NEW STATE |\n\t// +------------------------------------------------------------------+\n\t// | \"None\" | no | no state change |\n\t// | \"None + Pending Out\" | yes | \"None\" |\n\t// | \"None + Pending In\" | no | no state change |\n\t// | \"None + Pending Out/In\" | yes | \"None + Pending In\" |\n\t// | \"To\" | yes | \"None\" |\n\t// | \"To + Pending In\" | yes | \"None + Pending In\" |\n\t// | \"From\" | no | no state change |\n\t// | \"From + Pending Out\" | yes | \"From\" |\n\t// | \"Both\" | yes | \"From\" |\n\t// +------------------------------------------------------------------+\n\n\t/**\n\t * Enum description\n\t *\n\t */\n\tpublic enum StateTransition {\n\t\tnone(SubscriptionType.none,                                       // Table 1.\n\t\t\t\t SubscriptionType.none,                                       // Table 2.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 3.\n\t\t\t\t SubscriptionType.none,                                       // Table 4.\n\t\t\t\t SubscriptionType.none,                                       // Table 5.\n\t\t\t\t SubscriptionType.none,                                       // Table 6.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 7.\n\t\t\t\t SubscriptionType.none                                        // Table 8.\n\t\t\t\t ), none_pending_out(SubscriptionType.none_pending_out,       // Table 1.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 2.\n\t\t\t\t SubscriptionType.none_pending_out_in,                        // Table 3.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 4.\n\t\t\t\t SubscriptionType.to,                                         // Table 5.\n\t\t\t\t SubscriptionType.none,                                       // Table 6.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 7.\n\t\t\t\t SubscriptionType.none                                        // Table 8.\n\t\t\t\t ), none_pending_in(SubscriptionType.from,                    // Table 1.\n\t\t\t\t SubscriptionType.none,                                       // Table 2.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 3.\n\t\t\t\t SubscriptionType.none,                                       // Table 4.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 5.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 6.\n\t\t\t\t SubscriptionType.none_pending_out_in,                        // Table 7.\n\t\t\t\t SubscriptionType.none_pending_in                             // Table 8.\n\t\t\t\t ), none_pending_out_in(SubscriptionType.from_pending_out,    // Table 1.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 2.\n\t\t\t\t SubscriptionType.none_pending_out_in,                        // Table 3.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 4.\n\t\t\t\t SubscriptionType.to_pending_in,                              // Table 5.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 6.\n\t\t\t\t SubscriptionType.none_pending_out_in,                        // Table 7.\n\t\t\t\t SubscriptionType.none_pending_in                             // Table 8.\n\t\t\t\t ), to(SubscriptionType.to,                                   // Table 1.\n\t\t\t\t SubscriptionType.to,                                         // Table 2.\n\t\t\t\t SubscriptionType.to_pending_in,                              // Table 3.\n\t\t\t\t SubscriptionType.to,                                         // Table 4.\n\t\t\t\t SubscriptionType.to,                                         // Table 5.\n\t\t\t\t SubscriptionType.none,                                       // Table 6.\n\t\t\t\t SubscriptionType.to,                                         // Table 7.\n\t\t\t\t SubscriptionType.none                                        // Table 8.\n\t\t\t\t ), to_pending_in(SubscriptionType.both,                      // Table 1.\n\t\t\t\t SubscriptionType.to,                                         // Table 2.\n\t\t\t\t SubscriptionType.to_pending_in,                              // Table 3.\n\t\t\t\t SubscriptionType.to,                                         // Table 4.\n\t\t\t\t SubscriptionType.to_pending_in,                              // Table 5.\n\t\t\t\t SubscriptionType.none_pending_in,                            // Table 6.\n\t\t\t\t SubscriptionType.to_pending_in,                              // Table 7.\n\t\t\t\t SubscriptionType.none_pending_in                             // Table 8.\n\t\t\t\t ), from(SubscriptionType.from,                               // Table 1.\n\t\t\t\t SubscriptionType.none,                                       // Table 2.\n\t\t\t\t SubscriptionType.from,                                       // Table 3.\n\t\t\t\t SubscriptionType.none,                                       // Table 4.\n\t\t\t\t SubscriptionType.from,                                       // Table 5.\n\t\t\t\t SubscriptionType.from,                                       // Table 6.\n\t\t\t\t SubscriptionType.from_pending_out,                           // Table 7.\n\t\t\t\t SubscriptionType.from                                        // Table 8.\n\t\t\t\t ), from_pending_out(SubscriptionType.from_pending_out,       // Table 1.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 2.\n\t\t\t\t SubscriptionType.from_pending_out,                           // Table 3.\n\t\t\t\t SubscriptionType.none_pending_out,                           // Table 4.\n\t\t\t\t SubscriptionType.both,                                       // Table 5.\n\t\t\t\t SubscriptionType.from,                                       // Table 6.\n\t\t\t\t SubscriptionType.from_pending_out,                           // Table 7.\n\t\t\t\t SubscriptionType.from                                        // Table 8.\n\t\t\t\t ), both(SubscriptionType.both,                               // Table 1.\n\t\t\t\t SubscriptionType.to,                                         // Table 2.\n\t\t\t\t SubscriptionType.both,                                       // Table 3.\n\t\t\t\t SubscriptionType.to,                                         // Table 4.\n\t\t\t\t SubscriptionType.both,                                       // Table 5.\n\t\t\t\t SubscriptionType.from,                                       // Table 6.\n\t\t\t\t SubscriptionType.both,                                       // Table 7.\n\t\t\t\t SubscriptionType.from                                        // Table 8.\n\t\t\t\t );\n\n\t\tprivate EnumMap<PresenceType, SubscriptionType> stateTransition =\n\t\t\t\tnew EnumMap<PresenceType, SubscriptionType>(PresenceType.class);\n\n\t\t//~--- constructors -------------------------------------------------------\n\n\t\t// ~--- constructors -------------------------------------------------------\n\t\tprivate StateTransition(SubscriptionType out_subscribed,\n\t\t\t\tSubscriptionType out_unsubscribed, SubscriptionType in_subscribe,\n\t\t\t\tSubscriptionType in_unsubscribe, SubscriptionType in_subscribed,\n\t\t\t\tSubscriptionType in_unsubscribed, SubscriptionType out_subscribe,\n\t\t\t\tSubscriptionType out_unsubscribe) {\n\t\t\tstateTransition.put(PresenceType.out_subscribed, out_subscribed);\n\t\t\tstateTransition.put(PresenceType.out_unsubscribed, out_unsubscribed);\n\t\t\tstateTransition.put(PresenceType.in_subscribe, in_subscribe);\n\t\t\tstateTransition.put(PresenceType.in_unsubscribe, in_unsubscribe);\n\t\t\tstateTransition.put(PresenceType.in_subscribed, in_subscribed);\n\t\t\tstateTransition.put(PresenceType.in_unsubscribed, in_unsubscribed);\n\t\t\tstateTransition.put(PresenceType.out_subscribe, out_subscribe);\n\t\t\tstateTransition.put(PresenceType.out_unsubscribe, out_unsubscribe);\n\t\t}\n\n\t\tpublic SubscriptionType getStateTransition(PresenceType pres_type) {\n\t\t\tSubscriptionType res = stateTransition.get(pres_type);\n\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.finest(\"this=\" + this.toString() + \", pres_type=\" + pres_type + \", res=\" +\n\t\t\t\t\t\tres);\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t}\n\n\tpublic enum SubscriptionType {\n\t\tnone(\"none\", null), none_pending_out(\"none\", \"subscribe\"), none_pending_in(\"none\",\n\t\t\t\tnull), none_pending_out_in(\"none\", \"subscribe\"), to(\"to\", null), to_pending_in(\n\t\t\t\t\"to\", null), from(\"from\", null), from_pending_out(\"from\", \"subscribe\"), both(\n\t\t\t\t\"both\", null), remove(\"remove\", null);\n\n\t\tprivate Map<String, String> attrs = new LinkedHashMap<String, String>(2, 1.0f);\n\n\t\tprivate SubscriptionType(String subscr, String ask) {\n\t\t\tattrs.put(\"subscription\", subscr);\n\t\t\tif (ask != null) {\n\t\t\t\tattrs.put(\"ask\", ask);\n\t\t\t}    // end of if (ask != null)\n\t\t}\n\n\t\tpublic Map<String, String> getSubscriptionAttr() {\n\t\t\treturn attrs;\n\t\t}\n\t}\n\n\tpublic abstract void addBuddy(XMPPResourceConnection session, JID jid, String name,\n\t\t\tString[] groups, String otherData)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, PolicyViolationException;\n\n\tpublic abstract boolean addBuddyGroup(final XMPPResourceConnection session, JID buddy,\n\t\t\tfinal String[] groups)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract boolean containsBuddy(final XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic String groupNode(JID buddy) {\n\t\treturn ROSTER + \"/\" + buddy.getBareJID();\n\t}\n\n\tpublic void init(UserRepository repo) throws TigaseDBException, TigaseDBException {}\n\n\tpublic abstract void logout(XMPPResourceConnection session);\n\n\tpublic abstract boolean presenceSent(XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract boolean removeBuddy(final XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic void updateBuddyChange(final XMPPResourceConnection session,\n\t\t\tfinal Queue<Packet> results, final Element item)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, NoConnectionIdException {\n\t\tElement update = new Element(\"iq\");\n\n\t\tupdate.setXMLNS(CLIENT_XMLNS);\n\t\tupdate.setAttribute(\"type\", StanzaType.set.toString());\n\n\t\tElement query = new Element(\"query\");\n\n\t\tquery.setXMLNS(ROSTER_XMLNS);\n\t\tquery.addAttribute(VER_ATT, getBuddiesHash(session));\n\t\tquery.addChild(item);\n\t\tupdate.addChild(query);\n\t\tfor (XMPPResourceConnection conn : session.getActiveSessions()) {\n\t\t\tElement conn_update = update.clone();\n\n\t\t\tconn_update.setAttribute(\"to\", conn.getBareJID().toString());\n\t\t\tconn_update.setAttribute(\"id\", \"rst\" + session.nextStanzaId());\n\n\t\t\tPacket pack_update = Packet.packetInstance(conn_update, null, conn.getJID());\n\n\t\t\tpack_update.setPacketTo(conn.getConnectionId());\n\n\t\t\t// pack_update.setPacketFrom(session.getJID());\n\t\t\tresults.offer(pack_update);\n\t\t}    // end of for (XMPPResourceConnection conn: sessions)\n\t}\n\n\tpublic boolean updateBuddySubscription(final XMPPResourceConnection session,\n\t\t\tfinal PresenceType presence, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, PolicyViolationException {\n\t\tSubscriptionType current_subscription = getBuddySubscription(session, jid);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"current_subscription={0} for jid={1}\", new Object[] {\n\t\t\t\t\tcurrent_subscription,\n\t\t\t\t\tjid });\n\t\t}\n\t\tif (current_subscription == null) {\n\n\t\t\t// don't create new roster item for incomming unsubscribe presence #219 /\n\t\t\t// #210\n\t\t\tif ((presence != PresenceType.in_unsubscribe) && (presence != PresenceType\n\t\t\t\t\t.out_unsubscribe)) {\n\t\t\t\taddBuddy(session, jid, null, null, null);\n\t\t\t}\n\t\t\tcurrent_subscription = SubscriptionType.none;\n\t\t}\n\n\t\tfinal SubscriptionType new_subscription = getStateTransition(current_subscription,\n\t\t\t\tpresence);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"new_subscription={0} for presence={1}\", new Object[] {\n\t\t\t\t\tnew_subscription,\n\t\t\t\t\tpresence });\n\t\t}\n\t\tif ((current_subscription == SubscriptionType.none_pending_in) && (presence ==\n\t\t\t\tPresenceType.out_unsubscribed)) {\n\t\t\tremoveBuddy(session, jid);\n\n\t\t\treturn false;\n\t\t}\n\t\tif (current_subscription != new_subscription) {\n\t\t\tsetBuddySubscription(session, new_subscription, jid);\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\n\t}\n\n\tpublic void updateRosterHash(String roster_str, XMPPResourceConnection session) {\n\t\tString roster_hash = null;\n\n\t\ttry {\n\t\t\troster_hash = Algorithms.hexDigest(\"\", roster_str, \"MD5\");\n\t\t} catch (Exception e) {\n\t\t\troster_hash = null;\n\t\t}\n\t\tsession.putCommonSessionData(ROSTERHASH, roster_hash);\n\t}\n\n\tpublic abstract JID[] getBuddies(final XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic JID[] getBuddies(final XMPPResourceConnection session,\n\t\t\tfinal EnumSet<SubscriptionType> subscrs)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// final String[] allBuddies = getBuddies(session, onlineOnly);\n\t\tJID[] allBuddies = getBuddies(session);\n\n\t\tif (allBuddies == null) {\n\t\t\treturn null;\n\t\t}    // end of if (allBuddies == null)\n\n\t\tArrayList<JID> list = new ArrayList<JID>();\n\n\t\tfor (JID buddy : allBuddies) {\n\t\t\tfinal SubscriptionType subs = getBuddySubscription(session, buddy);\n\n\t\t\tif (subscrs.contains(subs)) {\n\t\t\t\tlist.add(buddy);\n\t\t\t}    // end of if (subscrs.contains(subs))\n\t\t}      // end of for ()\n\n\t\treturn list.toArray(new JID[list.size()]);\n\t}\n\n\tpublic String getBuddiesHash(final XMPPResourceConnection session) {\n\t\tString hash = (String) session.getCommonSessionData(ROSTERHASH);\n\n\t\treturn ((hash != null)\n\t\t\t\t? hash\n\t\t\t\t: \"\");\n\t}\n\n\tpublic abstract String[] getBuddyGroups(final XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic Element getBuddyItem(final XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType subscr = getBuddySubscription(session, buddy);\n\n\t\tif (subscr == null) {\n\t\t\tsubscr = SubscriptionType.none;\n\t\t\tsetBuddySubscription(session, subscr, buddy);\n\t\t}    // end of if\n\n\t\tElement item = new Element(\"item\");\n\n\t\titem.setAttribute(\"jid\", buddy.toString());\n\t\titem.addAttributes(subscr.getSubscriptionAttr());\n\n\t\tString name = getBuddyName(session, buddy);\n\n\t\tif (name != null) {\n\t\t\titem.setAttribute(\"name\", XMLUtils.escape(name));\n\t\t}\n\n\t\tString[] groups = getBuddyGroups(session, buddy);\n\n\t\tif (groups != null) {\n\t\t\tfor (String gr : groups) {\n\t\t\t\tElement group = new Element(\"group\");\n\n\t\t\t\tgroup.setCData(XMLUtils.escape(gr));\n\t\t\t\titem.addChild(group);\n\t\t\t}    // end of for ()\n\t\t}      // end of if-else\n\n\t\treturn item;\n\t}\n\n\tpublic abstract String getBuddyName(final XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract SubscriptionType getBuddySubscription(\n\t\t\tfinal XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract Element getCustomChild(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic List<Element> getCustomChildren(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\tList<Element> result = new LinkedList<Element>();\n\n\t\tElement customChild = getCustomChild( session, buddy );\n\t\tif (customChild != null ) {\n\t\t\tresult.add( customChild );\n\t\t}\n\t\treturn result;\n\t}\n\t\n\tpublic PresenceType getPresenceType(final XMPPResourceConnection session,\n\t\t\tfinal Packet packet)\n\t\t\t\t\tthrows NotAuthorizedException {\n\t\tBareJID    to   = (packet.getStanzaTo() != null)\n\t\t\t\t? packet.getStanzaTo().getBareJID()\n\t\t\t\t: null;\n\t\tStanzaType type = packet.getType();\n\n\t\tif (type == null) {\n\t\t\ttype = StanzaType.available;\n\t\t} else {\n\t\t\tif (type == StanzaType.error) {\n\t\t\t\treturn PresenceType.error;\n\t\t\t}\n\t\t}\n\t\tif ((to == null) ||!session.isUserId(to)) {\n\t\t\tif (INITIAL_PRESENCES.contains(type)) {\n\t\t\t\treturn PresenceType.out_initial;\n\t\t\t}\n\t\t\tif (type == StanzaType.subscribe) {\n\t\t\t\treturn PresenceType.out_subscribe;\n\t\t\t}    // end of if (type == StanzaType.subscribe)\n\t\t\tif (type == StanzaType.unsubscribe) {\n\t\t\t\treturn PresenceType.out_unsubscribe;\n\t\t\t}    // end of if (type == StanzaType.unsubscribe)\n\t\t\tif (type == StanzaType.subscribed) {\n\t\t\t\treturn PresenceType.out_subscribed;\n\t\t\t}    // end of if (type == StanzaType.subscribed)\n\t\t\tif (type == StanzaType.unsubscribed) {\n\t\t\t\treturn PresenceType.out_unsubscribed;\n\t\t\t}    // end of if (type == StanzaType.unsubscribed)\n\t\t\tif (type == StanzaType.probe) {\n\t\t\t\treturn PresenceType.out_probe;\n\t\t\t}\n\t\t\t// StanzaType.probe is invalid here....\n\t\t\t// if (type == StanzaType.probe) {\n\t\t\t// return PresenceType.out_probe;\n\t\t\t// } // if (type == StanzaType.probe)\n\t\t}      // end of if (to == null || to.equals(session.getUserId()))\n\t\tif ((to != null) && session.isUserId(to)) {\n\t\t\tif (INITIAL_PRESENCES.contains(type)) {\n\t\t\t\treturn PresenceType.in_initial;\n\t\t\t}\n\t\t\tif (type == StanzaType.subscribe) {\n\t\t\t\treturn PresenceType.in_subscribe;\n\t\t\t}    // end of if (type == StanzaType.subscribe)\n\t\t\tif (type == StanzaType.unsubscribe) {\n\t\t\t\treturn PresenceType.in_unsubscribe;\n\t\t\t}    // end of if (type == StanzaType.unsubscribe)\n\t\t\tif (type == StanzaType.subscribed) {\n\t\t\t\treturn PresenceType.in_subscribed;\n\t\t\t}    // end of if (type == StanzaType.subscribed)\n\t\t\tif (type == StanzaType.unsubscribed) {\n\t\t\t\treturn PresenceType.in_unsubscribed;\n\t\t\t}    // end of if (type == StanzaType.unsubscribed)\n\t\t\tif (type == StanzaType.probe) {\n\t\t\t\treturn PresenceType.in_probe;\n\t\t\t}    // end of if (type == StanzaType.probe)\n\t\t}      // end of if (to != null && !to.equals(session.getUserId()))\n\n\t\treturn null;\n\t}\n\n\tpublic abstract RosterElement getRosterElement(XMPPResourceConnection session,\n\t\t\tJID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic List<Element> getRosterItems(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tLinkedList<Element> items = new LinkedList<Element>();\n\n\t\t// String[] buddies = getBuddies(session, online);\n\t\tJID[] buddies = getBuddies(session);\n\n\t\tif (buddies != null) {\n\t\t\tfor (JID buddy : buddies) {\n\t\t\t\tElement buddy_item = getBuddyItem(session, buddy);\n\n\t\t\t\t// String item_group = buddy_item.getCData(\"/item/group\");\n\t\t\t\titems.add(buddy_item);\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic static SubscriptionType getStateTransition(final SubscriptionType subscription,\n\t\t\tfinal PresenceType presence) {\n\t\tStateTransition transition = subsToStateMap.get(subscription);\n\n\t\tif (transition == null) {\n\t\t\treturn getStateTransition(SubscriptionType.none, presence);\n\t\t}\n\n\t\treturn transition.getStateTransition(presence);\n\t}\n\n\t/**\n\t * Check if data containing user roster for this session is loaded from database\n\t * \n\t * @param session\n\t * @return \n\t */\n\tpublic abstract boolean isRosterLoaded(XMPPResourceConnection session);\t\n\t\n\tpublic abstract boolean isOnline(XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic boolean isPendingIn(final XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType subscr = getBuddySubscription(session, jid);\n\n\t\treturn PENDING_IN.contains(subscr);\n\t}\n\n\tpublic boolean isSubscribedFrom(final XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType subscr = getBuddySubscription(session, jid);\n\n\t\treturn FROM_SUBSCRIBED.contains(subscr);\n\t}\n\n\tpublic boolean isSubscribedFrom(SubscriptionType subscr) {\n\t\treturn FROM_SUBSCRIBED.contains(subscr);\n\t}\n\n\tpublic boolean isSubscribedTo(final XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tSubscriptionType subscr = getBuddySubscription(session, jid);\n\n\t\treturn TO_SUBSCRIBED.contains(subscr);\n\t}\n\n\tpublic abstract void setBuddyName(final XMPPResourceConnection session, JID buddy,\n\t\t\tfinal String name)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract void setBuddySubscription(final XMPPResourceConnection session,\n\t\t\tfinal SubscriptionType subscription, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract void setOnline(XMPPResourceConnection session, JID jid, boolean online)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic abstract void setPresenceSent(XMPPResourceConnection session, JID jid,\n\t\t\tboolean sent)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException;\n\n\tpublic void setProperties( Map<String, Object> settings ) {\n\t\tif ( settings.get( \"empty_name_enabled\" ) != null ){\n\t\t\temptyNameAllowed = Boolean.valueOf( (String) settings.get( \"empty_name_enabled\" ) );\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Configuring empty name allowed as: \" + emptyNameAllowed );\n\t\tif ( settings.get( \"max_roster_size\" ) != null ){\n\t\t\ttry {\n\t\t\t\tmaxRosterSize = Integer.parseInt( (String) settings.get( \"max_roster_size\" ) );\n\t\t\t} catch ( NumberFormatException e ) {\n\t\t\t\tmaxRosterSize = new Long( Runtime.getRuntime().maxMemory() / 250000L ).intValue();\n\t\t\t}\n\t\t}\n\t\tlog.log( Level.CONFIG, \"Setting maximum number of roster items as: \" + maxRosterSize );\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RosterElement.java",
    "content": "/*\n * RosterElement.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl.roster;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.util.XMPPStringPrepFactory;\nimport tigase.xml.Element;\nimport tigase.xml.XMLUtils;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Logger;\n\n/**\n * Describe class RosterElement here.\n *\n * Created: Wed Oct 29 14:21:16 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class RosterElement {\n\t/** Field description */\n\tprotected static final long INITIAL_LAST_SEEN_VAL = 1000l;\n\tprivate static final String ACTIVITY_ATT          = \"activity\";\n\tprivate static final String ELEM_NAME             = \"contact\";\n\tprivate static final String GRP_ATT               = \"groups\";\n\tprivate static final double INITIAL_ACTIVITY_VAL  = 1d;\n\tprivate static final double INITIAL_WEIGHT_VAL    = 1d;\n\tprivate static final String JID_ATT               = \"jid\";\n\tprivate static final String LAST_SEEN_ATT         = \"last-seen\";\n\tprivate static final Logger log                   =\n\t\tLogger.getLogger(RosterElement.class.getName());\n\tprivate static final String NAME_ATT              = \"name\";\n\tprivate static final String OTHER_ATT             = \"other\";\n\tprivate static final String STRINGPREP_ATT        = \"preped\";\n\tprivate static final String SUBS_ATT              = \"subs\";\n\tprivate static final String WEIGHT_ATT            = \"weight\";\n\n\t//~--- fields ---------------------------------------------------------------\n\n\tprivate String[] groups                = null;\n\tprivate JID jid                        = null;\n\tprivate String name                    = null;\n\tprivate String otherData               = null;\n\tprivate long lastSeen                  = INITIAL_LAST_SEEN_VAL;\n\tprivate double activity                = INITIAL_ACTIVITY_VAL;\n\tprivate XMPPResourceConnection session = null;\n\tprivate String stringpreped            = null;\n\tprivate SubscriptionType subscription  = null;\n\tprivate double weight                  = INITIAL_WEIGHT_VAL;\n\tprivate boolean presence_sent          = false;\n\tprivate boolean persistent             = true;\n\tprivate Map<String, Boolean> onlineMap = new ConcurrentHashMap<String, Boolean>();\n\n\t// private Element item = null;\n\t// private boolean online = false;\n\tprivate boolean modified = false;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\tpublic RosterElement(Element roster_el, XMPPResourceConnection session)\n\t\t\t\t\tthrows TigaseStringprepException {\n\t\tthis.session = session;\n\t\tif (roster_el.getName() == ELEM_NAME) {\n\t\t\tthis.stringpreped = roster_el.getAttributeStaticStr(STRINGPREP_ATT);\n\t\t\tsetJid(roster_el.getAttributeStaticStr(JID_ATT));\n\t\t\tsetName(roster_el.getAttributeStaticStr(NAME_ATT));\n\t\t\tif (roster_el.getAttributeStaticStr(SUBS_ATT) == null) {\n\t\t\t\tsubscription = SubscriptionType.none;\n\t\t\t} else {\n\t\t\t\tsubscription =\n\t\t\t\t\tSubscriptionType.valueOf(roster_el.getAttributeStaticStr(SUBS_ATT));\n\t\t\t}\n\n\t\t\tString grps = roster_el.getAttributeStaticStr(GRP_ATT);\n\n\t\t\tif ((grps != null) &&!grps.trim().isEmpty()) {\n\t\t\t\tsetGroups(grps.split(\",\"));\n\t\t\t}\n\n\t\t\tString other_data = roster_el.getAttributeStaticStr(OTHER_ATT);\n\n\t\t\tif ((other_data != null) &&!other_data.trim().isEmpty()) {\n\t\t\t\totherData = other_data;\n\t\t\t}\n\n\t\t\tString num_str = roster_el.getAttributeStaticStr(ACTIVITY_ATT);\n\n\t\t\tif (num_str != null) {\n\t\t\t\ttry {\n\t\t\t\t\tactivity = Double.parseDouble(num_str);\n\t\t\t\t} catch (NumberFormatException nfe) {\n\t\t\t\t\tlog.warning(\"Incorrect activity field: \" + num_str);\n\t\t\t\t\tactivity = INITIAL_ACTIVITY_VAL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnum_str = roster_el.getAttributeStaticStr(WEIGHT_ATT);\n\t\t\tif (num_str != null) {\n\t\t\t\ttry {\n\t\t\t\t\tweight = Double.parseDouble(num_str);\n\t\t\t\t} catch (NumberFormatException nfe) {\n\t\t\t\t\tlog.warning(\"Incorrect weight field: \" + num_str);\n\t\t\t\t\tweight = INITIAL_WEIGHT_VAL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnum_str = roster_el.getAttributeStaticStr(LAST_SEEN_ATT);\n\t\t\tif (num_str != null) {\n\t\t\t\ttry {\n\t\t\t\t\tlastSeen = Long.parseLong(num_str);\n\t\t\t\t} catch (NumberFormatException nfe) {\n\t\t\t\t\tlog.warning(\"Incorrect last seen field: \" + num_str);\n\t\t\t\t\tlastSeen = INITIAL_LAST_SEEN_VAL;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// how roster can be modified as it is read from DB?\n\t\t\tmodified = false;\n\t\t} else {\n\t\t\tlog.warning(\"Incorrect roster data: \" + roster_el.toString());\n\t\t}\n\t}\n\n\tpublic RosterElement(JID jid, String name, String[] groups,\n\t\t\t\t\t\t\t\t\t\t\t XMPPResourceConnection session) {\n\t\tthis.stringpreped = XMPPStringPrepFactory.STRINGPREP_PROCESSOR;\n\t\tthis.session      = session;\n\t\tsetJid(jid);\n\t\tsetName(name);\n\t\tsetGroups(groups);\n\t\tthis.subscription = SubscriptionType.none;\n\t}\n\n\tpublic void addGroups(String[] groups) {\n\t\tif (groups != null) {\n\t\t\tif (this.groups == null) {\n\t\t\t\tsetGroups(groups);\n\t\t\t} else {\n\n\t\t\t\t// Groups names must be unique\n\t\t\t\tSet<String> groupsSet = new HashSet<String>();\n\n\t\t\t\tfor (String group : this.groups) {\n\t\t\t\t\tgroupsSet.add(group);\n\t\t\t\t}\n\t\t\t\tfor (String group : groups) {\n\t\t\t\t\tgroupsSet.add(group);\n\t\t\t\t}\n\t\t\t\tsetGroups(groupsSet.toArray(new String[groupsSet.size()]));\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic String[] getGroups() {\n\t\treturn groups;\n\t}\n\n\tpublic JID getJid() {\n\t\treturn jid;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic String getOtherData() {\n\t\treturn otherData;\n\t}\n\n\tpublic Element getRosterElement() {\n\t\tElement elem = new Element(ELEM_NAME, new String[] { JID_ATT, SUBS_ATT, STRINGPREP_ATT },\n\t\t\t\tnew String[] { jid.toString(), subscription.toString(), \"\" + stringpreped });\n\n\t\tif (name != null)\n\t\t\telem.setAttribute(NAME_ATT, XMLUtils.escape(name));\n\n\t\tif ((groups != null) && (groups.length > 0)) {\n\t\t\tString grps = \"\";\n\n\t\t\tfor (String group : groups) {\n\t\t\t\tgrps += XMLUtils.escape(group) + \",\";\n\t\t\t}\n\t\t\tgrps = grps.substring(0, grps.length() - 1);\n\t\t\telem.setAttribute(GRP_ATT, grps);\n\t\t}\n\t\tif (otherData != null) {\n\t\t\telem.setAttribute(OTHER_ATT, otherData);\n\t\t}\n\t\telem.setAttribute(ACTIVITY_ATT, Double.toString(activity));\n\t\telem.setAttribute(WEIGHT_ATT, Double.toString(weight));\n\t\telem.setAttribute(LAST_SEEN_ATT, Long.toString(lastSeen));\n\t\tmodified = false;\n\n\t\treturn elem;\n\t}\n\n\tpublic Element getRosterItem() {\n\n\t\t// This is actually not a good idea to cache the item element.\n\t\t// This causes a huge memory consumption and usually the item\n\t\t// is needed only once at the roster retrieving time.\n\t\t// if (item == null) {\n\t\tElement item = new Element(\"item\");\n\n\t\titem.setAttribute(\"jid\", jid.toString());\n\t\titem.addAttributes(subscription.getSubscriptionAttr());\n\t\tif (name != null) {\n\t\t\titem.setAttribute(\"name\", XMLUtils.escape(name));\n\t\t}\n\t\tif (groups != null) {\n\t\t\tfor (String gr : groups) {\n\t\t\t\tElement group = new Element(\"group\");\n\n\t\t\t\tgroup.setCData(XMLUtils.escape(gr));\n\t\t\t\titem.addChild(group);\n\t\t\t}    // end of for ()\n\t\t}      // end of if-else\n\t\treturn item;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getRosterItem().toString();\n\t}\n\n\tpublic SubscriptionType getSubscription() {\n\t\treturn subscription;\n\t}\n\n\tpublic boolean isModified() {\n\t\treturn modified;\n\t}\n\n\tpublic boolean isOnline() {\n\t\treturn onlineMap.size() > 0;\n\t}\n\n\tpublic boolean isPresence_sent() {\n\t\treturn presence_sent;\n\t}\n\n\tpublic final void setGroups(String[] groups) {\n\t\tif ((groups != null) && (groups.length > 0)) {\n\t\t\tthis.groups = new String[groups.length];\n\t\t\tfor (int i = 0; i < groups.length; i++) {\n\t\t\t\tthis.groups[i] = XMLUtils.unescape(groups[i]);\n\t\t\t}\n\t\t\tmodified = true;\n\t\t}\n\t}\n\n\tpublic final void setName(final String name) {\n\t\tif(name==this.name || (name!=null && this.name!=null && name.equals(this.name))){\n\t\t\treturn ;\n\t\t} else {\n\t\t\tthis.name = name==null?null:XMLUtils.unescape(name);\n\t\t\tthis.modified = true;\n\t\t}\n\t\t\n\t\t\n\n\t\t\t\n\t\t\n\t\t\n\t\t\n//\t\tString old_name = this.name;\n//\t\tif (name == null) {\n//\t\t\tthis.name = this.jid.getLocalpart();\n//\t\t\tif ((this.name == null) || this.name.trim().isEmpty()) {\n//\t\t\t\tthis.name = this.jid.getBareJID().toString();\n//\t\t\t}\n//\t\t} else {\n//\t\t\tthis.name = XMLUtils.unescape(name);\n//\t\t}\n//\t\tif (!this.name.equals(old_name)) {\n//\t\t\tmodified = true;\n//\t\t}\n\t}\n\n\tpublic void setOnline(String resource, boolean online) {\n\t\tif ((onlineMap != null) && (resource != null)) {\n\t\t\tif (online) {\n\t\t\t\tonlineMap.put(resource, Boolean.TRUE);\n\t\t\t} else {\n\t\t\t\tonlineMap.remove(resource);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setOtherData(String other_data) {\n\t\totherData = other_data;\n\t}\n\n\tpublic void setPresence_sent(boolean presence_sent) {\n\t\tthis.presence_sent = presence_sent;\n\t}\n\n\tpublic void setSubscription(SubscriptionType subscription) {\n\t\tif (subscription == null) {\n\t\t\tthis.subscription = SubscriptionType.none;\n\t\t} else {\n\t\t\tthis.subscription = subscription;\n\t\t}\n\t\tmodified = true;\n\t}\n\n\tprivate void setJid(JID jid) {\n\t\tthis.jid = jid;\n\t\tmodified = true;\n\t}\n\n\tprivate void setJid(String jid) throws TigaseStringprepException {\n\t\tif (XMPPStringPrepFactory.STRINGPREP_PROCESSOR.equals(stringpreped)) {\n\t\t\tthis.jid = JID.jidInstanceNS(jid);\n\t\t} else {\n\t\t\tthis.jid = JID.jidInstance(jid);\n\t\t\tmodified = true;\n\t\t}\n\t\tstringpreped = XMPPStringPrepFactory.STRINGPREP_PROCESSOR;\n\t}\n\n\tpublic boolean isPersistent() {\n\t\treturn persistent;\n\t}\n\n\tpublic void setPersistent(boolean persistent) {\n\t\tthis.persistent = persistent;\n\t}\n\n\tpublic double getActivity() {\n\t\treturn activity;\n\t}\n\n\tpublic void setActivity(double activity) {\n\t\tthis.activity = activity;\n\t\tif (activity != 0) {\n\t\t\tweight = 1 / activity;\n\t\t}\n\t\tmodified = true;\n\t}\n\n\tpublic double getWeight() {\n\t\treturn weight;\n\t}\n\n\tpublic void setWeight(double weight) {\n\t\tthis.weight = weight;\n\t\tmodified    = true;\n\t}\n\n\tpublic long getLastSeen() {\n\t\treturn lastSeen;\n\t}\n\n\tpublic void setLastSeen(long lastSeen) {\n\t\tthis.lastSeen = lastSeen;\n\t\tmodified      = true;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RosterFactory.java",
    "content": "/*\n * RosterFactory.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.roster;\n\n/**\n * {@link RosterFactory} is an factory that is responsible for creation\n * appropriate instance of {@link RosterAbstract} class\n *\n * Created: Thu Sep 4 18:33:11 2008\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n * @version $Rev$\n */\npublic abstract class RosterFactory {\n\n\t/** Key used to configure class name holding roster implementation */\n\tpublic static final String ROSTER_IMPL_PROP_KEY = \"roster-implementation\";\n\t/** Default roster implementation class - {@link RosterFactory} */\n\tpublic static final String ROSTER_IMPL_PROP_VAL = RosterFlat.class\n\t\t\t.getCanonicalName();\n\t/** Holds shared implementation of {@link RosterAbstract} */\n\tprivate static RosterAbstract shared = null;\n\n\t//~--- get methods ----------------------------------------------------------\n\t/**\n\t * Creates new instance of class implementing {@link RosterAbstract} - either\n\t * default one ({@link RosterFlat}) or the one configured with\n\t * <em>\"roster-implementation\"</em> property.\n\t *\n\t * @param shared_impl determines whether to returns shared or non shared\n\t *                    implementation\n\t *\n\t * @return new instance of class implementing {@link RosterAbstract}\n\t */\n\tpublic static RosterAbstract getRosterImplementation( boolean shared_impl ) {\n\t\ttry {\n\t\t\tString cls_name = System.getProperty( ROSTER_IMPL_PROP_KEY, ROSTER_IMPL_PROP_VAL );\n\n\t\t\treturn getRosterImplementation( cls_name, shared_impl );\n\t\t} catch ( ClassNotFoundException | InstantiationException | IllegalAccessException e ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Creates new instance of class implementing {@link RosterAbstract} from\n\t * provided\n\t * <code>class_name</code>\n\t *\n\t * @param class_name  full qualified name of the class\n\t * @param shared_impl determines whether to returns shared or non shared\n\t *                    implementation\n\t *\n\t * @return new instance of class implementing {@link RosterAbstract}\n\t *\n\t * @throws ClassNotFoundException\n\t * @throws IllegalAccessException\n\t * @throws InstantiationException\n\t */\n\tpublic static RosterAbstract getRosterImplementation( String class_name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tboolean shared_impl )\n\t\t\tthrows ClassNotFoundException, InstantiationException, IllegalAccessException {\n\t\tif ( shared_impl ){\n\t\t\tif ( shared == null ){\n\t\t\t\tshared = (RosterAbstract) Class.forName( class_name ).newInstance();\n\t\t\t}\n\t\t\treturn shared;\n\t\t}\n\n\t\treturn (RosterAbstract) Class.forName( class_name ).newInstance();\n\t}\n}\n\n//~ Formatted in Tigase Code Convention on 13/04/24\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RosterFlat.java",
    "content": "/*\n * RosterFlat.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.db.TigaseDBException;\n\nimport tigase.server.PolicyViolationException;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\n//~--- JDK imports ------------------------------------------------------------\n\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * Describe class RosterFlat here.\n *\n * Created: Tue Feb 21 18:05:53 2006\n *\n * @author <a href=\"mailto:artur.hefczyc@tigase.org\">Artur Hefczyc</a>\n */\npublic class RosterFlat\n\t\t\t\textends RosterAbstract {\n\t/**\n\t * Private logger for class instances.\n\t */\n\tprivate static final Logger log          = Logger.getLogger(RosterFlat.class.getName());\n\tprivate static final SimpleParser parser = SingletonFactory.getParserInstance();\n\n\tprivate final SimpleDateFormat formatter;\n\t{\n\t\tthis.formatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tthis.formatter.setTimeZone( TimeZone.getTimeZone(\"UTC\") );\n\t}\n\n\tpublic static boolean addBuddy(RosterElement relem,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Map<BareJID, RosterElement> roster) {\n\t\tif (roster.size() < maxRosterSize) {\n\t\t\troster.put(relem.getJid().getBareJID(), relem);\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic RosterElement addTempBuddy(JID buddy, XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElementInstance(buddy.copyWithoutResource(), null, null, session);\n\n\t\trelem.setPersistent(false);\n\t\trelem.setSubscription( null );\n\t\taddBuddy(relem, getUserRoster(session));\n\n\t\tif ( log.isLoggable( Level.FINEST ) ){\n\t\t\tlog.log( Level.FINEST, \"Added temporary buddy to roster: {0}, name: {1}, item: {2}\",\n\t\t\t\t\t\t\t new Object[] { relem.getJid(), relem.getName(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trelem.getRosterItem(), relem.toString() } );\n\t\t}\n\t\treturn relem;\n\t}\n\n\tpublic static boolean parseRosterUtil(String roster_str,\n\t\t\t\t\tMap<BareJID, RosterElement> roster, XMPPResourceConnection session) {\n\t\tboolean result               = false;\n\t\tDomBuilderHandler domHandler = new DomBuilderHandler();\n\n\t\tparser.parse(domHandler, roster_str.toCharArray(), 0, roster_str.length());\n\n\t\tQueue<Element> elems = domHandler.getParsedElements();\n\n\t\tif ((elems != null) && (elems.size() > 0)) {\n\t\t\tfor (Element elem : elems) {\n\t\t\t\ttry {\n\t\t\t\t\tRosterElement relem = new RosterElement(elem, session);\n\n\t\t\t\t\tresult |= relem.isModified();\n\t\t\t\t\tif (!addBuddy(relem, roster)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlog.log(Level.WARNING, \"Can't load roster element: {0}\", elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void addBuddy(XMPPResourceConnection session, JID buddy, String name,\n\t\t\t\t\t\t\t\t\t\t\t String[] groups, String otherData)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException, PolicyViolationException {\n\n\t\t// String buddy = JIDUtils.getNodeID(jid);\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\n\t\t\trelem = getRosterElementInstance(buddy, name, groups, session);\n\t\t\tif (emptyNameAllowed && (name == null || name.isEmpty())) {\n\t\t\t\trelem.setName(null);\n\t\t\t} else if (name == null || name.isEmpty()) {\n\t\t\t\tString n = buddy.getLocalpart();\n\t\t\t\tif ((n == null) || n.trim().isEmpty()) {\n\t\t\t\t\tn = buddy.getBareJID().toString();\n\t\t\t\t}\n\t\t\t\trelem.setName(n);\n\t\t\t} else {\n\t\t\t\trelem.setName(name);\n\t\t\t}\n\t\t\trelem.setOtherData(otherData);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"1. Added buddy to roster: {0}, name: {1}, item: {2}\",\n\t\t\t\t\t\t\t\tnew Object[] { relem.getJid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t relem.getName(), relem.getRosterItem() });\n\t\t\t}\n\t\t\tif (addBuddy(relem, roster)) {\n\t\t\t\tsaveUserRoster(session);\n\t\t\t} else {\n\t\t\t\tthrow new PolicyViolationException(\"Too many elements in the user roster. Limit: \" + maxRosterSize);\n\t\t\t}\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"2. Added buddy to roster: {0}, name: {1}, item: {2}\",\n\t\t\t\t\t\t\t\tnew Object[] { relem.getJid(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t relem.getName(), relem.getRosterItem() });\n\t\t\t}\n\t\t} else {\n\t\t\tif (emptyNameAllowed && (name == null || name.isEmpty())) {\n\t\t\t\trelem.setName(null);\n\t\t\t} else if (name == null || name.isEmpty()) {\n\t\t\t\tString n = buddy.getLocalpart();\n\t\t\t\tif ((n == null) || n.trim().isEmpty()) {\n\t\t\t\t\tn = buddy.getBareJID().toString();\n\t\t\t\t}\n\t\t\t\trelem.setName(n);\n\t\t\t} else {\n\t\t\t\trelem.setName(name);\n\t\t\t}\n\t\t\t\t\n\t\t\t// Hm, as one user reported this make it impossible to remove the user\n\t\t\t// from\n\t\t\t// all groups. Let's comments it out for now to see how it works.\n\t\t\t// Probably added this some time ago , before RosterFlat to prevent NPE.\n\t\t\t// if ((groups != null) && (groups.length > 0)) {\n\t\t\trelem.setGroups(groups);\n\n\t\t\t// }\n\t\t\trelem.setPersistent( true );\n\t\t\tsaveUserRoster(session);\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Updated buddy in roster: {0}\", buddy);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean addBuddyGroup(XMPPResourceConnection session, JID buddy, String[] groups)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem != null) {\n\t\t\trelem.addGroups(groups);\n\n\t\t\t// Intentionally not saving the roster here.\n\t\t\t// At the moment it is only used to combine dynamic roster with the\n\t\t\t// static roster in case a contact exist in both but in a different\n\t\t\t// group.\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean containsBuddy(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\treturn (relem != null) && relem.isPersistent();\n\t}\n\n\t@Override\n\tpublic JID[] getBuddies(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\n\t\tif (roster.size() == 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tJID[] result = new JID[roster.size()];\n\t\tint idx      = 0;\n\n\t\tfor (RosterElement rosterElement : roster.values()) {\n\t\t\tresult[idx++] = rosterElement.getJid();\n\t\t}\n\n\t\t// TODO: this sorting should be optional as it may impact performance\n\t\tArrays.sort(result, new RosterElemComparator(roster));\n\n\t\treturn result;\n\n\t}\n\n\t@Override\n\tpublic String[] getBuddyGroups(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn relem.getGroups();\n\t\t}\n\t}\n\n\tpublic Element getBuddyItem(RosterElement relem) {\n\t\treturn relem.getRosterItem();\n\t}\n\n\t@Override\n\tpublic Element getBuddyItem(final XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn getBuddyItem(relem);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getBuddyName(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn relem.getName();\n\t\t}\n\t}\n\n\t@Override\n\tpublic SubscriptionType getBuddySubscription(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\t// either we don't have such contact or it's not persistend in which case it shouldn't\n\t\t// have subscription -- this is simpler solution instead of reworking whole RosterElement\n\t\t// to allow sub==null\n\t\tif ( relem == null || ( !relem.isPersistent() ) ){\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn relem.getSubscription();\n\t\t}\n\n\t\t// return SubscriptionType.both;\n\t}\n\n\tpublic RosterElement getRosterElementInstance(JID buddy, String name, String[] groups,\n\t\t\t\t\tXMPPResourceConnection session) {\n\t\treturn new RosterElement(buddy.copyWithoutResource(), name, groups, session);\n\t}\n\n\t@Override\n\tpublic List<Element> getRosterItems(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tLinkedList<Element> items          = new LinkedList<Element>();\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\n\t\tfor (RosterElement relem : roster.values()) {\n\n\t\t\t// Skip temporary roster elements added only for online presence tracking\n\t\t\t// from dynamic roster\n\t\t\tif (relem.isPersistent() && !SubscriptionType.none_pending_in.equals(relem.getSubscription())) {\n\t\t\t\titems.add(getBuddyItem(relem));\n\t\t\t}\n\t\t}\n\n\t\treturn items;\n\t}\n\n\t@Override\n\tpublic boolean isRosterLoaded(XMPPResourceConnection session) {\n\t\treturn session.getCommonSessionData(ROSTER) != null;\n\t}\n\t\n\t@Override\n\tpublic boolean isOnline(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\treturn (relem != null) && relem.isOnline();\n\t}\n\n\tpublic boolean parseRoster(String roster_str, Map<BareJID, RosterElement> roster,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t XMPPResourceConnection session) {\n\t\treturn parseRosterUtil(roster_str, roster, session);\n\t}\n\n\t@Override\n\tpublic boolean presenceSent(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\treturn (relem != null) && relem.isPresence_sent();\n\t}\n\n\t@Override\n\tpublic boolean removeBuddy(XMPPResourceConnection session, JID jid)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Removing roster buddy: {0}, before removal: {1}\",\n\t\t\t\t\t\t\tnew Object[] { jid,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t roster });\n\t\t}\n\t\troster.remove(jid.getBareJID());\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Removing roster buddy: {0}, after removal: {1}\",\n\t\t\t\t\t\t\tnew Object[] { jid,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t roster });\n\t\t}\n\t\tsaveUserRoster(session);\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void setBuddyName(XMPPResourceConnection session, JID buddy, String name)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem != null) {\n\t\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\t\tlog.log(Level.FINEST, \"Setting name: ''{0}'' for buddy: {1}\", new Object[] { name,\n\t\t\t\t\t\t\t\tbuddy });\n\t\t\t}\n\t\t\tif (emptyNameAllowed && (name == null || name.isEmpty())) {\n\t\t\t\trelem.setName(null);\n\t\t\t} else if (name == null || name.isEmpty()) {\n\t\t\t\tString n = buddy.getLocalpart();\n\t\t\t\tif ((n == null) || n.trim().isEmpty()) {\n\t\t\t\t\tn = buddy.getBareJID().toString();\n\t\t\t\t}\n\t\t\t\trelem.setName(n);\n\t\t\t} else {\n\t\t\t\trelem.setName(name);\n\t\t\t}\n\t\t\tsaveUserRoster(session);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Setting buddy name for non-existen contact: {0}\", buddy);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setBuddySubscription(XMPPResourceConnection session,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t SubscriptionType subscription, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem != null) {\n\t\t\trelem.setSubscription(subscription);\n\t\t\tsaveUserRoster(session);\n\t\t} else {\n\t\t\tlog.log(Level.WARNING, \"Missing roster contact for subscription set: {0}\", buddy);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setOnline(XMPPResourceConnection session, JID buddy, boolean online)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\trelem = addTempBuddy(buddy, session);\n\t\t}\n\t\trelem.setOnline(buddy.getResource(), online);\n\t}\n\n\t@Override\n\tpublic void setPresenceSent(XMPPResourceConnection session, JID buddy, boolean sent)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement relem = getRosterElement(session, buddy);\n\n\t\tif (relem == null) {\n\t\t\trelem = addTempBuddy(buddy, session);\n\t\t}\n\t\trelem.setPresence_sent(sent);\n\t}\n\n\t@Override\n\tpublic RosterElement getRosterElement(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\n\t\treturn roster.get(buddy.getBareJID());\n\t}\n\n\t@SuppressWarnings({ \"unchecked\" })\n\tprotected Map<BareJID, RosterElement> getUserRoster(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = null;\n\n\t\t// The method can be called from different plugins concurrently.\n\t\t// If the roster is not yet loaded from DB this causes concurent\n\t\t// access problems\n\t\tsynchronized (session) {\n\t\t\troster = (Map<BareJID, RosterElement>) session.getCommonSessionData(ROSTER);\n\t\t\tif (roster == null) {\n\t\t\t\troster = loadUserRoster(session);\n\t\t\t}\n\t\t}\n\n\t\treturn roster;\n\t}\n\n\tprotected void saveUserRoster(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\t\tStringBuilder sb                   = new StringBuilder(5000);\n\n\t\tfor (RosterElement relem : roster.values()) {\n\t\t\tif (relem.isPersistent()) {\n\t\t\t\tsb.append(relem.getRosterElement().toString());\n\t\t\t}\n\t\t}\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"{0} | Saving user roster: {1}\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String [] {session.getBareJID().toString(), sb.toString()});\n\t\t}\n\t\tsession.setData(null, ROSTER, sb.toString());\n\t}\n\n\tprivate Map<BareJID, RosterElement> loadUserRoster(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\n\t\t// In most times we just read from this data structure\n\t\t// From time to time there might be some modification, posibly concurrent\n\t\t// very unlikely by more than one thread\n\t\tMap<BareJID, RosterElement> roster = new ConcurrentHashMap<BareJID,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t RosterElement>(100, 0.25f, 1);\n\n\t\tsession.putCommonSessionData(ROSTER, roster);\n\n\t\tString roster_str = session.getData(null, ROSTER, null);\n\n\t\tif (log.isLoggable(Level.FINEST)) {\n\t\t\tlog.log(Level.FINEST, \"Loaded user roster: {0}\", roster_str);\n\t\t}\n\t\tif ((roster_str != null) &&!roster_str.isEmpty()) {\n\t\t\tupdateRosterHash(roster_str, session);\n\n\t\t\tboolean modified = parseRoster(roster_str, roster, session);\n\n\t\t\tif (modified) {\n\t\t\t\tsaveUserRoster(session);\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Try to load a roster from the 'old' style roster storage and\n\t\t\t// convert it the the flat roster storage\n\t\t\tRoster oldRoster = new Roster();\n\t\t\tJID[] buddies    = oldRoster.getBuddies(session);\n\n\t\t\tif ((buddies != null) && (buddies.length > 0)) {\n\t\t\t\tfor (JID buddy : buddies) {\n\t\t\t\t\tString name             = oldRoster.getBuddyName(session, buddy);\n\t\t\t\t\tSubscriptionType subscr = oldRoster.getBuddySubscription(session, buddy);\n\t\t\t\t\tString[] groups         = oldRoster.getBuddyGroups(session, buddy);\n\t\t\t\t\tRosterElement relem     = getRosterElementInstance(buddy, name, groups,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsession);\n\n\t\t\t\t\trelem.setSubscription(subscr);\n\t\t\t\t\tif (!addBuddy(relem, roster)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsaveUserRoster(session);\n\t\t\t}\n\t\t}\n\n\t\treturn roster;\n\t}\n\n\t@Override\n\tpublic Element getCustomChild(XMPPResourceConnection session, JID buddy)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tRosterElement rel = getRosterElement(session, buddy);\n\n\t\tif (rel != null && rel.getLastSeen() > RosterElement.INITIAL_LAST_SEEN_VAL) {\n\t\t\tString stamp;\n\t\t\tsynchronized (formatter) {\n\t\t\t\tstamp = formatter.format(new Date(rel.getLastSeen()));\n\t\t\t}\n\n\t\t\treturn new Element(\"delay\", new String[]{\n\t\t\t\t\t\"stamp\", \"xmlns\"}, new String[]{stamp, \"urn:xmpp:delay\"});\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void logout(XMPPResourceConnection session) {\n\t\ttry {\n\t\t\tif (session.isAuthorized() && isModified(session)) {\n\t\t\t\tsaveUserRoster(session);\n\t\t\t}\n\t\t} catch (NotAuthorizedException ex) {\n\n\t\t\t// TODO Auto-generated catch block\n\t\t\tex.printStackTrace();\n\t\t} catch (TigaseDBException ex) {\n\n\t\t\t// TODO Auto-generated catch block\n\t\t\tex.printStackTrace();\n\t\t}\n\t}\n\n\tpublic boolean isModified(XMPPResourceConnection session)\n\t\t\t\t\tthrows NotAuthorizedException, TigaseDBException {\n\t\tMap<BareJID, RosterElement> roster = getUserRoster(session);\n\t\tboolean result                     = false;\n\n\t\tif (roster != null) {\n\t\t\tfor (RosterElement rel : roster.values()) {\n\t\t\t\tresult |= rel.isModified();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate class RosterElemComparator\n\t\t\t\t\timplements Comparator<JID> {\n\t\tprivate Map<BareJID, RosterElement> roster = null;\n\n\t\tprivate RosterElemComparator(Map<BareJID, RosterElement> roster) {\n\t\t\tthis.roster = roster;\n\t\t}\n\n\t\t@Override\n\t\tpublic int compare(JID arg0, JID arg1) {\n\t\t\tdouble w0 = roster.get(arg0.getBareJID()).getWeight();\n\t\t\tdouble w1 = roster.get(arg1.getBareJID()).getWeight();\n\n\t\t\treturn Double.compare(w0, w1);\n\t\t}\n\t}\n}    // RosterFlat\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/roster/RosterRetrievingException.java",
    "content": "/*\n * RosterRetrievingException.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2013 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\npackage tigase.xmpp.impl.roster;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport tigase.xmpp.XMPPException;\n\n/**\n *\n * @author kobit\n */\npublic class RosterRetrievingException\n\t\t\t\textends XMPPException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t//~--- constructors ---------------------------------------------------------\n\n\t/**\n\t * Creates a new <code>PacketErrorTypeException</code> instance.\n\t *\n\t * @param message\n\t */\n\tpublic RosterRetrievingException(String message) {\n\t\tsuper(message);\n\t}\n\n\t/**\n\t * Constructs ...\n\t *\n\t *\n\t * @param message\n\t * @param cause\n\t */\n\tpublic RosterRetrievingException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/11/27\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/short_news-5.x/short_news.info",
    "content": "; $Id: $\nname = Short news\ndescription = Short news displaying from short_news table.\npackage = Tigase\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/short_news-5.x/short_news.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Short News Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction short_news_help($section='') {\n\n\t$output = '';\n\n\tswitch ($section) {\n\tcase \"admin/help#short_news\":\n\t\t$output = t(\"Short news displaying from short_news table.\") . \"\\n\"\n\t\t\t. t(\" This module displays N last short news found in 'short_news' table.\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction short_news_perm() {\n  return array('access short_news');\n}\n\n/**\n* Generate list of last short news to display on page\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction short_news_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Minis - short news');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t$posts_type = variable_get('short_news_blocktype', 'minis');\n\t\t$max_posts = variable_get('short_news_blockdisp', 3);\n    $result =\n\t\t\tdb_query_range(\"SELECT snid, publishing_time, author, subject, body\"\n\t\t\t\t. \" FROM short_news WHERE news_type = '\" . $posts_type. \"'\"\n\t\t\t\t. \" ORDER BY publishing_time DESC\"\n\t\t\t\t, 0, $max_posts);\n    while ($news_post = db_fetch_object($result)) {\n\t\t\tif ($block_content == '') {\n\t\t\t\t$block_content .= '<div class=\"short-news\">';\n\t\t\t}\n\t\t\t$block_content .= '<h6 class=\"title\">' . $news_post->subject . '</h6>';\n\t\t\t$block_content .=\t'<div class=\"body\">' .\t$news_post->body . '</div>';\n\t\t\t$block_content .= '<div class=\"author\">'\n\t\t\t\t. $news_post->snid . ', '\n\t\t\t\t. str_ireplace('@', '//', $news_post->author)\n\t\t\t\t. ', '\n\t\t\t\t. format_date(strtotime($news_post->publishing_time), 'small')\n\t\t\t\t. '</div>';\n    }\n    // check to see if there was any content before setting up the block\n    if ($block_content == '') {\n      // no content from a week ago, return nothing.\n      return;\n    } else {\n\t\t\t$block_content .= '</div>';\n\t\t}\n    // set up the block\n    $block['subject'] = 'Minis from XMPP';\n    $block['content'] = $block_content;\n    return $block;\n\t}\n}\n\n/**\n* Module configuration settings\n* @return settings HTML or deny access\n*/\nfunction short_news_menu() {\n\n  $items = array();\n\n  $items[] = array(\n    'path' => 'admin/settings/short_news',\n    'title' => t('Short news'),\n    'description' => t('Set short news displaying parameters.'),\n    'callback' => 'drupal_get_form',\n    'callback arguments' => 'short_news_admin_settings',\n    'access' => user_access('access administration pages'),\n    'type' => MENU_NORMAL_ITEM,\n   );\n\n  return $items;\n}\n\nfunction short_news_admin_settings() {\n\t$form['short_news_blockdisp'] = array(\n\t\t'#type' => 'textfield',\n\t\t'#title' => t('Number of posts to display in block'),\n\t\t'#default_value' => variable_get('short_news_blockdisp', 3),\n\t\t'#description' => t(\"The maximum number of posts to display in the block.\"),\n\t\t'#maxlength' => '2',\n\t\t'#size' => '2');\n\t$form['short_news_blocktype'] = array(\n\t\t'#type' => 'textfield',\n\t\t'#title' => t('Posts type to display in block'),\n\t\t'#default_value' => variable_get('short_news_blocktype', 'minis'),\n\t\t'#description' => t(\"The type of posts to display in block: 'minis', 'shorts', 'techs', 'funs', ...\"),\n\t\t'#maxlength' => '10',\n\t\t'#size' => '10');\n\treturn system_settings_form($form);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/short_news-6.x/short_news.info",
    "content": "; $Id: $\nname = Short news\ndescription = Short news displaying from short_news table.\npackage = Tigase\n\ncore = 6.x"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/short_news-6.x/short_news.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Short News Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction short_news_help($path='', $arg) {\n\n\t$output = '';\n\n\tswitch ($path) {\n\tcase \"admin/help#short_news\":\n\t\t$output = t(\"Short news displaying from short_news table.\") . \"\\n\"\n\t\t\t. t(\" This module displays N last short news found in 'short_news' table.\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction short_news_perm() {\n  return array('access short_news');\n}\n\n/**\n* Generate list of last short news to display on page\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction short_news_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Minis - short news');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t$posts_type = variable_get('short_news_blocktype', 'minis');\n\t\t$max_posts = variable_get('short_news_blockdisp', 3);\n    $result =\n\t\t\tdb_query_range(\"SELECT snid, publishing_time, author, subject, body\"\n\t\t\t\t. \" FROM short_news WHERE news_type = '\" . $posts_type. \"'\"\n\t\t\t\t. \" ORDER BY publishing_time DESC\"\n\t\t\t\t, 0, $max_posts);\n    while ($news_post = db_fetch_object($result)) {\n\t\t\tif ($block_content == '') {\n\t\t\t\t$block_content .= '<div class=\"short-news\">';\n\t\t\t}\n\t\t\t$block_content .= '<h6 class=\"title\">' . $news_post->subject . '</h6>';\n\t\t\t$block_content .=\t'<div class=\"body\">' .\t$news_post->body . '</div>';\n\t\t\t$block_content .= '<div class=\"author\">'\n\t\t\t\t. $news_post->snid . ', '\n\t\t\t\t. str_ireplace('@', '//', $news_post->author)\n\t\t\t\t. ', '\n\t\t\t\t. format_date(strtotime($news_post->publishing_time), 'small')\n\t\t\t\t. '</div>';\n    }\n    // check to see if there was any content before setting up the block\n    if ($block_content == '') {\n      // no content from a week ago, return nothing.\n      return;\n    } else {\n\t\t\t$block_content .= '</div>';\n\t\t}\n    // set up the block\n    $block['subject'] = 'Minis from XMPP';\n    $block['content'] = $block_content;\n    return $block;\n\t}\n}\n\n/**\n* Module configuration settings\n* @return settings HTML or deny access\n*/\nfunction short_news_menu() {\n\n  $items = array();\n\n  $items['admin/settings/short_news'] = array(\n    'title' => 'Short news',\n    'description' => 'Set short news displaying parameters.',\n    'page callback' => 'drupal_get_form',\n    'page arguments' => 'short_news_admin_settings',\n    'access arguments' => array('access administration pages'),\n    'type' => MENU_NORMAL_ITEM,\n   );\n\n  return $items;\n}\n\nfunction short_news_admin_settings() {\n\t$form['short_news_blockdisp'] = array(\n\t\t'#type' => 'textfield',\n\t\t'#title' => t('Number of posts to display in block'),\n\t\t'#default_value' => variable_get('short_news_blockdisp', 3),\n\t\t'#description' => t(\"The maximum number of posts to display in the block.\"),\n\t\t'#maxlength' => '2',\n\t\t'#size' => '2');\n\t$form['short_news_blocktype'] = array(\n\t\t'#type' => 'textfield',\n\t\t'#title' => t('Posts type to display in block'),\n\t\t'#default_value' => variable_get('short_news_blocktype', 'minis'),\n\t\t'#description' => t(\"The type of posts to display in block: 'minis', 'shorts', 'techs', 'funs', ...\"),\n\t\t'#maxlength' => '10',\n\t\t'#size' => '10');\n\treturn system_settings_form($form);\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/short_news.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Short News Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction short_news_help($section='') {\n\n\t$output = '';\n\n\tswitch ($section) {\n\tcase \"admin/modules#description\":\n\t\t$output = t(\"Short news displaying from short_news table.\");\n\t\tbreak;\n\tcase \"admin/help#short_news\":\n\t\t$output = t(\"Short news displaying fro short_news table.\") . \"\\n\"\n\t\t\t. t(\" This module displays N last short news found in 'short_news' table.\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction short_news_perm() {\n  return array('access short_news');\n}\n\n/**\n* Generate list of last short news to display on page\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction short_news_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Minis');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t$posts_type = variable_get('short_news_blocktype', 'minis');\n\t\t$max_posts = variable_get('short_news_blockdisp', 3);\n    $result =\n\t\t\tdb_query_range(\"SELECT snid, publishing_time, author, subject, body\"\n\t\t\t\t. \" FROM short_news WHERE news_type = '\" . $posts_type. \"'\"\n\t\t\t\t. \" ORDER BY publishing_time DESC\"\n\t\t\t\t, 0, $max_posts);\n    while ($news_post = db_fetch_object($result)) {\n\t\t\tif ($block_content == '') {\n\t\t\t\t$block_content .= '<div class=\"short-news\">';\n\t\t\t}\n\t\t\t$block_content .= '<h6 class=\"title\">' . $news_post->subject . '</h6>';\n\t\t\t$block_content .=\t'<div class=\"body\">' .\t$news_post->body . '</div>';\n\t\t\t$block_content .= '<div class=\"author\">'\n\t\t\t\t. $news_post->snid . ', '\n\t\t\t\t. str_ireplace('@', '//', $news_post->author)\n\t\t\t\t. ', '\n\t\t\t\t. format_date(strtotime($news_post->publishing_time), 'small')\n\t\t\t\t. '</div>';\n    }\n    // check to see if there was any content before setting up the block\n    if ($block_content == '') {\n      // no content from a week ago, return nothing.\n      return;\n    } else {\n\t\t\t$block_content .= '</div>';\n\t\t}\n    // set up the block\n    $block['subject'] = 'Minis from XMPP';\n    $block['content'] = $block_content;\n    return $block;\n\t}\n}\n\n/**\n* Module configuration settings\n* @return settings HTML or deny access\n*/\nfunction short_news_settings() {\n  // only administrators can access this module\n  if (!user_access(\"access administration pages\")) {\n    return t('you do not have rights to this resource.');\n  }\n\t$form['short_news_blockdisp'] =\n\t\tarray('#type' => 'textfield',\n\t\t\t'#title' => t('Number of posts to display in block'),\n\t\t\t'#default_value' => variable_get('short_news_blockdisp', 3),\n\t\t\t'#description' => t(\"The maximum number of posts to display in the block.\"),\n\t\t\t'#maxlength' => '2', '#size' => '2');\n\t$form['short_news_blocktype'] =\n\t\tarray('#type' => 'textfield',\n\t\t\t'#title' => t('Posts type to display in block'),\n\t\t\t'#default_value' => variable_get('short_news_blocktype', 'minis'),\n\t\t\t'#description' => t(\"The type of posts to display in block: 'minis', 'shorts', 'techs', 'funs', ...\"),\n\t\t\t'#maxlength' => '10', '#size' => '10');\n  return $form;\n}\n\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Module for Jabber/XMPP service\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction tigase_help($section='') {\n\n\t$output = '';\n\n\tswitch ($section) {\n\tcase \"admin/modules#description\":\n\t\t$output = t(\"Integration with Tigase Jabber/XMPP server.\");\n\t\tbreak;\n\tcase \"admin/help#tigase\":\n\t\t$output = t(\"Integration with Tigase Jabber/XMPP server.\") . \"\\n\"\n\t\t\t. t(\"This is not a Jabber/XMPP client within Drupal. This is more like\")\n\t\t\t. t(\" closer integration between Drupal and Tigase. The basic idea is to\")\n\t\t\t. t(\" allow for full Jabber/XMPP account data management from Drupal site.\")\n\t\t\t. \"\\n\" . t(\"The first step is to allow to display on-line user status on\")\n\t\t\t. t(\" Drupal site in similar form to 'Online users' list.\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction tigase_perm() {\n  return array('access tigase');\n}\n\n/**\n* Generate list of users loggedin to Jabber server\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction tigase_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Jabber online users');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.info",
    "content": "; $Id: $\nname = Tigase server monitor\ndescription = Displays Tigase server statistics\npackage = Tigase\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase_monitor-5.x/tigase_monitor.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Monitor Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction tigase_monitor_help($section='') {\n\n\t$output = '';\n\n\tswitch ($section) {\n\tcase \"admin/help#tigase_monitor\":\n\t\t$output = t(\"Monitor displaying various server statistics.\") . \"\\n\"\n\t\t\t. t(\" This module displays information about number of downloads, last software version, number of registered user accounts, number of users online, number of s2s connections and so on...\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction tigase_monitor_perm() {\n  return array('access tigase_monitor', 'access tigase_monitor content',\n\t\t'access tigase_monitor config');\n}\n\n/**\n* Output all monitor information\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction tigase_monitor_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Monitor - Tigase Server');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t$folder = 'files/downloads/tigase-server/';\n\t\t$descript = $folder . 'descript.ion';\n\t\t$info = tigase_monitor_decript($descript);\n\t\t$jabber_stats_file = 'files/jabber_stats.txt';\n\t\t$jabber_stats = tigase_monitor_stats($jabber_stats_file);\n \t\t$server_downloads = '';\n\t\t$server_version = ' ';\n\t\t$file = '';\n\t\tforeach ($info as $name => $description) {\n\t\t\tif (($name != 'TOTAL:') && !stripos($name, 'xmltools') && !stripos($name, 'utils')) {\n\t\t\t\t$name_ver = str_ireplace(\"tigase-server-\", \"\", $name);\n\t\t\t\t$name_ver = str_ireplace(\".zip\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".gz\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".tar\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".exe\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".jar\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".src\", \"\", $name_ver);\n\t\t\t\tif ($name_ver >= $server_version) {\n\t\t\t\t\t$server_version = $name_ver;\n\n\t\t\t\t\t$zip_file = \"$folder\".\"tigase-server-$server_version\".\".zip\";\n\t\t\t\t\t$exe_file = \"$folder\".\"tigase-server-$server_version\".\".exe\";\n\t\t\t\t\t$targz_file = \"$folder\".\"tigase-server-$server_version\".\".tar.gz\";\n\t\t\t\t\t$jar_file = \"$folder\".\"tigase-server-$server_version\".\".jar\";\n\n// \t\t\t\t\t\t$file = $name;\n// \t\t\t\t\tif (strpos($name, \".zip\")) {\n// \t\t\t\t\t\t$zip_file = \"$folder$file\";\n// \t\t\t\t\t}\n// \t\t\t\t\tif (strpos($name, \".exe\")) {\n// \t\t\t\t\t\t$exe_file = \"$folder$file\";\n// \t\t\t\t\t}\n// \t\t\t\t\tif (strpos($name, \".tar.gz\")) {\n// \t\t\t\t\t\t$targz_file = \"$folder$file\";\n// \t\t\t\t\t}\n// \t\t\t\t\tif (strpos($name, \".jar\")) {\n// \t\t\t\t\t\t$jar_file = \"$folder$file\";\n// \t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$server_downloads = $description[0];\n\t\t\t}\n\t\t}\n\t\t$link_jar = \"<a href=\\\"{$base_path}/{$jar_file}\\\">jar</a>, \";\n\t\t$link_exe = \"<a href=\\\"{$base_path}/{$exe_file}\\\">exe</a>, \";\n\t\t$link_targz = \"<a href=\\\"{$base_path}/{$targz_file}\\\">tar.gz</a>, \";\n\t\t$link_zip = \"<a href=\\\"{$base_path}/{$zip_file}\\\">zip</a>\";\n\t\t$link_all = \"<a href=\\\"{$base_path}/filebrowser/tigase-server\\\">$server_downloads</a>\";\n\t\t//$users_cnt = db_fetch_object(db_query(\"SELECT COUNT(*) as count from {users};\"));\n\t\t$online_cnt = db_fetch_object(db_query(\"SELECT COUNT(*) as count from {users} where online_status > 0;\"));\n\t\t// Count users with activity in the past defined period.\n\t\t$time_period = variable_get('user_block_seconds_online', 900);\n\t\t// Perform database queries to gather online user lists.\n\t\t$guests = db_fetch_object(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d AND uid = 0', time() - $time_period));\n\t\t$users = db_fetch_object(db_query('SELECT COUNT(*) AS count FROM {users} WHERE access >= %d AND uid != 0 ORDER BY access DESC', time() - $time_period));\n\t\t$block_content .= '<table border=\"0\">';\n\t\t//\t\t$block_content .= '<tr><td>Registered:</td><td>' . $users_cnt->count . '</td></tr>';\n\t\t//\t\t$block_content .= '<tr><td>Jabber Online:</td><td>' . $online_cnt->count . '</td></tr>';\n// \t\tprint_r( $jabber_stats );\n// \t\tprint_r( '<br/>' );\n\t\tforeach ($jabber_stats as $name => $description) {\n\t\t\t$block_content .= \"<tr><td>{$name}</td><td>{$description}</td></tr>\";\n\t\t}\n\t\t$block_content .= '<tr><td>Website online:</td><td>' . ($users->count + $guests->count) . '</td></tr>';\n\t\t$block_content .= '<tr><td>Ver ' . $server_version . ':</td><td>'\n\t\t\t. $link_jar . $link_exe . $link_targz . $link_zip . '</td></tr>';\n\t\t$block_content .= '<tr><td>All downloads:</td><td>' . $link_all . '</td></tr>';\n\t\t$block_content .= '<tr><td><a href=\"http://www.ohloh.net/\">Ohloh</a> stats:</td>' .\n\t\t\t'<td><a href=\"http://www.ohloh.net/projects/4171\"><img src=\"/files/ohloh_badge.gif\"/></a></td></tr>';\n\t\t$block_content .= '</table>';\n\t\t$block_content .=\n\t\t\t\"<div class=\\\"more-link\\\">\"\n\t\t\t.'More '\n\t\t\t.l(t(\"details...\"), \"jabber-stats\", array(\"title\" => t(\"Statistics details.\")))\n\t\t\t.' or '\n\t\t\t.l(t(\"configuration...\"), \"jabber-config\", array(\"title\" => t(\"Server configuration.\")))\n\t\t\t.\"</div>\";\n    // set up the block\n    $block['subject'] = 'Monitor';\n    $block['content'] = $block_content;\n    return $block;\n\t}\n}\n\n/**\n * Output full jabber statistics from files/jabber_stats.html file\n */\nfunction tigase_monitor_full_stats() {\n\t$page_content = '';\n\t$src_file = 'files/jabber_stats.html';\n\n  if (is_readable($src_file) && ($file = file($src_file))) {\n\t\t$started = 0;\n    foreach ($file as $line) {\n\t\t\tif (!$started) {\n\t\t\t\t$started = stripos($line, 'Server version info:')\n\t\t\t\t\t|| stripos($line, 'Tests results:');\n\t\t\t} else {\n\t\t\t\t$started = !stripos($line, 'Server basic configuration parameters:');\n\t\t\t}\n\t\t\tif ($started) {\n\t\t\t\t$page_content .= $line;\n\t\t\t}\n    }\n\t}\n\n\t// check to see if there was any content before\n  // setting up the block\n  if ($page_content == '') {\n    // No statistics file...\n    $page_content = \"Server statistics are not available yet...\";\n  }\n\n  return $page_content;\n}\n\n/**\n * Output full jabber statistics from files/jabber_stats.html file\n */\nfunction tigase_monitor_tigase_config() {\n\t$page_content = '';\n\t$src_file = 'files/jabber_stats.html';\n\n  if (is_readable($src_file) && ($file = file($src_file))) {\n\t\t$started = 0;\n    foreach ($file as $line) {\n\t\t\tif (!$started) {\n\t\t\t\t$started = stripos($line, 'Server basic configuration parameters:');\n\t\t\t} else {\n\t\t\t\t$started = !stripos($line, 'Tests results:');\n\t\t\t}\n\t\t\tif ($started) {\n\t\t\t\t$page_content .= $line;\n\t\t\t}\n    }\n\t}\n\n\t// check to see if there was any content before\n  // setting up the block\n  if ($page_content == '') {\n    // No statistics file...\n    $page_content = \"Server configuration are not available yet...\";\n  }\n\n  return $page_content;\n}\n\nfunction tigase_monitor_menu() {\n\n  $items = array();\n\n  $items[] = array(\n\t\t'path' => 'jabber-stats',\n\t\t'title' => t('Tigase server statistics'),\n\t\t'callback' => 'tigase_monitor_full_stats',\n\t\t'access' => user_access('access tigase_monitor content'),\n\t\t'type' => MENU_CALLBACK);\n  $items[] = array(\n\t\t'path' => 'jabber-config',\n\t\t'title' => t('Tigase server configuration'),\n\t\t'callback' => 'tigase_monitor_tigase_config',\n\t\t'access' => user_access('access tigase_monitor config'),\n\t\t'type' => MENU_CALLBACK);\n\n  return $items;\n}\n\n/**\n * Loads file metainformation from the specified file.\n */\nfunction tigase_monitor_decript($decript = NULL) {\n  static $decriptcols = array();\n\n  // Return (previously generated) decript column list\n  if (!isset($decript)) { return $decriptcols; }\n\n  // Build decript information list\n  $decriptinfo = array();\n  if (is_readable($decript) && ($file = file($decript))) {\n    foreach ($file as $line) {\n      // Skip empty and commented lines\n      if (trim($line) == '' || strpos(trim($line), '#') === 0) {\n        continue;\n      }\n      list($name, $description) = explode(\" \", $line, 2);\n      if (isset($decriptinfo[$name])) {\n        $decriptinfo[$name] .= trim($description) . \" \";\n      } else {\n        $decriptinfo[$name] = trim($description) . \" \";\n      }\n    }\n\n    foreach ($decriptinfo as $name => $description) {\n      $decriptinfo[$name] = array(trim($description));\n    }\n  }\n  return $decriptinfo;\n}\n\n/**\n * Loads file metainformation from the specified file.\n */\nfunction tigase_monitor_stats($stats = NULL) {\n  static $statscols = array();\n\n  // Return (previously generated) stats column list\n  if (!isset($stats)) { return $statscols; }\n\n\t// Build stats information list\n  $statsinfo = array();\n  if (is_readable($stats) && ($file = file($stats))) {\n    foreach ($file as $line) {\n      // Skip empty and commented lines\n      if ((trim($line) == '') || strpos(trim($line), '#')) {\n        continue;\n      }\n\t\t\tif (stripos($line, 'Registered')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Registered:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'Packets received')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Packets:'] = $split_line[2];\n\t\t\t}\n\t\t\tif (stripos($line, 'Open authorized sessions')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Sessions online:'] = $split_line[4];\n\t\t\t}\n\t\t\tif (stripos($line, 'Uptime')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Uptime:'] = $split_line[1] . substr($split_line[2], 0, 1)\n\t\t\t\t\t. ', ' . $split_line[3] . substr($split_line[4], 0, 1);\n\t\t\t}\n\t\t\tif (stripos($line, 'Connected servers')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Connected servers:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'Open s2s connections')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Server connections:'] = $split_line[4];\n\t\t\t}\n\t\t\tif (stripos($line, 'c2s')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Clients online:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'bosh')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Bosh online:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'Version')) {\n        $split_line = explode(' ', trim($line));\n        $statsinfo['Running version:'] = $split_line[1];\n      }\n\t\t\tif (stripos($line, 'CPU')) {\n        $split_line = explode(' ', trim($line));\n        $statsinfo['CPU usage:'] = $split_line[2];\n      }\n    }\n\n  }\n//  \tprint_r( $statsinfo );\n//  \tprint_r( '<br/>' );\n  return $statsinfo;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase_monitor.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal Monitor Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\n\t/**\n\t * Display help and module information\n\t * @param section which section of the site we're displaying help\n\t * @return help text for section\n\t */\nfunction tigase_monitor_help($section='') {\n\n\t$output = '';\n\n\tswitch ($section) {\n\tcase \"admin/modules#description\":\n\t\t$output = t(\"Monitor displaying various server statistics.\");\n\t\tbreak;\n\tcase \"admin/help#tigase_monitor\":\n\t\t$output = t(\"Monitor displaying various server statistics.\") . \"\\n\"\n\t\t\t. t(\" This module displays information about number of downloads, last software version, number of registered user accounts, number of users online, number of s2s connections and so on...\");\n\t\tbreak;\n\t}\n\n\treturn $output;\n}\n\nfunction tigase_monitor_perm() {\n  return array('access tigase_monitor', 'access tigase_monitor content',\n\t\t'access tigase_monitor config');\n}\n\n/**\n* Output all monitor information\n* @param op the operation from the URL\n* @param delta offset\n* @returns block HTML\n*/\nfunction tigase_monitor_block($op='list', $delta=0) {\n\t// listing of blocks, such as on the admin/block page\n\tif ($op == \"list\") {\n\t\t$block[0][\"info\"] = t('Monitor');\n\t\treturn $block;\n\t} else if ($op == 'view') {\n\t\t$folder = 'files/downloads/tigase-server/';\n\t\t$descript = $folder . 'descript.ion';\n\t\t$info = tigase_monitor_decript($descript);\n\t\t$jabber_stats_file = 'files/jabber_stats.txt';\n\t\t$jabber_stats = tigase_monitor_stats($jabber_stats_file);\n \t\t$server_downloads = '';\n\t\t$server_version = ' ';\n\t\t$file = '';\n\t\tforeach ($info as $name => $description) {\n\t\t\tif ($name != 'TOTAL:') {\n\t\t\t\t$name_ver = str_ireplace(\"tigase-server-\", \"\", $name);\n\t\t\t\t$name_ver = str_ireplace(\".zip\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".gz\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".tar\", \"\", $name_ver);\n\t\t\t\t$name_ver = str_ireplace(\".exe\", \"\", $name_ver);\n\t\t\t\tif ($name_ver >= $server_version) {\n\t\t\t\t\t$server_version = $name_ver;\n\t\t\t\t\t$file = $name;\n\t\t\t\t\tif (strpos($name, \".zip\")) {\n\t\t\t\t\t\t$zip_file = \"$folder/$file\";\n\t\t\t\t\t}\n\t\t\t\t\tif (strpos($name, \".exe\")) {\n\t\t\t\t\t\t$exe_file = \"$folder/$file\";\n\t\t\t\t\t}\n\t\t\t\t\tif (strpos($name, \".tar.gz\")) {\n\t\t\t\t\t\t$targz_file = \"$folder/$file\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$server_downloads = $description[0];\n\t\t\t}\n\t\t}\n\t\t$link_zip = \"<a href=\\\"{$base_path}{$zip_file}\\\">zip</a>, \";\n\t\t$link_exe = \"<a href=\\\"{$base_path}{$exe_file}\\\">exe</a>, \";\n\t\t$link_targz = \"<a href=\\\"{$base_path}{$targz_file}\\\">tar.gz</a>\";\n\t\t$link_all = \"<a href=\\\"{$base_path}/filebrowser/tigase-server\\\">$server_downloads</a>\";\n\t\t//$users_cnt = db_fetch_object(db_query(\"SELECT COUNT(*) as count from {users};\"));\n\t\t$online_cnt = db_fetch_object(db_query(\"SELECT COUNT(*) as count from {users} where online_status > 0;\"));\n\t\t// Count users with activity in the past defined period.\n\t\t$time_period = variable_get('user_block_seconds_online', 900);\n\t\t// Perform database queries to gather online user lists.\n\t\t$guests = db_fetch_object(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d AND uid = 0', time() - $time_period));\n\t\t$users = db_fetch_object(db_query('SELECT COUNT(*) AS count FROM {users} WHERE access >= %d AND uid != 0 ORDER BY access DESC', time() - $time_period));\n\t\t$block_content .= '<table border=\"0\">';\n\t\t//\t\t$block_content .= '<tr><td>Registered:</td><td>' . $users_cnt->count . '</td></tr>';\n\t\t//\t\t$block_content .= '<tr><td>Jabber Online:</td><td>' . $online_cnt->count . '</td></tr>';\n// \t\tprint_r( $jabber_stats );\n// \t\tprint_r( '<br/>' );\n\t\tforeach ($jabber_stats as $name => $description) {\n\t\t\t$block_content .= \"<tr><td>{$name}</td><td>{$description}</td></tr>\";\n\t\t}\n\t\t$block_content .= '<tr><td>Website online:</td><td>' . ($users->count + $guests->count) . '</td></tr>';\n\t\t$block_content .= '<tr><td>Ver ' . $server_version . ':</td><td>'\n\t\t\t. $link_zip . $link_exe . $link_targz . '</td></tr>';\n\t\t$block_content .= '<tr><td>All downloads:</td><td>' . $link_all . '</td></tr>';\n\t\t$block_content .= '<tr><td><a href=\"http://www.ohloh.net/\">Ohloh</a> stats:</td>' .\n\t\t\t'<td><a href=\"http://www.ohloh.net/projects/4171\"><img src=\"/files/ohloh_badge.gif\"/></a></td></tr>';\n\t\t$block_content .= '</table>';\n\t\t$block_content .=\n\t\t\t\"<div class=\\\"more-link\\\">\"\n\t\t\t.'More '\n\t\t\t.l(t(\"details...\"), \"jabber-stats\", array(\"title\" => t(\"Statistics details.\")))\n\t\t\t.' or '\n\t\t\t.l(t(\"configuration...\"), \"jabber-config\", array(\"title\" => t(\"Server configuration.\")))\n\t\t\t.\"</div>\";\n    // set up the block\n    $block['subject'] = 'Monitor';\n    $block['content'] = $block_content;\n    return $block;\n\t}\n}\n\n/**\n * Output full jabber statistics from files/jabber_stats.html file\n */\nfunction tigase_monitor_full_stats() {\n\t$page_content = '';\n\t$src_file = 'files/jabber_stats.html';\n\n  if (is_readable($src_file) && ($file = file($src_file))) {\n\t\t$started = 0;\n    foreach ($file as $line) {\n\t\t\tif (!$started) {\n\t\t\t\t$started = stripos($line, 'Server version info:')\n\t\t\t\t\t|| stripos($line, 'Tests results:');\n\t\t\t} else {\n\t\t\t\t$started = !stripos($line, 'Server basic configuration parameters:');\n\t\t\t}\n\t\t\tif ($started) {\n\t\t\t\t$page_content .= $line;\n\t\t\t}\n    }\n\t}\n\n\t// check to see if there was any content before\n  // setting up the block\n  if ($page_content == '') {\n    // No statistics file...\n    $page_content = \"Server statistics are not available yet...\";\n  }\n\n  return $page_content;\n}\n\n/**\n * Output full jabber statistics from files/jabber_stats.html file\n */\nfunction tigase_monitor_tigase_config() {\n\t$page_content = '';\n\t$src_file = 'files/jabber_stats.html';\n\n  if (is_readable($src_file) && ($file = file($src_file))) {\n\t\t$started = 0;\n    foreach ($file as $line) {\n\t\t\tif (!$started) {\n\t\t\t\t$started = stripos($line, 'Server basic configuration parameters:');\n\t\t\t} else {\n\t\t\t\t$started = !stripos($line, 'Tests results:');\n\t\t\t}\n\t\t\tif ($started) {\n\t\t\t\t$page_content .= $line;\n\t\t\t}\n    }\n\t}\n\n\t// check to see if there was any content before\n  // setting up the block\n  if ($page_content == '') {\n    // No statistics file...\n    $page_content = \"Server configuration are not available yet...\";\n  }\n\n  return $page_content;\n}\n\nfunction tigase_monitor_menu() {\n\n  $items = array();\n\n  $items[] = array('path' => 'jabber-stats',\n\t\t'title' => t('Tigase server statistics'),\n\t\t'callback' => 'tigase_monitor_full_stats',\n\t\t'access' => user_access('access tigase_monitor content'),\n\t\t'type' => MENU_CALLBACK);\n  $items[] = array('path' => 'jabber-config',\n\t\t'title' => t('Tigase server configuration'),\n\t\t'callback' => 'tigase_monitor_tigase_config',\n\t\t'access' => user_access('access tigase_monitor config'),\n\t\t'type' => MENU_CALLBACK);\n\n  return $items;\n}\n\n/**\n * Loads file metainformation from the specified file.\n */\nfunction tigase_monitor_decript($decript = NULL) {\n  static $decriptcols = array();\n\n  // Return (previously generated) decript column list\n  if (!isset($decript)) { return $decriptcols; }\n\n  // Build decript information list\n  $decriptinfo = array();\n  if (is_readable($decript) && ($file = file($decript))) {\n    foreach ($file as $line) {\n      // Skip empty and commented lines\n      if (trim($line) == '' || strpos(trim($line), '#') === 0) {\n        continue;\n      }\n      list($name, $description) = explode(\" \", $line, 2);\n      if (isset($decriptinfo[$name])) {\n        $decriptinfo[$name] .= trim($description) . \" \";\n      } else {\n        $decriptinfo[$name] = trim($description) . \" \";\n      }\n    }\n\n    foreach ($decriptinfo as $name => $description) {\n      $decriptinfo[$name] = array(trim($description));\n    }\n  }\n  return $decriptinfo;\n}\n\n/**\n * Loads file metainformation from the specified file.\n */\nfunction tigase_monitor_stats($stats = NULL) {\n  static $statscols = array();\n\n  // Return (previously generated) stats column list\n  if (!isset($stats)) { return $statscols; }\n\n\t// Build stats information list\n  $statsinfo = array();\n  if (is_readable($stats) && ($file = file($stats))) {\n    foreach ($file as $line) {\n      // Skip empty and commented lines\n      if ((trim($line) == '') || strpos(trim($line), '#')) {\n        continue;\n      }\n\t\t\tif (stripos($line, 'Registered')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Registered:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'Packets received')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Packets:'] = $split_line[2];\n\t\t\t}\n\t\t\tif (stripos($line, 'Open authorized sessions')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Sessions online:'] = $split_line[4];\n\t\t\t}\n\t\t\tif (stripos($line, 'Uptime')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Uptime:'] = $split_line[1] . substr($split_line[2], 0, 1)\n\t\t\t\t\t. ', ' . $split_line[3] . substr($split_line[4], 0, 1);\n\t\t\t}\n\t\t\tif (stripos($line, 's2s')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Servers online:'] = $split_line[4];\n\t\t\t}\n\t\t\tif (stripos($line, 'c2s')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Clients online:'] = $split_line[3];\n\t\t\t}\n\t\t\tif (stripos($line, 'bosh')) {\n\t\t\t\t$split_line = explode(' ', trim($line));\n\t\t\t\t$statsinfo['Bosh online:'] = $split_line[3];\n\t\t\t}\n    }\n\n  }\n//  \tprint_r( $statsinfo );\n//  \tprint_r( '<br/>' );\n  return $statsinfo;\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase_usrreg-5.x/tigase_usrreg.info",
    "content": "; $Rev: $\n; Last modified by $Author: $\n; $Date: $\n\nname = User register hook\ndescription = Catches user creation event and for each new user creates a file in the filesystem with the new user name. This file is later used by system scripts which create system directory for the user so he can receive emails.\npackage = Tigase\nversion = 1.0\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/php/drupal/modules/tigase_usrreg-5.x/tigase_usrreg.module",
    "content": "<?php\n\t/*\n\t * Tigase Drupal User Register Module\n\t * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n\t *\n\t * This program is free software: you can redistribute it and/or modify\n\t * it under the terms of the GNU Affero General Public License as published by\n\t * the Free Software Foundation, either version 3 of the License.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU Affero General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU Affero General Public License\n\t * along with this program. Look for COPYING file in the top folder.\n\t * If not, see http://www.gnu.org/licenses/.\n\t *\n\t * $Rev:  $\n\t * Last modified by $Author: $\n\t * $Date:  $\n\t */\n\nfunction tigase_usrreg_user($op, &$edit, &$user) {\n\n  if ($op == 'insert') {\n\t  $folder = 'users-list/';\n\t\t$user_name = $user->name;\n\t\t$handle = fopen($folder . $user_name, \"w+\");\n\t\tfwrite($handle, $user_name);\n\t\tfclose($handle);\n  }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/python/tigase/admin/PythonExample.py",
    "content": "# Tigase Jabber/XMPP Server\n# Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, version 3 of the License.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n#\n# You should have received a copy of the GNU Affero General Public License\n# along with this program. Look for COPYING file in the top folder.\n# If not, see http://www.gnu.org/licenses/.\n#\n# $Rev: $\n# Last modified by $Author: $\n# $Date: $\n\nfrom java.lang import *\nfrom tigase.server import *\n\n\nnum1 = Command.getFieldValue(packet, \"num1\")\nnum2 = Command.getFieldValue(packet, \"num2\")\n\nif num1 is None or num2 is None:\n   res = Iq.commandResultForm(packet)\n   Command.addTextField(res, \"Note\", \"This is Python script!\")\n   Command.addFieldValue(res, \"num1\", \"\")\n   Command.addFieldValue(res, \"num2\", \"\")\n   packet = res\nelse:\n   result = num1 + num2\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/resources/META-INF/MANIFEST.MF",
    "content": "Specification-Title: Tigase Jabber Server\nSpecification-Vendor: tigase.org\nSpecification-Version: 1.0.0"
  },
  {
    "path": "tigase-server 7.1.0/src/main/resources/META-INF/java.security.Provider",
    "content": "# our security providers\ntigase.auth.TigaseSaslProvider"
  },
  {
    "path": "tigase-server 7.1.0/src/main/resources/mib/JVM-MANAGEMENT-MIB.mib",
    "content": "-- \n-- @(#)JVM-MANAGEMENT-MIB.mib\t1.32 04/07/16\n-- \n-- Copyright 2004 Sun Microsystems, Inc. All rights reserved.\n-- This software is the proprietary information of Sun Microsystems, Inc.\n-- Use is subject to license terms.\n--\n-- The JVM-MANAGEMENT-MIB Module\n--\n-- See jvmManagementMIB MODULE-IDENTITY for a description overview.\n-- See conformance statements for mandatory objects \n--\n\nJVM-MANAGEMENT-MIB DEFINITIONS ::= BEGIN\n\nIMPORTS\n    MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, Counter32, Gauge32, \n\tInteger32, Counter64, enterprises\n        FROM SNMPv2-SMI\n    DisplayString, TEXTUAL-CONVENTION, RowPointer\n        FROM SNMPv2-TC\n    MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP\n        FROM SNMPv2-CONF;\n\n-- Module Identity\n------------------\n\njvmMgtMIB MODULE-IDENTITY \n    LAST-UPDATED \"200403041800Z\"\n    -- Format is \"YYYYMMDDhhmmZ\"\n    ORGANIZATION \"Sun Microsystems, Inc.\"\n    CONTACT-INFO \"Sun Microsystems, Inc.\n                  4150 Network Circle\n\t\t  Santa Clara, CA 95054\n\t\t  1-800-555-9SUN or\n\t\t  1-650-960-1300\n\t\t  http://www.sun.com\n\t\t  or contact your local support representative\"            \n    DESCRIPTION\n            \"Copyright 2004 Sun Microsystems, Inc. All rights reserved.\n\n             This module defines the MIB that provides access to the\n\t     Java[tm] Virtual Machine monitoring data.\n\t     This module is derived from the Java[tm] programming language APIs\n             described in the java.lang.management package of \n             Java[tm] 2, Standard Edition, 5.0.\n\n\t     See the Java programming language APIs of JSR 163 for\n             'Monitoring and Management of the Java[TM] Virtual Machine'\n             for more details.\n\n\t     Where the Java programming language API uses long, or int, \n             the MIB often uses the corresponding unsigned quantity - \n             which is closer to the object semantics.\n\n             In those cases, it often happens that the -1 value that might\n             be used by the API to indicate an unknown/unimplemented\n             value cannot be used. Instead the MIB uses the value 0, which\n             stricly speaking cannot be distinguished from a valid value.\n             In many cases however, a running system will have non-zero\n             values, so using 0 instead of -1 to indicate an unknown \n             quantity does not lose any functionality.\n\t    \"\n    REVISION     \"200403041800Z\"\n    -- Format is \"YYYYMMDDhhmmZ\"\n    DESCRIPTION\n            \"\n            JVM-MANAGEMENT-MIB - JSR 163 Final Release 1.0\n            \"\n\n    ::= { standard jsr163(163) 1 }\n\n\n-- Enterprise OIDs\n------------------\n\n--        internet          OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) 1 }\n--        private           OBJECT IDENTIFIER ::= { internet 4 }\n--        enterprises       OBJECT IDENTIFIER ::= { private 1 }\n\tsun\t  \t  OBJECT IDENTIFIER ::= { enterprises 42 }\n\tjmgt\t\t  OBJECT IDENTIFIER ::= { sun products(2) 145 }\n\t-- experimental      OBJECT IDENTIFIER ::= { jmgt 1 }\n        standard          OBJECT IDENTIFIER ::= { jmgt 3 }\n\n----------------------------------------------------------------------------\n-- Textual Conventions\n----------------------\n--\n-- Note: Some of the TEXTUAL-CONVENTIONs defined in this module are \n--       OCTET STRING with a 1023 size limitation (SIZE(0..1023)).\n--\n-- As per RFC2578, section 7.1.2.  OCTET STRING:\n--\n--       \"The OCTET STRING type represents arbitrary binary or textual data.\n--        Although the SMI-specified size limitation for this type is 65535\n--        octets, MIB designers should realize that there may be \n--        implementation and interoperability limitations for sizes in \n--        excess of 255 octets.\"\n--\n-- As a consequence an agent implementing this MIB may decide to \n-- restrict this maximum size to a lesser value than 1023, provided that \n-- it makes it clear in an AGENT-CAPABILITY statement.\n-- \n----------------------------------------------------------------------------\n\nJvmUnsigned64TC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n           \"A non-negative 64-bit bit integer, without counter\n            semantics.\"\n    -- We have cloned the Unsigned64TC defined in RFC 2564 rather\n    -- than importing it because the JVM-MANAGEMENT-MIB and the\n    -- APPLICATION-MIB are not related.\n    --\n    REFERENCE \"RFC 2564 - APPLICATION-MIB, Unsigned64TC.\"\n    SYNTAX Counter64\n\n\nJvmJavaObjectNameTC ::= TEXTUAL-CONVENTION\n    DISPLAY-HINT \"255a\"\n    STATUS       current\n    DESCRIPTION\n          \"An Object Name, as implemented by the java.lang.management API,\n\t  which identify a runtime Object (e.g. a Class Loader, a\n          Memory Manager, etc...). \n\t  The name is assumed to be unique in the scope of the object's\n\t  class.\n\n\t  This object syntax is equivalent to a DisplayString, but with a\n          a 1023 bytes size limits (instead of 255 for a DisplayString).\n\t  \n\t  Note that the SNMP agent may have to truncate the string returned\n          by the underlying API if it does not fit in this type. \n\t  (1023 bytes max).\n\t  \"\n    SYNTAX       OCTET STRING (SIZE (0..1023))\n\nJvmPathElementTC ::= TEXTUAL-CONVENTION\n    DISPLAY-HINT \"255a\"\n    STATUS       current\n    DESCRIPTION\n          \"A file or directory element in a PATH/CLASSPATH/LIBRARY_PATH\n           structure.\n\n\t  This object syntax is equivalent to a DisplayString, but with a\n          a 1023 bytes size limits (instead of 255 for a DisplayString).\n\t  \n\t  Note that the SNMP agent may have to truncate the string returned\n          by the underlying API if it does not fit in this type. \n\t  (1023 bytes max).\n\t  \"\n    SYNTAX       OCTET STRING (SIZE (0..1023))\n\nJvmArgValueTC ::= TEXTUAL-CONVENTION\n    DISPLAY-HINT \"255a\"\n    STATUS       current\n    DESCRIPTION\n          \"A string representing an input argument.\n\n\t  This object syntax is equivalent to a DisplayString, but with a\n          a 1023 bytes size limits (instead of 255 for a DisplayString).\n\t  \n\t  Note that the SNMP agent may have to truncate the string returned\n          by the underlying API if it does not fit in this type. \n\t  (1023 bytes max).\n\t  \"\n    SYNTAX       OCTET STRING (SIZE (0..1023))\n\nJvmVerboseLevelTC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n\t\"Defines whether the verbose flag for a feature is active.\n\t verbose: the flag is on.\n\t silent:  the flag is off.\n\t\"\n    SYNTAX INTEGER { silent(1), verbose(2) }\n\n\nJvmImplSupportStateTC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n\t\"Defines whether a feature is supported or not.\n\t\"\n    SYNTAX INTEGER { unsupported(1), supported(2) }\n\nJvmImplOptFeatureStateTC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n\t\"Defines whether an optional feature is supported, enabled, \n\t or disabled.\n\n         An optional feature can be:\n\n\t unsupported: The JVM does not support this feature.\n\t enabled    : The JVM supports this feature, and it\n\t              is enabled.\n\t disabled   : The JVM supports this feature, and it\n\t              is disabled.\n\n         Only enabled(3) and disabled(4) may be supplied as values to a\n         SET request. unsupported(1) can only be set internally by the\n         agent.\t \n\t \"\n    SYNTAX INTEGER { unsupported(1), enabled(3), disabled(4) }\n\nJvmTimeMillis64TC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n          \"An elapsed time, expressed in milli-seconds.\n           This type is based on Counter64, but without its specific\n           semantics.\n\t  \"  \n    SYNTAX Counter64\n\nJvmTimeNanos64TC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n          \"An elapsed time, expressed in nano-seconds.\n           This type is based on Counter64, but without its specific\n           semantics.\n\t  \"  \n    SYNTAX Counter64\n\nJvmPositive32TC ::= TEXTUAL-CONVENTION\n    STATUS       current\n    DESCRIPTION\n          \"A positive Integer32. In Java that would be a number \n           in [0..Integer.MAX_VALUE].\n\t  \"  \n    -- We use Integer32 (0..2147483647) rather than Unsigned32 because\n    -- Unsigned32 (0..2147483647) because Unsigned32 is based on \n    -- Gauge32 - which has a specific ASN.1 tag and a specific semantics. \n    -- In principle you cannot use a Gauge32 as base type for an index \n    -- in a table.\n    -- Note also that Unsigned32 is (0..2^32-1) \n    --          while Positive32 is (0..2^31-1)\n    -- \n    SYNTAX Integer32 (0..2147483647)\n\nJvmManagedMemoryTypeTC ::= TEXTUAL-CONVENTION\n    STATUS  current\n    DESCRIPTION\n\t\"\n         Defines the type of memory contained in a memory pool.\n\t The pool may contain, heap memory or non-heap memory.\n\t\"\n    SYNTAX  INTEGER { nonheap(1), heap(2) }\n\t\n    \nJvmValidityStateTC ::= TEXTUAL-CONVENTION\n    STATUS  current\n    DESCRIPTION\n\t\"\n         Defines whether an object is still valid.\n\t\"\n    SYNTAX  INTEGER { invalid(1), valid(2) }\n\t\n    \nJvmThreadStateTC ::= TEXTUAL-CONVENTION\n    STATUS  current\n    DESCRIPTION\n\t\"Defines the possible states of a thread running in the \n\t Java virtual machine. They are virtual machine thread states \n\t and do not reflect any operating system thread states. \n\t \n\t The first two bits: inNative(1) and suspended(2) can be \n         combined together and with any other bits. The remaining\n         bits 3-9, are mutually exclusive. Bits 10-16 are reserved\n         for future evolution of this MIB.\n\n         An agent MUST always return a thread state with one of the\n         bits in the range 3-9 set to 1. The other(9) bit should only\n         be set to 1 if new thread states which are mutally exclusive\n         with bits 3-8 are defined.  An implementation can define \n         additional implementation dependant states and uses bits\n         from bit 17. \n\n\t See java.lang.Thread.State,\n\t     java.lang.management.ThreadInfo.\n\t \"\n     --\n     -- Take care that in SNMP bits are numbered starting at 1, from\n     -- left to right (1 is the highest bit). A bitmap defined by the\n     -- BITS construct is thus a byte array where bit 1 is the highest bit\n     -- of the first byte.\n     --\n     SYNTAX  BITS { -- Bits 1-2 may be specified in any combination\n                    inNative(1),\n                    suspended(2),\n\n                    -- Bits 3-9 are mutually exclusive. Attempting to\n                    -- set more than a single bit to 1 will result in\n                    -- a returned error-status of inconsistentValue.\n                    newThread(3),\n                    runnable(4),\n                    blocked(5),\n                    terminated(6),\n                    waiting(7),\n                    timedWaiting(8),\n                    other(9)\n                    -- Bits 10-16 are reserved for future use by\n                    -- this MIB\n                  }\n\n\nJvmIndex64TC ::= TEXTUAL-CONVENTION\n    STATUS current\n    DESCRIPTION\n\t\"A 64 bits string mapping an unsigned 64 bits integer value\n         in big-endian ordering (i.e: 1 is encoded as 0x0000000000000001).\n\n\t This type can be used when an unsigned 64 bits integer needs\n\t to be used inside a table index.\n\t\"\n    SYNTAX OCTET STRING (SIZE(8))\n          \n  \n-- OBJECT-TYPE OID tree\n-----------------------\n                  \njvmMgtMIBObjects \n\tOBJECT IDENTIFIER ::= { jvmMgtMIB 1 }\njvmMgtMIBNotifications \n\tOBJECT IDENTIFIER ::= { jvmMgtMIB 2 }\njvmMgtMIBConformance\n\tOBJECT IDENTIFIER ::= { jvmMgtMIB 3 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Class Loading group\n--\n-- A collection of objects used to monitor Class Loading in the\n-- Java Virtual Machine. These objects define the SNMP  management \n-- interface for the class loading system of the Java virtual machine.\n--\n-- This group only contains a few scalar object and no tables. The objects\n-- from this group are mapped from the java.lang.management.ClassLoadingMXBean\n-- interface.\n-- \n-- See J2SE 5.0 API Specification, \n--     java.lang.management.ClassLoadingMXBean\n-----------------------------------------------------------------------\n\n-- Root OBJECT IDENTIFIER for ClassLoading group.\n--\njvmClassLoading   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 1 }\n\n-- The following objects are mapped from the ClassLoadingMXBean interface.\n-----------------------------------------------------------------------\n\njvmClassesLoadedCount OBJECT-TYPE\n    SYNTAX      Gauge32 \n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n            \"The number of classes currently loaded in the JVM.\n\n\t     See java.lang.management.ClassLoadingMXBean.getLoadedClassCount()\n            \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ClassLoadingMXBean\"\n    ::= { jvmClassLoading 1 }\n\njvmClassesTotalLoadedCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n            \"The total number of classes that have been loaded since\n\t     the JVM has started execution.\n\n\t     See java.lang.management.ClassLoadingMXBean.\n\t              getTotalLoadedClassCount()\n            \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ClassLoadingMXBean\"\n    ::= { jvmClassLoading 2 }\n\njvmClassesUnloadedCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n            \"The total number of classes that have been unloaded since\n\t     the JVM has started execution.\n\n\t     See java.lang.management.ClassLoadingMXBean.getUnloadedClassCount()\n            \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ClassLoadingMXBean\"\n    ::= { jvmClassLoading 3 }\n\njvmClassesVerboseLevel OBJECT-TYPE\n    SYNTAX      JvmVerboseLevelTC\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n            \"Enables or disables the verbose output for the class loading \n             system. The verbose output information and the output stream \n             to which the verbose information is emitted are implementation \n             dependent. Typically, a Java virtual machine implementation \n             prints a message each time a class file is loaded.\n\n\t     verbose: if the verbose output is enabled.\n\t     silent:  otherwise. \n\n\t     See java.lang.management.ClassLoadingMXBean.isVerbose(), \n                 java.lang.management.ClassLoadingMXBean.setVerbose()\n            \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ClassLoadingMXBean\"\n    DEFVAL { silent }\n    ::= { jvmClassLoading 4 }\n\n\n-----------------------------------------------------------------------\n--\n-- The JVM Memory group\n--\n-- A collection of objects used to monitor memory management in the\n-- Java Virtual Machine. These objects define management interface for \n-- the memory system of the Java virtual machine. \n--\n-- Memory:\n--\n-- The memory system of the Java virtual machine manages the following \n-- kinds of memory: heap, and non-heap. More information on these types\n-- of memory can be obtained from the J2SE 5.0 API Specification,\n-- java.lang.management.MemoryMXBean.\n--\n-- Memory Pools and Memory Managers:\n--\n-- Memory pools and memory managers are the abstract entities that monitor \n-- and manage the memory system of the Java virtual machine.\n--\n-- Memory managers are represented by the jvmMemManagerTable, which contains\n-- one row per Memory manager. \n-- The garbage collector is one type of memory  manager responsible for \n-- reclaiming memory occupied by unreachable objects.\n-- The jvmMemGCTable is an extension of the jvmMemManagerTable, which contains\n-- the attribute specific to garbage collectors. A garbage collector entity\n-- is thus represented by one row in the jvmMemManagerTable, and one \n-- extension row in the jvmMemGCTable.\n--\n-- Memory Pools are represented by the jvmMemPoolTable, which contains one \n-- row per memory pool. A Java virtual machine may create or remove \n-- memory pools during execution. A memory pool can belong to either the \n-- heap or the non-heap memory. \n--\n-- A memory manager is responsible for managing one or more memory pools. \n-- A memory pool can be managed by more than one memory manager.\n-- The jvmMemMgrRelPoolTable represents this managing/managed relationship. \n--\n-- A Java virtual machine may add or remove memory managers during execution. \n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryMXBean for\n--     more information on memory types, memory managers, memory pools,\n--     and the memory subsystem.\n--\n-----------------------------------------------------------------------\n\n-- Root OBJECT IDENTIFIER for the JVM Memory group.\n--\njvmMemory   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 2 }\n\n-- The following objects are mapped from the MemoryMXBean interface.\n-----------------------------------------------------------------------\n\njvmMemoryPendingFinalCount OBJECT-TYPE\n    SYNTAX      Gauge32\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate number objects that are pending for finalization.\n        \n\t See java.lang.management.MemoryMXBean.\n                  getObjectPendingFinalizationCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean\"\n    ::= { jvmMemory 1 }\n\njvmMemoryGCVerboseLevel OBJECT-TYPE\n    SYNTAX      JvmVerboseLevelTC\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"Enables or disables verbose output for the memory system. \n         The verbose output information and the output stream to which \n         the verbose information is emitted are implementation dependent. \n         Typically, a Java virtual machine implementation prints a \n         message whenever it frees memory at garbage collection.\n\n\t verbose: if the verbose output is enabled,\n         silent:  otherwise.\n\n\t See java.lang.management.MemoryMXBean.isVerbose(), \n             java.lang.management.MemoryMXBean.setVerbose()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean\"\n    ::= { jvmMemory 2 }\n\njvmMemoryGCCall OBJECT-TYPE\n    SYNTAX      INTEGER { unsupported(1), supported(2), start(3), \n                          started(4), failed(5) }\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"This object makes it possible to remotelly trigger the\n\t Garbage Collector in the JVM.\n\n\t This object's syntax is an enumeration which defines:\n\n\t * Two state values, that can be returned from a GET request:\n\n           unsupported(1): means that remote invocation of gc() is not \n                           supported by the SNMP agent.\n           supported(2)  : means that remote invocation of gc() is supported\n\t                   by the SNMP agent.\n\n         * One action value, that can be provided in a SET request to\n           trigger the garbage collector:\n\n           start(3)      : means that a manager wishes to trigger\n                           garbage collection.\n\n         * Two result value, that will be returned in the response to a\n           SET request when remote invocation of gc is supported\n\t   by the SNMP agent:\n\n\t   started(4)    : means that garbage collection was \n                           successfully triggered. It does not mean \n                           however that the action was successfullly\n                           completed: gc might still be running when\n                           this value is returned.\n\t   failed(5)     : means that garbage collection couldn't be\n                           triggered.\n\n         * If remote invocation is not supported by the SNMP agent, then\n           unsupported(1) will always be returned as a result of either\n           a GET request, or a SET request with start(3) as input value.\n\n         * If a SET request with anything but start(3) is received, then\n\t   the agent will return a wrongValue error.\n\n\t See java.lang.management.MemoryMXBean.gc()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean\"\n    ::= { jvmMemory 3 }\n\n-- The object identifiers in the range jvmMemory.[4-9] are reserved for future\n-- evolution of this MIB.\n--\n-- We use the range jvmMemory.[10..19] for objects related to global JVM \n-- heap memory  usage, as returned by \n--      java.lang.management.MemoryMXBean.getHeapMemoryUsage().\n-- Object identifiers in the range jvmMemory.[14..19] are not used but \n-- reserved for future evolution of this MIB.\n--\njvmMemoryHeapInitSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of memory (in bytes) that the Java virtual machine \n        initially requests from the operating system for memory management\n\tfor heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getHeapMemoryUsage().getInit()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 10 }\n\n\njvmMemoryHeapUsed OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of used memory (in bytes) from heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getHeapMemoryUsage().getUsed()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 11 }\n\njvmMemoryHeapCommitted OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of memory (in bytes) committed by heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getHeapMemoryUsage().\n\t         getCommitted()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 12 }\n\njvmMemoryHeapMaxSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total maximum size of memory (in bytes) for all heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getHeapMemoryUsage().getMax()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 13 }\n\n-- We use the range jvmMemory.[20..29] for objects related to global JVM \n-- heap memory usage, as returned by\n--      lang.management.MemoryMXBean.getNonHeapMemoryUsage().\n-- Object identifiers in the range jvmMemory.[24..29] are not used but are\n-- reserved for future evolution of this MIB.\n--\njvmMemoryNonHeapInitSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of memory (in bytes) that the Java virtual machine \n        initially requests from the operating system for memory management\n\tfor non heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getNonHeapMemoryUsage().getInit()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 20 }\n\n\njvmMemoryNonHeapUsed OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of used memory (in bytes) from non heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getNonHeapMemoryUsage().getUsed()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 21 }\n\njvmMemoryNonHeapCommitted OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total amount of memory (in bytes) committed by non heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.\n\t         getNonHeapMemoryUsage().getCommitted()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 22 }\n\njvmMemoryNonHeapMaxSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Total maximum size of memory (in bytes) for all non heap memory pools.\n\n\tSee java.lang.management.MemoryMXBean.getNonHeapMemoryUsage().getMax()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemory 23 }\n\n-- The object identifiers in the range jvmMemory.[30-99] are not used but are \n-- reserved for future evolution of this MIB. \n--\n-- The JVM Memory Manager Table\n--\n-- The jvmMemManagerTable represent memory manager abstract entities.\n-- The jvmMemManagerTable contains one row per memory manager. In \n-- addition, those memory managers which are also garbage collectors have\n-- an extension row in the jvmMemGCTable.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryMXBean for\n--     a detailed description of the memory subsystem.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryManagerMXBean \n--     for more information on memory managers.\n-- \n-----------------------------------------------------------------------\n--\n-- We use the range jvmMemory.[100..109] for objects related to memory \n-- managers. \n-- Object identifiers in the range jvmMemory.[102-109] are not used \n-- but are reserved for future evolution of this MIB. \n--\njvmMemManagerTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmMemManagerEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Memory Manager Table contains the whole list of Memory \n\t Managers  as returned by ManagementFactory.getMemoryManagerMXBeans(). \n\n\t When a MemoryManagerMXBean object is an instance of \n\t GarbageCollectorMXBean, then additional information specific to \n\t the GarbageCollectorMXBean class will be found in the \n\t jvmGCTable, at the same index. \n\n\t Relationships between MemoryManagers and MemoryPools are shown \n\t by the Memory Manager-Pool Relation table (jvmMemMgrPoolRelTable). \n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemory 100 }\n\njvmMemManagerEntry OBJECT-TYPE\n    SYNTAX      JvmMemManagerEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"A jvmMemManagerEntry conceptual row represent an instance of the\n\t java.lang.management.MemoryManagerMXBean interface. If that instance \n\t is also an instance of java.lang.management.GarbageCollectorMXBean, \n\t then additional information will be found in the jvmGCTable, at the \n         same index.\n\n\t Columnar objects in this table are mapped from attributes of\n\t the MemoryManagerMXBean interface.\n\n\t See java.lang.management.MemoryManagerMXBean\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryManagerMXBean\"\n    INDEX { jvmMemManagerIndex }\n    ::= { jvmMemManagerTable 1 }\n\nJvmMemManagerEntry ::= SEQUENCE {\n        jvmMemManagerIndex JvmPositive32TC,\n        jvmMemManagerName  JvmJavaObjectNameTC,\n\tjvmMemManagerState JvmValidityStateTC\n}\n\njvmMemManagerIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"An index opaquely computed by the agent and which uniquely \n\t identifies a Memory Manager.\n\n\t The jvmMemManagerIndex index is opaquely computed by the agent,\n\t from e.g the hash code of the MemoryManager (or MemoryManager name). \n\t The agent is responsible for allocating a free index when it needs \n\t one (e.g. if two objects have the same hash, then it may increment\n\t one of the values until the conflict is resolved). As a result a \n\t manager must not depend on the value of that index across, \n\t e.g. reboot of the agent, as this value is not guaranteed to \n\t stay identical after the agent restarts.\n\t \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemManagerEntry 1 }\n\njvmMemManagerName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name of this memory manager, as returned by \n\t MemoryManagerMXBean.getName().\n\n\t See java.mangement.MemoryManagerMXBean.getName().\n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemManagerEntry 2 }\n\njvmMemManagerState OBJECT-TYPE\n    SYNTAX      JvmValidityStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n         Indicates whether this memory manager is valid in the Java \n         virtual machine. A memory manager becomes invalid once the \n         Java virtual machine removes it from the memory system.\n\n\t See java.lang.management.MemoryManagerMXBean.isValid()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemManagerEntry 3 }\n\n\n-- The JVM Garbage Collector Table\n--\n-- The jvmMemGCTable is an extension of the jvmMemManagerTable.\n-- It represents garbage collector abstract entities. A garbage collector \n-- is a memory manager responsible for reclaiming  memory occupied by \n-- unreachable objects.\n-- \n-- A garbage collector is thus represented by one row in the \n-- jvmMemManagerTable, plus an extension row in the jvmMemGCTable.\n-- The extension row in the jvmMemGCTable contains those attributes which\n-- are specific to garbage collectors.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryMXBean for\n--     a detailed description of the memory subsystem.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryManagerMXBean \n--     for more information on memory managers, and \n--     java.lang.management.GarbageCollectorMXBean for more information on \n--     garbage collectors.\n-- \n-----------------------------------------------------------------------\n\njvmMemGCTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmMemGCEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Garbage Collector table provides additional information \n\t on those MemoryManagers which are also GarbageCollectors. \n\t This table extends the  jvmMemManagerTable table. The index \n\t used in the jvmMemGCTable table is imported from the \n\t jvmMemManagerTable table. If a row from the jvmMemManagerTable \n\t table is deleted, and if it has an extension in the jvmMemGCTable \n\t table, then the extension row will also be deleted.\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.GarbageCollectorMXBean\"\n    ::= { jvmMemory 101 }\n\njvmMemGCEntry OBJECT-TYPE\n    SYNTAX      JvmMemGCEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"Provide additional information on Garbage Collectors.\n\t \n\t Columnar objects in this table are mapped from the\n\t GarbageCollectorMXBean interface.\n\n\t See java.lang.management.GarbageCollectorMXBean\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.GarbageCollectorMXBean\"\n    INDEX   { jvmMemManagerIndex }\n    ::= {jvmMemGCTable 1 }\n\nJvmMemGCEntry ::= SEQUENCE {\n        jvmMemGCCount  Counter64,\n        jvmMemGCTimeMs JvmTimeMillis64TC\n}\n\njvmMemGCCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The total number of collections that have occurred, \n\t as returned by GarbageCollectorMXBean.getCollectionCount().\n\t \n\t If garbage collection statistics are not available, this\n\t object is set to 0. \n\n\t See java.lang.management.GarbageCollectorMXBean.getCollectionCount()\n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.GarbageCollectorMXBean\"\n    ::= { jvmMemGCEntry 2 }\n\njvmMemGCTimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate accumulated collection elapsed time in \n\t milliseconds, since the Java virtual machine has started. \n\t This object is set to 0 if the collection elapsed time is \n\t undefined for this collector.\n\n\t See java.lang.management.GarbageCollectorMXBean.getCollectionTime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.GarbageCollectorMXBean\"\n    DEFVAL { 0 }\n    ::= { jvmMemGCEntry 3 }\n\n-- The JVM Memory Pool Table\n--\n-- The jvmMemPoolTable represent memory pool abstract entities.\n-- The jvmMemPoolTable contains one row per memory pool. \n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryMXBean for\n--     a detailed description of the memory subsystem.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryPoolMXBean \n--     for more information on memory pool.\n-- \n-----------------------------------------------------------------------\n--\n-- We use the range jvmMemory.[110..119] for objects related to memory pools. \n-- Object identifiers in the range jvmMemory.[111-119] are not used but\n-- are reserved for future evolution of this MIB. \n--\njvmMemPoolTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmMemPoolEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Memory Pool Table contains the whole list of MemoryPools \n\t as returned by ManagementFactory.getMemoryPoolMXBeans(). \n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemory 110 }\n\njvmMemPoolEntry OBJECT-TYPE\n    SYNTAX      JvmMemPoolEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"\n         Represents a memory pool. The pool may contain heap memory or\n         non-heap memory. A row in this table represents\n\t an instance of MemoryPoolMXBean.\n\n\t See java.lang.management.MemoryPoolMXBean\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    INDEX { jvmMemPoolIndex }\n    ::= { jvmMemPoolTable 1 }\n\nJvmMemPoolEntry ::= SEQUENCE {\n        jvmMemPoolIndex                 JvmPositive32TC,\n\tjvmMemPoolName                  JvmJavaObjectNameTC,\n\tjvmMemPoolType                  JvmManagedMemoryTypeTC,\n\tjvmMemPoolState                 JvmValidityStateTC,\n\tjvmMemPoolPeakReset             JvmTimeMillis64TC,\n\n\tjvmMemPoolInitSize              JvmUnsigned64TC,\n\tjvmMemPoolUsed                  JvmUnsigned64TC,\n\tjvmMemPoolCommitted             JvmUnsigned64TC,\n\tjvmMemPoolMaxSize               JvmUnsigned64TC,\n\n\tjvmMemPoolPeakUsed              JvmUnsigned64TC,\n\tjvmMemPoolPeakCommitted         JvmUnsigned64TC,\n\tjvmMemPoolPeakMaxSize           JvmUnsigned64TC,\t\n\t\n\tjvmMemPoolCollectUsed           JvmUnsigned64TC,\n\tjvmMemPoolCollectCommitted      JvmUnsigned64TC,\n\tjvmMemPoolCollectMaxSize        JvmUnsigned64TC,\n\n\tjvmMemPoolThreshold             JvmUnsigned64TC,\n\tjvmMemPoolThreshdCount          Counter64,\n\tjvmMemPoolThreshdSupport        JvmImplSupportStateTC,\t\n\tjvmMemPoolCollectThreshold      JvmUnsigned64TC,\n\tjvmMemPoolCollectThreshdCount   Counter64,\n\tjvmMemPoolCollectThreshdSupport JvmImplSupportStateTC\n\n}\n\njvmMemPoolIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"An index value opaquely computed by the agent which uniquely\n\t identifies a row in the jvmMemPoolTable.\n\n\t The jvmMemPoolIndex index is opaquely computed by the agent, \n\t from e.g the hash code of the MemoryPool (or MemoryPool name). \n\t The agent is responsible for allocating a free index when it \n\t needs one (e.g. if two objects have the same hash, then it may \n\t increment one of the values until the conflict is resolved).  \n\t As a result a manager must not depend on the value of that \n\t index across, e.g. reboot of the agent, as this value is not \n\t guaranteed to stay identical after the agent restarts.\n        \"\n    ::= { jvmMemPoolEntry 1 }\n\njvmMemPoolName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name of this memory pool, as returned by \n         MemoryPoolMXBean.getName().\n\n\t See java.lang.management.MemoryPoolMXBean.getName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 2 }\n\njvmMemPoolType OBJECT-TYPE\n    SYNTAX      JvmManagedMemoryTypeTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The type of memory managed in this pool. This pool may be used for\n\t heap memory or non-heap memory.\n\n\t See java.lang.management.MemoryPoolMXBean.getMemoryType()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 3 }\n\njvmMemPoolState OBJECT-TYPE\n    SYNTAX      JvmValidityStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n         Indicates whether this memory pool is valid in the Java \n         virtual machine. A memory pool becomes invalid once the \n         Java virtual machine removes it from the memory system.\n\n\t See java.lang.management.MemoryPoolMXBean.isValid()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 4 }\n\njvmMemPoolPeakReset OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"\n        This object indicates the last time - in milliseconds - at which \n        the peak memory usage statistic of this memory pool was reset\n\tto the current memory usage. This corresponds to a time stamp\n\tas returned by java.lang.System.currentTimeMillis();\n\n\tSetting this object to a time earlier than its current time value\n\thas no effect. Setting this object to a time later than its current\n\ttime value causes the peak memory usage statistic of this memory \n\tpool to be reset to the current memory usage. The new value of this\n\tobject will be the time at which the reset operation is triggered.\n\n\tThere could be a delay between the time at which the reset operation \n\tis triggered and the time at which the actual resetting happens, so\n\tthis value is only indicative.\n\n\t See java.lang.management.MemoryPoolMXBean.resetPeakUsage()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 5 }\n\n\n-- The object identifier arcs in the range jvmMemPoolEntry.[6-9] are \n-- reserved for future evolution of this MIB.\n--\n-- We use the range jvmMemPoolEntry.[10..19] for objects related to this \n-- pool memory usage, as returned by \n--      java.lang.management.MemoryPoolMXBean.getUsage().\n-- Object identifiers in the range jvmMemPoolEntry.[14..19] are not \n-- used but are reserved for future evolution of this MIB.\n--\njvmMemPoolInitSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Initial size of this memory pool.\n\n\tSee java.lang.management.MemoryPoolMXBean.getUsage().getInit()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 10 }\n\n\njvmMemPoolUsed OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Amount of used memory in this memory pool.\n\n\tSee java.lang.management.MemoryPoolMXBean.getUsage().getUsed()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 11 }\n\njvmMemPoolCommitted OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Amount of committed memory in this memory pool.\n\n\tSee java.lang.management.MemoryPoolMXBean.getUsage().getCommitted()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 12 }\n\njvmMemPoolMaxSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Maximal size of this memory pool.\n\n\tSee java.lang.management.MemoryPoolMXBean.getUsage().getMax()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 13 }\n\n-- We use the range jvmMemPoolEntry.[20..29] for objects related to \n-- this pool peak memory usage, as returned by \n--      java.lang.management.MemoryPoolMXBean.getPeakUsage().\n-- The object identifier arc jvmMemPoolEntry.20 which would have been \n-- used for the initial size is not used because the notion of initial \n-- size in the context of peak usage is meaningless. \n-- Therefore, we start numbering objects at 21.\n-- Object identifiers in the range jvmMemPoolEntry.[24..29] are not \n-- used but are reserved for future evolution of this MIB.\n--\njvmMemPoolPeakUsed OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Amount of used memory in this memory pool when the peak usage \n\twas reached.\n\n\tSee java.lang.management.MemoryPoolMXBean.getPeakUsage().getUsed()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 21 }\n\njvmMemPoolPeakCommitted OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Amount of committed memory in this memory pool when the peak usage \n\twas reached.\n\n\tSee java.lang.management.MemoryPoolMXBean.getPeakUsage().getCommitted()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 22 }\n\njvmMemPoolPeakMaxSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n        Maximal size of this memory pool when the peak usage \n\twas reached.\n\n\tSee java.lang.management.MemoryPoolMXBean.getPeakUsage().getMax()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 23 }\n\n-- We use the range jvmMemPoolEntry.[30..39] for objects related to this \n-- pool collection memory usage, as returned by \n--      java.lang.management.MemoryPoolMXBean.getCollectionUsage().\n-- The object identifier arc jvmMemPoolEntry.30 which would have been used \n-- for the initial size is not used because the notion of initial size in the\n-- context of collection usage is meaningless. \n-- Therefore, we start numbering objects at 31.\n-- Object identifiers in the range jvmMemPoolEntry.[34..39] are not used \n-- but are reserved for future evolution of this MIB.\n--\njvmMemPoolCollectUsed OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n         The amount of used memory at the most recent time that the \n\t Java virtual machine has expended effort in recycling unused objects\n\t in this memory pool.  \n\t \n\tSee java.lang.management.MemoryPoolMXBean.getCollectionUsage().getUsed()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 31 }\n\njvmMemPoolCollectCommitted OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n         The amount of committed memory at the most recent time that the \n\t Java virtual machine has expended effort in recycling unused objects\n\t in this memory pool.  \n\t \n\t See java.lang.management.MemoryPoolMXBean.getCollectionUsage().\n            getCommitted()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 32 }\n\njvmMemPoolCollectMaxSize OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"\n         The value of the maximum amount of memory at the most recent time \n\t that the Java virtual machine has expended effort in recycling \n\t unused objects in this memory pool.  \n\t \n\tSee java.lang.management.MemoryPoolMXBean.getCollectionUsage().getMax()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n              java.lang.management.MemoryUsage\"\n    ::= { jvmMemPoolEntry 33 }\n\n-- Object identifiers in the range jvmMemPoolEntry.[40-109] are reserved \n-- for future evolution of this MIB.\n--\n-- We use the range jvmMemPoolEntry.[110..119] for objects related to this \n-- pool memory usage thresholds (range jvmMemPoolEntry.[10..19] was used for \n-- this pool memory usage). \n-- Object identifier arcs in the range jvmMemPoolEntry.[113..119] are not \n-- used but are reserved for future evolution of this MIB.\n--\njvmMemPoolThreshold OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"The threshold value for the memory usage of this memory pool, \n\t in bytes. A zero value (0) indicates that no threshold value is\n         configured.\n\t When the amount of used memory crosses over this threshold \n\t value the JVM will trigger a usage memory threshold exceeded \n\t notification, and the jvmMemPoolThreshdCount increases.\n\n\t If memory usage threshold is not supported, then this object, if\n\t implemented, will always be equals to 0. In that case, attempting \n         to set this object will trigger an inconsistentValue error.\n\n\t See also jvmMemPoolThreshdSupport.\n\n\t See java.lang.management.MemoryPoolMXBean.getUsageThreshold(),\n             java.lang.management.MemoryPoolMXBean.setUsageThreshold(long),\n             java.lang.management.MemoryPoolMXBean.getUsageThresholdCount(),\n             java.lang.management.MemoryPoolMXBean.isUsageThresholdSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    DEFVAL { 0 }\n    ::= { jvmMemPoolEntry 110 }\n\njvmMemPoolThreshdCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The number of times that the memory usage has crossed\n\t the usage threshold, as detected by the Java virtual machine.\n\n\t If memory usage threshold is not supported, then this object, if\n\t implemented, will always be equals to 0.\n\n\t See also jvmMemPoolThresholdSupport.\n\n\t See java.lang.management.MemoryPoolMXBean.getUsageThresholdCount(),\n             java.lang.management.MemoryPoolMXBean.isUsageThresholdSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 111 }\n\njvmMemPoolThreshdSupport OBJECT-TYPE\n    SYNTAX      JvmImplSupportStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Tells whether this memory pool supports usage threshold.\n\n\t See java.lang.management.MemoryPoolMXBean.isUsageThresholdSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 112 }\n\n-- Object identifiers in the range jvmMemPoolEntry.[120-129] are reserved \n-- for future evolution of this MIB.\n--\n-- We use the range jvmMemPoolEntry.[130..139] for objects related to \n-- this pool memory collection usage thresholds (range \n-- jvmMemPoolEntry.[30..39] was used for this pool collection memory usage). \n-- Object identifiers in the range jvmMemPoolEntry.[133..139] are not used \n-- but are reserved for future evolution of this MIB.\n--\njvmMemPoolCollectThreshold OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    UNITS       \"bytes\"\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"The threshold value for the collection usage of this memory pool, \n\t in bytes. A zero value (0) indicates that no threshold value is\n         configured.\n\t When the amount of used memory crosses over this threshold \n\t value the JVM will trigger a collection memory threshold exceeded\n\t notification, and the jvmMemPoolCollectThreshdCount increases.\n\n\t If collection usage threshold is not supported, then this object, if\n\t implemented, will always be equals to 0. In that case, attempting \n         to set this object will trigger an inconsistentValue error.\n\n\t See also jvmMemPoolCollectThreshdSupport.\n\n\t See java.lang.management.MemoryPoolMXBean.\n                                  getCollectionUsageThreshold(),\n             java.lang.management.MemoryPoolMXBean.\n                                  setCollectionUsageThreshold(long),\n\t     java.lang.management.MemoryPoolMXBean.\n\t                          isCollectionUsageThresholdSupported(),\n\t     java.lang.management.MemoryPoolMXBean.\n\t                          getCollectionUsageThresholdCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    DEFVAL { 0 }\n    ::= { jvmMemPoolEntry 131 }\n\njvmMemPoolCollectThreshdCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The number of times that the memory usage has crossed\n\t the collection usage threshold, as detected by the Java virtual \n\t machine.\n\n\t If memory usage threshold is not supported, then this object, if\n\t implemented, will always be equals to 0.\n\n\t See also jvmMemPoolCollectThreshdSupport.\n\n\t See java.lang.management.MemoryPoolMXBean.\n                                  getCollectionUsageThresholdCount(),\n             java.lang.management.MemoryPoolMXBean.\n                                  isCollectionUsageThresholdSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 132 }\n\njvmMemPoolCollectThreshdSupport OBJECT-TYPE\n    SYNTAX      JvmImplSupportStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Tells whether this memory pool supports collection usage threshold.\n\n\t See java.lang.management.MemoryPoolMXBean.\n                       isCollectionUsageThresholdSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemPoolEntry 133 }\n\n-- The JVM Memory Manager-Pool Relation Table \n-----------------------------------------------------------------------\n-- The JVM Memory Pool Table\n--\n-- The jvmMemPoolTable represent memory pool abstract entities.\n-- The jvmMemPoolTable contains one row per memory pool. \n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryMXBean for\n--     a detailed description of the memory subsystem.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.MemoryPoolMXBean \n--     for more information on memory pool.\n-- \n-----------------------------------------------------------------------\n--\n-- We use the range jvmMemory.[110..119] for objects related to memory pools. \n-- Object identifier arcs in the range jvmMemory.[111-119] are not used \n-- but are reserved for future evolution of this MIB. \n--\n\njvmMemMgrPoolRelTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmMemMgrPoolRelEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Memory Manager-Pool Relation Table shows the \n         Memory Manager / Memory Pool relations, as returned by \n         MemoryPoolMXBean.getMemoryManagerNames() and \n         MemoryManagerMXBean.getMemoryPoolNames(). \n         This table imports the indexes from the jvmMemManagerTable table \n         and jvmMemPoolTable table. The jvmMemMgrRelManagerName and \n         jvmMemMgrRelPoolName objects are not actually necessary since \n         the indexes are self-sufficient to express the relationship - \n         but the names  will make the table more understandable when displayed \n         in a management console. \n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n\t      java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemory 120 }\n\njvmMemMgrPoolRelEntry OBJECT-TYPE\n    SYNTAX      JvmMemMgrPoolRelEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"A row in this table indicates that the Memory Manager identified\n         by jvmMemManagerIndex manages the Memory Pool identified by\n         jvmMemPoolIndex. Note that a pool may be managed by several \n         memory managers, and a memory manager can manage several \n         memory pool.\n\n\t See java.lang.management.MemoryManagerMXBean.getMemoryPoolNames(),\n\t     java.lang.management.MemoryPoolMXBean.getMemoryManagerNames()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean,\n\t      java.lang.management.MemoryManagerMXBean\"\n    INDEX { jvmMemManagerIndex, jvmMemPoolIndex }\n    ::= { jvmMemMgrPoolRelTable 1 }\n\nJvmMemMgrPoolRelEntry ::= SEQUENCE {\n       jvmMemMgrRelManagerName JvmJavaObjectNameTC,\n       jvmMemMgrRelPoolName    JvmJavaObjectNameTC\n}\n\njvmMemMgrRelManagerName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name of the memory manager.\n\n\t See java.manangement.MemoryManagerMXBean.getName();\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n\t      java.lang.management.MemoryManagerMXBean\"\n    ::= { jvmMemMgrPoolRelEntry 2 }\n\njvmMemMgrRelPoolName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name of the memory pool.\n\n\t See java.manangement.MemoryPoolMXBean.getName();\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmMemMgrPoolRelEntry 3 }\n\n\n-----------------------------------------------------------------------\n--\n-- The JVM Thread group\n--\n-- A collection of objects used to monitor threads in the\n-- Java Virtual Machine. These objects define the SNMP management \n-- interface for the thread system of the Java virtual machine. \n--\n-- The jvmThreadInstanceTable represents the threads which are currently\n-- alive in the system. The representation of a thread is derived from the\n-- set of methods in the ThreadMXBean that return information about a\n-- given thread.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.ThreadMXBean for\n--     a detailed description of the threading subsystem.\n-- \n-----------------------------------------------------------------------\n\n--\n-----------------------------------------------------------------------\n\njvmThreading   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 3 }\n\n-- The following objects are mapped from the ThreadMXBean interface.\n-----------------------------------------------------------------------\n\njvmThreadCount OBJECT-TYPE\n    SYNTAX      Gauge32\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The current number of live threads.\n\n\t See java.lang.management.ThreadMXBean.getThreadCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 1 }\n\njvmThreadDaemonCount OBJECT-TYPE\n    SYNTAX      Gauge32\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The current number of daemon threads.\n\t \n\t See java.lang.management.ThreadMXBean.getDaemonThreadCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 2 }\n\njvmThreadPeakCount OBJECT-TYPE\n    SYNTAX      Counter32\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The peak thread count since the execution of the application.\n\n\t See java.lang.management.ThreadMXBean.getPeakThreadCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 3 }\n\njvmThreadTotalStartedCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The total number of threads created and started since the Java\n\t Virtual Machine started.\n\n\t See java.lang.management.ThreadMXBean.getTotalStartedThreadCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 4 }\n\njvmThreadContentionMonitoring OBJECT-TYPE\n    SYNTAX      JvmImplOptFeatureStateTC\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"The state of the Thread Contention Monitoring feature.\n         This feature can be:\n\n\t unsupported: The JVM does not support Thread Contention Monitoring.\n\t enabled    : The JVM supports Thread Contention Monitoring, and it\n\t              is enabled.\n\t disabled   : The JVM supports Thread Contention Monitoring, and it\n\t              is disabled.\n\n         Only enabled(3) and disabled(4) may be supplied as values to a\n         SET request. unsupported(1) can only be set internally by the\n         agent.\n\n\t When the feature is unsupported(1), any attempt to change\n\t that value will fail: trying to set this object to \n         enabled(3) or disabled(4) will result in an `inconsistentValue'\n         error. Trying to set it to any other value will result in an\n\t `wrongValue' error.\n\n\t See java.lang.management.ThreadMXBean.\n\t                     isThreadContentionMonitoringSupported(),\n\t     java.lang.management.ThreadMXBean.\n                             isThreadContentionMonitoringEnabled(),\n             java.lang.management.ThreadMXBean.\n                             setThreadContentionMonitoringEnabled()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 5 }\n\njvmThreadCpuTimeMonitoring OBJECT-TYPE\n    SYNTAX      JvmImplOptFeatureStateTC\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"The state of the Thread CPU Time Monitoring feature.\n         This feature can be:\n\n\t unsupported: The JVM does not support Thread CPU Time Monitoring.\n\t enabled    : The JVM supports Thread CPU Time Monitoring, and it\n\t              is enabled.\n\t disabled   : The JVM supports Thread CPU Time Monitoring, and it\n\t              is disabled.\n\n         Only enabled(3) and disabled(4) may be supplied as values to a\n         SET request. unsupported(1) can only be set internally by the\n         agent.\n\n\t When the feature is unsupported(1), any attempt to change\n\t that value will fail: trying to set this object to \n         enabled(3) or disabled(4) will result in an `inconsistentValue'\n         error. Trying to set it to any other value will result in an\n\t `wrongValue' error.\n\n\t See java.lang.management.ThreadMXBean.\n\t                     isThreadCpuTimeSupported(),\n\t     java.lang.management.ThreadMXBean.\n                             isThreadCpuTimeEnabled(),\n             java.lang.management.ThreadMXBean.\n                             setThreadCpuTimeEnabled()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 6 }\n\njvmThreadPeakCountReset OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-write\n    STATUS      current\n    DESCRIPTION\n\t\"\n        This object indicates the last time - in milliseconds - at which \n        the peak thread count was reset to the current thread count.\n\tThis corresponds to a time stamp as returned by\n\tjava.lang.System.currentTimeMillis().\n\n\tSetting this object to a time earlier than its current time value\n\thas no effect. Setting this object to a time later than its current\n\ttime value causes the peak thread count statistic to be reset to \n        the current thread count. The new value of this object will be \n        the time at which the reset operation is triggered.\n\n\tThere could be a delay between the time at which the reset operation \n\tis triggered and the time at which the actual resetting happens, so\n\tthis value is only indicative.\n\n\t See java.lang.management.ThreadMXBean.resetPeakThreadCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 7 }\n\n\n-- Object identifiers in the range jvmThreading.[8-10] are reserved \n-- for future evolution of this MIB.\n--\n-----------------------------------------------------------------------\n-- The JVM Thread Instance Table\n--\n-- The jvmThreadInstanceTable represents the threads which are currently\n-- alive in the system. The representation of a thread is derived from the\n-- set of methods in the ThreadMXBean that return information about a\n-- given thread.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.ThreadMXBean for\n--     a detailed description of the threading subsystem.\n-- See also J2SE 5.0 API Specification, java.lang.management.ThreadInfo,\n--     and java.lang.Thread\n-- \n-----------------------------------------------------------------------\n\njvmThreadInstanceTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmThreadInstanceEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Thread Instance Table is built from all the methods of \n\t ThreadMXBean that take a ThreadID as parameter. \n\n\t See java.lang.management.ThreadMXBean.getAllThreadIds()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreading 10 }\n\njvmThreadInstanceEntry OBJECT-TYPE\n    SYNTAX      JvmThreadInstanceEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"A row in this table represents a live thread.\n\t Attributes in this row are built from all the methods of \n\t ThreadMXBean that take a ThreadID as parameter.\n\n\t See java.lang.management.ThreadMXBean\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    INDEX { jvmThreadInstIndex }\n    ::= { jvmThreadInstanceTable 1 }\n\nJvmThreadInstanceEntry ::= SEQUENCE {\n        jvmThreadInstIndex            JvmIndex64TC,\n\tjvmThreadInstId               JvmUnsigned64TC,\n\tjvmThreadInstState            JvmThreadStateTC,\n        jvmThreadInstBlockCount       Counter64,\n        jvmThreadInstBlockTimeMs      JvmTimeMillis64TC,\n        jvmThreadInstWaitCount        Counter64,\n        jvmThreadInstWaitTimeMs       JvmTimeMillis64TC,\n        jvmThreadInstCpuTimeNs        JvmTimeNanos64TC,\n\tjvmThreadInstLockName         JvmJavaObjectNameTC,\n\tjvmThreadInstLockOwnerPtr     RowPointer,\n\tjvmThreadInstName             JvmJavaObjectNameTC\n}\n\njvmThreadInstIndex OBJECT-TYPE\n    SYNTAX      JvmIndex64TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"An index uniquely identifying a live thread, and directly\n         derived from the value of jvmThreadInstId. The jvmThreadInstId \n\t cannot be used directly as index in the table, because integer \n\t indexes cannot exceed an unsigned 32 int. \n\t \n\t The jvmThreadInstIndex index is an 8 byte octet string as\n         defined by the JvmIndex64TC TEXTUAL-CONVENTION. Its value is \n         directly derived from the value of the corresponding ThreadID\n         returned by jvmThreadInstId.\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean, java.lang.Thread\"\n    ::= { jvmThreadInstanceEntry 1 }\n\njvmThreadInstId OBJECT-TYPE\n    SYNTAX      JvmUnsigned64TC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The thread ID, as returned by Thread.getId().\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getThreadId()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean, java.lang.Thread\"\n    ::= { jvmThreadInstanceEntry 2 }\n\njvmThreadInstState OBJECT-TYPE\n    SYNTAX      JvmThreadStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The state of this thread instance.\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getThreadState()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 3 }\n\njvmThreadInstBlockCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The total number of times that this thread has blocked to enter\n         or re-enter a monitor..\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getBlockedCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 4 }\n\njvmThreadInstBlockTimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate accumulated elapsed time (in millisecond) \n\t that a thread has blocked to enter or re-enter a monitor since\n         it has started - or since thread contention monitoring was\n\t enabled.\n\n\t This object is always set to 0 if thread contention monitoring \n\t is disabled or not supported.\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getBlockedTime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 5 }\n\njvmThreadInstWaitCount OBJECT-TYPE\n    SYNTAX      Counter64\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The total number of times that this thread has waited for\n         notification.\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getWaitedCount()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 6 }\n\njvmThreadInstWaitTimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate accumulated elapsed time (in millisecond) \n\t that a thread has waited on a monitor through a \n         java.lang.Object.wait method since it has started - or since \n\t thread contention monitoring wasenabled.\n\n\t This object is always set to 0 if thread contention monitoring \n\t is disabled or not supported.\n\n\t See java.lang.management.ThreadMXBean.getThreadInfo(long,boolean).\n\t                          getWaitedTime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 7 }\n\njvmThreadInstCpuTimeNs OBJECT-TYPE\n    SYNTAX      JvmTimeNanos64TC\n    UNITS       \"nanoseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate accumulated CPU time (in nanosecond) for a thread\n         since it has started - or since thread CPU time monitoring was\n\t enabled.\n\n\t If the thread of the specified ID is not alive or does not exist,\n\t or the CPU time measurement is disabled or not supported, \n\t this object is set to 0.\n\n\t See java.lang.management.ThreadMXBean.getThreadCpuTime(long),\n\t     java.lang.management.ThreadMXBean.isThreadCpuTimeSupported(),\n\t     java.lang.management.ThreadMXBean.isThreadCpuTimeEnabled()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean\"\n    ::= { jvmThreadInstanceEntry 8 }\n\njvmThreadInstName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"This thread name - as returned by Thread.getThreadName().\n\n\t See java.lang.management.ThreadInfo.getThreadName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean,\n              java.lang.management.ThreadInfo\"\n    ::= { jvmThreadInstanceEntry 9 }\n\njvmThreadInstLockName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The string representation of the monitor lock that this thread \n\t is blocked to enter or waiting to be notified through the \n\t Object.wait method. \n\n\t See J2SE 5.0 API Specification, \n             java.lang.management.ThreadInfo.getLockName()\n         for more information on the format of this string.\n\n\t If this thread is not blocked then a zero-length string is returned.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the JvmJavaObjectNameTC \n\t (1023 bytes max).\n\n\t See java.lang.management.ThreadInfo.getLockName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean,\n              java.lang.management.ThreadInfo\"\n    ::= { jvmThreadInstanceEntry 10 }\n\njvmThreadInstLockOwnerPtr OBJECT-TYPE\n    SYNTAX      RowPointer\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"A pointer to the thread which owns the monitor of the\n\t object on which this thread instance is blocked.\n         This object will point to jvmThreadInstId of the\n\t lock owner thread.\n\n\t If this thread is not blocked then 0.0 is returned.\n\n\t See java.lang.management.ThreadInfo.getLockOwnerId()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.ThreadMXBean,\n              java.lang.management.ThreadInfo\"\n    ::= { jvmThreadInstanceEntry 11 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Runtime group\n--\n-- A collection of objects used to monitor the Java Virtual Machine\n-- Runtime. These objects define the SNMP management interface for the \n-- runtime system of the Java virtual machine.\n--\n-- The JVM Runtime group defines object mapped from the\n-- java.lang.management.RuntimeMXBean interface.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.RuntimeMXBean for\n--     a detailed description of the runtime system.\n--\n-----------------------------------------------------------------------\n\njvmRuntime   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 4 }\n\n-- The following objects are mapped from the RuntimeMXBean interface.\n-----------------------------------------------------------------------\n\njvmRTName OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name representing the running Java virtual machine.\n\n\t Note that the SNMP agent may have to truncate the name returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 1 }\n\njvmRTVMName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine implementation name.\n\n\t See java.lang.management.RuntimeMXBean.getVmName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 2 }\n\njvmRTVMVendor OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine implementation vendor.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getVmVendor()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 3 }\n\njvmRTVMVersion OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine implementation version.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getVmVersion()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 4 }\n\njvmRTSpecName OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine specification name.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getSpecName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 5 }\n\njvmRTSpecVendor OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine specification vendor.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n         See java.lang.management.RuntimeMXBean.getSpecVendor()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 6 }\n\njvmRTSpecVersion OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The Java virtual machine specification version.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n         See java.lang.management.RuntimeMXBean.getSpecVersion()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 7 }\n\njvmRTManagementSpecVersion OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The version of the management specification for the Java virtual \n\t machine implementation.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n         See java.lang.management.RuntimeMXBean.getManagementSpecVersion()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 8 }\n\njvmRTBootClassPathSupport OBJECT-TYPE\n    SYNTAX      JvmImplSupportStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Indicates whether the Java virtual machine supports the \n\t boot class path mechanism used by the bootstrap class loader \n         to search for class files.\n\n\t See java.lang.management.RuntimeMXBean.isBootClassPathSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 9 }\n\njvmRTInputArgsCount OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The number of input arguments passed to the Java Virtual Machine.\n\t \n\t See java.lang.management.RuntimeMXBean.getInputArguments()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 10 }\n\njvmRTUptimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Uptime of the Java virtual machine, in milliseconds. This is\n         equivalent to ( System.currentTimeMillis() - jvmStartTimeMs ).\n\n         See also jvmRTStartTimeMs.\n\n         See java.lang.management.RuntimeMXBean.getUptime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 11 }\n\njvmRTStartTimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The approximate time when the Java virtual machine started, in\n         milliseconds. This is a time stamp as returned by \n         System.currentTimeMillis(). This time will not change unless\n         the Java Virtual Machine is restarted. \n\n         See also jvmRTUptimeMs.\n\n         See java.lang.management.RuntimeMXBean.getStartTime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 12 }\n\n\n-- Object identifiers in the range jvmRuntime.[13-19] are reserved \n-- for future evolution of this MIB.\n--\n-----------------------------------------------------------------------\n--\n-- The JVM Input Argument Table\n--\n-- The jvmRTInputArgsTable contains one row per input argument given on\n-- the Java command line.\n--\n-- See J2SE 5.0 API Specification,\n--     java.lang.management.RuntimeMXBean.getInputArguments()\n--     for more information.\n-----------------------------------------------------------------------\n\njvmRTInputArgsTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmRTInputArgsEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The Input Argument Table lists the input arguments passed\n\t to the Java Virtual Machine. \n\n\t The jvmRTInputArgsIndex is the index of the argument in \n\t the array returned by RuntimeMXBean.getInputArguments().\n\t \n\t See java.lang.management.RuntimeMXBean.getInputArguments()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 20 }\n\njvmRTInputArgsEntry OBJECT-TYPE\n    SYNTAX      JvmRTInputArgsEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"Represent an input argument passed to the Java Virtual Machine.\n\n\t See java.lang.management.RuntimeMXBean.getInputArguments()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    INDEX { jvmRTInputArgsIndex }\n    ::= { jvmRTInputArgsTable 1 }\n\nJvmRTInputArgsEntry ::= SEQUENCE {\n        jvmRTInputArgsIndex JvmPositive32TC,\n\tjvmRTInputArgsItem  JvmArgValueTC\n}\n\njvmRTInputArgsIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The index of the input argument, as in the array returned \n\t by RuntimeMXBean.getInputArguments().\n\n\t See java.lang.management.RuntimeMXBean.getInputArguments()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTInputArgsEntry 1 }\n\njvmRTInputArgsItem OBJECT-TYPE\n    SYNTAX      JvmArgValueTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"An input argument at index jvmRTInputArgsIndex, as in the array \n\t returned by RuntimeMXBean.getInputArguments().\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the JvmArgValueTC \n         (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getInputArguments()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTInputArgsEntry 2 }\n\n\n-----------------------------------------------------------------------\n--\n-- The JVM Boot Class Path Table\n--\n-- The jvmRTBootClassPathTable contains one row per path element in the\n-- bootclasspath. This table may not be implemented (or may be empty) if\n-- the bootclasspath feature is not supported by the underlying \n-- implementation.\n--\n-- See J2SE 5.0 API Specification,\n--     java.lang.management.RuntimeMXBean.getBootClassPath()\n--     java.lang.management.RuntimeMXBean.isBootClassPathSupported()\n--     for more information.\n-----------------------------------------------------------------------\n\njvmRTBootClassPathTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmRTBootClassPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The boot class path that is used by the bootstrap class loader \n\t to search for a class file for loading.\n\t \n\t Note that the SNMP agent may have to truncate the bootclasspath\n\t elements contained in the string returned by the underlying API \n\t if it does not fit in the JvmPathElementTC (1023 bytes max).\n\n\t This table is not implemented (or empty) if jvmRTBootClassPathSupport\n         is unsupported(1).\n\t \n\t See java.lang.management.RuntimeMXBean.getBootClassPath()\n\t     java.lang.management.RuntimeMXBean.isBootClassPathSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 21 }\n\njvmRTBootClassPathEntry OBJECT-TYPE\n    SYNTAX      JvmRTBootClassPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"Represent a path element in the Java Virtual Machine bootclasspath.  \n\n\t See java.lang.management.RuntimeMXBean.getBootClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    INDEX { jvmRTBootClassPathIndex }\n    ::= { jvmRTBootClassPathTable 1 }\n\nJvmRTBootClassPathEntry ::= SEQUENCE {\n        jvmRTBootClassPathIndex JvmPositive32TC,\n\tjvmRTBootClassPathItem  JvmPathElementTC\n}\n\njvmRTBootClassPathIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The index of the path element, as in the array obtained \n\t by splitting RuntimeMXBean.getBootClassPath() in its elementary path\n\t constituents.\n\n\t See java.lang.management.RuntimeMXBean.getBootClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTBootClassPathEntry 1 }\n\njvmRTBootClassPathItem OBJECT-TYPE\n    SYNTAX      JvmPathElementTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"An path element at index jvmRTBootClassPathIndex, as in the \n\t array obtained by splitting RuntimeMXBean.getBootClassPath() in \n\t its elementary path constituents.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the JvmPathElementTC\n\t (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getBootClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTBootClassPathEntry 2 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Class Path Table\n--\n-- The jvmRTClassPathTable contains one row per path element in the\n-- classpath.\n--\n-- See J2SE 5.0 API Specification,\n--     java.lang.management.RuntimeMXBean.getClassPath()\n--     for more information.\n-----------------------------------------------------------------------\n\njvmRTClassPathTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmRTClassPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The  class path that is used by the system class loader \n\t to search for a class file.\n\t \n\t Note that the SNMP agent may have to truncate the classpath\n\t elements contained in the string returned by the underlying API \n\t if it does not fit in the JvmPathElementTC (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 22 }\n\njvmRTClassPathEntry OBJECT-TYPE\n    SYNTAX      JvmRTClassPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"Represent a path element in the Java Virtual Machine classpath.  \n\n\t See java.lang.management.RuntimeMXBean.getClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    INDEX { jvmRTClassPathIndex }\n    ::= { jvmRTClassPathTable 1 }\n\nJvmRTClassPathEntry ::= SEQUENCE {\n        jvmRTClassPathIndex JvmPositive32TC,\n\tjvmRTClassPathItem  JvmPathElementTC\n}\n\njvmRTClassPathIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The index of the path element, as in the array obtained \n\t by splitting RuntimeMXBean.getClassPath() in its elementary\n\t path constituents.\n\n\t See java.lang.management.RuntimeMXBean.getClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTClassPathEntry 1 }\n\njvmRTClassPathItem OBJECT-TYPE\n    SYNTAX      JvmPathElementTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"An path element at index jvmRTClassPathIndex, as in the array \n\t obtained by splitting RuntimeMXBean.getClassPath() in its elementary\n\t path constituents.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the JvmPathElementTC\n\t (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getClassPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTClassPathEntry 2 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Library Path Table\n--\n-- The jvmRTLibraryPathTable contains one row per path element in the\n-- librarypath.\n--\n-- See J2SE 5.0 API Specification,\n--     java.lang.management.RuntimeMXBean.getLibraryPath()\n--     for more information.\n-----------------------------------------------------------------------\n\njvmRTLibraryPathTable OBJECT-TYPE\n    SYNTAX      SEQUENCE OF JvmRTLibraryPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The  library path.\n\t \n\t Note that the SNMP agent may have to truncate the librarypath\n\t elements contained in the string returned by the underlying API \n\t if it does not fit in the JvmPathElementTC (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getLibraryPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRuntime 23 }\n\njvmRTLibraryPathEntry OBJECT-TYPE\n    SYNTAX      JvmRTLibraryPathEntry\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"Represent a path element in the Java Virtual Machine librarypath.  \n\n\t See java.lang.management.RuntimeMXBean.getLibraryPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    INDEX { jvmRTLibraryPathIndex }\n    ::= { jvmRTLibraryPathTable 1 }\n\nJvmRTLibraryPathEntry ::= SEQUENCE {\n        jvmRTLibraryPathIndex JvmPositive32TC,\n\tjvmRTLibraryPathItem  JvmPathElementTC\n}\n\njvmRTLibraryPathIndex OBJECT-TYPE\n    SYNTAX      JvmPositive32TC\n    MAX-ACCESS  not-accessible\n    STATUS      current\n    DESCRIPTION\n\t\"The index of the path element, as in the array obtained \n\t by splitting RuntimeMXBean.getLibraryPath() in its elementary\n\t constituents.\n\n\t See java.lang.management.RuntimeMXBean.getLibraryPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTLibraryPathEntry 1 }\n\njvmRTLibraryPathItem OBJECT-TYPE\n    SYNTAX      JvmPathElementTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"An path element at index jvmRTLibraryPathIndex, as in the array \n\t obtained by splitting RuntimeMXBean.getLibraryPath() in its elementary\n\t path constituents.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the JvmPathElementTC\n\t (1023 bytes max).\n\n\t See java.lang.management.RuntimeMXBean.getLibraryPath()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.RuntimeMXBean\"\n    ::= { jvmRTLibraryPathEntry 2 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Compilation group\n--\n-- A collection of objects used to monitor the Java Virtual Machine\n-- Runtime Compiler (JIT). These objects define the SNMP management \n-- interface for the compilation system of the Java virtual machine. \n--\n-- The JVM Compilation group defines object mapped from the\n-- java.lang.management.CompilationMXBean interface.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.CompilationMXBean for\n--     a detailed description of the runtime system.\n--\n-----------------------------------------------------------------------\n\njvmCompilation   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 5 }\n\n-- The following objects are mapped from the CompilationMXBean interface.\n-----------------------------------------------------------------------\n\njvmJITCompilerName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The name of the Just-in-time (JIT) compiler.\n\n\t See java.lang.management.CompilationMXBean.getName()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.CompilationMXBean\"\n    ::= { jvmCompilation 1 }\n\njvmJITCompilerTimeMs OBJECT-TYPE\n    SYNTAX      JvmTimeMillis64TC\n    UNITS       \"milliseconds\"\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Gets the approximate accumulated elapsed time (in milliseconds) \n\t spent in compilation since the Java virtual machine has started. \n\t If multiple threads are used for compilation, this value is \n\t the summation of the approximate time that each thread \n\t spent in compilation.\n\n\t If compiler time monitoring is not supported, then this object\n\t remains set to 0.\n\t \n\t See java.lang.management.CompilationMXBean.getTotalCompilationTime()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.CompilationMXBean\"\n    ::= { jvmCompilation 2 }\n\n\njvmJITCompilerTimeMonitoring OBJECT-TYPE\n    SYNTAX      JvmImplSupportStateTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"Indicates whether the Java virtual machine supports\n\t compilation time monitoring.\n\n\t See java.lang.management.CompilationMXBean.\n                             isCompilationTimeMonitoringSupported()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.CompilationMXBean\"\n    ::= { jvmCompilation 3 }\n\n-----------------------------------------------------------------------\n--\n-- The JVM Operating System group\n--\n-- A collection of objects used to monitor some resource of the \n-- Operating System the Java Virtual Machine is running on. These objects \n-- define the SNMP management interface offered by the Java virtual machine\n-- for the operating system on which it is running. \n--\n-- The JVM Operating System group defines object mapped from the\n-- java.lang.management.OperatingSystemMXBean interface.\n--\n-- See J2SE 5.0 API Specification, java.lang.management.OperatingSystemMXBean \n--     for a detailed description of the operating system.\n--\n-----------------------------------------------------------------------\n\njvmOS   OBJECT IDENTIFIER ::= { jvmMgtMIBObjects 6 }\n\n-- The following objects are mapped from the OperatingSystemMXBean interface.\n-----------------------------------------------------------------------\n\njvmOSName OBJECT-TYPE\n    SYNTAX      JvmJavaObjectNameTC\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The operating system name.\n\n\t See java.lang.management.OperatingSystemMXBean.getName()\n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.OperatingSystemMXBean\"\n    ::= { jvmOS 1 }\n\njvmOSArch OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The operating system architecture.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.OperatingSystemMXBean.getArch()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.OperatingSystemMXBean\"\n    ::= { jvmOS 2 }\n\njvmOSVersion OBJECT-TYPE\n    SYNTAX      DisplayString\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The operating system version.\n\n\t Note that the SNMP agent may have to truncate the string returned\n         by the underlying API if it does not fit in the DisplayString \n\t (255 bytes max).\n\n\t See java.lang.management.OperatingSystemMXBean.getVersion()\n\t\"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.OperatingSystemMXBean\"\n    ::= { jvmOS 3 }\n\njvmOSProcessorCount OBJECT-TYPE\n\n    SYNTAX      Integer32\n    MAX-ACCESS  read-only\n    STATUS      current\n    DESCRIPTION\n\t\"The number of processors available to the Java virtual machine.\n\n         See java.lang.management.OperatingSystemMXBean.getAvailableProcessors()\n        \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.OperatingSystemMXBean\"\n    ::= { jvmOS 4 }\n\n--\n-- NOTIFICATIONS\n--\n-----------------------------------------------------------------------\n\n--\n-- Low Memory Notifications\n--\n\njvmMgtMIBMemoryNotifs    OBJECT IDENTIFIER ::= { jvmMgtMIBNotifications 2 }\njvmMgtMIBLowMemoryNotifs OBJECT IDENTIFIER ::= { jvmMgtMIBMemoryNotifs  1 }\n\njvmLowMemoryPrefix OBJECT IDENTIFIER \n    ::= { jvmMgtMIBLowMemoryNotifs 0 } \n\n-- Not used at this time, but reserved for future evolution of this MIB:\n--\n-- jvmLowMemoryData OBJECT IDENTIFIER \n--    ::= { jvmMgtMIBLowMemoryNotifs 1 } \n--\n\njvmLowMemoryPoolUsageNotif NOTIFICATION-TYPE\n    OBJECTS {  jvmMemPoolName, jvmMemPoolUsed, jvmMemPoolThreshdCount }\n    STATUS current\n    DESCRIPTION\n           \"This notification is sent when the memory usage threshold of\n\t    a memory pool is exceeded.\n           \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryNotification,\n\t      java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmLowMemoryPrefix  1 }\n\njvmLowMemoryPoolCollectNotif NOTIFICATION-TYPE\n    OBJECTS {  jvmMemPoolName, jvmMemPoolCollectUsed, \n               jvmMemPoolCollectThreshdCount }\n    STATUS current\n    DESCRIPTION\n           \"This notification is sent when the collection memory usage \n\t    threshold of a memory pool is exceeded.\n           \"\n    REFERENCE \"J2SE 5.0 API Specification,\n              java.lang.management.MemoryNotification,\n\t      java.lang.management.MemoryPoolMXBean\"\n    ::= { jvmLowMemoryPrefix  2 }\n\n--\n-- Conformance Section\n--\n-----------------------------------------------------------------------\n\n-- conformance information\n\njvmMgtMIBCompliances\n               OBJECT IDENTIFIER ::= { jvmMgtMIBConformance 1 }\njvmMgtMIBGroups  \n               OBJECT IDENTIFIER ::= { jvmMgtMIBConformance 2 }\n\n\n-- compliance statements\n\njvmManagementCompliance MODULE-COMPLIANCE\n    STATUS  current\n    DESCRIPTION\n            \"The compliance statement for SNMP entities which\n            implement this MIB.\"\n    MODULE  -- this module\n    MANDATORY-GROUPS { \n                     jvmClassLoadingBasicGroup,\n\t\t     jvmClassLoadingSetGroup,\n\t\t     jvmMemoryBasicGroup,\n\t\t     jvmMemoryHeapUsageGroup,\n\t\t     jvmMemoryNonHeapUsageGroup,\n\t\t     jvmMemorySetGroup,\n\t\t     jvmMemManagerGroup,\n\t\t     jvmMemGCGroup,\n\t\t     jvmMemPoolBasicGroup,\n\t\t     jvmMemPoolUsageGroup,\n\t\t     jvmMemPoolPeakUsageGroup,\n\t\t     jvmMemPoolCollectUsageGroup,\n\t\t     jvmMemMgrPoolRelationGroup,\n\t\t     jvmThreadBasicGroup,\n\t\t     jvmThreadInstanceBasicGroup,\n\t\t     jvmRuntimeBasicGroup,\n\t\t     jvmOSGroup\n    }\n\n    -- optional/conditional groups\n    GROUP  jvmMemPoolMonitoringGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support low memory detection in memory usage.\n\t    \"\n    GROUP  jvmMemPoolCollectMonitoringGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support low memory detection in collection \n\t     memory usage.\n\t    \"\n    GROUP  jvmLowMemoryUsageNotifGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support low memory usage detection.\n\t    \"\n    GROUP  jvmLowMemoryCollectNotifGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support low collection memory usage detection.\n\t    \"\n    GROUP  jvmThreadInstanceCpuGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support CPU time measurement for other threads.\n\t    \"\n    GROUP  jvmThreadInstanceBlockGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine does not support thread contention monitoring.\n\t    \"\n    GROUP  jvmRuntimeBootCPGroup\n        DESCRIPTION\n            \"This group may not be implemented if the underlying \n\t     implementation does not support the bootclasspath feature.\n            \"\n    GROUP  jvmJITCompilerBasicGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine has no compilation system.\n\t    \"        \n    GROUP  jvmJITCompilerTimeStatGroup\n        DESCRIPTION\n            \"This group may not be implemented if the Java virtual \n             machine has no compilation system, or does not support \n             JIT Compiler time statistics.\n\t    \"\n    ::= { jvmMgtMIBCompliances 1 }\n\n\n-- units of conformance\n\njvmClassLoadingGroups OBJECT IDENTIFIER ::= { jvmMgtMIBGroups 1 }\n\njvmClassLoadingBasicGroup  OBJECT-GROUP\n    OBJECTS {\n             jvmClassesLoadedCount,\n\t     jvmClassesTotalLoadedCount,\n\t     jvmClassesUnloadedCount\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of  objects that are mapped from JSR 163 \n\t java.lang.management.ClassLoadingMXBean interface.\n        \"\n    ::= { jvmClassLoadingGroups 1 }\n\njvmClassLoadingSetGroup  OBJECT-GROUP\n    OBJECTS {\n             jvmClassesVerboseLevel\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of writable scalar objects that are mapped from JSR 163 \n\t java.lang.management.ClassLoadingMXBean interface, and make it possible\n\t to act on class loading. Accessing these objects may\n\t require special permissions - the agent implementation is\n\t responsible for puting in place the appropriate access control\n\t if needed.\n        \"\n    ::= { jvmClassLoadingGroups 2 }\n\njvmMemoryGroups OBJECT IDENTIFIER ::= { jvmMgtMIBGroups 2 }\n\njvmMemoryBasicGroup  OBJECT-GROUP\n    OBJECTS {\n             jvmMemoryPendingFinalCount\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.MemoryManagerMXBean interface.\n        \"\n    ::= { jvmMemoryGroups 1 }\n\njvmMemoryHeapUsageGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemoryHeapInitSize,\n\t     jvmMemoryHeapUsed,\n\t     jvmMemoryHeapCommitted,\n\t     jvmMemoryHeapMaxSize\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.MemoryMXBean.getHeapMemoryUsage().\n\t When several of these objects are requested within a single\n\t SNMP request, the agent must ensure that \n         java.lang.management.MemoryPoolMXBean.getHeapMemoryUsage() is \n\t called only once, in order to guarantee that the set of\n\t values returned for these objects remain coherent and give\n\t a consistent snapshot of the heap memory usage made by \n\t Heap Memory Pools.\n        \"\n    ::= { jvmMemoryGroups 2 }\n\njvmMemoryNonHeapUsageGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemoryNonHeapInitSize,\n\t     jvmMemoryNonHeapUsed,\n\t     jvmMemoryNonHeapCommitted,\n\t     jvmMemoryNonHeapMaxSize\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.MemoryMXBean.getNonHeapMemoryUsage().\n\t When several of these objects are requested within a single\n\t SNMP request, the agent must ensure that \n         java.lang.management.MemoryPoolMXBean.getNonHeapMemoryUsage() is \n\t called only once, in order to guarantee that the set of\n\t values returned for these objects remain coherent and give\n\t a consistent snapshot of the non heap memory usage made by \n\t Non Heap Memory Pools.\n        \"\n    ::= { jvmMemoryGroups 3 }\n\njvmMemorySetGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemoryGCVerboseLevel,\n\t     jvmMemoryGCCall\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of writable scalar objects that are mapped from JSR 163 \n\t java.lang.management.MemoryMXBean interface, and make it possible\n\t to act on the Garbage Collector. Accessing these objects may\n\t require special permissions - the agent implementation is\n\t responsible for puting in place the appropriate access control\n\t if needed.\n        \"\n    ::= { jvmMemoryGroups 4 }\n\njvmMemManagerGroup  OBJECT-GROUP\n    OBJECTS {\n\t     jvmMemManagerName,\n\t     jvmMemManagerState\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.MemoryManagerMXBean interface.\n        \"\n    ::= { jvmMemoryGroups 5 }\n\njvmMemGCGroup  OBJECT-GROUP\n    OBJECTS {\n             jvmMemGCCount,\n             jvmMemGCTimeMs\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.GarbageCollectorMXBean interface, and are\n\t specific to GarbageCollector MXBeans. \n\t These objects are used to model the inheritence link between \n\t GarbageCollectorMXBean and its super interface - MemoryManagerMXBean.\n        \"\n    ::= { jvmMemoryGroups 6 }\n\njvmMemPoolGroups OBJECT IDENTIFIER ::= { jvmMemoryGroups 7 }\n\njvmMemPoolBasicGroup  OBJECT-GROUP\n    OBJECTS {\n\t     jvmMemPoolName,\n\t     jvmMemPoolType,\n\t     jvmMemPoolState,\n\t     jvmMemPoolPeakReset,\n\t     jvmMemPoolThreshdSupport,\n\t     jvmMemPoolCollectThreshdSupport\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean interface.\n        \"\n    ::= { jvmMemPoolGroups 1 }\n\njvmMemPoolMonitoringGroup OBJECT-GROUP\n     OBJECTS {   \n\t     jvmMemPoolThreshold,\n\t     jvmMemPoolThreshdCount\n     }\n    STATUS current\n    DESCRIPTION\n\t\"Memory usage threshold objects mapped from \n\t JSR 163 java.lang.management.MemoryPoolMXBean interface, which makes \n\t it possible to configure low memory detection.\n\t Accessing this object may require special permissions - the agent \n\t implementation is responsible for puting in place the appropriate \n\t access control if needed.\n        \"\n    ::= { jvmMemPoolGroups 2 }\n\njvmMemPoolUsageGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemPoolInitSize,\n\t     jvmMemPoolUsed,\n\t     jvmMemPoolCommitted,\n\t     jvmMemPoolMaxSize\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean.getUsage().\n\t When several of these objects are requested within a single\n\t SNMP request, the agent must ensure that \n         java.lang.management.MemoryPoolMXBean.getUsage() is \n\t called only once, in order to guarantee that the set of\n\t values returned for these objects remain coherent and give\n\t a consistent snapshot of the memory used by this Memory\n\t Pool.\n        \"\n    ::= { jvmMemPoolGroups 3 }\n\njvmMemPoolPeakUsageGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemPoolPeakUsed,\n\t     jvmMemPoolPeakCommitted,\n\t     jvmMemPoolPeakMaxSize\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean.getPeakUsage().\n\t When several of these objects are requested within a single\n\t SNMP request, the agent must ensure that \n         java.lang.management.MemoryPoolMXBean.getPeakUsage() is \n\t called only once, in order to guarantee that the set of\n\t values returned for these objects remain coherent and give\n\t a consistent snapshot of the peak memory usage made by \n\t this Memory Pool.\n        \"\n    ::= { jvmMemPoolGroups 4 }\n\njvmMemPoolCollectUsageGroup OBJECT-GROUP\n    OBJECTS {\n             jvmMemPoolCollectUsed,\n\t     jvmMemPoolCollectCommitted,\n\t     jvmMemPoolCollectMaxSize\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean.getCollectionUsage().\n\t When several of these objects are requested within a single\n\t SNMP request, the agent must ensure that \n         java.lang.management.MemoryPoolMXBean.getCollectionUsage() is \n\t called only once, in order to guarantee that the set of\n\t values returned for these objects remain coherent and give\n\t a consistent snapshot of the collection memory usage made by \n\t this Memory Pool.\n        \"\n    ::= { jvmMemPoolGroups 5 }\n\njvmMemPoolCollectMonitoringGroup OBJECT-GROUP\n     OBJECTS { \n\t     jvmMemPoolCollectThreshold,\n\t     jvmMemPoolCollectThreshdCount\n     }\n    STATUS current\n    DESCRIPTION\n\t\"Memory collection usage threshold objects mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean interface, which makes \n\t it possible to configure low memory detection.\n\t Accessing this object may require special permissions - the agent \n\t implementation is responsible for putting in place the appropriate \n\t access control if needed.\n        \"\n    ::= { jvmMemPoolGroups 6 }\n\n\njvmMemMgrPoolRelationGroup  OBJECT-GROUP\n    OBJECTS {\n             jvmMemMgrRelManagerName,\n\t     jvmMemMgrRelPoolName\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.MemoryPoolMXBean and \n         java.lang.management.MemoryManagerMXBean interface, and show the\n\t relationship between Memory Managers and Memory Pools.\n        \"\n    ::= { jvmMemoryGroups 8 }\n\njvmThreadGroups OBJECT IDENTIFIER ::= { jvmMgtMIBGroups 3 }\n\njvmThreadBasicGroup OBJECT-GROUP\n    OBJECTS {\n             jvmThreadCount,\n\t     jvmThreadDaemonCount,\n\t     jvmThreadPeakCount,\n\t     jvmThreadTotalStartedCount,\n\t     jvmThreadContentionMonitoring,\n\t     jvmThreadCpuTimeMonitoring,\n\t     jvmThreadPeakCountReset\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of scalar objects that are mapped from JSR 163 \n\t java.lang.management.ThreadMXBean interface.\n        \"\n    ::= { jvmThreadGroups 1 }\n\njvmThreadInstanceGroups OBJECT IDENTIFIER ::= { jvmThreadGroups 2 }\n\njvmThreadInstanceBasicGroup OBJECT-GROUP\n    OBJECTS {\n\t     jvmThreadInstId,\n\t     jvmThreadInstState,\n\t     jvmThreadInstName,\n\t     jvmThreadInstLockName,\n\t     jvmThreadInstLockOwnerPtr\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.ThreadMXBean interface, and are\n\t relative to an instance of java.lang.Thread.\n        \"\n    ::= { jvmThreadInstanceGroups 1}\n\njvmThreadInstanceCpuGroup OBJECT-GROUP\n    OBJECTS {\n\t     jvmThreadInstCpuTimeNs\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A columnar object mapped from JSR 163 \n\t java.lang.management.ThreadMXBean interface which provides CPU\n\t time statistics about an instance of java.lang.Thread.\n        \"\n    ::= { jvmThreadInstanceGroups 2 }\n\n    \njvmThreadInstanceBlockGroup OBJECT-GROUP\n    OBJECTS {\n\t     jvmThreadInstBlockCount,\n\t     jvmThreadInstBlockTimeMs,\n\t     jvmThreadInstWaitCount,\n\t     jvmThreadInstWaitTimeMs\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of columnar objects that are mapped from JSR 163 \n\t java.lang.management.ThreadMXBean interface, and which provide\n         synchronization statistics about an instance of java.lang.Thread.\n        \"\n    ::= { jvmThreadInstanceGroups 3 }\n\n\njvmRuntimeGroups OBJECT IDENTIFIER ::= { jvmMgtMIBGroups 4 }\n\njvmRuntimeBasicGroup OBJECT-GROUP\n    OBJECTS {\n             jvmRTName,\n\t     jvmRTVMName,\n\t     jvmRTVMVendor,\n\t     jvmRTVMVersion,\n\t     jvmRTSpecName,\n\t     jvmRTSpecVendor,\n\t     jvmRTSpecVersion,\n\t     jvmRTManagementSpecVersion,\n\t     jvmRTUptimeMs,\n\t     jvmRTStartTimeMs,\n\t     jvmRTBootClassPathSupport,\n\t     jvmRTInputArgsCount,\n\t     jvmRTInputArgsItem,\n\t     jvmRTClassPathItem,\n\t     jvmRTLibraryPathItem\n    }\t\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.RuntimeMXBean interface.        \n        \"\n    ::= { jvmRuntimeGroups 1 }\n\n\njvmRuntimeBootCPGroup OBJECT-GROUP\n    OBJECTS {\n\t     jvmRTBootClassPathItem\n    }\t\n    STATUS current\n    DESCRIPTION\n\t\"A columnar object that is mapped from JSR 163 \n\t java.lang.management.RuntimeMXBean.getBootClassPath() interface, \n\t and provide information about bootclasspath elements.         \n        \"\n    ::= { jvmRuntimeGroups 2 }\n\njvmJITCompilerGroups OBJECT IDENTIFIER ::= { jvmMgtMIBGroups 5 }\n\njvmJITCompilerBasicGroup OBJECT-GROUP\n    OBJECTS {\n             jvmJITCompilerName,\n             jvmJITCompilerTimeMonitoring\n    }    \n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.CompilationMXBean interface.        \n        \"\n    ::= { jvmJITCompilerGroups 1 }\n\njvmJITCompilerTimeStatGroup OBJECT-GROUP\n    OBJECTS {\n             jvmJITCompilerTimeMs\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.CompilationMXBean interface and provide\n\t time statistic about the JIT Compiler.\n        \"\n    ::= { jvmJITCompilerGroups 2 }\n    \njvmOSGroup OBJECT-GROUP\n    OBJECTS {\n             jvmOSName,\n\t     jvmOSArch,\n\t     jvmOSVersion,\n\t     jvmOSProcessorCount\n    }\n    STATUS current\n    DESCRIPTION\n\t\"A collection of objects that are mapped from JSR 163 \n\t java.lang.management.OperatingSystemMXBean interface.        \n        \"\n    ::= { jvmMgtMIBGroups 6 }\n\njvmLowMemoryUsageNotifGroup NOTIFICATION-GROUP\n    NOTIFICATIONS  {  \n             jvmLowMemoryPoolUsageNotif\n    }\n    STATUS current\n    DESCRIPTION\n           \"A collection of notifications emitted when low\n            memory usage conditions are detected.\n           \"\n    ::= { jvmMgtMIBGroups 7 }\n\njvmLowMemoryCollectNotifGroup NOTIFICATION-GROUP\n    NOTIFICATIONS  {  \n             jvmLowMemoryPoolCollectNotif\n    }\n    STATUS current\n    DESCRIPTION\n           \"A collection of notifications emitted when low\n            collection memory usage conditions are detected.\n           \"\n    ::= { jvmMgtMIBGroups 8 }\n\nEND\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/ruby/tigase/admin/RubyExample.rb",
    "content": "# Tigase Jabber/XMPP Server\n# Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n# \n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, version 3 of the License.\n# \n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n# \n# You should have received a copy of the GNU Affero General Public License\n# along with this program. Look for COPYING file in the top folder.\n# If not, see http://www.gnu.org/licenses/.\n# \n# $Rev: $\n# Last modified by $Author: $\n# $Date: $\n\nrequire 'java'\n\nimport java.lang.System\n\ninclude_class 'tigase.server.Command'\ninclude_class 'tigase.server.Packet'\n\n\nnum1 = Command.getFieldValue($packet, \"num1\")\nnum2 = Command.getFieldValue($packet, \"num2\")\n\nif num1.nil? || num2.nil?\n   res = Packet.commandResultForm($packet)\n   Command.addTextField(res, \"Note\", \"This is JRuby script!\")\n\t Command.addFieldValue(res, \"num1\", \"\")\n   Command.addFieldValue(res, \"num2\", \"\")\n   return res\nelse\n  return num1 + num2\nend\n"
  },
  {
    "path": "tigase-server 7.1.0/src/main/scala/tigase/admin/ScalaExample.scala",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev: $\n * Last modified by $Author: $\n * $Date: $\n */\n\npackage tigase.admin\n\nimport tigase.server. { Command, Packet }\n\nval num1 = Command getFieldValue(packet, \"num1\")\nval num2 = Command getFieldValue(packet, \"num2\")\n\nscriptResult = if (num1 == null || num2 == null) {\n\tval cmd = Packet.commandResultForm(packet)\n\tCommand.addTextField(cmd, \"Note\", \"This is a Scala script!\")\n\tCommand.addFieldValue(cmd, \"num1\", \"\")\n\tCommand.addFieldValue(cmd, \"num2\", \"\")\n\tcmd\n} else {\n\tnum1 + num2\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/auth/mechanisms/SaslANONYMOUSTest.java",
    "content": "package tigase.auth.mechanisms;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\n\nimport junit.framework.TestCase;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\npublic class SaslANONYMOUSTest extends TestCase {\n\n\tprivate SaslANONYMOUS sasl;\n\n\t@Override\n\t@Before\n\tpublic void setUp() {\n\t\tMap<? super String, ?> props = new HashMap<String, Object>();\n\t\tCallbackHandler callbackHandler = new CallbackHandler() {\n\n\t\t\t@Override\n\t\t\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\t\t\tfor (Callback callback : callbacks) {\n\t\t\t\t\tif (callback instanceof NameCallback) {\n\t\t\t\t\t\t((NameCallback) callback).setName(\"somerandomname@domain.com\");\n\t\t\t\t\t} else\n\t\t\t\t\t\tthrow new UnsupportedCallbackException(callback);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.sasl = new SaslANONYMOUS(props, callbackHandler);\n\t}\n\n\t@Test\n\tpublic void testSuccess() {\n\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\".getBytes());\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(sasl.isComplete());\n\t\tassertEquals(\"somerandomname@domain.com\", sasl.getAuthorizationID());\n\t\tassertTrue((Boolean) sasl.getNegotiatedProperty(SaslANONYMOUS.IS_ANONYMOUS_PROPERTY));\n\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/auth/mechanisms/SaslPLAINTest.java",
    "content": "package tigase.auth.mechanisms;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\n\nimport junit.framework.TestCase;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport tigase.auth.XmppSaslException;\nimport tigase.auth.callbacks.VerifyPasswordCallback;\n\npublic class SaslPLAINTest extends TestCase {\n\n\tprivate SaslPLAIN sasl;\n\n\t@Override\n\t@Before\n\tpublic void setUp() {\n\t\tMap<? super String, ?> props = new HashMap<String, Object>();\n\t\tCallbackHandler callbackHandler = new CallbackHandler() {\n\n\t\t\tprivate String username;\n\n\t\t\t@Override\n\t\t\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\t\t\tfor (Callback callback : callbacks) {\n\t\t\t\t\tif (callback instanceof NameCallback) {\n\t\t\t\t\t\tusername = ((NameCallback) callback).getDefaultName() + \"@domain.com\";\n\t\t\t\t\t\t((NameCallback) callback).setName(username);\n\t\t\t\t\t} else if (callback instanceof VerifyPasswordCallback) {\n\t\t\t\t\t\t((VerifyPasswordCallback) callback).setVerified(\"juliet@domain.com:xsecret\".equals(username + \":\"\n\t\t\t\t\t\t\t\t+ ((VerifyPasswordCallback) callback).getPassword()));\n\t\t\t\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\t\t\t\tboolean a = ((AuthorizeCallback) callback).getAuthorizationID().equals(\n\t\t\t\t\t\t\t\t((AuthorizeCallback) callback).getAuthenticationID());\n\t\t\t\t\t\t((AuthorizeCallback) callback).setAuthorized(a);\n\t\t\t\t\t\tif (a)\n\t\t\t\t\t\t\t((AuthorizeCallback) callback).setAuthorizedID(((AuthorizeCallback) callback).getAuthorizationID());\n\t\t\t\t\t} else\n\t\t\t\t\t\tthrow new UnsupportedCallbackException(callback);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.sasl = new SaslPLAIN(props, callbackHandler);\n\t}\n\n\t@Test\n\tpublic void testEmptyPassword() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0juliet\\0\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"not-authorized\", e.getSaslErrorElementName());\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t} catch (SaslException e) {\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testEmptyUsername() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0\\0qaz\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testEmptyUsernamePassword() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0\\0\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testInvalidAuthzId() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"romeo\\0juliet\\0xsecret\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"invalid-authzid\", e.getSaslErrorElementName());\n\t\t\tassertEquals(\"PLAIN: juliet is not authorized to act as romeo\", e.getMessage());\n\t\t} catch (SaslException e) {\n\t\t\tassertEquals(\"PLAIN: juliet is not authorized to act as romeo\", e.getMessage());\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testInvalidPassword() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0juliet\\0ysecret\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"not-authorized\", e.getSaslErrorElementName());\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t} catch (SaslException e) {\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testInvalidUsername() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0romeo\\0xsecret\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"not-authorized\", e.getSaslErrorElementName());\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t} catch (SaslException e) {\n\t\t\tassertEquals(\"Password not verified\", e.getMessage());\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testmalformedRequest1() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testmalformedRequest2() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(null);\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testmalformedRequest3() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0juliet\\0xsecret\\0\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testmalformedRequest4() {\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"xyz\".getBytes());\n\t\t\tfail(\"Exception must be throwed\");\n\t\t} catch (XmppSaslException e) {\n\t\t\tassertEquals(\"malformed-request\", e.getSaslErrorElementName());\n\t\t} catch (SaslException e) {\n\t\t}\n\n\t\tassertFalse(sasl.isComplete());\n\t\tassertNull(\"Authorization ID must be null\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testSuccess() {\n\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"\\0juliet\\0xsecret\".getBytes());\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(sasl.isComplete());\n\t\tassertEquals(\"juliet@domain.com\", sasl.getAuthorizationID());\n\n\t}\n\n\t@Test\n\tpublic void testSuccessWithAuthzId() {\n\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"juliet@domain.com\\0juliet\\0xsecret\".getBytes());\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(sasl.isComplete());\n\t\tassertEquals(\"juliet@domain.com\", sasl.getAuthorizationID());\n\t}\n\n\t@Test\n\tpublic void testSuccessWithAuthzId2() {\n\n\t\tMap<? super String, ?> props = new HashMap<String, Object>();\n\t\tCallbackHandler callbackHandler = new CallbackHandler() {\n\n\t\t\tprivate String username;\n\n\t\t\t@Override\n\t\t\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\t\t\tfor (Callback callback : callbacks) {\n\t\t\t\t\tif (callback instanceof NameCallback) {\n\t\t\t\t\t\tusername = ((NameCallback) callback).getDefaultName();\n\t\t\t\t\t} else if (callback instanceof VerifyPasswordCallback) {\n\t\t\t\t\t\t((VerifyPasswordCallback) callback).setVerified(\"secondwitch:shakespeare\".equals(username + \":\"\n\t\t\t\t\t\t\t\t+ ((VerifyPasswordCallback) callback).getPassword()));\n\t\t\t\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\t\t\t\tboolean a = ((AuthorizeCallback) callback).getAuthorizationID().equals(\"romeo@example.net\");\n\t\t\t\t\t\ta = a && username.equals(\"secondwitch\");\n\t\t\t\t\t\t((AuthorizeCallback) callback).setAuthorized(a);\n\t\t\t\t\t\tif (a)\n\t\t\t\t\t\t\t((AuthorizeCallback) callback).setAuthorizedID(((AuthorizeCallback) callback).getAuthorizationID());\n\t\t\t\t\t} else\n\t\t\t\t\t\tthrow new UnsupportedCallbackException(callback);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tfinal SaslPLAIN sasl = new SaslPLAIN(props, callbackHandler);\n\n\t\ttry {\n\t\t\tsasl.evaluateResponse(\"romeo@example.net\\0secondwitch\\0shakespeare\".getBytes());\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(sasl.isComplete());\n\t\tassertEquals(\"romeo@example.net\", sasl.getAuthorizationID());\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/auth/mechanisms/SaslSCRAMPlusTest.java",
    "content": "package tigase.auth.mechanisms;\n\nimport junit.framework.TestCase;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.auth.callbacks.*;\nimport tigase.util.Base64;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\nimport java.io.IOException;\n\npublic class SaslSCRAMPlusTest extends TestCase {\n\n\tprivate AbstractSaslSCRAM m;\n\n\t@Override\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tm = new SaslSCRAMPlus(null,\n\t\t\t\tnew TestCallbackHandler(\"Ey6OJnGx7JEJAIJp\", new byte[]{'D', 'P', 'I'}), \"5kLrhitKUHVoSOmzdR\") {\n\t\t};\n\t}\n\n\n\t@Test\n\tpublic void testChannelBindingEncodingEncoding() throws SaslException {\n\t\tString CFM = \"cD10bHMtdW5pcXVlLCxuPWJtYWxrb3cscj1TanF1Y3NIdmkzQjR0c1lrTkpCS0lJdHM=\";\n\t\tString SFM = \"cj1TanF1Y3NIdmkzQjR0c1lrTkpCS0lJdHNjdUVZWGMvU210dWtTUjIycVoscz1NZzRxWVlUckh6VkUyUUdZLGk9NDA5Ng==\";\n\t\tString CSM = \"Yz1jRDEwYkhNdGRXNXBjWFZsTEN4WHhZRFpldWFPU01qWTE3cG5QZXE2K2FDaUdIODg1dW9PVlFKMm5rQlk4dz09LHI9U2pxdWNzSHZpM0I0dHNZa05KQktJSXRzY3VFWVhjL1NtdHVrU1IyMnFaLHA9NC9ZeHptOUZsV24xT1duaUJVQ08yeC9jMXo4PQ==\";\n\n\n\t\tSaslSCRAMPlus m = new SaslSCRAMPlus(null,\n\t\t\t\tnew TestCallbackHandler(\"Mg4qYYTrHzVE2QGY\", Base64.decode(\"V8WA2XrmjkjI2Ne6Zz3quvmgohh/PObqDlUCdp5AWPM=\")), \"cuEYXc/SmtukSR22qZ\") {\n\t\t};\n\n\t\tbyte[] req;\n\t\tbyte[] rsp;\n\n\t\treq = Base64.decode(CFM);\n\t\trsp = m.evaluateResponse(req);\n\n\t\tSystem.out.println(new String(rsp));\n\t\tSystem.out.println(new String(Base64.decode(SFM)));\n\n\t\treq = Base64.decode(CSM);\n\t\trsp = m.evaluateResponse(req);\n\t}\n\n\t@Test\n\tpublic void testInvalidBinding() {\n\t\tSaslSCRAMPlus m = new SaslSCRAMPlus(null,\n\t\t\t\tnew TestCallbackHandler(\"AecUfGKyBAbZjjXW\", new byte[]{'D', 'P', 'I'}), \"k5m3fXaEqPQ0zxIjpl\") {\n\t\t};\n\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"p=tls-unique,,n=bmalkow,r=mnKBtk4+09BtRQM3AkSsjsE5\".getBytes());\n\t\t\tAssert.assertEquals(\"r=mnKBtk4+09BtRQM3AkSsjsE5k5m3fXaEqPQ0zxIjpl,s=AecUfGKyBAbZjjXW,i=4096\", new String(r));\n\n\t\t\tr = m.evaluateResponse(\"c=cD10bHMtdW5pcXVlLCxEVVBB,r=mnKBtk4+09BtRQM3AkSsjsE5k5m3fXaEqPQ0zxIjpl,p=BatbnZpQ+UolSyWBozXyvS8Yl78=\".getBytes());\n\t\t\tfail();\n\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Channel bindings does not match\", e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testModifiedBinding() {\n\t\tfinal SaslSCRAMPlus m = new SaslSCRAMPlus(null,\n\t\t\t\tnew TestCallbackHandler(\"AecUfGKyBAbZjjXW\", new byte[]{'D', 'P', 'I'}), \"k5m3fXaEqPQ0zxIjpl\");\n\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"p=tls-unique,,n=bmalkow,r=mnKBtk4+09BtRQM3AkSsjsE5\".getBytes());\n\t\t\tAssert.assertEquals(\"r=mnKBtk4+09BtRQM3AkSsjsE5k5m3fXaEqPQ0zxIjpl,s=AecUfGKyBAbZjjXW,i=4096\", new String(r));\n\n\t\t\t// Channel binding data modified by Mallet to value expected by server\n\t\t\tr = m.evaluateResponse(\"c=cD10bHMtdW5pcXVlLCxEUEk=,r=mnKBtk4+09BtRQM3AkSsjsE5k5m3fXaEqPQ0zxIjpl,p=BatbnZpQ+UolSyWBozXyvS8Yl78=\".getBytes());\n\t\t\tfail();\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Password not verified\", e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessageFail_1() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL\".getBytes());\n\t\t\tfail();\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Invalid request for SCRAM-SHA-1-PLUS\", e.getMessage());\n\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessageFail_2() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"y,,n=user,r=fyko+d2lbbFgONRv9qkxdawL\".getBytes());\n\t\t\tfail();\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Server supports PLUS. Please use 'p'\", e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessageWithBinding() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"p=tls-unique,,n=bmalkow,r=SpiXKmhi57DBp5sdE5G3H3ms\".getBytes());\n\t\t\tAssert.assertEquals(\"r=SpiXKmhi57DBp5sdE5G3H3ms5kLrhitKUHVoSOmzdR,s=Ey6OJnGx7JEJAIJp,i=4096\", new String(r));\n\n\t\t\tr = m.evaluateResponse(\"c=cD10bHMtdW5pcXVlLCxEUEk=,r=SpiXKmhi57DBp5sdE5G3H3ms5kLrhitKUHVoSOmzdR,p=+zQvUd4nQqo03thSCcc2K6gueD4=\".getBytes());\n\t\t\tAssert.assertEquals(\"v=NQ/f8FjeMxUuRK9F88G8tMji4pk=\", new String(r));\n\n\t\t} catch (SaslException e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(m.isComplete());\n\t\tassertEquals(\"user@domain.com\", m.getAuthorizationID());\n\t}\n\n\tprivate class TestCallbackHandler implements CallbackHandler {\n\n\t\tprivate final byte[] bindingData;\n\n\t\tprivate final String salt;\n\n\t\tpublic TestCallbackHandler(String salt, byte[] bindingData) {\n\t\t\tthis.bindingData = bindingData;\n\t\t\tthis.salt = salt;\n\t\t}\n\n\t\t@Override\n\t\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\t\tfor (Callback callback : callbacks) {\n\t\t\t\tif (callback instanceof XMPPSessionCallback) {\n\t\t\t\t} else if (callback instanceof ChannelBindingCallback) {\n\t\t\t\t\tif (((ChannelBindingCallback) callback).getRequestedBindType() == AbstractSaslSCRAM.BindType.tls_unique)\n\t\t\t\t\t\t((ChannelBindingCallback) callback).setBindingData(bindingData);\n\t\t\t\t} else if (callback instanceof PBKDIterationsCallback) {\n\t\t\t\t\t((PBKDIterationsCallback) callback).setInterations(4096);\n\t\t\t\t} else if (callback instanceof SaltedPasswordCallback) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tbyte[] r = AbstractSaslSCRAM.hi(\"SHA1\", \"123456\".getBytes(), Base64.decode(salt), 4096);\n\t\t\t\t\t\t((SaltedPasswordCallback) callback).setSaltedPassword(r);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t}\n\t\t\t\t} else if (callback instanceof NameCallback) {\n\t\t\t\t\t((NameCallback) callback).setName(\"user@domain.com\");\n\t\t\t\t} else if (callback instanceof SaltCallback) {\n\t\t\t\t\t((SaltCallback) callback).setSalt(Base64.decode(salt));\n\t\t\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\t\t\t((AuthorizeCallback) callback).setAuthorized(true);\n\t\t\t\t\t((AuthorizeCallback) callback).setAuthorizedID(\"user@domain.com\");\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback \" + callback);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/auth/mechanisms/SaslSCRAMTest.java",
    "content": "package tigase.auth.mechanisms;\n\nimport junit.framework.TestCase;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport tigase.auth.callbacks.*;\nimport tigase.util.Base64;\n\nimport javax.security.auth.callback.Callback;\nimport javax.security.auth.callback.CallbackHandler;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.UnsupportedCallbackException;\nimport javax.security.sasl.AuthorizeCallback;\nimport javax.security.sasl.SaslException;\nimport java.io.IOException;\nimport java.security.NoSuchAlgorithmException;\n\npublic class SaslSCRAMTest extends TestCase {\n\n\tprivate AbstractSaslSCRAM m;\n\n\t@Override\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tm = new SaslSCRAM(null,\n\t\t\t\tnew TestCallbackHandler(), \"3rfcNHYJY1ZVvWVs7j\") {\n\t\t};\n\t}\n\n\t@Test\n\tpublic void testH() {\n\t\ttry {\n\t\t\tbyte[] r = m.h(\"The quick brown fox jumps over the lazy cog\".getBytes());\n\t\t\tAssert.assertArrayEquals(Base64.decode(\"3p8sf9JeGzr60+haC9F9mxANtLM=\"), r);\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testHi() {\n\t\ttry {\n\t\t\tbyte[] r = AbstractSaslSCRAM.hi(\"SHA1\", \"password\".getBytes(), \"salt\".getBytes(), 1);\n\t\t\tAssert.assertArrayEquals(new byte[]{(byte) 0x0c, (byte) 0x60, (byte) 0xc8, (byte) 0x0f, (byte) 0x96, (byte) 0x1f,\n\t\t\t\t\t(byte) 0x0e, (byte) 0x71, (byte) 0xf3, (byte) 0xa9, (byte) 0xb5, (byte) 0x24, (byte) 0xaf, (byte) 0x60,\n\t\t\t\t\t(byte) 0x12, (byte) 0x06, (byte) 0x2f, (byte) 0xe0, (byte) 0x37, (byte) 0xa6}, r);\n\n\t\t\tr = AbstractSaslSCRAM.hi(\"SHA1\", \"password\".getBytes(), \"salt\".getBytes(), 2);\n\t\t\tAssert.assertArrayEquals(new byte[]{(byte) 0xea, (byte) 0x6c, (byte) 0x01, (byte) 0x4d, (byte) 0xc7, (byte) 0x2d,\n\t\t\t\t\t(byte) 0x6f, (byte) 0x8c, (byte) 0xcd, (byte) 0x1e, (byte) 0xd9, (byte) 0x2a, (byte) 0xce, (byte) 0x1d,\n\t\t\t\t\t(byte) 0x41, (byte) 0xf0, (byte) 0xd8, (byte) 0xde, (byte) 0x89, (byte) 0x57}, r);\n\n\t\t\tr = AbstractSaslSCRAM.hi(\"SHA1\", \"password\".getBytes(), \"salt\".getBytes(), 4096);\n\t\t\tAssert.assertArrayEquals(new byte[]{(byte) 0x4b, (byte) 0x00, (byte) 0x79, (byte) 0x01, (byte) 0xb7, (byte) 0x65,\n\t\t\t\t\t(byte) 0x48, (byte) 0x9a, (byte) 0xbe, (byte) 0xad, (byte) 0x49, (byte) 0xd9, (byte) 0x26, (byte) 0xf7,\n\t\t\t\t\t(byte) 0x21, (byte) 0xd0, (byte) 0x65, (byte) 0xa4, (byte) 0x29, (byte) 0xc1}, r);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\t}\n\n\t@Category(tigase.tests.SlowTest.class)\n\t@Test\n\tpublic void testHiLong() {\n\t\ttry {\n\t\t\tbyte[] r = AbstractSaslSCRAM.hi(\"SHA1\", \"password\".getBytes(), \"salt\".getBytes(), 16777216);\n\t\t\tAssert.assertArrayEquals(new byte[]{(byte) 0xee, (byte) 0xfe, (byte) 0x3d, (byte) 0x61, (byte) 0xcd, (byte) 0x4d,\n\t\t\t\t\t(byte) 0xa4, (byte) 0xe4, (byte) 0xe9, (byte) 0x94, (byte) 0x5b, (byte) 0x3d, (byte) 0x6b, (byte) 0xa2,\n\t\t\t\t\t(byte) 0x15, (byte) 0x8c, (byte) 0x26, (byte) 0x34, (byte) 0xe9, (byte) 0x84}, r);\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testHmac() {\n\t\ttry {\n\t\t\tbyte[] r = AbstractSaslSCRAM.hmac(m.key(\"foo\".getBytes()), \"foobar\".getBytes());\n\n\t\t\tAssert.assertArrayEquals(new byte[]{(byte) 0xa4, (byte) 0xee, (byte) 0xba, (byte) 0x8e, 0x63, 0x3d, 0x77,\n\t\t\t\t\t(byte) 0x88, 0x69, (byte) 0xf5, 0x68, (byte) 0xd0, 0x5a, 0x1b, 0x3d, (byte) 0xc7, 0x2b, (byte) 0xfd, 0x4,\n\t\t\t\t\t(byte) 0xdd}, r);\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessage() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL\".getBytes());\n\t\t\tAssert.assertEquals(\"r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096\", new String(r));\n\n\t\t\tr = m.evaluateResponse(\"c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=\".getBytes());\n\t\t\tAssert.assertEquals(\"v=rmF9pqV8S7suAoZWja4dJRkFsKQ=\", new String(r));\n\n\t\t} catch (SaslException e) {\n\t\t\te.printStackTrace();\n\t\t\tfail(e.getMessage());\n\t\t}\n\n\t\tassertTrue(m.isComplete());\n\t\tassertEquals(\"user@domain.com\", m.getAuthorizationID());\n\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessageFail_1() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"p=tls-unique,,n=bmalkow,r=SpiXKmhi57DBp5sdE5G3H3ms\".getBytes());\n\t\t\tfail();\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Invalid request for SCRAM-SHA-1\", e.getMessage());\n\n\t\t}\n\t}\n\n\t@Test\n\tpublic void testServerFirstMessageFail_2() {\n\t\ttry {\n\t\t\tbyte[] r = m.evaluateResponse(\"y,,n=bmalkow,r=SpiXKmhi57DBp5sdE5G3H3ms\".getBytes());\n\t\t\tfail();\n\t\t} catch (SaslException e) {\n\t\t\tAssert.assertEquals(\"Server supports PLUS. Please use 'p'\", e.getMessage());\n\n\t\t}\n\t}\n\n\tprivate class TestCallbackHandler implements CallbackHandler {\n\n\t\t@Override\n\t\tpublic void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {\n\t\t\tfor (Callback callback : callbacks) {\n\t\t\t\tif (callback instanceof XMPPSessionCallback) {\n\t\t\t\t} else if (callback instanceof ChannelBindingCallback) {\n\t\t\t\t\t((ChannelBindingCallback) callback).setBindingData(new byte[]{'D', 'P', 'I'});\n\t\t\t\t} else if (callback instanceof PBKDIterationsCallback) {\n\t\t\t\t\t((PBKDIterationsCallback) callback).setInterations(4096);\n\t\t\t\t} else if (callback instanceof SaltedPasswordCallback) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tbyte[] r = AbstractSaslSCRAM.hi(\"SHA1\", \"pencil\".getBytes(), Base64.decode(\"QSXCR+Q6sek8bf92\"), 4096);\n\t\t\t\t\t\t((SaltedPasswordCallback) callback).setSaltedPassword(r);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t}\n\t\t\t\t} else if (callback instanceof NameCallback) {\n\t\t\t\t\t((NameCallback) callback).setName(\"user@domain.com\");\n\t\t\t\t} else if (callback instanceof SaltCallback) {\n\t\t\t\t\t((SaltCallback) callback).setSalt(Base64.decode(\"QSXCR+Q6sek8bf92\"));\n\t\t\t\t} else if (callback instanceof AuthorizeCallback) {\n\t\t\t\t\t((AuthorizeCallback) callback).setAuthorized(true);\n\t\t\t\t\t((AuthorizeCallback) callback).setAuthorizedID(\"user@domain.com\");\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UnsupportedCallbackException(callback, \"Unrecognized Callback \" + callback);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/cluster/ClusterConnectionSelectorTest.java",
    "content": "/*\n * ClusterConnectionSelectorTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.cluster;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport junit.framework.TestCase;\nimport org.junit.Test;\nimport static tigase.cluster.ClusterConnectionSelector.CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY;\nimport tigase.cluster.api.ClusterConnectionHandler;\nimport tigase.server.Packet;\nimport tigase.server.Priority;\nimport tigase.xml.Element;\nimport tigase.xmpp.XMPPIOService;\n\n/**\n *\n * @author andrzej\n */\npublic class ClusterConnectionSelectorTest extends TestCase {\n\n\t@Test\n\tpublic void testSelectConnection() throws Exception {\n\t\tClusterConnection conn = new ClusterConnection(\"test\");\n\t\tClusterConnectionSelector selector = new ClusterConnectionSelector();\n\t\tselector.setClusterConnectionHandler(new ClusterConnectionHandler() {\n\n\t\t\t@Override\n\t\t\tpublic int hashCodeForPacket(Packet packet) {\n\t\t\t\treturn packet.getStanzaFrom().hashCode();\n\t\t\t}\n\t\t});\n\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY, 1);\n\t\tselector.setProperties(props);\n\t\t\n\t\tElement el = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test1\" });\n\t\tPacket p = Packet.packetInstance(el);\n\t\tassertNull(selector.selectConnection(p, conn));\n\t\t\n\t\tXMPPIOService<Object> serv1 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv1);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\n\t\tp.setPriority(null);\n\t\tXMPPIOService<Object> serv2 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv2);\n\t\tassertEquals(2, conn.size());\n\t\tassertEquals(serv2, selector.selectConnection(p, conn));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\n\t\tp.setPriority(null);\n\t\tXMPPIOService<Object> serv3 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv3);\n\t\tassertEquals(3, conn.size());\n\t\tassertNotSame(serv1, selector.selectConnection(p, conn));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\t\t\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test2\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertNotSame(serv1, selector.selectConnection(p, conn));\n\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test3\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertNotSame(serv1, selector.selectConnection(p, conn));\n\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test4\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertNotSame(serv1, selector.selectConnection(p, conn));\t\t\n\t}\n\t\n\t@Test\n\tpublic void testSelectConnectionFor2() throws Exception {\n\t\tClusterConnection conn = new ClusterConnection(\"test\");\n\t\tClusterConnectionSelector selector = new ClusterConnectionSelector();\n\t\tselector.setClusterConnectionHandler(new ClusterConnectionHandler() {\n\n\t\t\t@Override\n\t\t\tpublic int hashCodeForPacket(Packet packet) {\n\t\t\t\treturn packet.getStanzaFrom().hashCode();\n\t\t\t}\n\t\t});\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(CLUSTER_SYS_CONNECTIONS_PER_NODE_PROP_KEY, 2);\n\t\tselector.setProperties(props);\n\t\t\n\t\tElement el = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test1\" });\n\t\tPacket p = Packet.packetInstance(el);\n\t\tassertNull(selector.selectConnection(p, conn));\n\t\t\n\t\tXMPPIOService<Object> serv1 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv1);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertEquals(serv1, selector.selectConnection(p, conn));\n\n\t\tp.setPriority(null);\n\t\tXMPPIOService<Object> serv2 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv2);\n\t\tSet<XMPPIOService<Object>> sysServs = new HashSet<>(Arrays.asList(serv1, serv2));\n\t\tassertEquals(2, conn.size());\n\t\tassertTrue(sysServs.contains(selector.selectConnection(p, conn)));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertTrue(sysServs.contains(selector.selectConnection(p, conn)));\n\n\t\tp.setPriority(null);\n\t\tXMPPIOService<Object> serv3 = new XMPPIOService<Object>();\n\t\tconn.addConn(serv3);\n\t\tassertEquals(3, conn.size());\n\t\tassertSame(serv3, selector.selectConnection(p, conn));\n\t\t\n\t\tp.setPriority(Priority.SYSTEM);\n\t\tassertTrue(sysServs.contains(selector.selectConnection(p, conn)));\n\t\t\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test2\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertSame(serv3, selector.selectConnection(p, conn));\n\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test3\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertSame(serv3, selector.selectConnection(p, conn));\n\n\t\tel = new Element(\"iq\", new String[] { \"from\" }, new String[] { \"test4\" });\n\t\tp = Packet.packetInstance(el);\n\t\tassertEquals(3, conn.size());\n\t\tassertSame(serv3, selector.selectConnection(p, conn));\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/cluster/api/ClusterElementTest.java",
    "content": "/*\n * ClusterElementTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2012 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\n\n\n/*\n* To change this template, choose Tools | Templates\n* and open the template in the editor.\n */\npackage tigase.cluster.api;\n\n//~--- non-JDK imports --------------------------------------------------------\n\nimport junit.framework.TestCase;\n\nimport org.junit.Test;\n\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\n\n/**\n *\n * @author andrzej\n */\npublic class ClusterElementTest\n\t\t\t\textends TestCase {\n\t/**\n\t * Method description\n\t *\n\t */\n\t@Test\n\t@SuppressWarnings(\"deprecation\")\n\tpublic void testGetMethodName() {\n\t\tSimpleParser parser       = new SimpleParser();\n\t\tDomBuilderHandler handler = new DomBuilderHandler();\n\t\tchar[] data               =\n\t\t\t\"<cluster to=\\\"sess-man@blue\\\" type=\\\"set\\\" id=\\\"cl-6627\\\" xmlns=\\\"tigase:cluster\\\" from=\\\"sess-man@green\\\"><control><visited-nodes><node-id>sess-man@green</node-id></visited-nodes><method-call name=\\\"packet-forward-sm-cmd\\\"/><first-node>sess-man@green</first-node></control><data><presence to=\\\"test2@test\\\" xmlns=\\\"jabber:client\\\" from=\\\"test1@test/test\\\"><status/><priority>5</priority></presence></data></cluster>\".toCharArray();\n\n\t\tparser.parse(handler, data, 0, data.length);\n\n\t\tElement elem = handler.getParsedElements().poll();\n\n\t\tassertEquals(\n\t\t\t\t\"packet-forward-sm-cmd\",\n\t\t\t\telem.findChild(\"/cluster/control/method-call\").getAttributeStaticStr(\"name\"));\n\n//  assertEquals(\"cluster/control/method-call\".split(\"/\"),\n//               ClusterElement.CLUSTER_METHOD_PATH);\n\t\tClusterElement clElem = new ClusterElement(elem);\n\n\t\tassertEquals(\"packet-forward-sm-cmd\", clElem.getMethodName());\n\t}\n}\n\n\n//~ Formatted in Tigase Code Convention on 13/02/20\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/db/jdbc/JDBCRepositoryTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.db.jdbc;\n\nimport tigase.db.DBInitException;\nimport tigase.db.RepositoryFactory;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserExistsException;\nimport tigase.db.UserRepository;\n\nimport tigase.xmpp.BareJID;\n\nimport java.time.LocalDateTime;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.junit.*;\n\n/**\n *\n * @author Wojtek\n */\npublic class JDBCRepositoryTest {\n\n\tUserRepository repo = null;\n\tboolean initialised = false;\n\n\tpublic JDBCRepositoryTest() {\n\t}\n\n\t@Before\n\tpublic void setUp() {\n\n\t\tHashMap map = new LinkedHashMap();\n\t\tmap.put( RepositoryFactory.DATA_REPO_POOL_SIZE_PROP_KEY, \"2\");\n\n\t\tString repositoryURI = null;\n//\t\trepositoryURI = \"jdbc:mysql://localhost:3306/tigasedb?user=tigase&password=tigase&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\";\n//\t\trepositoryURI = \"jdbc:jtds:sqlserver://sqlserverhost:1433;databaseName=tigasedb;user=tigase;password=mypass;schema=dbo;lastUpdateCount=false;autoCreateUser=true\";\n//\t\trepositoryURI = \"jdbc:sqlserver://sqlserverhost:1433;databaseName=tigasedb;user=tigase;password=mypass;schema=dbo;lastUpdateCount=false;autoCreateUser=true\";\n//\t\trepositoryURI = \"jdbc:postgresql://localhost/tigasedb?user=tigase&password=tigase&useUnicode=true&characterEncoding=UTF-8&autoCreateUser=true\";\n//\t\trepositoryURI = \"jdbc:derby:/Users/wojtek/dev/tigase/tigase-server/derbyDb\";\n//\t\trepositoryURI = \"mongodb://localhost/tigase_test?autoCreateUser=true\";\n\t\tAssume.assumeNotNull(repositoryURI);\n\t\trepo = new JDBCRepository();\n\t\ttry {\n\t\t\trepo.initRepository( repositoryURI, map );\n\t\t\tinitialised = true;\n\t\t} catch ( DBInitException ex ) {\n\t\t\tLogger.getLogger( JDBCRepositoryTest.class.getName() ).log( Level.SEVERE, \"db initialisation failed\", ex );\n\t\t}\n\n\t\tAssume.assumeTrue(initialised);\n\n\t}\n\n\tprivate void getData( BareJID user )  {\n\t\tif ( user == null ){\n\t\t\tuser = BareJID.bareJIDInstanceNS( \"user\", \"domain\" );\n\t\t}\n\t\tSystem.out.println( \"retrieve: \" + user + \" / thread: \" + Thread.currentThread().getName() );\n\t\ttry {\n//\t\t\trepo.getData( user, \"privacy\", \"default-list\", null );\n\t\t\trepo.addUser( user );\n\t\t} catch ( UserExistsException ex ) {\n\t\t\tSystem.out.println( \"User exists, ignore: \" + ex.getUserId() );\n\t\t} catch ( TigaseDBException ex ) {\n\t\t\tLogger.getLogger( JDBCRepositoryTest.class.getName() ).log( Level.SEVERE, null, ex );\n\t\t}\n\n\t}\n\n\t@Test\n\tpublic void testLongNode() throws InterruptedException, TigaseDBException {\n\n\t\tBareJID user = BareJID.bareJIDInstanceNS( \"user\", \"domain\" );\n\t\trepo.setData( user, \"node1/node2/node3\", \"key\", \"value\" );\n\t\tString node3val;\n\t\tnode3val = repo.getData( user, \"node1/node2/node3\", \"key\" );\n\t\tAssert.assertEquals(\"String differ from expected!\", \"value\", node3val);\n\t\trepo.removeSubnode( user, \"node1\" );\n\t\tnode3val = repo.getData( user, \"node1/node2/node3\", \"key\" );\n\t\tAssert.assertNull( \"Node not removed\", node3val );\n\n\t}\n\n\n\t@Test\n\tpublic void testGetData() throws InterruptedException {\n\n\t\tSystem.out.println( \"repo: \" + repo );\n\t\tif ( repo != null ){\n\t\t\tLocalDateTime localNow = LocalDateTime.now();\n//\t\t\tgetData( null );\n\n\t\t\tlong initalDelay = 5;\n\n\t\t\tScheduledExecutorService scheduler = Executors.newScheduledThreadPool( 10 );\n\t\t\tfinal int iter = 50;\n\t\t\tfinal int threads = 10;\n\n\t\t\tfor ( int i = 0 ; i < threads ; i++ ) {\n\t\t\t\tscheduler.scheduleAtFixedRate( new RunnableImpl( iter ), initalDelay, 100, TimeUnit.MILLISECONDS );\n\t\t\t}\n\n\t\t\tThread.sleep( threads * 1000 );\n\t\t}\n\n\n\t}\n\n\tprivate class RunnableImpl implements Runnable {\n\n\t\tint count = 0;\n\t\tint max = 50;\n\t\tpublic RunnableImpl(int max) {\n\t\t\tthis.max = max;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile ( count < max ) {\n\t\t\t\tcount++;\n\t\t\t\tBareJID user;\n\t\t\t\tuser = BareJID.bareJIDInstanceNS( String.valueOf( ( new Date() ).getTime() / 10 ), \"domain\" );\n\t\t\t\tgetData( user );\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/disteventbus/component/NodeNameUtilTest.java",
    "content": "package tigase.disteventbus.component;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\nimport tigase.disteventbus.impl.EventName;\n\npublic class NodeNameUtilTest {\n\n\t@Test\n\tpublic void testCreateNodeName() throws Exception {\n\t\tassertEquals(\"1|2\", NodeNameUtil.createNodeName(\"1\", \"2\"));\n\t\tassertEquals(\"*|2\", NodeNameUtil.createNodeName(null, \"2\"));\n\t\tassertEquals(\"*|*\", NodeNameUtil.createNodeName(null, null));\n\t\tassertEquals(\"1|*\", NodeNameUtil.createNodeName(\"1\", null));\n\t}\n\n\t@Test\n\tpublic void testParseNodeName() throws Exception {\n\t\tassertEquals(new EventName(\"1\", \"2\"), NodeNameUtil.parseNodeName(\"1|2\"));\n\t\tassertEquals(new EventName(null, \"2\"), NodeNameUtil.parseNodeName(\"*|2\"));\n\t\tassertEquals(new EventName(null, null), NodeNameUtil.parseNodeName(\"*|*\"));\n\t\tassertEquals(new EventName(\"1\", null), NodeNameUtil.parseNodeName(\"1|*\"));\n\t\tassertEquals(new EventName(\"1\", \"\"), NodeNameUtil.parseNodeName(\"1|\"));\n\t\tassertEquals(new EventName(\"\", \"\"), NodeNameUtil.parseNodeName(\"|\"));\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/disteventbus/impl/EventNameTest.java",
    "content": "package tigase.disteventbus.impl;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotEquals;\n\nimport org.junit.Test;\n\n/**\n * Created by bmalkow on 17.11.2015.\n */\npublic class EventNameTest {\n\n\t@Test\n\tpublic void testEquals() throws Exception {\n\t\tassertEquals(new EventName(null, null), new EventName(null, null));\n\t\tassertEquals(new EventName(null, \"2\"), new EventName(null, \"2\"));\n\t\tassertEquals(new EventName(\"1\", \"2\"), new EventName(\"1\", \"2\"));\n\n\t\tassertNotEquals(new EventName(null, null), new EventName(\"2\", \"2\"));\n\t\tassertNotEquals(new EventName(null, null), new EventName(null, \"2\"));\n\t\tassertNotEquals(new EventName(null, null), new EventName(\"2\", null));\n\t\tassertNotEquals(new EventName(\"1\", null), new EventName(\"2\", \"2\"));\n\t\tassertNotEquals(new EventName(null, \"2\"), new EventName(\"2\", \"2\"));\n\t\tassertNotEquals(new EventName(\"2\", \"1\"), new EventName(\"2\", \"2\"));\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/disteventbus/impl/EventsNameMapTest.java",
    "content": "package tigase.disteventbus.impl;\n\nimport static org.hamcrest.CoreMatchers.not;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertThat;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.Test;\n\n/**\n * Created by bmalkow on 17.11.2015.\n */\npublic class EventsNameMapTest {\n\n\t@Test\n\tpublic void test01() throws Exception {\n\t\tEventsNameMap<String> map = new EventsNameMap<String>();\n\t\tmap.put(null, null, \"null-null\");\n\t\tmap.put(null, null, \"null-null2\");\n\t\tmap.put(null, \"2\", \"null-2\");\n\t\tmap.put(\"1\", null, \"1-null\");\n\t\tmap.put(\"1\", \"2\", \"1-2\");\n\t\tmap.put(\"1\", \"2\", \"1-2_2\");\n\n\t\tmap.put(\"a0\", \"b0\", \"U\");\n\t\tmap.put(\"a1\", \"b0\", \"U\");\n\t\tmap.put(\"a0\", \"b1\", \"U\");\n\t\tmap.put(\"a1\", \"b1\", \"U\");\n\n\t\tassertEquals(7, map.getAllData().size());\n\t\tassertEquals(8, map.getAllListenedEvents().size());\n\n\t\tassertEquals(2, map.get(\"1\", \"2\").size());\n\t\tassertThat(map.get(\"1\", \"2\"), CoreMatchers.hasItem(\"1-2\"));\n\t\tassertThat(map.get(\"1\", \"2\"), CoreMatchers.hasItem(\"1-2_2\"));\n\t\tassertThat(map.get(\"1\", null), CoreMatchers.hasItem(\"1-null\"));\n\t\tassertThat(map.get(null, \"2\"), CoreMatchers.hasItem(\"null-2\"));\n\t\tassertThat(map.get(null, null), CoreMatchers.hasItem(\"null-null\"));\n\t\tassertEquals(2, map.get(null, null).size());\n\n\t\tmap.delete(\"1\", \"2\", \"1-2_2\");\n\t\tassertEquals(1, map.get(\"1\", \"2\").size());\n\n\t\tassertThat(map.get(\"1\", \"2\"), CoreMatchers.hasItem(\"1-2\"));\n\t\tassertThat(map.get(\"1\", \"2\"), not(CoreMatchers.hasItem(\"1-2_2\")));\n\n\t\tassertEquals(6, map.getAllData().size());\n\t\tassertEquals(8, map.getAllListenedEvents().size());\n\n\t\tmap.delete(\"U\");\n\n\t\tassertEquals(5, map.getAllData().size());\n\t\tassertEquals(4, map.getAllListenedEvents().size());\n\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/disteventbus/impl/LocalEventBusTest.java",
    "content": "package tigase.disteventbus.impl;\n\nimport static org.junit.Assert.*;\n\nimport java.util.HashSet;\nimport java.util.concurrent.Executor;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.Test;\n\nimport tigase.disteventbus.EventBus;\nimport tigase.disteventbus.EventHandler;\nimport tigase.xml.Element;\n\n/**\n * Created by bmalkow on 17.11.2015.\n */\npublic class LocalEventBusTest {\n\n\t@Test\n\tpublic void test01() {\n\t\tfinal HashSet<String> results = new HashSet<>();\n\n\t\tLocalEventBus eb = new LocalEventBus();\n\t\teb.setExecutor(new Executor() {\n\t\t\t@Override\n\t\t\tpublic void execute(Runnable command) {\n\t\t\t\tcommand.run();\n\t\t\t}\n\t\t});\n\t\teb.addHandler(null, null, new EventHandler() {\n\t\t\t@Override\n\t\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\t\tresults.add(\"*.*_\" + name + \".\" + xmlns);\n\t\t\t}\n\t\t});\n\t\teb.addHandler(null, \"b\", new EventHandler() {\n\t\t\t@Override\n\t\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\t\tresults.add(\"*.b_\" + name + \".\" + xmlns);\n\t\t\t}\n\t\t});\n\t\teb.addHandler(\"a\", \"b\", new EventHandler() {\n\t\t\t@Override\n\t\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\t\tresults.add(\"a.b_\" + name + \".\" + xmlns);\n\t\t\t}\n\t\t});\n\t\ttry {\n\t\t\teb.addHandler(\"a\", null, new EventHandler() {\n\t\t\t\t@Override\n\t\t\t\tpublic void onEvent(String name, String xmlns, Element event) {\n\t\t\t\t\tSystem.out.println(\"!!! \");\n\t\t\t\t\tresults.add(\"a.*_\" + name + \".\" + xmlns);\n\t\t\t\t}\n\t\t\t});\n\t\t\tfail(\"This registration should not be possible!\");\n\t\t} catch (RuntimeException e) {\n\t\t\tassertEquals(\"Illegal handler registration. If name is specified, then xmlns must also be specified.\",\n\t\t\t\t\te.getMessage());\n\t\t}\n\t\teb.fire(new Element(\"a\", new String[] { \"xmlns\" }, new String[] { \"b\" }));\n\t\teb.fire(new Element(\"c\", new String[] { \"xmlns\" }, new String[] { \"d\" }));\n\n\t\tassertThat(results, CoreMatchers.hasItem(\"*.*_c.d\"));\n\t\tassertThat(results, CoreMatchers.hasItem(\"*.*_a.b\"));\n\t\tassertThat(results, CoreMatchers.hasItem(\"*.b_a.b\"));\n\t\tassertThat(results, CoreMatchers.hasItem(\"a.b_a.b\"));\n\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/io/SSLContextContainerTest.java",
    "content": "package tigase.io;\n\nimport static org.junit.Assert.*;\n\nimport java.util.HashMap;\n\nimport org.junit.Test;\n\npublic class SSLContextContainerTest {\n\n\t@Test\n\tpublic void testFind() {\n\t\tfinal HashMap<String, String> domains = new HashMap<String, String>();\n\t\tdomains.put(\"one.com\", \"one.com\");\n\t\tdomains.put(\"a.two.com\", \"a.two.com\");\n\t\tdomains.put(\"*.two.com\", \"*.two.com\");\n\n\t\tassertEquals(\"one.com\", SSLContextContainer.find(domains, \"one.com\"));\n\t\tassertNull(SSLContextContainer.find(domains, \"tone.com\"));\n\t\tassertNull(SSLContextContainer.find(domains, \"zero.com\"));\n\t\tassertEquals(\"a.two.com\", SSLContextContainer.find(domains, \"a.two.com\"));\n\t\tassertEquals(\"*.two.com\", SSLContextContainer.find(domains, \"b.two.com\"));\n\t\tassertEquals(\"*.two.com\", SSLContextContainer.find(domains, \"b.two.com\"));\n\t\tassertNull(SSLContextContainer.find(domains, \"btwo.com\"));\n\t\tassertEquals(\"*.two.com\", SSLContextContainer.find(domains, \".two.com\"));\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean1.java",
    "content": "package tigase.kernel;\n\nimport java.util.Set;\n\nimport tigase.kernel.beans.Bean;\nimport tigase.kernel.beans.Inject;\n\n@Bean(name = \"bean1\")\npublic class Bean1 {\n\n\t@Inject\n\tprivate Bean2 bean2;\n\n\t@Inject\n\tprivate Bean3 bean3;\n\n\t@Inject(type = Special.class)\n\tprivate Set<Special> collectionOfSpecial;\n\n\t@Inject\n\tprivate Special[] tableOfSpecial;\n\n\tpublic Bean2 getBean2() {\n\t\treturn bean2;\n\t}\n\n\tpublic Bean3 getBean3() {\n\t\treturn bean3;\n\t}\n\n\tpublic Set<Special> getCollectionOfSpecial() {\n\t\treturn collectionOfSpecial;\n\t}\n\n\tpublic Special[] getTableOfSpecial() {\n\t\treturn tableOfSpecial;\n\t}\n\n\tpublic void setBean2(Bean2 bean2) {\n\t\tthis.bean2 = bean2;\n\t}\n\n\tpublic void setBean3(Bean3 bean3) {\n\t\tthis.bean3 = bean3;\n\t}\n\n\tpublic void setCollectionOfSpecial(Set<Special> xxx) {\n\t\tthis.collectionOfSpecial = xxx;\n\t}\n\n\tpublic void setTableOfSpecial(Special[] ss) {\n\t\tthis.tableOfSpecial = ss;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean2.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.Inject;\n\npublic class Bean2 {\n\n\t@Inject\n\tprivate Bean3 bean3;\n\n\t@Inject(bean = \"bean4_1\", nullAllowed = true)\n\tprivate Bean4 bean4;\n\n\tpublic Bean3 getBean3() {\n\t\treturn bean3;\n\t}\n\n\tpublic Bean4 getBean4() {\n\t\treturn bean4;\n\t}\n\n\tpublic void setBean3(Bean3 bean3) {\n\t\tthis.bean3 = bean3;\n\t}\n\n\tpublic void setBean4(Bean4 bean4) {\n\t\tthis.bean4 = bean4;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean3.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.Inject;\n\npublic class Bean3 implements Special {\n\n\t@Inject(bean = \"bean4\")\n\tprivate Bean4 bean4;\n\n\t@Inject(bean = \"bean4_1\", nullAllowed = true)\n\tprivate Bean4 bean41;\n\n\tpublic Bean4 getBean4() {\n\t\treturn bean4;\n\t}\n\n\tpublic Bean4 getBean41() {\n\t\treturn bean41;\n\t}\n\t//\n\t// public void setBean4(Bean4 bean4) {\n\t// this.bean4 = bean4;\n\t// }\n\t//\n\t// public void setBean41(Bean4 bean41) {\n\t// this.bean41 = bean41;\n\t// }\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean4.java",
    "content": "package tigase.kernel;\n\npublic class Bean4 implements Special {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean5.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.UnregisterAware;\nimport tigase.kernel.beans.config.ConfigField;\n\npublic class Bean5 implements UnregisterAware {\n\n\t@ConfigField(desc = \"One field with value\")\n\tprivate Long value = 15l;\n\n\t@Override\n\tpublic void beforeUnregister() {\n\t\tSystem.out.println(\"Destroying Bean5 class\");\n\t}\n\n\tpublic Long getValue() {\n\t\treturn value;\n\t}\n\n\tpublic void setValue(Long value) {\n\t\tthis.value = value;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean5Factory.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.BeanFactory;\nimport tigase.kernel.beans.Inject;\n\npublic class Bean5Factory implements BeanFactory<Bean5> {\n\n\t@Inject\n\tprivate Bean1 bean;\n\n\t@Override\n\tpublic Bean5 createInstance() throws KernelException {\n\t\treturn new Bean5();\n\t}\n\n\tpublic Bean1 getBean() {\n\t\treturn bean;\n\t}\n\n\tpublic void setBean(Bean1 bean) {\n\t\tthis.bean = bean;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean6.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.config.ConfigField;\n\npublic class Bean6 implements Special {\n\n\t@ConfigField(desc = \"Field with string value\")\n\tprivate String testValue;\n\n\tpublic String getTestValue() {\n\t\treturn testValue;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Bean7.java",
    "content": "package tigase.kernel;\n\nimport tigase.kernel.beans.Inject;\n\npublic class Bean7 implements Special {\n\n\t@Inject(bean = \"beanX\")\n\tprivate Object obj;\n\n\tpublic Object getObj() {\n\t\treturn obj;\n\t}\n\n\tpublic void setObj(Object obj) {\n\t\tthis.obj = obj;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/KernelTest.java",
    "content": "package tigase.kernel;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.ConsoleHandler;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.junit.AfterClass;\nimport org.junit.Assert;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\nimport tigase.kernel.beans.config.AbstractBeanConfigurator;\nimport tigase.kernel.beans.config.BeanConfigurator;\nimport tigase.kernel.core.BeanConfig;\nimport tigase.kernel.core.DependencyGrapher;\nimport tigase.kernel.core.Kernel;\n\npublic class KernelTest {\n\n    public static class TestBeanConfigurationProvider extends AbstractBeanConfigurator {\n\n        @Override\n        public Map<String, Object> getConfiguration(BeanConfig beanConfig) {\n            if (beanConfig.getBeanName().equals(\"bean5\")) {\n                HashMap<String, Object> result = new HashMap<String, Object>();\n                result.put(\"value\", Long.valueOf(9987));\n                return result;\n            } else if (beanConfig.getBeanName().equals(\"bean6\")) {\n                HashMap<String, Object> result = new HashMap<String, Object>();\n                result.put(\"testValue\", \"yytestxx\");\n                return result;\n            } else\n                return null;\n        }\n    }\n\n    @BeforeClass\n    public static void setUpBeforeClass() throws Exception {\n    }\n\n    @AfterClass\n    public static void tearDownAfterClass() throws Exception {\n    }\n\n    public KernelTest() {\n        Logger logger = Logger.getLogger(\"tigase.kernel.Kernel\");\n\n        // create a ConsoleHandler\n        Handler handler = new ConsoleHandler();\n        handler.setLevel(Level.ALL);\n        logger.addHandler(handler);\n        logger.setLevel(Level.ALL);\n\n        if (logger.isLoggable(Level.CONFIG))\n            logger.config(\"Logger successfully initialized\");\n    }\n\n    @Test\n    public void test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n        Kernel krnl = new Kernel();\n\n        Bean4 bean4_1_o = new Bean4();\n        krnl.registerBean(Bean1.class).exec();\n        krnl.registerBean(\"bean2\").asClass(Bean2.class).exec();\n        krnl.registerBean(\"bean3\").asClass(Bean3.class).exec();\n        krnl.registerBean(\"bean4\").asClass(Bean4.class).exec();\n        krnl.registerBean(\"bean4_1\").asInstance(bean4_1_o).exec();\n        krnl.registerBean(\"bean5\").asClass(Bean5.class).withFactory(Bean5Factory.class).exec();\n\n        DependencyGrapher dg = new DependencyGrapher(krnl);\n        System.out.println(dg.getDependencyGraph());\n\n        Bean1 b1 = krnl.getInstance(\"bean1\");\n        Bean2 b2 = krnl.getInstance(\"bean2\");\n        Bean3 b3 = krnl.getInstance(\"bean3\");\n        Bean4 b4 = krnl.getInstance(\"bean4\");\n        Bean4 b41 = krnl.getInstance(\"bean4_1\");\n\n        assertNotNull(b1);\n        assertNotNull(b2);\n        assertNotNull(b3);\n        assertNotNull(b4);\n        assertNotNull(b41);\n\n        assertEquals(b41, bean4_1_o);\n\n        assertTrue(b1 instanceof Bean1);\n        assertTrue(b2 instanceof Bean2);\n        assertTrue(b3 instanceof Bean3);\n        assertTrue(b4 instanceof Bean4);\n        assertTrue(b41 instanceof Bean4);\n\n        assertEquals(b2, b1.getBean2());\n        assertEquals(b3, b1.getBean3());\n        assertEquals(b3, b2.getBean3());\n        assertEquals(b41, b2.getBean4());\n        assertEquals(b4, b3.getBean4());\n        assertEquals(b41, b3.getBean41());\n\n        assertNotNull(b1.getTableOfSpecial());\n        assertEquals(3, b1.getTableOfSpecial().length);\n\n        assertEquals(3, b1.getCollectionOfSpecial().size());\n        assertTrue(b1.getCollectionOfSpecial().contains(b3));\n        assertTrue(b1.getCollectionOfSpecial().contains(b4));\n        assertTrue(b1.getCollectionOfSpecial().contains(b41));\n\n        krnl.unregister(\"bean4_1\");\n        try {\n            assertNull(krnl.getInstance(\"bean4_1\"));\n            Assert.fail();\n        } catch (KernelException e) {\n            assertEquals(\"Unknown bean 'bean4_1'.\", e.getMessage());\n        }\n        assertNull(b3.getBean41());\n        assertNull(b2.getBean4());\n\n        assertNotNull(b1.getBean2());\n        assertNotNull(b1.getBean3());\n\n        assertEquals(2, b1.getTableOfSpecial().length);\n\n        assertEquals(2, b1.getCollectionOfSpecial().size());\n        assertTrue(b1.getCollectionOfSpecial().contains(b3));\n        assertTrue(b1.getCollectionOfSpecial().contains(b4));\n\n        krnl.registerBean(\"bean6\").asClass(Bean6.class).exec();\n\n        assertEquals(3, b1.getTableOfSpecial().length);\n        assertEquals(3, b1.getCollectionOfSpecial().size());\n\n        System.out.println(dg.getDependencyGraph());\n\n    }\n\n    @Test\n    public void test2() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n        Kernel krnl = new Kernel();\n        krnl.registerBean(\"bean7\").asClass(Bean7.class).exec();\n\n        krnl.registerBean(\"beanX\").asClass(Bean4.class).exec();\n        krnl.registerBean(\"beanX\").asClass(Bean5.class).withFactory(Bean5Factory.class).exec();\n\n        assertEquals(Bean5.class, krnl.getInstance(Bean7.class).getObj().getClass());\n        assertEquals(Bean5.class, krnl.getInstance(\"beanX\").getClass());\n\n        krnl.registerBean(\"beanX\").asClass(Bean6.class).exec();\n\n        assertEquals(Bean6.class, krnl.getInstance(\"beanX\").getClass());\n        assertEquals(Bean6.class, krnl.getInstance(Bean7.class).getObj().getClass());\n    }\n\n    @Test\n    public void test3() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n        Kernel krnl = new Kernel();\n\n        krnl.registerBean(Bean1.class).exec();\n        krnl.registerBean(\"bean4\").asClass(Bean4.class).exec();\n        // krnl.registerBean(\"bean41\").asClass(Bean4.class).exec();\n\n        Bean1 b1 = krnl.getInstance(\"bean1\");\n\n        assertNotNull(b1);\n\n        assertNotNull(b1.getTableOfSpecial());\n        assertEquals(1, b1.getTableOfSpecial().length);\n\n        assertEquals(1, b1.getCollectionOfSpecial().size());\n    }\n\n    @Test\n    public void test4() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n        Kernel krnl = new Kernel();\n\n        krnl.registerBean(Bean1.class).exec();\n\n        Bean1 b1 = krnl.getInstance(\"bean1\");\n\n        assertNotNull(b1);\n\n        assertNull(b1.getTableOfSpecial());\n\n        assertEquals(0, b1.getCollectionOfSpecial().size());\n    }\n\n    @Test\n    public void testBeanConfiguration() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n        Kernel krnl = new Kernel();\n        krnl.registerBean(\"bean5\").asClass(Bean5.class).exec();\n        krnl.registerBean(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME).asClass(TestBeanConfigurationProvider.class).exec();\n        krnl.registerBean(\"bean6\").asClass(Bean6.class).exec();\n\n        Bean5 b5 = krnl.getInstance(Bean5.class);\n        Bean6 b6 = krnl.getInstance(Bean6.class);\n\n        assertEquals(\"yytestxx\", b6.getTestValue());\n        assertEquals(9987l, b5.getValue().longValue());\n\n        ((TestBeanConfigurationProvider) krnl.getInstance(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME)).restoreDefaults(\"bean5\");\n        assertEquals(\"yytestxx\", b6.getTestValue());\n        assertEquals(15l, b5.getValue().longValue());\n\n        ((TestBeanConfigurationProvider) krnl.getInstance(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME)).restoreDefaults(\"bean6\");\n        assertNull(b6.getTestValue());\n        assertEquals(15l, b5.getValue().longValue());\n    }\n\n    @Test\n    public void testCascadeKernels() throws Exception {\n        Kernel krnlParent = new Kernel(\"Parent\");\n        krnlParent.registerBean(\"bean1\").asClass(Bean1.class).exec();\n        krnlParent.registerBean(\"bean40\").asClass(Bean4.class).exportable().exec();\n        krnlParent.registerBean(\"bean41\").asClass(Bean4.class).exec();\n        krnlParent.registerBean(\"bean42\").asClass(Bean4.class).exportable().exec();\n        krnlParent.registerBean(\"bean5\").asClass(Bean5.class).exportable().exec();\n        final Bean5 b5parent = new Bean5();\n        final Bean5 b51parent = new Bean5();\n        krnlParent.registerBean(\"bean5\").asInstance(b5parent).exportable().exec();\n        krnlParent.registerBean(\"bean51\").asInstance(b51parent).exportable().exec();\n\n        Kernel krnlChild1 = new Kernel(\"Child01\");\n        krnlChild1.registerBean(\"bean40\").asClass(Bean4.class).exportable().exec();\n\n        final Bean5 b5ch1 = new Bean5();\n        krnlChild1.registerBean(\"bean5\").asInstance(b5ch1).exportable().exec();\n\n        Kernel krnlChild2 = new Kernel(\"Child02\");\n        krnlChild2.registerBean(\"bean1\").asClass(Bean1.class).exec();\n        krnlChild2.registerBean(\"bean43\").asClass(Bean4.class).exec();\n\n        krnlParent.registerBean(krnlChild1.getName()).asInstance(krnlChild1).exec();\n        krnlParent.registerBean(krnlChild2.getName()).asInstance(krnlChild2).exec();\n\n        Bean1 bean1 = krnlChild2.getInstance(Bean1.class);\n\n        assertEquals(3, bean1.getCollectionOfSpecial().size());\n\n        assertTrue(\"Bean should be located in parent\", krnlChild2.isBeanClassRegistered(\"bean40\"));\n        assertNotNull(\"Bean should be get from parent!\", krnlChild2.getInstance(\"bean40\"));\n        assertEquals(\"Beans from parent and child2 are different!\", (Object) krnlParent.getInstance(\"bean40\"), (Object) krnlChild2.getInstance(\"bean40\"));\n\n        assertTrue(bean1.getCollectionOfSpecial().contains(krnlParent.getInstance(\"bean40\")));\n        assertTrue(bean1.getCollectionOfSpecial().contains(krnlParent.getInstance(\"bean42\")));\n\n        assertEquals(3, bean1.getTableOfSpecial().length);\n\n        DependencyGrapher dg = new DependencyGrapher(krnlParent);\n        System.out.println(dg.getDependencyGraph());\n\n        assertEquals(b5ch1, krnlChild1.getInstance(\"bean5\"));\n        assertEquals(b51parent, krnlChild1.getInstance(\"bean51\"));\n\n        assertNotNull(krnlChild1.getInstance(Bean5.class));\n\n        try {\n            krnlChild1.getInstance(Bean1.class);\n            Assert.fail();\n        } catch (KernelException e) {\n            assertEquals(\"Can't find bean implementing class tigase.kernel.Bean1\", e.getMessage());\n        }\n        try {\n            krnlChild1.getInstance(Bean3.class);\n            Assert.fail();\n        } catch (KernelException e) {\n            assertEquals(\"Can't find bean implementing class tigase.kernel.Bean3\", e.getMessage());\n        }\n\n        try {\n            krnlChild1.getInstance(\"zzz\");\n            Assert.fail();\n        } catch (KernelException e) {\n            assertEquals(\"Unknown bean 'zzz'.\", e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/RegistrarKernelTest.java",
    "content": "package tigase.kernel;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport tigase.kernel.core.DependencyGrapher;\nimport tigase.kernel.core.Kernel;\nimport tigase.kernel.core.RegistrarKernel;\nimport tigase.kernel.module1.Module1Registrar;\nimport tigase.kernel.module1.Module1Service;\nimport tigase.kernel.module2.Module2Registrar;\nimport tigase.kernel.module2.Module2Service;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.logging.ConsoleHandler;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\npublic class RegistrarKernelTest {\n\n\tpublic RegistrarKernelTest() {\n\t\tLogger logger = Logger.getLogger(\"tigase.kernel\");\n\n\t\t// create a ConsoleHandler\n\t\tHandler handler = new ConsoleHandler();\n\t\thandler.setLevel(Level.ALL);\n\t\tlogger.addHandler(handler);\n\t\tlogger.setLevel(Level.ALL);\n\n\t\tif (logger.isLoggable(Level.CONFIG))\n\t\t\tlogger.config(\"Logger successfully initialized\");\n\t}\n\n\t@Test\n\tpublic void test01() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n\n\t\tfinal RegistrarKernel krnl = new RegistrarKernel();\n\t\tkrnl.setName(\"root\");\n\t\tkrnl.setRegistrar(new TestRegistrar());\n\n\t\tkrnl.startSubKernels();\n\n\t\tDependencyGrapher dg = new DependencyGrapher(krnl);\n\t\tSystem.out.println(dg.getDependencyGraph());\n\n\t\tKernel m1k = krnl.getInstance(\"module1#KERNEL\");\n\t\tKernel m2k = krnl.getInstance(\"module2#KERNEL\");\n\n\t\tAssert.assertEquals(krnl.getInstance(\"bean1\"), m1k.getInstance(Module1Service.class).getBean1());\n\t\tAssert.assertEquals(krnl.getInstance(\"bean1\"), m2k.getInstance(Module2Service.class).getBean1());\n\n\t\tAssert.assertEquals((Object)krnl.getInstance(\"Module1Service\"),(Object) m1k.getInstance(\"service\"));\n\t\tAssert.assertEquals((Object)krnl.getInstance(\"Module2Service\"),(Object) m2k.getInstance(\"service\"));\n\n\t}\n\n\tpublic static class TestRegistrar implements Registrar {\n\n\t\t@Override\n\t\tpublic void register(Kernel krnl) {\n\t\t\tkrnl.registerBean(Bean1.class).exportable().exec();\n\t\t\tkrnl.registerBean(\"bean2\").asClass(Bean2.class).exec();\n\t\t\tkrnl.registerBean(\"bean3\").asClass(Bean3.class).exec();\n\t\t\tkrnl.registerBean(\"bean4\").asClass(Bean4.class).exec();\n\t\t\tkrnl.registerBean(\"bean4_1\").asClass(Bean4.class).exec();\n\t\t\tkrnl.registerBean(\"bean5\").asClass(Bean5.class).withFactory(Bean5Factory.class).exec();\n\n\t\t\tkrnl.registerBean(\"module1\").asClass(Module1Registrar.class).exec();\n\t\t\tkrnl.registerBean(\"module2\").asClass(Module2Registrar.class).exec();\n\t\t}\n\n\t\t@Override\n\t\tpublic void start(Kernel krnl) {\n\t\t\tSystem.out.println(((Bean1) krnl.getInstance(\"bean1\")).getBean2());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/Special.java",
    "content": "package tigase.kernel;\n\npublic interface Special {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/module1/Bean11.java",
    "content": "package tigase.kernel.module1;\n\npublic class Bean11 {\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/module1/Module1Registrar.java",
    "content": "package tigase.kernel.module1;\n\nimport tigase.kernel.Registrar;\nimport tigase.kernel.core.Kernel;\n\npublic class Module1Registrar implements Registrar {\n\n\t@Override\n\tpublic void register(Kernel kernel) {\n\t\tkernel.registerBean(\"service\").asClass(Module1Service.class).exec();\n\t\tkernel.registerBean(\"util\").asClass(Bean11.class).exec();\n\t}\n\n\t@Override\n\tpublic void start(Kernel krnl) {\n\t\tSystem.out.println(\"Initializing Module1\");\n\t\t// krnl.getParent().registerBean(\"Module1Service\").asInstance(krnl.getInstance(\"service\")).exec();\n\t\tkrnl.ln(\"service\", krnl.getParent(), \"Module1Service\");\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/module1/Module1Service.java",
    "content": "package tigase.kernel.module1;\n\nimport tigase.kernel.Bean1;\nimport tigase.kernel.beans.Initializable;\nimport tigase.kernel.beans.Inject;\n\npublic class Module1Service implements Initializable {\n\n\t@Inject(nullAllowed = false)\n\tprivate Bean1 bean1;\n\n\t@Inject\n\tprivate Bean11 bean11;\n\n\tpublic Bean1 getBean1() {\n\t\treturn bean1;\n\t}\n\n\tpublic Bean11 getBean11() {\n\t\treturn bean11;\n\t}\n\n\t@Override\n\tpublic void initialize() {\n\t\tSystem.out.println(\"Service1 STARTED!!! WOW!\");\n\t}\n\n\tpublic void setBean1(Bean1 bean1) {\n\t\tSystem.out.println(\"????????::::\" + bean1);\n\t\tthis.bean1 = bean1;\n\t}\n\n\tpublic void setBean11(Bean11 bean11) {\n\t\tthis.bean11 = bean11;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/module2/Module2Registrar.java",
    "content": "package tigase.kernel.module2;\n\nimport tigase.kernel.Registrar;\nimport tigase.kernel.core.Kernel;\n\npublic class Module2Registrar implements Registrar {\n\n\t@Override\n\tpublic void register(Kernel kernel) {\n\t\tkernel.registerBean(\"service\").asClass(Module2Service.class).exec();\n\t}\n\n\t@Override\n\tpublic void start(Kernel krnl) {\n\t\tSystem.out.println(\"Initializing Module2\");\n\t\t// krnl.getParent().registerBean(\"Module2Service\").asInstance(krnl.getInstance(\"service\")).exec();\n\t\tkrnl.ln(\"service\", krnl.getParent(), \"Module2Service\");\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/kernel/module2/Module2Service.java",
    "content": "package tigase.kernel.module2;\n\nimport tigase.kernel.Bean1;\nimport tigase.kernel.beans.Inject;\n\npublic class Module2Service {\n\n\t@Inject(nullAllowed = false)\n\tprivate Bean1 bean1;\n\n\tpublic Bean1 getBean1() {\n\t\treturn bean1;\n\t}\n\n\tpublic void setBean1(Bean1 bean1) {\n\t\tthis.bean1 = bean1;\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/monitor/tasks/UsersDisconnectTaskTest.java",
    "content": "package tigase.monitor.tasks;\n\nimport static org.junit.Assert.*;\nimport static tigase.monitor.tasks.ConnectionsTask.createAlarmEvent;\n\nimport org.junit.Test;\n\nimport tigase.xml.Element;\n\npublic class UsersDisconnectTaskTest {\n\n\t@Test\n\tpublic void testCreateAlarmEvent() throws Exception {\n\t\tElement e = createAlarmEvent(100, 200, 10, 50);\n\t\tassertNotNull(e);\n\t\tassertEquals(100, Integer.parseInt(e.getCData(new String[] { \"UsersDisconnected\", \"disconnections\" })));\n\t\tassertEquals(50f, Float.parseFloat(e.getCData(new String[] { \"UsersDisconnected\", \"disconnectionsPercent\" })), 0);\n\n\t\te = createAlarmEvent(99, 250, 10, 50);\n\t\tassertNotNull(e);\n\t\tassertEquals(151, Integer.parseInt(e.getCData(new String[] { \"UsersDisconnected\", \"disconnections\" })));\n\t\tassertEquals(60.4, Float.parseFloat(e.getCData(new String[] { \"UsersDisconnected\", \"disconnectionsPercent\" })), 0.01);\n\n\t\te = createAlarmEvent(0, 99, 10, 50);\n\t\tassertNotNull(e);\n\t\tassertEquals(99, Integer.parseInt(e.getCData(new String[] { \"UsersDisconnected\", \"disconnections\" })));\n\t\tassertEquals(100.0, Float.parseFloat(e.getCData(new String[] { \"UsersDisconnected\", \"disconnectionsPercent\" })), 0.01);\n\n\t\te = createAlarmEvent(99, 250, 152, 50);\n\t\tassertNull(e);\n\n\t\te = createAlarmEvent(99, 250, 10, 61);\n\t\tassertNull(e);\n\n\t\te = createAlarmEvent(250, 0, 10, 50);\n\t\tassertNull(e);\n\n\t\te = createAlarmEvent(0, 0, 10, 50);\n\t\tassertNull(e);\n\n\t\te = createAlarmEvent(1, 1, 10, 50);\n\t\tassertNull(e);\n\n\t\te = createAlarmEvent(0, 1, 10, 50);\n\t\tassertNull(e);\n\t}\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/PacketTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.server;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\n\nimport tigase.xml.Element;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport org.junit.Before;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author Wojciech Kapcia\n */\npublic class PacketTest {\n\n\tPacket packetInstance;\n\n\tpublic PacketTest() {\n\t}\n\n\t@Before\n\tpublic void setUp() {\n\n\t\tJID from = JID.jidInstanceNS( \"server\" );\n\t\tJID to = JID.jidInstanceNS( \"user\" );\n\n\t\tElement property = new Element( \"property\", new String[] { \"name\", \"value\", \"xmlns\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"some name\", \"some value\", \"namespace\" } );\n\t\tElement iq = Command.createIqCommand( from, to, StanzaType.get, \"myId\", \"node\", Command.DataType.submit );\n\t\tiq.findChild( new String[] { \"iq\", \"command\", \"x\" } ).addChild( property );\n\t\tpacketInstance = Iq.packetInstance( iq, from, to );\n\t\tpacketInstance.getStanzaFrom().getDomain();\n\n\t}\n\n\n\t@Test\n\tpublic void testOkResult_String_int() {\n\n\t\tString includeXML = null;\n\t\tint depth = 5;\n\t\tPacket result = packetInstance.okResult( includeXML, depth );\n\t\tElement property = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\", \"property\" } );\n\n\t\tassertEquals( \"some name\", property.getAttributeStaticStr( \"name\" ) );\n\t\tassertEquals( \"some value\", property.getAttributeStaticStr( \"value\" ) );\n\t\tassertEquals( \"namespace\", property.getAttributeStaticStr( \"xmlns\" ) );\n\t\tassertEquals( null, property.getAttributeStaticStr( \"unknown\" ) );\n\n\t\tdepth = 0;\n\t\tresult = packetInstance.okResult( includeXML, depth );\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\", \"property\" } );\n\n\t\tassertEquals( null, property );\n\n\t\tdepth = 1;\n\t\tresult = packetInstance.okResult( includeXML, depth );\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\" } );\n\t\tassertEquals( null, property );\n\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\" } );\n\t\tassertEquals( \"command\", property.getName() );\n\t\tassertEquals( \"http://jabber.org/protocol/commands\", property.getAttributeStaticStr( \"xmlns\" ) );\n\t\tassertEquals( \"node\", property.getAttributeStaticStr( \"node\" ) );\n\t\tassertEquals( null, property.getAttributeStaticStr( \"unknown\" ) );\n\n\t}\n\n\t@Test\n\tpublic void testOkResult_Element_int() {\n\t\tElement includeXML = null;\n\t\tint depth = 5;\n\t\tPacket result = packetInstance.okResult( includeXML, depth );\n\t\tElement property = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\", \"property\" } );\n\n\t\tassertEquals( \"some name\", property.getAttributeStaticStr( \"name\" ) );\n\t\tassertEquals( \"some value\", property.getAttributeStaticStr( \"value\" ) );\n\t\tassertEquals( \"namespace\", property.getAttributeStaticStr( \"xmlns\" ) );\n\t\tassertEquals( null, property.getAttributeStaticStr( \"unknown\" ) );\n\n\t\tdepth = 0;\n\t\tresult = packetInstance.okResult( includeXML, depth );\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\", \"property\" } );\n\n\t\tassertEquals( null, property );\n\n\t\tdepth = 1;\n\t\tresult = packetInstance.okResult( includeXML, depth );\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\", \"x\" } );\n\t\tassertEquals( null, property );\n\n\t\tproperty = result.getElement().findChild( new String[] { \"iq\", \"command\" } );\n\t\tassertEquals( \"command\", property.getName() );\n\t\tassertEquals( \"http://jabber.org/protocol/commands\", property.getAttributeStaticStr( \"xmlns\" ) );\n\t\tassertEquals( \"node\", property.getAttributeStaticStr( \"node\" ) );\n\t\tassertEquals( null, property.getAttributeStaticStr( \"unknown\" ) );\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/websocket/WebSocketHixie76Test.java",
    "content": "/*\n * WebSocketHixie76Test.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport junit.framework.TestCase;\nimport org.junit.Assert;\nimport org.junit.Test;\n\n/**\n *\n * @author andrzej\n */\npublic class WebSocketHixie76Test extends TestCase {\n\t\n\tprivate WebSocketHixie76 impl;\n\t\n\t@Override\n\tprotected void setUp() throws Exception {\n\t\timpl = new WebSocketHixie76();\n\t}\n\n\t@Override\n\tprotected void tearDown() throws Exception {\n\t\timpl = null;\n\t}\n\t\n\t@Test\n\tpublic void testFrameEncodingDecoding() throws IOException {\n\t\tString input = \"<test-data><subdata/></test-data>\";\n\t\tByteBuffer buf = ByteBuffer.wrap(input.getBytes());\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(1024);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t};\n\t\timpl.encodeFrameAndWrite(io, buf);\n\t\ttmp.flip();\n\t\tByteBuffer decoded = impl.decodeFrame(io, tmp);\n\t\tAssert.assertArrayEquals(\"Data before encoding do not match data after decoding\", input.getBytes(), decoded.array());\n\t}\n\t\n\t@Test\n\tpublic void testHandshakeOK() throws NoSuchAlgorithmException, IOException {\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(2048);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getLocalPort() {\n\t\t\t\treturn 80;\n\t\t\t}\n\n\t\t};\t\t\n\t\tMap<String,String> params = new HashMap<String,String>();\n\t\tparams.put(\"Sec-WebSocket-Key1\", \"1C2J899_05  6  !  M 9    ^4\");\n\t\tparams.put(\"Sec-WebSocket-Key2\", \"23 2ff0M_E0#.454X23\");\n\t\tparams.put(\"Sec-WebSocket-Protocol\", \"xmpp\");\n\t\tbyte[] bytes = new byte[10];\n\t\tbytes[0] = '\\r';\n\t\tbytes[1] = '\\n';\n\t\tAssert.assertTrue(\"Handshake failed\", impl.handshake(io, params, bytes));\n\t}\n\t\n\t@Test\n\tpublic void testHandshakeFail() throws NoSuchAlgorithmException, IOException {\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(2048);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getLocalPort() {\n\t\t\t\treturn 80;\n\t\t\t}\n\n\t\t};\t\t\n\t\tMap<String,String> params = new HashMap<String,String>();\n\t\tparams.put(\"Sec-WebSocket-Version\", \"13\");\n\t\tparams.put(\"Sec-WebSocket-Protocol\", \"xmpp\");\t\t\n\t\tbyte[] bytes = new byte[10];\n\t\tbytes[0] = '\\r';\n\t\tbytes[1] = '\\n';\n\t\tAssert.assertFalse(\"Handshake succeeded\", impl.handshake(io, params, bytes));\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/websocket/WebSocketHybiTest.java",
    "content": "/*\n * WebSocketHybiTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport junit.framework.TestCase;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n *\n * @author andrzej\n */\npublic class WebSocketHybiTest extends TestCase {\n\t\n\tprivate WebSocketHybi impl;\n\t\n\t@Override\n\tprotected void setUp() throws Exception {\n\t\timpl = new WebSocketHybi();\n\t}\n\n\t@Override\n\tprotected void tearDown() throws Exception {\n\t\timpl = null;\n\t}\n\n\t@Test\n\tpublic void testFrameEncodingDecoding() throws IOException {\n\t\tString input = \"<test-data><subdata/></test-data>\";\n\t\tByteBuffer buf = ByteBuffer.wrap(input.getBytes());\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(1024);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t};\n\t\tio.maskingKey = new byte[4];\n\t\timpl.encodeFrameAndWrite(io, buf);\n\t\ttmp.flip();\n\t\tByteBuffer tmp1 = maskFrame(tmp);\n\t\tByteBuffer decoded = impl.decodeFrame(io, tmp1);\n\t\tAssert.assertArrayEquals(\"Data before encoding do not match data after decoding\", input.getBytes(), decoded.array());\n\t}\n\n\tprivate ByteBuffer maskFrame(ByteBuffer data) {\n\t\tByteBuffer tmp = ByteBuffer.allocate(1024);\n\t\tbyte[] header = new byte[2];\n\t\tdata.get(header);\n\t\theader[header.length - 1] = (byte) (header[header.length - 1] | 0x80);\n\t\ttmp.put(header);\n\t\tbyte[] mask = { 0x00, 0x00, 0x00, 0x00 };\n\t\ttmp.put(mask);\n\t\tbyte b;\n\t\twhile (data.hasRemaining()) {\n\t\t\tb = data.get();\n\t\t\tb = (byte) (b ^ 0x00);\n\t\t\ttmp.put(b);\n\t\t}\n\t\ttmp.flip();\n\t\treturn tmp;\n\t}\n\n\n\t@Test\n\tpublic void testHandshakeFail() throws NoSuchAlgorithmException, IOException {\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(2048);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getLocalPort() {\n\t\t\t\treturn 80;\n\t\t\t}\n\n\t\t};\n\t\tMap<String,String> params = new HashMap<String,String>();\n\t\tparams.put(\"Sec-WebSocket-Key1\", \"1C2J899_05  6  !  M 9    ^4\");\n\t\tparams.put(\"Sec-WebSocket-Key2\", \"23 2ff0M_E0#.454X23\");\n\t\tparams.put(\"Sec-WebSocket-Protocol\", \"xmpp\");\n\t\tbyte[] bytes = new byte[10];\n\t\tbytes[0] = '\\r';\n\t\tbytes[1] = '\\n';\n\t\tAssert.assertFalse(\"Handshake succeeded\", impl.handshake(io, params, bytes));\n\t}\n\t\n\t@Test\n\tpublic void testHandshakeOK() throws NoSuchAlgorithmException, IOException {\n\t\tfinal ByteBuffer tmp = ByteBuffer.allocate(2048);\n\t\tWebSocketXMPPIOService<Object> io = new WebSocketXMPPIOService<Object>(new WebSocketProtocolIfc[]{ new WebSocketHixie76() }) {\n\n\t\t\t@Override\n\t\t\tprotected void writeBytes(ByteBuffer data) {\n\t\t\t\ttmp.put(data);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getLocalPort() {\n\t\t\t\treturn 80;\n\t\t\t}\n\n\t\t};\t\t\n\t\tMap<String,String> params = new HashMap<String,String>();\n\t\tparams.put(\"Sec-WebSocket-Version\", \"13\");\n\t\tparams.put(\"Sec-WebSocket-Key\", \"some random data as a key\");\n\t\tparams.put(\"Sec-WebSocket-Protocol\", \"xmpp\");\n\t\tbyte[] bytes = new byte[10];\n\t\tbytes[0] = '\\r';\n\t\tbytes[1] = '\\n';\n\t\tAssert.assertTrue(\"Handshake failed\", impl.handshake(io, params, bytes));\n\t}\t\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/websocket/WebSocketXMPPIOServiceTest.java",
    "content": "/*\n * WebSocketXMPPIOServiceTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.websocket;\n\nimport junit.framework.TestCase;\nimport org.junit.Test;\n\nimport java.io.UnsupportedEncodingException;\nimport java.util.*;\n\n/**\n * Created by andrzej on 18.07.2016.\n */\npublic class WebSocketXMPPIOServiceTest extends TestCase {\n\n\tprivate HashMap<String, String> headers;\n\tprivate WebSocketXMPPIOService service;\n\n\t@Override\n\tprotected void setUp() throws Exception {\n\t\tservice = new WebSocketXMPPIOService(new WebSocketProtocolIfc[0]);\n\t\theaders = new HashMap<String, String>();\n\t\theaders.put(\"Connection\", \"Upgrade\");\n\t\theaders.put(\"Host\", \"test.example.com:5291\");\n\t\theaders.put(\"Origin\", \"test.example.com:5291\");\n\t\theaders.put(\"Sec-WebSocket-Key\", \"JRqGsrthbnle6zl8sFQPpQ==\");\n\t\theaders.put(\"Sec-WebSocket-Protocol\", \"xmpp\");\n\t\theaders.put(\"Sec-WebSocket-Version\", \"13\");\n\t\theaders.put(\"Upgrade\", \"websocket\");\n\t}\n\n\t@Override\n\tprotected void tearDown() throws Exception {\n\t\tservice = null;\n\t}\n\n\t@Test\n\tpublic void testHttpHeadersParsingWithSpaces() throws UnsupportedEncodingException {\n\t\tbyte[] data = prepareHTTPRequest(headers, true);\n\n\t\tMap<String, String> parsedHeaders = new HashMap<>();\n\t\tservice.parseHttpHeaders(data, parsedHeaders);\n\n\t\tassertMaps(headers, parsedHeaders);\n\t}\n\n\t@Test\n\tpublic void testHttpHeadersParsingWithoutSpaces() throws UnsupportedEncodingException {\n\t\tbyte[] data = prepareHTTPRequest(headers, false);\n\n\t\tMap<String, String> parsedHeaders = new HashMap<>();\n\t\tservice.parseHttpHeaders(data, parsedHeaders);\n\n\t\tassertMaps(headers, parsedHeaders);\n\t}\n\n\tprivate void assertMaps(Map<String, String> expected, Map<String, String> actual) {\n\t\tList<String> expectedKeys = new ArrayList<>(expected.keySet());\n\t\tList<String> actualKeys = new ArrayList<>(actual.keySet());\n\n\t\tCollections.sort(expectedKeys);\n\t\tCollections.sort(actualKeys);\n\n\t\tassertEquals(expectedKeys, actualKeys);\n\n\t\tfor (String key : expectedKeys) {\n\t\t\tassertEquals(expected.get(key), actual.get(key));\n\t\t}\n\t}\n\n\tprivate byte[] prepareHTTPRequest(Map<String,String> headers, boolean useSpaces) throws UnsupportedEncodingException {\n\t\tStringBuilder sb = new StringBuilder(\"GET HTTP/1.1\\r\\n\");\n\t\tfor (Map.Entry<String,String> e : headers.entrySet()) {\n\t\t\tsb.append(e.getKey());\n\t\t\tsb.append(':');\n\t\t\tif (useSpaces) {\n\t\t\t\tsb.append(' ');\n\t\t\t}\n\t\t\tsb.append(e.getValue()).append(\"\\r\\n\");\n\t\t}\n\t\tsb.append(\"\\r\\n\");\n\t\treturn sb.toString().getBytes(\"UTF-8\");\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/xmppclient/StreamManagementIOProcessorTest.java",
    "content": "/*\n * StreamManagementIOProcessorTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppclient;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport junit.framework.TestCase;\nimport static junit.framework.TestCase.assertEquals;\nimport org.junit.Test;\nimport tigase.server.Message;\nimport tigase.server.Packet;\nimport tigase.server.xmppclient.StreamManagementIOProcessor.OutQueue;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\n/**\n * Test class for StreamManagementIOProcessor class.\n * \n * Currently tests if acking works correctly for overflow in OutQueue counter. \n * \n * @author andrzej\n */\npublic class StreamManagementIOProcessorTest extends TestCase {\n\t\n\tprivate static final String[] DELAY_PATH = { Message.ELEM_NAME, \"delay\" };\n\tprivate static final String DELAY_XMLNS = \"urn:xmpp:delay\";\n\t\t\n\t@Test\n\tpublic void testValidateOutQueueOverflowToZero() {\n\t\tOutQueue queue = new OutQueue();\n\t\tint start = Integer.MAX_VALUE-10;\n\t\tqueue.setCounter(start-1);\n\t\t\n\t\tint packetToAck = start+5;\n\t\t\n\t\tfor (int i=start; i<=Integer.MAX_VALUE && i > 0; i++) {\n\t\t\ttry {\n\t\t\t\tPacket p = Packet.packetInstance(new Element(\"message\", new String[] { \"id\", \"from\", \"to\" },\n\t\t\t\t\t\tnew String[] { String.valueOf(i), \"from@example.com\", \"to@example.com\" }));\n\t\t\t\tqueue.append(p);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t}\n\t\t}\n\n\t\tqueue.ack(packetToAck);\n\t\t\n\t\tint size = queue.waitingForAck();\n\t\tassertEquals(5, size);\n\t\tassertEquals(queue.getQueue().peek().getPacketWithStamp().getElement().getAttributeStaticStr(\"id\"), String.valueOf(packetToAck+1));\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) -> \n\t\t\t\tassertTrue(e.getPacketWithStamp().isXMLNSStaticStr(DELAY_PATH, DELAY_XMLNS))\n\t\t);\n\t}\t\t\n\n\t@Test\n\tpublic void testValidateOutQueueOverflowOverZero() {\n\t\tOutQueue queue = new OutQueue();\n\t\tint start = Integer.MAX_VALUE-5;\n\t\tqueue.setCounter(start-1);\n\t\tint packetToAck = start + 3;\n\t\t\n\t\tfor (int i=start; i<=Integer.MAX_VALUE && i > 0; i++) {\n\t\t\ttry {\n\t\t\t\tPacket p = Packet.packetInstance(new Element(\"message\", new String[] { \"id\", \"from\", \"to\" },\n\t\t\t\t\t\tnew String[] { String.valueOf(i), \"from@example.com\", \"to@example.com\" }));\n\t\t\t\tqueue.append(p);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t}\n\t\t}\n\n\t\tfor (int i=0; i<3; i++) {\n\t\t\ttry {\n\t\t\t\tPacket p = Packet.packetInstance(new Element(\"message\", new String[] { \"id\", \"from\", \"to\" },\n\t\t\t\t\t\tnew String[] { String.valueOf(i), \"from@example.com\", \"to@example.com\" }));\n\t\t\t\tqueue.append(p);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t}\n\t\t}\n\n\t\tqueue.ack(packetToAck);\n\t\t\n\t\tint size = queue.waitingForAck();\n\t\tassertEquals(5, size);\n\t\tassertEquals(queue.getQueue().peek().getPacketWithStamp().getElement().getAttributeStaticStr(\"id\"), String.valueOf(packetToAck+1));\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) ->\n\t\t\t\tassertTrue(e.getPacketWithStamp().isXMLNSStaticStr(DELAY_PATH, DELAY_XMLNS))\n\t\t);\n\t}\n\t\n\t@Test\n\tpublic void testNoDelayForIq() {\n\t\tOutQueue queue = new OutQueue();\n\t\tint start = Integer.MAX_VALUE-10;\n\t\tqueue.setCounter(start-1);\n\t\t\n\t\tint packetToAck = start+5;\n\t\t\n\t\tfor (int i=start; i<=Integer.MAX_VALUE && i > 0; i++) {\n\t\t\ttry {\n\t\t\t\tPacket p = Packet.packetInstance(new Element(\"iq\", new String[] { \"id\", \"from\", \"to\" },\n\t\t\t\t\t\tnew String[] { String.valueOf(i), \"from@example.com\", \"to@example.com\" }));\n\t\t\t\tqueue.append(p);\n\t\t\t} catch (TigaseStringprepException ex) {\n\t\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t\t}\n\t\t}\n\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) ->\n\t\t\t\tassertFalse(e.getPacketWithStamp().isXMLNSStaticStr(new String[] { \"iq\", \"delay\" }, DELAY_XMLNS))\n\t\t);\n\t}\n\t\n\t@Test\n\tpublic void testForceDelayForResumption() {\n\t\tOutQueue queue = new OutQueue();\n\t\t\n\t\ttry {\n\t\t\tPacket p = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\t\tnew Element(\"delay\", new String[]{\"xmlns\", \"stamp\"}, new String[]{DELAY_XMLNS, \"2015-07-10T00:00:00.000Z\"})\n\t\t\t}, new String[]{\"id\", \"from\", \"to\"},\n\t\t\t\t\tnew String[]{String.valueOf(\"id-1\"), \"from@example.com\", \"to@example.com\"}));\n\t\t\tqueue.append(p);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t\t\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) ->\n\t\t\t\tassertEquals(1, e.getPacketWithStamp().getElement().findChildren((Element el) -> el.getName() == \"delay\").size())\n\t\t);\t\t\n\n\t\tqueue.getQueue().clear();\n\t\t\n\t\tqueue.setResumptionEnabled(true);\n\t\t\n\t\ttry {\n\t\t\tPacket p = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\t\tnew Element(\"delay\", new String[]{\"xmlns\", \"stamp\"}, new String[]{DELAY_XMLNS, \"2015-07-10T00:00:00.000Z\"})\n\t\t\t}, new String[]{\"id\", \"from\", \"to\"},\n\t\t\t\t\tnew String[]{String.valueOf(\"id-1\"), \"from@example.com\", \"to@example.com\"}));\n\t\t\tqueue.append(p);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t\t\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) ->\n\t\t\t\tassertEquals(1, e.getPacketWithStamp().getElement().findChildren((Element el) -> el.getName() == \"delay\").size())\n\t\t);\t\t\n\n\t\tqueue.getQueue().clear();\n\t\t\n\t\ttry {\n\t\t\tPacket p = Packet.packetInstance(new Element(\"iq\", new String[]{\"id\", \"from\", \"to\"},\n\t\t\t\t\tnew String[]{String.valueOf(\"id-2\"), \"from@example.com\", \"to@example.com\"}));\n\t\t\tqueue.append(p);\n\t\t} catch (TigaseStringprepException ex) {\n\t\t\tLogger.getLogger(StreamManagementIOProcessorTest.class.getName()).log(Level.SEVERE, null, ex);\n\t\t}\n\t\t\n\t\tqueue.getQueue().forEach((OutQueue.Entry e) ->\n\t\t\t\tassertFalse(e.getPacketWithStamp().isXMLNSStaticStr(new String[] { \"iq\", \"delay\" }, DELAY_XMLNS))\n\t\t);\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/xmppserver/S2SConnectionManagerDomainServerNameMapperTest.java",
    "content": "/*\n * S2SConnectionManagerDomainServerNameMapperTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppserver;\n\nimport junit.framework.TestCase;\nimport org.junit.Test;\nimport tigase.server.xmppserver.S2SConnectionManager.DomainServerNameMapper;\n\n/**\n *\n * @author andrzej\n */\npublic class S2SConnectionManagerDomainServerNameMapperTest extends TestCase {\n\t\n\t@Test\n\tpublic void testSortingOfMappings() {\n\t\tDomainServerNameMapper mapper = new DomainServerNameMapper();\n\t\t\n\t\t// adding mapping entries\n\t\tmapper.addEntry(\"*\", \"test1\");\n\t\tmapper.addEntry(\"*.local\", \"test2\");\n\t\tmapper.addEntry(\"*.test\", \"test3\");\n\t\tmapper.addEntry(\"*.test.local\", \"test4\");\n\t\tmapper.addEntry(\"test\", \"test5\");\n\t\tmapper.addEntry(\"local\", \"test6\");\n\t\tmapper.addEntry(\"test1.test\", \"test7\");\n\t\tmapper.addEntry(\"test1.test.local\", \"test8\");\n\t\t\n\t\t//System.out.println(mapper.toString());\n\t\t\n\t\t// checking assertions to make sure that due to sorting of mappings\n\t\t// mappings are used in proper order\n\t\tassertEquals(\"test1\", mapper.getServerNameForDomain(\"tigase.org\"));\n\t\tassertEquals(\"test4\", mapper.getServerNameForDomain(\"test.local\"));\n\t\tassertEquals(\"test2\", mapper.getServerNameForDomain(\"test1.local\"));\n\t\tassertEquals(\"test5\", mapper.getServerNameForDomain(\"test\"));\n\t\tassertEquals(\"test6\", mapper.getServerNameForDomain(\"local\"));\n\t\tassertEquals(\"test3\", mapper.getServerNameForDomain(\"test.test\"));\n\t\tassertEquals(\"test4\", mapper.getServerNameForDomain(\"test.test.local\"));\n\t\tassertEquals(\"test7\", mapper.getServerNameForDomain(\"test1.test\"));\n\t\tassertEquals(\"test8\", mapper.getServerNameForDomain(\"test1.test.local\"));\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/server/xmppserver/proc/DialbackTest.java",
    "content": "/*\n * DialbackTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.server.xmppserver.proc;\n\nimport java.util.ArrayDeque;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\nimport junit.framework.TestCase;\nimport org.junit.Test;\nimport static tigase.net.IOService.PORT_TYPE_PROP_KEY;\nimport tigase.server.Packet;\nimport tigase.server.xmppserver.CID;\nimport tigase.server.xmppserver.CIDConnections;\nimport tigase.server.xmppserver.LocalhostException;\nimport tigase.server.xmppserver.NotLocalhostException;\nimport tigase.server.xmppserver.S2SConnectionHandlerIfc;\nimport tigase.server.xmppserver.S2SConnectionManager;\nimport tigase.server.xmppserver.S2SIOService;\nimport tigase.server.xmppserver.S2SRandomSelector;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.StanzaType;\n\n/**\n *\n * @author andrzej\n */\npublic class DialbackTest extends TestCase {\n\t\n\tprivate Dialback dialback = new Dialback() {\n\n\t\t@Override\n\t\tpublic boolean skipTLSForHost(String hostname) {\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean wasVerifyRequested(S2SIOService serv, String domain) {\n\t\t\treturn true;\n\t\t}\n\t\t\n\t};\n\tprivate S2SConnectionHandlerIfc<S2SIOService> handler = null;\n\t\n\tprivate String remote1 = \"remote1.com\";\n\tprivate String remote2 = \"remote2.com\";\n\tprivate String local = \"local.com\";\n\t\n\t@Test\n\tpublic void testAuthorizationForSingleDomain() throws TigaseStringprepException {\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\thandler = new S2SConnectionHandlerImpl(results);\n\t\tdialback.init(handler, new HashMap());\n\t\t\n\t\tString key = UUID.randomUUID().toString();\n\t\t\n\t\tS2SIOService serv = new S2SIOService();\n\t\tserv.setSessionId(\"sess-id-1\");\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(PORT_TYPE_PROP_KEY, \"accept\");\n\t\tserv.setSessionData(props);\n\n\t\tPacket p = null;\n\t\t\n\t\tElement resultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote1);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tPacket r = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"valid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.valid && remote1.equals(p.getStanzaTo().getDomain()));\n\t\t\n\t\tserv.getCIDs().forEach((CID cid) -> assertEquals(remote1, cid.getRemoteHost()));\n\t}\n\t\n\t@Test\n\tpublic void testAuthorizationForSingleDomainFailure() throws TigaseStringprepException {\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\thandler = new S2SConnectionHandlerImpl(results);\n\t\tdialback.init(handler, new HashMap());\n\t\t\n\t\tString key = UUID.randomUUID().toString();\n\t\t\n\t\tS2SIOService serv = new S2SIOService();\n\t\tserv.setSessionId(\"sess-id-1\");\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(PORT_TYPE_PROP_KEY, \"accept\");\n\t\tserv.setSessionData(props);\n\n\t\tPacket p = null;\n\t\t\n\t\tElement resultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote1);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tPacket r = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"invalid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.invalid && remote1.equals(p.getStanzaTo().getDomain()));\n\t\t\n\t\tserv.getCIDs().forEach((CID cid) -> assertNotSame(remote1, cid.getRemoteHost()));\n\t}\t\n\t\n\t@Test\n\tpublic void testAuthorizationWithMultiplexing() throws TigaseStringprepException {\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\thandler = new S2SConnectionHandlerImpl(results);\n\t\tdialback.init(handler, new HashMap());\n\t\t\n\t\tString key = UUID.randomUUID().toString();\n\t\t\n\t\tS2SIOService serv = new S2SIOService();\n\t\tserv.setSessionId(\"sess-id-1\");\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(PORT_TYPE_PROP_KEY, \"accept\");\n\t\tserv.setSessionData(props);\n\n\t\tPacket p = null;\n\t\t\n\t\tElement resultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote1);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tPacket r = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"valid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.valid && remote1.equals(p.getStanzaTo().getDomain()));\n\t\tserv.getCIDs().forEach((CID cid) -> assertEquals(remote1, cid.getRemoteHost()));\n\t\t\n\t\tkey = UUID.randomUUID().toString();\n\t\t\n\t\tresultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote2);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tr = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"valid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\t\t\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.valid && remote2.equals(p.getStanzaTo().getDomain()));\n\t\tassertTrue(serv.getCIDs().stream().anyMatch((CID cid) -> remote1.equals(cid.getRemoteHost())));\n\t\tassertTrue(serv.getCIDs().stream().anyMatch((CID cid) -> remote2.equals(cid.getRemoteHost())));\n\t}\n\n\t@Test\n\tpublic void testAuthorizationWithMultiplexingWithFailure() throws TigaseStringprepException {\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\thandler = new S2SConnectionHandlerImpl(results);\n\t\tdialback.init(handler, new HashMap());\n\t\t\n\t\tString key = UUID.randomUUID().toString();\n\t\t\n\t\tS2SIOService serv = new S2SIOService();\n\t\tserv.setSessionId(\"sess-id-1\");\n\t\tMap<String,Object> props = new HashMap<>();\n\t\tprops.put(PORT_TYPE_PROP_KEY, \"accept\");\n\t\tserv.setSessionData(props);\n\n\t\tPacket p = null;\n\t\t\n\t\tElement resultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote1);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tPacket r = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"valid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.valid && remote1.equals(p.getStanzaTo().getDomain()));\n\t\tserv.getCIDs().forEach((CID cid) -> assertEquals(remote1, cid.getRemoteHost()));\n\t\t\n\t\tkey = UUID.randomUUID().toString();\n\t\t\n\t\tresultEl = new Element(\"db:result\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"from\", remote2);\n\t\tresultEl.setAttribute(\"to\", local);\n\t\tresultEl.setCData(key);\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\n\t\t\n\t\tr = results.poll();\n\t\tresultEl = new Element(\"db:verify\");\n\t\tresultEl.setXMLNS(Dialback.XMLNS_DB_VAL);\n\t\tresultEl.setAttribute(\"id\", r.getAttributeStaticStr(\"id\"));\n\t\tresultEl.setAttribute(\"from\", r.getAttributeStaticStr(\"to\"));\n\t\tresultEl.setAttribute(\"to\", r.getAttributeStaticStr(\"from\"));\n\t\tresultEl.setAttribute(\"type\", \"invalid\");\n\t\tp = Packet.packetInstance(resultEl);\n\t\tdialback.process(p, serv, results);\t\t\n\t\t\n\t\tp = results.poll();\n\t\tassertTrue(p.getType() == StanzaType.invalid && remote2.equals(p.getStanzaTo().getDomain()));\n\t\tassertTrue(serv.getCIDs().stream().anyMatch((CID cid) -> remote1.equals(cid.getRemoteHost())));\n\t\tassertTrue(serv.getCIDs().stream().allMatch((CID cid) -> !remote2.equals(cid.getRemoteHost())));\n\t}\n\n\t\n\tprivate static class S2SConnectionHandlerImpl extends S2SConnectionManager {\n\n\t\tprivate Queue<Packet> results;\n\t\t\n\t\tpublic S2SConnectionHandlerImpl(Queue<Packet> results) {\n\t\t\tthis.results = results;\n\t\t}\n\n\t\t@Override\n\t\tprotected CIDConnections createNewCIDConnections(CID cid)\n\t\t\t\t\tthrows NotLocalhostException, LocalhostException {\n\n\t\t\tCIDConnections conns =  new CIDConnections(cid, this, new S2SRandomSelector(),\n\t\t\t\t\t\t5, 5, 5,\n\t\t\t\t\t\t5000) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void sendHandshakingOnly(Packet verify_req) {\n\t\t\t\t\t\tresults.offer(verify_req);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic boolean sendControlPacket(String sessionId, Packet packet) {\n\t\t\t\t\t\treturn results.offer(packet);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void sendPacket(Packet packet) {\n\t\t\t\t\t\tresults.offer(packet);\n\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t};\n\t\t\tcidConnections.put(cid, conns);\n\t\t\treturn conns;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isTlsRequired(String domain) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/tests/SlowTest.java",
    "content": "package tigase.tests;\n\n/**\n * Interface used in annotation as a category to mark long running JUnit tests,\n * so they can be run on server when snapshot is created and not during\n * normal compilation in development environment\n * \n * @author andrzej\n */\npublic interface SlowTest {}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/util/DataTypesTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.util;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author Wojtek\n */\npublic class DataTypesTest {\n\n\t@Test\n\tpublic void testParseNum() {\n\n\t\tassertEquals( new Long( 262144L ), Long.valueOf( Integer.class.cast( DataTypes.parseNum( \"256k\", Integer.class, 1 ) ) ) );\n\t\tassertEquals( new Long( 262144L ), Long.class.cast( DataTypes.parseNum( \"256k\", Long.class, 1L ) ) );\n\t\tassertEquals( new Double( 670720.0D ), Double.class.cast( DataTypes.parseNum( \"655k\", Double.class, 1D ) ) );\n\t\tassertEquals( new Double( 262144F ), Double.valueOf( Float.class.cast( DataTypes.parseNum( \"256k\", Float.class, 1F ) ) ) );\n\t\tassertEquals( new Long( 25 ), Long.valueOf( (long) DataTypes.parseNum( \"25\", Short.class, Short.valueOf( \"1\" ) ) ) );\n\t\tassertEquals( new Long( 25 ), Long.valueOf( Byte.class.cast( DataTypes.parseNum( \"25\", Byte.class, Byte.valueOf( \"1\" ) ) ) ) );\n\t}\n\n\t@Test\n\tpublic void testParseSizeInt() {\n\t\tSystem.out.println( \"parseSizeInt\" );\n\t\tassertEquals( 1, DataTypes.parseSizeInt( \"1\", 1 ) );\n\t\tassertEquals( 1024, DataTypes.parseSizeInt( \"1k\", 1 ) );\n\t\tassertEquals( 1024 * 1024, DataTypes.parseSizeInt( \"1m\", 1 ) );\n\t\tassertEquals( 1024 * 1024 * 1024, DataTypes.parseSizeInt( \"1g\", 1 ) );\n\t\tassertEquals( 1, DataTypes.parseSizeInt( \"fail\", 1 ) );\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/vhosts/VHostItemTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts;\n\nimport tigase.vhosts.filter.DomainFilterPolicy;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.Arrays;\n\nimport junit.framework.TestCase;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport tigase.xmpp.JID;\n\n/**\n *\n * @author Wojciech Kapcia <wojciech.kapcia@tigase.org>\n */\npublic class VHostItemTest extends TestCase {\n\n\tpublic void testVHostItem() throws TigaseStringprepException {\n\t\tassertEquals( new VHostItem( \"lowercase.com\" ), new VHostItem( \"lowercase.com\" ) );\n\t\tassertEquals( new VHostItem( \"CAPITAL.COM\" ), new VHostItem( \"capital.com\" ) );\n\t\tassertNotSame( new VHostItem( \"CAPITAL.COM\" ), new VHostItem( \"lowercase.com\" ) );\n\n\t}\n\n\tpublic void testVHostDomainPolicy() throws TigaseStringprepException {\n\n\t\tElement el;\n\t\tVHostItem vHostItem;\n\n\t\tvHostItem = new VHostItem();\n\t\tvHostItem.initFromPropertyString( \"domain1:domain-filter=LOCAL:max-users=1000\" );\n\t\tassertEquals( DomainFilterPolicy.LOCAL, vHostItem.getDomainFilter() );\n\t\tassertTrue( vHostItem.getDomainFilterDomains() == null );\n\n\t\tvHostItem = new VHostItem();\n\t\tvHostItem.initFromPropertyString( \"domain1:domain-filter=LIST=domain1;domain2;domain3:max-users=1000\" );\n\t\tassertEquals( DomainFilterPolicy.LIST, vHostItem.getDomainFilter() );\n\t\tassertTrue( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain1\" ) );\n\t\tassertTrue( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain3\" ) );\n\t\tassertFalse( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain5\" ) );\n\n\t\tvHostItem = new VHostItem();\n\t\tel = new Element( \"vhost\",\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"hostname\", \"domain-filter\", \"domain-filter-domains\" },\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"domain3\", \"ALL\", \"domain1;domain2;domain3\" }\n\t\t);\n\n\t\tvHostItem.initFromElement( el );\n\n\t\tassertEquals( DomainFilterPolicy.ALL, vHostItem.getDomainFilter() );\n\t\tassertTrue( vHostItem.getDomainFilterDomains() == null );\n\t\tassertTrue( vHostItem.toPropertyString().contains( \"domain-filter=ALL\" ) );\n\n\t\tvHostItem = new VHostItem();\n\t\tel = new Element( \"vhost\",\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"hostname\", \"domain-filter\", \"domain-filter-domains\" },\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"domain3\", \"BLACKLIST\", \"domain1;domain2;domain3\" }\n\t\t);\n\n\t\tvHostItem.initFromElement( el );\n\t\tassertEquals( DomainFilterPolicy.BLACKLIST, vHostItem.getDomainFilter() );\n\t\tassertTrue( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain1\" ) );\n\t\tassertTrue( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain3\" ) );\n\t\tassertFalse( Arrays.asList( vHostItem.getDomainFilterDomains() ).contains( \"domain5\" ) );\n\t\tassertTrue( vHostItem.toPropertyString().contains( \"domain-filter=BLACKLIST\" ) );\n\n\n\t\tvHostItem = new VHostItem();\n\t\tel = new Element( \"vhost\",\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"hostname\", \"domain-filter\", \"domain-filter-domains\" },\n\t\t\t\t\t\t\t\t\t\t\tnew String[] { \"domain3\", \"CUSTOM\", \"4,deny,all;1,allow,self;3,allow,jid,pubsub@test.com;2,allow,jid,admin@test2.com\" }\n\t\t);\n\n\t\tvHostItem.initFromElement( el );\n\t\tassertEquals( DomainFilterPolicy.CUSTOM, vHostItem.getDomainFilter() );\n\t\tassertTrue( vHostItem.toPropertyString().contains( \"domain-filter=CUSTOM=4,deny,all;1,allow,self;3,allow,jid,pubsub@test.com;2,allow,jid,admin@test2.com\" ) );\n\n\n\n\t\tvHostItem = new VHostItem();\n\t\tvHostItem.initFromPropertyString(\"domain1:domain-filter=CUSTOM=4|deny|all;1|allow|self;3|allow|jid|pubsub@test.com;2|allow|jid|admin@test2.com\" );\n\t\tassertEquals( DomainFilterPolicy.CUSTOM, vHostItem.getDomainFilter() );\n\t\tfinal String toPropertyString = vHostItem.toPropertyString();\n\t\tSystem.out.println( \"to property string: \" + toPropertyString );\n\t\tassertTrue(\"different\" , toPropertyString.contains( \"domain-filter=CUSTOM=4|deny|all;1|allow|self;3|allow|jid|pubsub@test.com;2|allow|jid|admin@test2.com\" )  );\n\n\n\n\n\t}\n\n\tpublic void testInitFromPropertyString() throws TigaseStringprepException {\n\t\tJID jid = JID.jidInstanceNS(\"comp1@example.com\");\n\t\tJID notTrusted = JID.jidInstanceNS(\"not-trusted@example.com\");\n\t\t\n\t\tVHostItem item = new VHostItem();\n\t\titem.toString();\n\t\tAssert.assertNull(item.getTrustedJIDs());\n\t\tAssert.assertFalse(item.isTrustedJID(jid));\n\t\t\n\t\titem.initFromPropertyString(\"example.com:trusted-jids=comp1@example.com\");\n\t\tAssert.assertArrayEquals(new String[] { jid.toString() }, item.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(jid));\n\t\tAssert.assertTrue(item.isTrustedJID(jid.copyWithResource(\"test\")));\n\t\tAssert.assertFalse(item.isTrustedJID(notTrusted));\n\t\t\n\t\titem = new VHostItem();\n\t\titem.initFromPropertyString(\"example.com:trusted-jids=comp1@example.com,comp2@example.com\");\n\t\tAssert.assertArrayEquals(new String[] { jid.toString(), \"comp2@example.com\" }, item.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(jid));\n\t\tAssert.assertTrue(item.isTrustedJID(jid.copyWithResource(\"test\")));\n\t\tAssert.assertFalse(item.isTrustedJID(notTrusted));\n\t\t\n\t\titem = new VHostItem();\n\t\titem.initFromPropertyString(\"example.com:trusted-jids=comp1@example.com;comp2@example.com\");\n\t\tAssert.assertArrayEquals(new String[] { jid.toString(), \"comp2@example.com\" }, item.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(jid));\n\t\tAssert.assertTrue(item.isTrustedJID(jid.copyWithResource(\"test\")));\n\t\tAssert.assertFalse(item.isTrustedJID(notTrusted));\n\t\t\n\t\titem = new VHostItem();\n\t\titem.toString();\n\t\titem.initFromPropertyString(\"example.com:trusted-jids=example.com\");\n\t\titem.toString();\n\t\tAssert.assertArrayEquals(new String[] { \"example.com\" }, item.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(jid));\n\t\tAssert.assertTrue(item.isTrustedJID(jid.copyWithResource(\"test\")));\n\t\tAssert.assertTrue(item.isTrustedJID(notTrusted));\t\n\t\t\n\t\tSystem.setProperty(\"trusted\", \"comp3@example.com,comp4@example.com\");\n\t\tVHostItem.initGlobalTrustedJids();\n\t\titem = new VHostItem();\n\t\titem.toString();\n\t\tAssert.assertArrayEquals(new String[] { \"comp3@example.com\", \"comp4@example.com\" }, \n\t\t\t\titem.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(JID.jidInstanceNS(\"comp3@example.com\")));\n\t\tAssert.assertTrue(item.isTrustedJID(JID.jidInstanceNS(\"comp3@example.com\").copyWithResource(\"test\")));\n\t\tAssert.assertFalse(item.isTrustedJID(notTrusted));\n\t\t\n\t\titem.initFromPropertyString(\"example.com:trusted-jids=comp1@example.com;comp2@example.com\");\n\t\tAssert.assertArrayEquals(new String[] { jid.toString(), \"comp2@example.com\" }, item.getTrustedJIDs().toArray(new String[0]));\n\t\tAssert.assertTrue(item.isTrustedJID(jid));\n\t\tAssert.assertTrue(item.isTrustedJID(jid.copyWithResource(\"test\")));\n\t\tAssert.assertFalse(item.isTrustedJID(notTrusted));\n\t\tAssert.assertFalse(item.isTrustedJID(JID.jidInstanceNS(\"comp3@example.com\")));\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/vhosts/VHostJDBCRepositoryTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts;\n\nimport tigase.util.TigaseStringprepException;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport junit.framework.TestCase;\nimport org.junit.Test;\n\nimport static tigase.vhosts.VHostJDBCRepository.*;\n\npublic class VHostJDBCRepositoryTest extends TestCase {\n\n\tVHostJDBCRepository vHostJDBCRepository;\n\tString domain = \"domain.com\";\n\n\t@Override\n\tprotected void setUp() throws Exception {\n\t\tMap<String, Object> properties = new HashMap<>();\n\t\tproperties.put( DOMAINS_PER_USER_LIMIT_PROP_KEY, DOMAINS_PER_USER_LIMIT_PROP_VAL );\n\t\tvHostJDBCRepository = new VHostJDBCRepository();\n\t\tvHostJDBCRepository.setProperties(properties);\n\t}\n\n\t@Test\n\tpublic void testDomainNameCases() throws TigaseStringprepException {\n\t\tVHostItem vHostItem = new VHostItem( domain );\n\t\tvHostJDBCRepository.addItem( vHostItem );\n\t\tassertEquals( vHostItem, vHostJDBCRepository.getItem( domain.toUpperCase() ) );\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/vhosts/filter/CustomDomainFilterTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts.filter;\n\nimport tigase.xmpp.JID;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.filter.Rule.RuleType;\n\nimport java.text.ParseException;\nimport java.util.Set;\nimport java.util.TreeSet;\n\nimport org.junit.Before;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author Wojtek\n */\npublic class CustomDomainFilterTest {\n\n\tpublic CustomDomainFilterTest() {\n\t}\n\n\tString[] rules = {\n\t\t\"4|deny|all\",\n\t\t\"1|allow|self\",\n\t\t\"3|allow|jid|pubsub@test.com\",\n\t\t\"2|allow|jid|admin@test2.com\", };\n\n\n\t@BeforeClass\n\tpublic static void setUpClass() {\n\t}\n\n\t@Before\n\tpublic void setUp() {\n\t}\n\n\t@Test\n\tpublic void testParseRules() throws TigaseStringprepException, ParseException {\n\t\tSystem.out.println( \"parseRules\" );\n\n\t\tSet<Rule> expResult = new TreeSet<>();\n\t\tRule rule = new Rule( 1, true, RuleType.self, null );\n\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 2, true, RuleType.jid, JID.jidInstance( \"admin@test2.com\" ) );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 3, true, RuleType.jid, JID.jidInstance( \"pubsub@test.com\" ) );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 4, false, RuleType.all, null );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\n\t\tSet<Rule> result = CustomDomainFilter.parseRules( rules );\n\t\tassertEquals( expResult, result );\n\t}\n\n\t@Test\n\tpublic void testParseRulesString() throws TigaseStringprepException, ParseException {\n\t\tSystem.out.println( \"parseRules\" );\n\t\tString rulseString = \"4|deny|all;1|allow|self;3|allow|jid|pubsub@test.com;2|allow|jid|admin@test2.com\";\n\n\t\tSet<Rule> expResult = new TreeSet<>();\n\t\tRule rule = new Rule( 1, true, RuleType.self, null );\n\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 2, true, RuleType.jid, JID.jidInstance( \"admin@test2.com\" ) );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 3, true, RuleType.jid, JID.jidInstance( \"pubsub@test.com\" ) );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\t\trule = new Rule( 4, false, RuleType.all, null );\n\t\tif ( rule != null ){\n\t\t\texpResult.add( rule );\n\t\t}\n\n\t\tSet<Rule> result = CustomDomainFilter.parseRules( rulseString );\n\t\tassertEquals( expResult, result );\n\n\t\trulseString = \"1|allow|self;2|allow|jid|admin@test2.com;3|allow|jid|pubsub@test.com;4|deny|all;\";\n\t\tString resultString = new String();\n\t\tfor ( Rule res : result) {\n\t\t\tresultString += res.toConfigurationString();\n\t\t}\n\t\tassertEquals( rulseString, resultString );\n\n\t}\n\n\t@Test(expected = ParseException.class)\n\tpublic void testParseRulesException() throws TigaseStringprepException, ParseException {\n\t\tString[] rules_fail = {\n\t\t\t\"8|deny|||self,\",\n\t\t\t\"|||18|||deny,self::::\"\n\t\t};\n\t\tSet<Rule> result = CustomDomainFilter.parseRules( rules_fail );\n\t}\n\n\t@Test\n\tpublic void testIsAllowed() throws TigaseStringprepException, ParseException {\n\n\t\tJID jid1_r1 = JID.jidInstance( \"user1\", \"domain1\", \"resource1\" );\n\t\tJID jid1_r2 = JID.jidInstance( \"user1\", \"domain1\", \"resource2\" );\n\t\tJID jid2_r1 = JID.jidInstance( \"user2\", \"domain1\", \"resource1\" );\n\t\tJID jid3_r1 = JID.jidInstance( \"user3\", \"domain1\", \"resource1\" );\n\t\tJID admin = JID.jidInstance( \"admin\", \"test2.com\" );\n\t\tJID pubsub = JID.jidInstance( \"pubsub\", \"test.com\" );\n\n\t\tboolean allowed = CustomDomainFilter.isAllowed( jid1_r1, jid1_r2, rules );\n\t\tassertTrue( \"should be allowed / self / permitted jid\", allowed );\n\n\t\tallowed = CustomDomainFilter.isAllowed( jid1_r1, admin, rules );\n\t\tassertTrue( \"should be allowed / permitted jid\", allowed );\n\n\t\tallowed = CustomDomainFilter.isAllowed( jid1_r1, pubsub, rules );\n\t\tassertTrue( \"should be allowed / permitted jid\", allowed );\n\n\t\tallowed = CustomDomainFilter.isAllowed( jid1_r1, jid2_r1, rules );\n\t\tassertFalse( \"should be denyed / permitted jid\", allowed );\n\n\t\tallowed = CustomDomainFilter.isAllowed( jid2_r1, jid2_r1, rules );\n\t\tassertTrue( \"should be allowed / self\", allowed );\n\n\t\tallowed = CustomDomainFilter.isAllowed( jid3_r1, jid2_r1, rules );\n\t\tassertFalse( \"should be denied / not permitted jids\", allowed );\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/vhosts/filter/DomainFilterPolicyTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.vhosts.filter;\n\nimport java.util.HashSet;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author Wojtek\n */\npublic class DomainFilterPolicyTest {\n\n\tpublic DomainFilterPolicyTest() {\n\t}\n\n\n\t@Test\n\tpublic void testValuePoliciesWithDomainListStr() {\n\t\tSystem.out.println( \"valuePoliciesWithDomainListStr\" );\n\t\tHashSet<String> result = DomainFilterPolicy.valuePoliciesWithDomainListStr();\n\t\tassertEquals( true, result.contains( DomainFilterPolicy.CUSTOM.name()) );\n\t\tassertEquals( true, result.contains( DomainFilterPolicy.LIST.name()) );\n\t\tassertEquals( true, result.contains( DomainFilterPolicy.BLACKLIST.name()) );\n\t\tassertEquals( false, result.contains( DomainFilterPolicy.ALL.name()) );\n\t\tassertEquals( false, result.contains( DomainFilterPolicy.BLOCK.name()) );\n\t\tassertEquals( false, result.contains( DomainFilterPolicy.LOCAL.name()) );\n\t\tassertEquals( false, result.contains( DomainFilterPolicy.OWN.name()) );\n\t}\n\n\t@Test\n\tpublic void testIsDomainListRequired() {\n\t\tSystem.out.println( \"isDomainListRequired\" );\n\t\tassertEquals( false, DomainFilterPolicy.ALL.isDomainListRequired() );\n\t\tassertEquals( true, DomainFilterPolicy.BLACKLIST.isDomainListRequired() );\n\t\tassertEquals( false, DomainFilterPolicy.BLOCK.isDomainListRequired() );\n\t\tassertEquals( true, DomainFilterPolicy.CUSTOM.isDomainListRequired() );\n\t\tassertEquals( true, DomainFilterPolicy.LIST.isDomainListRequired() );\n\t\tassertEquals( false, DomainFilterPolicy.LOCAL.isDomainListRequired() );\n\t\tassertEquals( false, DomainFilterPolicy.OWN.isDomainListRequired() );\n\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/XMPPDomBuilderHandlerTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2016 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n * $Rev$\n * Last modified by $Author$\n * $Date$\n */\npackage tigase.xmpp;\n\nimport java.util.Map;\nimport static org.junit.Assert.*;\nimport org.junit.Test;\nimport tigase.xml.Element;\n\n/**\n *\n * @author andrzej\n */\npublic class XMPPDomBuilderHandlerTest {\n\t\n\t@Test\n\tpublic void testPrefixesAndNamespacesHandling() {\n\t\tXMPPIOService ioserv = new XMPPIOService() {\n\t\t\t@Override\n\t\t\tprotected void xmppStreamOpened(Map attribs) {\n\t\t\t}\n\t\t\t\n\t\t};\n\t\tboolean error = false;\n\t\tXMPPDomBuilderHandler<Element> handler = new XMPPDomBuilderHandler<>(ioserv);\n\t\thandler.setElementsLimit(10);\n\t\thandler.startElement(new StringBuilder(\"stream:stream\"), new StringBuilder[] { new StringBuilder(\"xmlns\"), new StringBuilder(\"xmlns:stream\"), new StringBuilder(\"xmlns:db\") }, \n\t\t\t\tnew StringBuilder[] { new StringBuilder(\"jabber:server\"), new StringBuilder(\"http://etherx.jabber.org/streams\"), new StringBuilder(\"jabber:server:dialback\") });\n\t\t\n\t\thandler.startElement(new StringBuilder(\"db:result\"), new StringBuilder[] { new StringBuilder(\"to\") }, new StringBuilder[] { new StringBuilder(\"example.com\") });\n\t\thandler.elementCData(new StringBuilder(\"CAESBxCXyf6RqCoaEGPHnXDLTIeKBNx9ZJ1SmzM=\"));\n\t\terror = !handler.endElement(new StringBuilder(\"db:result\"));\n\t\t\n\t\tassertFalse(handler.parseError() || error);\n\t\tassertEquals(\"result\", handler.getParsedElements().peek().getName());\n\t\tassertEquals(\"jabber:server:dialback\", handler.getParsedElements().peek().getXMLNS());\n\t\t\n\t\thandler.getParsedElements().clear();\n\t\thandler.startElement(new StringBuilder(\"test:message\"), null, null);\n\t\terror = !handler.endElement(new StringBuilder(\"test:message\"));\n\t\tassertFalse(handler.parseError() || error);\n\n\t\thandler.getParsedElements().clear();\n\t\thandler.startElement(new StringBuilder(\"message\"), null, null);\n\t\terror = !handler.endElement(new StringBuilder(\"message\"));\n\t\tassertFalse(handler.parseError() || error);\n\n\t\thandler.getParsedElements().clear();\n\t\thandler.startElement(new StringBuilder(\"test:message\"), null, null);\n\t\terror = !handler.endElement(new StringBuilder(\"message\"));\n\t\tassertTrue(handler.parseError() || error);\n\n\t\thandler.getParsedElements().clear();\n\t\thandler.startElement(new StringBuilder(\"message\"), null, null);\n\t\terror = !handler.endElement(new StringBuilder(\"test:message\"));\n\t\tassertTrue(handler.parseError() || error);\n\n\t\thandler.getParsedElements().clear();\n\t\thandler.startElement(new StringBuilder(\"message\"), null, null);\n\t\terror = !handler.endElement(new StringBuilder(\"db:message\"));\n\t\tassertTrue(handler.parseError() || error);\n\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/BindResourceTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport tigase.db.NonAuthUserRepository;\n\nimport tigase.server.Packet;\n\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NoConnectionIdException;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\n\nimport java.util.ArrayDeque;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author Wojtek\n */\npublic class BindResourceTest extends ProcessorTestCase {\n\n\tBindResource bindResource;\n\n\tpublic BindResourceTest() {\n\t}\n\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tbindResource = new BindResource();\n\t\tsuper.setUp();\n\t}\n\n\t@After\n\tpublic void tearDown() throws Exception {\n\t\tbindResource = null;\n\t\tsuper.tearDown();\n\t}\n\n\t@Test\n\tpublic void testPreProcess() throws TigaseStringprepException, NotAuthorizedException, NoConnectionIdException {\n\t\tJID senderJid = JID.jidInstance(\"sender@example.com/res-1\");\n\t\tJID recipientJid = JID.jidInstance(\"recipient@example.com/res-2\");\n\t\tXMPPResourceConnection senderSession = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsenderJid);\n\n\t\tElement messageEl = new Element(\"message\",\n\t\t\t\tnew String[] { \"from\" },\n\t\t\t\tnew String[] { senderJid.toString() });\n\t\tPacket p = Packet.packetInstance(messageEl);\n\t\tp.setPacketFrom(senderSession.getConnectionId());\n\n\t\tMap<String,Object> settings = new HashMap<>();\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\n\t\t// message / non-presence\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tSystem.out.println(  );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\" );\n\n\t\tp.getElement().setAttribute( \"from\", senderJid.getBareJID().toString());\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\");\n\n\t\tp.getElement().removeAttribute(\"from\");\n\t\tSystem.out.println( p.getElement()  +\"\");\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\"  );\n\n\t\t// presence -- non-sub\n\t\tSystem.out.println( \"=====\"  );\n\n\t\tElement presenceEl = new Element(\"presence\",\n\t\t\t\tnew String[] { \"from\" },\n\t\t\t\tnew String[] { senderJid.toString() });\n\t\tp = Packet.packetInstance(presenceEl);\n\t\tp.setPacketFrom(senderSession.getConnectionId());\n\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tSystem.out.println(  );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\" );\n\n\t\tp.getElement().setAttribute( \"from\", senderJid.getBareJID().toString());\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\");\n\n\t\tp.getElement().removeAttribute(\"from\");\n\t\tSystem.out.println( p.getElement()  +\"\");\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(senderJid, p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\"  );\n\n\t\t// presence -- sub\n\t\tSystem.out.println( \"=====\"  );\n\n\t\tp.getElement().setAttribute( \"type\", \"subscribe\");\n\t\tp.getElement().setAttribute( \"from\", senderJid.toString());\n\t\tp = Packet.packetInstance(p.getElement());\n\t\tp.setPacketFrom(senderSession.getConnectionId());\n\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(JID.jidInstance( senderJid.getBareJID()), p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\" );\n\n\t\tp.getElement().setAttribute( \"from\", senderJid.getBareJID().toString());\n\t\tSystem.out.println( p.getElement() +\"\" );\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(JID.jidInstance( senderJid.getBareJID()), p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\");\n\n\t\tp.getElement().removeAttribute(\"from\");\n\t\tSystem.out.println( p.getElement()  +\"\");\n\t\tassertFalse(bindResource.preProcess(p, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\tassertEquals(JID.jidInstance( senderJid.getBareJID()), p.getStanzaFrom());\n\t\tSystem.out.println( p.getStanzaFrom() +\"\\n\"  );\n\n\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/BlockingCommandTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.HashMap;\nimport java.util.List;\nimport org.junit.After;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.db.TigaseDBException;\nimport tigase.server.Iq;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.impl.roster.RosterAbstract;\nimport tigase.xmpp.impl.roster.RosterFactory;\n\n/**\n *\n * @author andrzej\n */\npublic class BlockingCommandTest extends ProcessorTestCase {\n\t\n\tprivate BlockingCommand blockingCommand;\n\tprivate JabberIqPrivacy privacy;\n\tprivate ArrayDeque<Packet> results;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tsuper.setUp();\n\t\tblockingCommand = new BlockingCommand();\n\t\tblockingCommand.init(new HashMap<String, Object>());\n\t\tprivacy = new JabberIqPrivacy();\n\t\tprivacy.init(new HashMap<String, Object>());\n\t\tresults = new ArrayDeque<Packet>();\n\t}\n\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tsuper.tearDown();\n\t\tblockingCommand = null;\n\t}\n\t\n\t@Test\n\tpublic void testBlockUnblock() throws Exception {\n\t\tJID connJid = JID.jidInstanceNS(\"c2s@example.com/test-111\");\n\t\tJID userJid = JID.jidInstanceNS(\"user-1@example.com/res-1\");\n\t\tXMPPResourceConnection sess = getSession(connJid, userJid);\n\t\t\n\t\tString blockJid = \"block-1@example.com\";\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tList<String> blocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t\t\n\t\tblock(sess, blockJid);\n\t\tassertEquals(2, results.size());\n\t\tprivacy.filter(null, sess, null, results);\t\t\n\t\t\n\t\tassertEquals(2, results.size());\n\t\tPacket result = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, true);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked.contains(blockJid));\n\t\t\n\t\tunblock(sess, blockJid);\n\t\tassertEquals(2, results.size());\n\t\tprivacy.filter(null, sess, null, results);\t\t\n\n\t\tassertEquals(2, results.size());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\t\n\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t}\n\t\n\t@Test\n\tpublic void testBlockUnblockAll() throws Exception {\n\t\tJID connJid = JID.jidInstanceNS(\"c2s@example.com/test-111\");\n\t\tJID userJid = JID.jidInstanceNS(\"user-1@example.com/res-1\");\n\t\tXMPPResourceConnection sess = getSession(connJid, userJid);\n\t\t\n\t\tString blockJid = \"block-1@example.com\";\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tList<String> blocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t\t\n\t\tblock(sess, blockJid);\n\t\tassertEquals(2, results.size());\n\t\tprivacy.filter(null, sess, null, results);\t\t\n\t\t\n\t\tassertEquals(2, results.size());\n\t\tPacket result = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\t\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, true);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked.contains(blockJid));\n\t\t\n\t\tunblock(sess, blockJid);\n\t\tassertEquals(2, results.size());\n\t\tprivacy.filter(null, sess, null, results);\n\n\t\tassertEquals(2, results.size());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t}\t\n\t\n\t@Test\n\tpublic void testBlockUnblockWithPresence() throws Exception {\n\t\tJID connJid = JID.jidInstanceNS(\"c2s@example.com/test-111\");\n\t\tJID userJid = JID.jidInstanceNS(\"user-1@example.com/res-1\");\n\t\tXMPPResourceConnection sess = getSession(connJid, userJid);\n\t\t\n\t\tString blockJid = \"block-1@example.com\";\n\t\tRosterAbstract roster_util = RosterFactory.getRosterImplementation(true);\n\t\troster_util.addBuddy(sess, JID.jidInstance(blockJid), \"Block-1\", null, null);\n\t\troster_util.setBuddySubscription(sess, RosterAbstract.SubscriptionType.both, JID.jidInstance(blockJid));\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tList<String> blocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t\t\n\t\tblock(sess, blockJid);\n\t\tassertEquals(3, results.size());\n\t\tprivacy.filter(null, sess, null, results);\n\t\t\n\t\tassertEquals(3, results.size());\n\t\tPacket result = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(tigase.server.Presence.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.unavailable, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\t\n\t\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, true);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked.contains(blockJid));\n\t\t\n\t\tunblock(sess, blockJid);\n\t\tassertEquals(3, results.size());\n\t\tprivacy.filter(null, sess, null, results);\n\n\t\tassertEquals(3, results.size());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(tigase.server.Presence.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.probe, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.result, result.getType());\n\t\tresult = results.poll();\n\t\tassertNotNull(result);\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\tassertEquals(StanzaType.set, result.getType());\n\t\t\n\t\n\t\tcheckPrivacyJidBlocked(sess, blockJid, false);\n\t\tblocked = getBlocked(sess);\n\t\tassertTrue(blocked == null || blocked.isEmpty());\n\t}\t\n\t\n\tprivate void block(XMPPResourceConnection sess, String jid) throws Exception {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\" }, new String[] { \"set\" });\n\t\tElement block = new Element(\"block\", new String[] { \"xmlns\" }, new String[] { BlockingCommand.XMLNS });\n\t\tElement item = new Element(\"item\", new String[] { \"jid\" }, new String[] { jid });\n\t\tblock.addChild(item);\n\t\tiq.addChild(block);\n\t\tPacket p = Packet.packetInstance(iq);\n\t\tblockingCommand.process(p, sess, null, results, null);\n\t}\n\t\n\tprivate void unblock(XMPPResourceConnection sess, String jid) throws Exception {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\" }, new String[] { \"set\" });\n\t\tElement block = new Element(\"unblock\", new String[] { \"xmlns\" }, new String[] { BlockingCommand.XMLNS });\n\t\tElement item = new Element(\"item\", new String[] { \"jid\" }, new String[] { jid });\n\t\tblock.addChild(item);\n\t\tiq.addChild(block);\n\t\tPacket p = Packet.packetInstance(iq);\n\t\tblockingCommand.process(p, sess, null, results, null);\t\t\n\t}\n\t\n\tprivate void unblockAll(XMPPResourceConnection sess) throws Exception {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\" }, new String[] { \"set\" });\n\t\tElement block = new Element(\"unblock\", new String[] { \"xmlns\" }, new String[] { BlockingCommand.XMLNS });\n\t\tiq.addChild(block);\n\t\tPacket p = Packet.packetInstance(iq);\n\t\tblockingCommand.process(p, sess, null, results, null);\t\t\n\t}\n\tprivate void checkPrivacyJidBlocked(XMPPResourceConnection sess, String jid, boolean value) throws NotAuthorizedException, TigaseDBException {\n\t\tList<String> blocked = Privacy.getBlocked(sess);\n\t\tif (value) {\n\t\t\tassertTrue(blocked != null && blocked.contains(jid));\n\t\t} else {\n\t\t\tassertTrue(blocked == null || !blocked.contains(jid));\n\t\t}\n\t}\n\t\n\tprivate List<String> getBlocked(XMPPResourceConnection sess) throws XMPPException, TigaseStringprepException {\n\t\tElement iq = new Element(\"iq\", new String[] { \"type\" }, new String[] { \"get\" });\n\t\tElement blocklist = new Element(\"blocklist\", new String[] { \"xmlns\" }, new String[] { BlockingCommand.XMLNS });\n\t\tiq.addChild(blocklist);\n\t\t\n\t\tPacket p = Packet.packetInstance(iq);\n\t\tblockingCommand.process(p, sess, null, results, null);\n\t\tassertEquals(1, results.size());\n\t\tPacket result = results.poll();\n\t\tassertEquals(Iq.ELEM_NAME, result.getElemName());\n\t\treturn result.getElement().getChild(\"blocklist\").mapChildren(c -> c.getName() == \"item\", c -> c.getAttributeStaticStr(\"jid\"));\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/C2SDeliveryErrorProcessorTest.java",
    "content": "/*\n * C2SDeliveryErrorProcessorTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayDeque;\nimport java.util.Date;\nimport java.util.Queue;\nimport java.util.TimeZone;\nimport java.util.UUID;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic class C2SDeliveryErrorProcessorTest extends ProcessorTestCase {\n\n\tprivate static final SimpleDateFormat formatter;\n\t\n\tstatic {\n\t\tformatter = new SimpleDateFormat( \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" );\n\t\tformatter.setTimeZone( TimeZone.getTimeZone( \"UTC\" ) );\n\t}\t\t\n\t\n\tprivate Message messageProcessor = new Message();\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tsuper.setUp();\n\t}\t\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tsuper.tearDown();\n\t}\n\t\n\t@Test\n\tpublic void test() throws Exception {\n\t\tElement packetEl = null;\n\t\tPacket packet = null;\n\t\tJID from = JID.jidInstance(\"from@example.com/res\");\n\t\tJID to = JID.jidInstance(\"to@example.com\");\n\t\t\n\t\t\n\t\tpacketEl = new Element(\"iq\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacket = Packet.packetInstance(packetEl);\n\n\t\tPacket error = C2SDeliveryErrorProcessor.makeDeliveryError(packet, 12L);\n\t\tElement deliveryError = C2SDeliveryErrorProcessor.getDeliveryError(error);\n\t\tassertNotNull(deliveryError);\n\t\tassertEquals(\"12\", deliveryError.getAttributeStaticStr(\"stamp\"));\n\t\t\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\t\n\t\terror = C2SDeliveryErrorProcessor.makeDeliveryError(packet, 12L);\n\t\tdeliveryError = C2SDeliveryErrorProcessor.getDeliveryError(error);\n\t\tassertNotNull(deliveryError);\n\t\tassertEquals(\"12\", deliveryError.getAttributeStaticStr(\"stamp\"));\t\t\n\t}\n\t\n\t@Test\n\tpublic void testPreprocessingNotSupportedPackets() throws Exception {\n\t\tElement packetEl = null;\n\t\tPacket packet = null;\n\t\tJID from = JID.jidInstance(\"from@example.com/res\");\n\t\tJID to = JID.jidInstance(\"to@example.com\");\n\t\t\n\t\t\n\t\tpacketEl = new Element(\"iq\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertFalse(C2SDeliveryErrorProcessor.preProcess(packet, null, null, null, null, messageProcessor));\n\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertFalse(C2SDeliveryErrorProcessor.preProcess(packet, null, null, null, null, messageProcessor));\t\n\n\t\t// packet is still not supported as session is null\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\" }, new String[] { \"http://tigase.org/delivery-error\" }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertFalse(C2SDeliveryErrorProcessor.preProcess(packet, null, null, null, null, messageProcessor));\t\t\n\t}\t\n\n\t@Test\n\tpublic void testPreprocessingWithDeliveryErrorForBareJID() throws Exception {\n\t\tElement packetEl = null;\n\t\tPacket packet = null;\n\t\tJID from = JID.jidInstance(\"from@example.com/res\");\n\t\tJID to = JID.jidInstance(\"to@example.com\");\n\t\tJID toRes1 = to.copyWithResource(\"res1\");\n\t\tJID toRes2 = to.copyWithResource(\"res2\");\n\t\t\n\t\tXMPPResourceConnection sessionToRes2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), toRes2);\n\t\tThread.sleep(1);\n\t\tString stampBefore = String.valueOf(System.currentTimeMillis());\n\t\tThread.sleep(1);\n\t\tXMPPResourceConnection sessionToRes1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), toRes1);\n\t\tThread.sleep(1);\n\t\tString stampAfter = String.valueOf(System.currentTimeMillis());\n\t\t\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\" }, new String[] { \"http://tigase.org/delivery-error\" }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertFalse(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, null, null, messageProcessor));\n\t\t\n\t\tsessionToRes1.setPriority(10);\n\t\tsessionToRes1.setPresence(new Element(\"presence\"));\n\t\t\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\" }, new String[] { \"http://tigase.org/delivery-error\" }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertTrue(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, null, null, messageProcessor));\n\t\t\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\" }, new String[] { \"http://tigase.org/delivery-error\" }));\n\t\tpacketEl.addChild(new Element(\"delay\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:delay\" }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertTrue(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, null, null, messageProcessor));\n\n\t\tQueue<Packet> results = new ArrayDeque();\n\t\tresults.clear();\n\t\t\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\", \"stamp\" }, new String[] { \"http://tigase.org/delivery-error\", stampBefore }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertTrue(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, results, null, messageProcessor));\n\t\tassertEquals(1, results.size());\n\t\tPacket result = results.poll();\n\t\tassertEquals(sessionToRes1.getConnectionId(), result.getPacketTo());\n\n\t\tsessionToRes2.setPriority(10);\n\t\tsessionToRes2.setPresence(new Element(\"presence\"));\n\t\tresults.clear();\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\", \"stamp\" }, new String[] { \"http://tigase.org/delivery-error\", stampBefore }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertTrue(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, results, null, messageProcessor));\n\t\tassertEquals(1, results.size());\n\t\tresult = results.peek();\n\t\tassertEquals(sessionToRes1.getConnectionId(), result.getPacketTo());\t\n\t\tC2SDeliveryErrorProcessor.filter(packet, sessionToRes1, null, results, null);\n\t\tassertEquals(1, results.size());\n\t\tresult = results.peek();\n\t\tassertFalse(C2SDeliveryErrorProcessor.isDeliveryError(result));\n\t\t\n\t\t\n\t\tresults.clear();\n\t\tpacketEl = new Element(\"message\", new String[] { \"id\", \"from\", \"to\" }, \n\t\t\t\tnew String[] { UUID.randomUUID().toString(), from.toString(), to.toString() });\n\t\tpacketEl.addChild(new Element(\"delivery-error\", new String[] { \"xmlns\", \"stamp\" }, new String[] { \"http://tigase.org/delivery-error\", stampAfter }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tassertTrue(C2SDeliveryErrorProcessor.preProcess(packet, sessionToRes1, null, results, null, messageProcessor));\n\t\tassertEquals(0, results.size());\n\t}\t\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/DomainFilterTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport tigase.db.AuthRepository;\nimport tigase.db.TigaseDBException;\nimport tigase.db.UserRepository;\nimport tigase.db.xml.XMLRepository;\n\nimport tigase.server.Packet;\nimport tigase.server.xmppsession.SessionManagerHandler;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\nimport tigase.util.LogFormatter;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.filter.DomainFilterPolicy;\nimport tigase.vhosts.VHostItem;\n\nimport java.io.IOException;\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.ConsoleHandler;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.junit.*;\n\nimport static tigase.xmpp.impl.DomainFilter.ALLOWED_DOMAINS_KEY;\nimport static tigase.xmpp.impl.DomainFilter.ALLOWED_DOMAINS_LIST_KEY;\n\n/**\n *\n * @author Wojciech Kapcia <wojciech.kapcia@tigase.org>\n */\npublic class DomainFilterTest extends ProcessorTestCase {\n\n\tprivate DomainFilter domainFilter;\n\tprivate static Logger log;\n\tString domain = \"domain\";\n\tJID recp1 = JID.jidInstanceNS( \"user1\", domain + 1, \"resource1\" );\n\tJID sameDomainUser = JID.jidInstanceNS( \"user2\", domain + 1, \"resource2\" );\n\tJID localDomainUser = JID.jidInstanceNS( \"user2\", domain + 2, \"resource2\" );\n\tJID externalDomainUser = JID.jidInstanceNS( \"user2\", domain + \"-ext\", \"resource2\" );\n\tJID connId1 = JID.jidInstanceNS( \"c2s@localhost/recipient1-res1\" );\n\tArrayDeque<Packet> results;\n\tPacket p;\n\tXMPPResourceConnection session;\n\n\t@BeforeClass\n\tpublic static void setUpLogger() throws TigaseDBException, IOException {\n\t\tLevel lvl;\n//\t\tlvl = Level.ALL;\n\t\tlvl = Level.CONFIG;\n\t\tConsoleHandler consoleHandler = new ConsoleHandler();\n\t\tconsoleHandler.setLevel( lvl );\n\t\tconsoleHandler.setFormatter( new LogFormatter() );\n\t\tlog = Logger.getLogger( DomainFilter.class.getName() );\n\t\tlog.setUseParentHandlers( false );\n\t\tlog.setLevel( lvl );\n\t\tlog.addHandler( consoleHandler );\n\n\t}\n\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tsuper.setUp();\n\t\tdomainFilter = new DomainFilter();\n\t\tdomainFilter.init( new HashMap<String, Object>() );\n\t\tresults = new ArrayDeque<Packet>();\n\t}\n\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tsuper.tearDown();\n\t\tdomainFilter = null;\n\t}\n\n\t@Test\n\tpublic void testPolicyHierarchy() throws NotAuthorizedException, TigaseStringprepException, TigaseDBException {\n\t\tString[] domainsList;\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.LIST,\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew String[] { domain + 1, domain + 2, domain + 3 } );\n\n\t\tAssert.assertEquals( \"Reading DomainFilterPolicy from VHost\", DomainFilterPolicy.LIST,\n\t\t\t\t\t\t\t\t\t\t\t\t domainFilter.getDomains( session ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_KEY );\n\n\t\t// configuration from UserRepository\n\t\tsession.setData( null, ALLOWED_DOMAINS_KEY, DomainFilterPolicy.ALL.name() );\n\t\tAssert.assertEquals( \"Reading DomainFilterPolicy from UserRepo, takes precendence over VHost\",\n\t\t\t\t\t\t\t\t\t\t\t\t DomainFilterPolicy.ALL, domainFilter.getDomains( session ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_KEY );\n\n\t\t// user session data takes precedence over repository and VHost configuration\n\t\tsession.putCommonSessionData( ALLOWED_DOMAINS_KEY, DomainFilterPolicy.BLOCK );\n\t\tAssert.assertEquals( \"Reading DomainFilterPolicy from user session, takes precendence over UserRepository\",\n\t\t\t\t\t\t\t\t\t\t\t\t DomainFilterPolicy.BLOCK, domainFilter.getDomains( session ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_KEY );\n\n\t\t// let's check hierarchy of domain list: VHost, UserRepo, session\n\t\tdomainsList = domainFilter.getDomainsList( session );\n\t\tAssert.assertTrue( \"Reading domain list from VHost\", Arrays.asList( domainsList ).contains( domain + 1 ) );\n\t\tAssert.assertFalse( \"Reading domain list from VHost\", Arrays.asList( domainsList ).contains( domain + 5 ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_LIST_KEY );\n\n\t\t// configuration from UserRepository\n\t\tsession.setData( null, ALLOWED_DOMAINS_LIST_KEY, ( domain + 11 + \";\" + domain + 12 + \";\" + domain + 13 ) );\n\t\tdomainsList = domainFilter.getDomainsList( session );\n\t\tlog.log( Level.FINE, Arrays.asList( domainsList ).toString() );\n\t\tAssert.assertTrue( \"Reading domain list from repository\", Arrays.asList( domainsList ).contains( domain + 11 ) );\n\t\tAssert.assertFalse( \"Reading domain list from repository\", Arrays.asList( domainsList ).contains( domain + 15 ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_LIST_KEY );\n\n\t\t// user session data takes precedence over repository and VHost configuration\n\t\tsession.putCommonSessionData( ALLOWED_DOMAINS_LIST_KEY, new String[] { domain + 21, domain + 22, domain + 23 } );\n\t\tdomainsList = domainFilter.getDomainsList( session );\n\t\tlog.log( Level.FINE, Arrays.asList( domainsList ).toString() );\n\t\tAssert.assertTrue( \"Reading domain list from session\", Arrays.asList( domainsList ).contains( domain + 21 ) );\n\t\tAssert.assertFalse( \"Reading domain list from session\", Arrays.asList( domainsList ).contains( domain + 25 ) );\n\t\tsession.removeCommonSessionData( ALLOWED_DOMAINS_LIST_KEY );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testFilterAllPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.ALL, null );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertFalse( \"ALL policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\t// two local domains\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertFalse( \"ALL policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertFalse( \"ALL policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\n\n\t@Test\n\tpublic void testFilterLocalPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.LOCAL, null );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertFalse( \"LOCAL policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertFalse( \"LOCAL policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"LOCAL policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testFilterOwnPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.OWN, null );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertFalse( \"OWN policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"OWN policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"OWN policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testFilterWhielistPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tString[] whitelistDomains = new String[] { \"domain1\", externalDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.LIST, whitelistDomains );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertFalse( \"WHITELIST policy, message between same domains (both whitelist)\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"WHITELIST policy, message between different local domains (only sender whitelist)\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertFalse( \"WHITELIST policy, message to external domain (whitelisted)\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testFilterBlacklistPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tString[] blacklistedDomains = new String[] { localDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.BLACKLIST, blacklistedDomains );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertFalse( \"BLACKLIST policy, message between same domains (not on blacklist)\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"BLACKLIST policy, message between different local domains (receiver domain blacklisted)\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertFalse( \"BLACKLIST policy, message to external domain (not blacklisted)\",\n\t\t\t\t\t\t\t\t\t\t\t\tresults.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testFilterBlockPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tString[] blacklistedDomains = new String[] { localDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.BLOCK, blacklistedDomains );\n\n\t\tfilterPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tfilterPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorAllPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.ALL, null );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"ALL policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"ALL policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"ALL policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorLocalPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.LOCAL, null );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"LOCAL policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"LOCAL policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"LOCAL policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorOwnPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.OWN, null );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"OWN policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"OWN policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"OWN policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorWhielistPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\t\tString[] whitelistDomains = new String[] { \"domain1\", externalDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.LIST, whitelistDomains );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"WHITELIST policy, message between same domains (both whitelist)\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"WHITELIST policy, message between different local domains (only sender whitelist)\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"WHITELIST policy, message to external domain (whitelisted)\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorBlacklistPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\n\t\t// blacklisting other local user\n\t\tString[] blacklistedDomains = new String[] { localDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.BLACKLIST, blacklistedDomains );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"BLACKLIST policy, message between same domains (not on blacklist)\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"BLACKLIST policy, message between different local domains (receiver domain blacklisted)\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"BLACKLIST policy, message to external domain (not blacklisted)\",\n\t\t\t\t\t\t\t\t\t\t\t results.isEmpty() );\n\n\t\tsession.logout();\n\n\t}\n\n\t@Test\n\tpublic void testPreprocessorBlockPolicy() throws NotAuthorizedException, TigaseStringprepException {\n\n\t\tString[] blacklistedDomains = new String[] { localDomainUser.getDomain() };\n\n\t\tsession = getSession( connId1, recp1, DomainFilterPolicy.BLOCK, blacklistedDomains );\n\n\t\tprocessPacket( session, sameDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message between same domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tprocessPacket( session, localDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message between different local domains\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tprocessPacket( session, externalDomainUser );\n\t\tAssert.assertTrue( \"BLOCK policy, message to external domain\",\n\t\t\t\t\t\t\t\t\t\t\t results.pop().getType().equals( StanzaType.error ) );\n\n\t\tsession.logout();\n\n\t}\n\n\tprivate void filterPacket( XMPPResourceConnection session, JID reciever ) throws TigaseStringprepException {\n\t\tp = Packet.packetInstance( \"message\", recp1.toString(), reciever.toString(), StanzaType.chat );\n\t\tp.setPacketFrom( connId1 );\n\t\tresults.offer( p );\n\t\tdomainFilter.filter( p, session, null, results );\n\t\tlog.log( Level.FINEST, \"results: \" + results );\n\t}\n\n\tprivate void processPacket( XMPPResourceConnection session, JID reciever ) throws TigaseStringprepException {\n\t\tp = Packet.packetInstance( \"message\", recp1.toString(), reciever.toString(), StanzaType.chat );\n\t\tp.setPacketFrom( connId1 );\n\t\tdomainFilter.preProcess( p, session, null, results, null );\n\t\tlog.log( Level.FINEST, \"results: \" + results );\n\t}\n\n\tprivate XMPPResourceConnection getSession( JID connId, JID userJid, DomainFilterPolicy dfp, String[] domains ) throws NotAuthorizedException, TigaseStringprepException {\n\t\tXMPPResourceConnection conn = super.getSession(connId, userJid);\n\t\tVHostItem vhost = conn.getDomain();\n\t\tvhost.setDomainFilter( dfp );\n\t\tvhost.setDomainFilterDomains( domains );\n\n\t\treturn conn;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/JabberIqPrivacyTest.java",
    "content": "package tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport junit.framework.TestCase;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n * Test class for JabberIqPrivacyTest\n * \n * Currently class tests validateList method checking validation of type, \n * subscription and action. Other cases are not tested due to missing instance \n * of XMPPResourceConnection\n */\npublic class JabberIqPrivacyTest extends ProcessorTestCase {\n\n\tprivate JabberIqPrivacy privacyFilter;\n\tprivate ArrayDeque<Packet> results;\n\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tsuper.setUp();\n\t\tprivacyFilter = new JabberIqPrivacy();\n\t\tprivacyFilter.init(new HashMap<String, Object>());\n\t\tresults = new ArrayDeque<Packet>();\n\t}\n\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tsuper.tearDown();\n\t\tprivacyFilter = null;\n\t}\n\t\n        @Test\n        public void testValidateListGood() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n                         \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"subscription\", \"both\", \"allow\", \"10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"15\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(null, result);\n        }\n\n        @Test\n        public void testValidateListBadAction() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n             \n             \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"subscription\", \"both\", \"ignore\", \"10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"15\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(Authorization.BAD_REQUEST, result);\n        }\n        \n        @Test\n        public void testValidateListBadSubscription() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n                          \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"subscription\", \"or\", \"allow\", \"10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"15\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(Authorization.BAD_REQUEST, result);\n        }\n        \n        @Test\n        public void testValidateListBadType() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n                          \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"other\", \"both\", \"allow\", \"10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"15\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(Authorization.BAD_REQUEST, result);\n        }\n        \n        @Test\n        public void testValidateListOrderUnsignedInt() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n                          \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"subscription\", \"both\", \"allow\", \"-10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"15\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(Authorization.BAD_REQUEST, result);\n             \n        }\n\n        @Test\n        public void testValidateListOrderAttributeDuplicate() {\n             List<Element> items = new ArrayList<Element>();\n             \n             Authorization result = null;\n                          \n             items.add(new Element(\"item\", new String[] { \"type\", \"value\", \"action\", \"order\" },\n                     new String[] { \"subscription\", \"both\", \"allow\", \"10\" }));\n             items.add(new Element(\"item\", new String[] { \"action\", \"order\" },\n                     new String[] { \"deny\", \"10\" }));\n             \n             // session is allowed to be null here\n             result = JabberIqPrivacy.validateList(null, items);\n             assertEquals(Authorization.BAD_REQUEST, result);\n             \n        }\n        \n\t\t@Test\n\t\tpublic void testFilterPresenceOut() throws Exception {\n\t\t\tJID jid = JID.jidInstance(\"test@example/res-1\");\n\t\t\tJID connId = JID.jidInstance(\"c2s@example.com/asdasd\");\n\t\t\tXMPPResourceConnection session = getSession(connId, jid);\n\t\t\t\n\t\t\t//List<Element> items = new ArrayList<Element>();\n\t\t\tElement list = new Element(\"list\", new String[] { \"name\" }, new String[] { \"default\" });\n\t\t\tElement item = new Element(\"item\", new String[]{\"type\", \"value\", \"action\", \"order\"},\n\t\t\t\t\tnew String[]{\"jid\", \"test1.example.com\", \"deny\", \"100\"});\n\t\t\titem.addChild(new Element(\"presence-out\"));\n\t\t\tlist.addChild(item);\n\t\t\tlist.addChild(new Element(\"item\", new String[]{\"action\", \"order\"},\n\t\t\t\t\tnew String[]{\"allow\", \"110\"}));\n\t\t\t\n\t\t\tsession.putSessionData(\"active-list\", list);\n\t\t\t\n\t\t\tPacket presence = Packet.packetInstance(new Element(\"presence\", \n\t\t\t\t\tnew String[] { \"from\", \"to\" }, \n\t\t\t\t\tnew String[] { \"test@example/res-1\", \"test1.example.com\" }));\n\t\t\t\t\t\n\t\t\tassertFalse(privacyFilter.allowed(presence, session));\n\t\t\t\n\t\t\tpresence = Packet.packetInstance(new Element(\"presence\", \n\t\t\t\t\tnew String[] { \"to\", \"from\" }, \n\t\t\t\t\tnew String[] { \"test@example/res-1\", \"test1.example.com\" }));\t\t\t\n\t\t\t\n\t\t\tassertTrue(privacyFilter.allowed(presence, session));\n\t\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/JabberIqRegisterWhitelistTest.java",
    "content": "package tigase.xmpp.impl;\n\nimport java.util.HashMap;\n\nimport junit.framework.TestCase;\n\nimport org.junit.Test;\n\nimport tigase.xmpp.JID;\n\n/**\n * Test class for JabberIqPrivacyTest\n * \n * Currently class tests validateList method checking validation of type,\n * subscription and action. Other cases are not tested due to missing instance\n * of XMPPResourceConnection\n */\npublic class JabberIqRegisterWhitelistTest extends TestCase {\n\n\tprivate static final String CONNECTION_ID = connectionId(\"127.0.0.2\");\n\t\n\tprivate static final String connectionId(String remoteAddress) {\n\t\treturn \"c2s@0123456789/127.0.0.1_5222_\" + remoteAddress + \"_50123\";\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationAllowedDefaultSettings() throws Exception {\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(new HashMap<String, Object>());\n\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationAllowedNotInBlacklist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.REGISTRATION_BLACKLIST_PROP_KEY, \n\t\t\t\t\"127.0.0.3,127.0.0.4\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationAllowedInWhitelist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.2,127.0.0.3\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationAllowedInCIDRWhitelist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.0/24\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationAllowedInCIDRMultipleWhitelist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.0/24,127.0.0.1/24\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationFromMultipleSourcesAllowedInCIDRWhitelist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.0/24\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tfor (int i = 0; i <= 255; i++) {\n\t\t\tassertTrue(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\t\tJID.jidInstance(connectionId(\"127.0.0.\" + i))));\n\t\t}\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedWhitelistOnlyEmpty() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedWhitelistOnly() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.3,127.0.0.4\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedCIDRWhitelistOnly() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.0/24\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tfor (int i = 0; i <= 255; i++) {\n\t\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\t\tJID.jidInstance(connectionId(\"127.0.1.\" + i))));\n\t\t}\n\t}\n\t\n\tpublic void testRegistrationNotAllowedWhitelistSingle() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.WHITELIST_REGISTRATION_ONLY_PROP_KEY, \n\t\t\t\tBoolean.TRUE.toString());\n\t\tsettings.put(JabberIqRegister.REGISTRATION_WHITELIST_PROP_KEY, \n\t\t\t\t\"127.0.0.3\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedInBlacklist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.REGISTRATION_BLACKLIST_PROP_KEY, \n\t\t\t\t\"127.0.0.2,127.0.0.3\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedInBlacklistSingle() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.REGISTRATION_BLACKLIST_PROP_KEY, \n\t\t\t\t\"127.0.0.2\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\tJID.jidInstance(CONNECTION_ID)));\n\t}\n\t\n\t@Test\n\tpublic void testRegistrationNotAllowedInCIDRBlacklist() throws Exception {\n\t\tHashMap<String, Object> settings = new HashMap<String, Object>();\n\t\tsettings.put(JabberIqRegister.REGISTRATION_BLACKLIST_PROP_KEY, \n\t\t\t\t\"127.0.0.0/24\");\n\t\t\n\t\tJabberIqRegister jabberIqRegister = new JabberIqRegister();\n\t\tjabberIqRegister.init(settings);\n\t\tfor (int i = 0; i <= 255; i++) {\n\t\t\tassertFalse(jabberIqRegister.isRegistrationAllowedForConnection(\n\t\t\t\t\tJID.jidInstance(connectionId(\"127.0.0.\" + i))));\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/MessageAmpTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\n\nimport org.junit.After;\nimport org.junit.Before;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic class MessageAmpTest extends ProcessorTestCase {\n\t\n\tprivate static final String XMLNS = \"http://jabber.org/protocol/amp\";\n\n\tprivate JID ampJid;\n\tprivate MessageAmp messageAmp;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tmessageAmp = new MessageAmp();\n\t\tMap<String,Object> settings = new HashMap<String,Object>();\n\t\tampJid = JID.jidInstance(\"amp@example1.com\");\n\t\tsettings.put(\"amp-jid\", ampJid.toString());\n\t\tmessageAmp.init(settings);\n\t\tsuper.setUp();\n\t}\t\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tmessageAmp = null;\n\t\tsuper.tearDown();\n\t}\t\t\n\t\n\t@Test\n\tpublic void testMessageProcessingWithAmp() throws Exception {\n\t\tJID senderJid = JID.jidInstance(\"sender@example.com/res-1\");\n\t\tJID recipientJid = JID.jidInstance(\"recipient@example.com/res-2\");\n\t\tXMPPResourceConnection senderSession = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), senderJid);\n\t\tXMPPResourceConnection recipientSession = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), recipientJid);\n\t\t\n\t\tElement messageEl = new Element(\"message\", \n\t\t\t\tnew String[] { \"from\", \"to\", \"type\" }, \n\t\t\t\tnew String[] { senderJid.toString(), recipientJid.toString(), \"chat\" });\n\t\tmessageEl.addChild(new Element(\"body\", \"Test 123\"));\n\t\tElement ampEl = new Element(\"amp\", new String[] { \"xmlns\" }, new String[] { XMLNS });\n\t\tampEl.addChild(new Element(\"rule\", new String[] { \"condition\", \"action\", \"value\" }, \n\t\t\t\tnew String[] { \"expire-at\", \"drop\", \"2024-01-01T00:00:00Z\" }));\n\t\tmessageEl.addChild(ampEl);\n\t\tPacket message = Packet.packetInstance(messageEl);\n\t\tmessage.setPacketFrom(senderSession.getConnectionId());\n\t\t\n\t\tMap<String,Object> settings = new HashMap<>();\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\tassertFalse(messageAmp.preProcess(message, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\t\n\t\tmessageAmp.process(message, senderSession, null, results, settings);\n\t\tassertEquals(1, results.size());\n\t\tmessage = results.poll();\n\t\tassertEquals(senderSession.getConnectionId().toString(), message.getAttributeStaticStr(\"from-conn-id\"));\n\t\tassertEquals(ampJid, message.getPacketTo());\n\t\t\n\t\tmessage.getElement().removeAttribute(\"from-conn-id\");\n\t\tmessage.setPacketTo(null);\n\t\tassertFalse(messageAmp.preProcess(message, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\t\t\n\t\t\n\t\tassertTrue(messageAmp.preProcess(message, recipientSession, null, results, settings));\n\t\tassertEquals(1, results.size());\t\n\t\tmessage = results.poll();\n\t\tassertEquals(null, message.getAttributeStaticStr(\"from-conn-id\"));\n\t\tassertEquals(ampJid, message.getPacketTo());\n\t\t\n\t\tmessage.setPacketFrom(ampJid);\n\t\tmessage.setPacketTo(null);\n\t\tassertFalse(messageAmp.preProcess(message, recipientSession, null, results, settings));\n\t\tassertEquals(0, results.size());\t\t\n\t\t\n\t\tmessageAmp.process(message, recipientSession, null, results, settings);\n\t\tassertEquals(1, results.size());\n\t\tmessage = results.poll();\n\t\tassertEquals(null, message.getAttributeStaticStr(\"from-conn-id\"));\n\t\tassertEquals(recipientSession.getConnectionId(), message.getPacketTo());\n\t}\n\n\n\t@Test\n\tpublic void testSilentlyIgnoringMessages() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\n\t\t// testing default behaviour - error message\n\t\tElement packetEl = new Element(\"message\", new String[] { \"from\", \"to\" },\n\t\t\t\tnew String[] { \"remote-user@test.com/res1\", res1.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tmessageAmp.process(packet, null, null, results, null);\n\t\tassertTrue(\"no error was generated\", !results.isEmpty());\n\t\tassertTrue(\"generated result is not an error\", results.poll().getType().equals( StanzaType.error));\n\n\n\t\t// testing silently ignoring error responses\n\t\tresults.clear();\n\t\tfinal HashMap<String, Object> settings = new HashMap<String,Object>();\n\t\tsettings.put( \"silently-ignore-message\", \"true\");\n\t\tmessageAmp.init(settings);\n\n\t\tmessageAmp.process(packet, null, null, results, null);\n\t\tassertTrue(\"result was generated\", results.isEmpty());\n\n\n\t}\n\t@Test\n\tpublic void testMessageProcessingWithoutAmp() throws Exception {\n\t\tJID senderJid = JID.jidInstance(\"sender@example.com/res-1\");\n\t\tJID recipientJid = JID.jidInstance(\"recipient@example.com/res-2\");\n\t\tXMPPResourceConnection senderSession = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), senderJid);\n\t\tXMPPResourceConnection recipientSession = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), recipientJid);\n\t\t\n\t\tElement messageEl = new Element(\"message\", \n\t\t\t\tnew String[] { \"from\", \"to\", \"type\" }, \n\t\t\t\tnew String[] { senderJid.toString(), recipientJid.toString(), \"chat\" });\n\t\tmessageEl.addChild(new Element(\"body\", \"Test 123\"));\t\t\n\t\t\n\t\tPacket message = Packet.packetInstance(messageEl);\n\t\tmessage.setPacketFrom(senderSession.getConnectionId());\n\t\t\n\t\tMap<String,Object> settings = new HashMap<>();\n\t\tQueue<Packet> results = new ArrayDeque<>();\n\t\tassertFalse(messageAmp.preProcess(message, senderSession, null, results, settings));\n\t\tassertEquals(0, results.size());\n\t\t\n\t\tmessageAmp.process(message, senderSession, null, results, settings);\n\t\tassertEquals(1, results.size());\n\t\tmessage = results.poll();\n\t\tassertEquals(null, message.getAttributeStaticStr(\"from-conn-id\"));\n\t\tassertEquals(null, message.getPacketFrom());\n\t\tassertEquals(null, message.getPacketTo());\n\n\t\tassertFalse(messageAmp.preProcess(message, recipientSession, null, results, settings));\n\t\tassertEquals(0, results.size());\t\t\n\t\t\n\t\tmessageAmp.process(message, recipientSession, null, results, settings);\n\t\tassertEquals(1, results.size());\n\t\tmessage = results.poll();\n\t\tassertEquals(null, message.getAttributeStaticStr(\"from-conn-id\"));\n\t\tassertEquals(recipientSession.getConnectionId(), message.getPacketTo());\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/MessageCarbonsTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.UUID;\nimport org.junit.After;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic class MessageCarbonsTest extends ProcessorTestCase {\n\n\tprivate MessageCarbons carbonsProcessor;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tcarbonsProcessor = new MessageCarbons();\n\t\tcarbonsProcessor.init(new HashMap<String,Object>());\n\t\tsuper.setUp();\n\t}\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tcarbonsProcessor = null;\n\t\tsuper.tearDown();\n\t}\t\t\n\t\n\t@Test\n\tpublic void testResourceSelectionForMessageDeliveryForBareJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tsession2.putSessionData(MessageCarbons.XMLNS + \"-enabled\", true);\n\t\tMap<JID,Boolean> enabled = new HashMap<>();\n\t\tenabled.put(res2, true);\n\t\tsession2.putCommonSessionData(MessageCarbons.XMLNS + \"-resources\", enabled);\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", userJid.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session2, null, results, null);\n\t\tassertEquals(\"generated result even than no resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session2.getJID()), collectStanzaTo(results));\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session2, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 1 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session2.getJID()), collectStanzaTo(results));\n\t\t\n\t\tsession2.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session1, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 2 resource had nonnegative priority\", 0, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(), \n\t\t\t\tcollectStanzaTo(results));\t\t\n\t}\t\n\t\n\t@Test\n\tpublic void testResourceSelectionForMessageDeliveryForFullJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tsession2.putSessionData(MessageCarbons.XMLNS + \"-enabled\", true);\n\t\tMap<JID,Boolean> enabled = new HashMap<>();\n\t\tenabled.put(res2, true);\n\t\tsession2.putCommonSessionData(MessageCarbons.XMLNS + \"-resources\", enabled);\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", res1.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session1, null, results, null);\n\t\tassertEquals(\"generated result even than no resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session2.getJID()), collectStanzaTo(results));\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session1, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 1 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session2.getJID()), collectStanzaTo(results));\n\t\t\n\t\tsession2.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tcarbonsProcessor.process(packet, session1, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 2 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session2.getJID()), collectStanzaTo(results));\n\n\t\tresults = new ArrayDeque<Packet>();\n\t\tPacket packet1 = packet.copyElementOnly();\n\t\tpacket1.getElement().addChild(new Element(\"no-copy\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:hints\" }));\n\t\tcarbonsProcessor.process(packet1, session1, null, results, null);\t\t\n\t\tassertEquals(\"generated result even that no-copy was sent\", 0, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Collections.EMPTY_LIST, collectStanzaTo(results));\n\t\n\t}\t\n\n\tprotected List<JID> collectStanzaTo(Queue<Packet> packets) {\n\t\tList<JID> result = new ArrayList<JID>();\n\t\tPacket p;\n\t\twhile ((p = packets.poll()) != null) {\n\t\t\tresult.add(p.getStanzaTo());\n\t\t}\n\t\treturn result;\n\t}\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/MessageTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.UUID;\n\nimport org.junit.After;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport tigase.server.Packet;\n\nimport tigase.xml.Element;\n\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\n\n/**\n *\n * @author andrzej\n */\npublic class MessageTest extends ProcessorTestCase {\n\t\n\tprivate Message messageProcessor;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tmessageProcessor = new Message();\n\t\tmessageProcessor.init(new HashMap<String,Object>());\n\t\tsuper.setUp();\n\t}\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tmessageProcessor = null;\n\t\tsuper.tearDown();\n\t}\t\n\n\t@Test\n\tpublic void testSilentlyIgnoringMessages() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\n\t\t// testing default behaviour - error message\n\t\tElement packetEl = new Element(\"message\", new String[] { \"from\", \"to\" },\n\t\t\t\tnew String[] { \"remote-user@test.com/res1\", res1.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, null, null, results, null);\n\t\tassertTrue(\"no error was generated\", !results.isEmpty());\n\t\tassertTrue(\"generated result is not an error\", results.poll().getType().equals( StanzaType.error));\n\n\n\t\t// testing silently ignoring error responses\n\t\tresults.clear();\n\t\tfinal HashMap<String, Object> settings = new HashMap<String,Object>();\n\t\tsettings.put( \"silently-ignore-message\", \"true\");\n\t\tmessageProcessor.init(settings);\n\n\t\tmessageProcessor.process(packet, null, null, results, null);\n\t\tassertTrue(\"result was generated\", results.isEmpty());\n\t}\n\t\n\t@Test\n\tpublic void testResourceSelectionForMessageDeliveryMethods() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(res1, res1);\n\t\tXMPPResourceConnection session2 = getSession(res2, res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\tassertEquals(Collections.emptyList(), messageProcessor.getConnectionsForMessageDelivery(session1));\n\t\t\n\t\tassertFalse(\"found XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tsession1.setPriority(1);\n\t\tassertFalse(\"found XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\t\n\t\tassertEquals(Arrays.asList(session1), messageProcessor.getConnectionsForMessageDelivery(session2));\n\t\t\n\t\tsession2.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tassertEquals(Arrays.asList(session1, session2), messageProcessor.getConnectionsForMessageDelivery(session2));\n\t}\n\t\n\t@Test\n\tpublic void testResourceSelectionForMessageDeliveryForBareJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\tassertEquals(Collections.emptyList(), messageProcessor.getConnectionsForMessageDelivery(session1));\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", userJid.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\n\t\tassertTrue(\"generated result even than no resource had nonnegative priority\", results.isEmpty());\n\t\t\n\t\tsession1.setPriority(1);\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\n\t\tassertTrue(\"generated result even than no resource had nonnegative priority\", results.isEmpty());\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 1 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId()), collectPacketTo(results));\n\t\t\n\t\tsession2.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session1, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 2 resource had nonnegative priority\", 2, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId(), session2.getConnectionId()), \n\t\t\t\tcollectPacketTo(results));\t\t\n\t}\t\n\t\n\t@Test\n\tpublic void testResourceSelectionForMessageDeliveryForFullJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\tassertEquals(Collections.emptyList(), messageProcessor.getConnectionsForMessageDelivery(session1));\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", res1.toString() });\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\n\t\tassertEquals(\"not generated result even than no resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId()), collectPacketTo(results));\n\t\t\n\t\tsession1.setPriority(1);\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\n\t\tassertEquals(\"not generated result even than no resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId()), collectPacketTo(results));\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session2, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 1 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId()), collectPacketTo(results));\n\t\t\n\t\tsession2.setPresence(new Element(\"presence\"));\n\t\tassertTrue(\"could not find XMPPResourceConnection for delivery of message\", \n\t\t\t\tmessageProcessor.hasConnectionForMessageDelivery(session1));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tmessageProcessor.process(packet, session1, null, results, null);\t\t\n\t\tassertEquals(\"not generated result even than 2 resource had nonnegative priority\", 1, results.size());\n\t\tassertEquals(\"packet sent to wrong jids\", Arrays.asList(session1.getConnectionId()), collectPacketTo(results));\n\t}\t\n\n\t\n\tprotected List<JID> collectPacketTo(Queue<Packet> packets) {\n\t\tList<JID> result = new ArrayList<JID>();\n\t\tPacket p;\n\t\twhile ((p = packets.poll()) != null) {\n\t\t\tresult.add(p.getPacketTo());\n\t\t}\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/MobileV3Test.java",
    "content": "/*\n * MobileV3Test.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2014 \"Artur Hefczyc\" <artur.hefczyc@tigase.org>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\n\npackage tigase.xmpp.impl;\n\nimport java.util.ArrayDeque;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport junit.framework.TestCase;\nimport org.junit.After;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport tigase.db.TigaseDBException;\nimport tigase.server.Packet;\nimport tigase.server.xmppsession.SessionManagerHandler;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\n/**\n *\n * @author andrzej\n */\npublic class MobileV3Test extends ProcessorTestCase {\n\t\n\tprivate MobileV3 mobileV3;\n\tprivate SessionManagerHandler loginHandler;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tmobileV3 = new MobileV3();\n\t\tmobileV3.init(new HashMap<String,Object>());\n\t\tsuper.setUp();\n\t}\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tmobileV3 = null;\n\t\tsuper.tearDown();\n\t}\n\t\n\t@Test\n\tpublic void testRecipientDisabledFor2ResourcesMessage() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\tPacket p = Packet.packetInstance(\"message\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(p);\n\t\tPacket[] expected = results.toArray(new Packet[0]);\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t}\n\t\n\t@Test\n\tpublic void testRecipientEnabledFor2ResourcesMessage() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\t\n\t\tenableMobileV3(session1, recp1);\n\t\t\n\t\tPacket p = Packet.packetInstance(\"message\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(p);\n\t\tPacket[] expected = results.toArray(new Packet[0]);\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t}\n\n\t@Test\n\tpublic void testRecipientDisabledFor2ResourcesPresence() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\tPacket p = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(p);\n\t\tPacket[] expected = results.toArray(new Packet[0]);\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t}\n\n\t@Test\n\tpublic void testRecipientEnabledFor2ResourcesPresence() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\t\n\t\tenableMobileV3(session1, recp1);\n\t\t\n\t\tPacket presence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(presence);\n\t\tPacket[] expected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t}\n\n\t@Test\n\tpublic void testRecipientEnabledFor2Resources2Presences() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\t\n\t\tenableMobileV3(session1, recp1);\n\t\t\n\t\tPacket presence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(presence);\n\t\tPacket[] expected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t\t\n\t\tpresence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tresults = new ArrayDeque<Packet>();\n\t\tresults.offer(presence);\n\t\texpected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t\n\t\tresults.clear();\n\t\tPacket p = Packet.packetInstance(\"message\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tresults.offer(p);\n\t\tPacket p1 = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.error);\n\t\tp1.setPacketTo(connId1);\t\t\n\t\tresults.offer(p1);\n\t\texpected = new Packet[] { presence, p, p1 };\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\t\t\n\t}\t\n\t\n\t\n\t@Test\n\tpublic void testRecipientEnabledFor2Resources() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\t\n\t\tenableMobileV3(session1, recp1);\n\t\t\n\t\tPacket presence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(presence);\n\t\tPacket[] expected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t\t\n\t\tresults.clear();\n\t\tPacket p = Packet.packetInstance(\"message\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tresults.offer(p);\n\t\tPacket p1 = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.error);\n\t\tp1.setPacketTo(connId1);\t\t\n\t\tresults.offer(p1);\n\t\texpected = new Packet[] { presence, p, p1 };\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\t\t\n\t}\t\n\t\n\t@Test\n\tpublic void testRecipientEnabledFor2ResourcesMixed() throws TigaseStringprepException, NotAuthorizedException {\n\t\tString recipient = \"recipient-1@localhost\";\n\t\tJID recp1 = JID.jidInstanceNS(recipient + \"/res1\");\n\t\tJID recp2 = JID.jidInstanceNS(recipient + \"/res2\");\n\t\tJID connId1 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res1\");\n\t\tJID connId2 = JID.jidInstanceNS(\"c2s@localhost/recipient1-res2\");\n\t\tXMPPResourceConnection session1 = getSession(connId1, recp1);\n\t\tgetSession(connId2, recp2);\n\t\t\n\t\tenableMobileV3(session1, recp1);\n\t\t\n\t\tPacket presence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tresults.offer(presence);\n\t\tPacket[] expected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tPacket[] processed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\n\t\tresults.clear();\n\t\tPacket m1 = Packet.packetInstance(\"message\", recp2.toString(), recp1.toString(), StanzaType.chat);\n\t\tElement receivedEl = new Element(\"received\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:carbons:2\" });\n\t\tElement forwardedEl = new Element(\"forwarded\", new String[] {\"xmlns\" }, new String[] { \"urn:xmpp:forward:0\" });\n\t\tforwardedEl.addChild(new Element(\"message\", new String[] { \"from\", \"to\" }, new String[] { recp2.toString(), \"sender-1@localhost/res1\" }));\n\t\treceivedEl.addChild(forwardedEl);\n\t\tm1.getElement().addChild(receivedEl);\n\t\tm1.setPacketTo(connId1);\n\t\tresults.offer(m1);\n\t\texpected = new Packet[0];\n\t\tmobileV3.filter(m1, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\t\t\t\n\t\t\n\t\tresults.clear();\n\t\tpresence = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.available);\n\t\tpresence.setPacketTo(connId1);\n\t\tresults.offer(presence);\n\t\texpected = new Packet[0];// results.toArray(new Packet[0]);\n\t\tmobileV3.filter(presence, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\n\t\n\t\tresults.clear();\n\t\tPacket p = Packet.packetInstance(\"message\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.chat);\n\t\tp.setPacketTo(connId1);\n\t\tresults.offer(p);\n\t\tPacket p1 = Packet.packetInstance(\"presence\", \"sender-1@localhost/res1\", recp1.toString(), StanzaType.error);\n\t\tp1.setPacketTo(connId1);\t\t\n\t\tresults.offer(p1);\n\t\texpected = new Packet[] { presence, m1, p, p1 };\n\t\tmobileV3.filter(p, session1, null, results);\n\t\tprocessed = results.toArray(new Packet[0]);\n\t\tAssert.assertArrayEquals(expected, processed);\t\t\n\t}\t\n\n\tprivate Queue<Packet> enableMobileV3(XMPPResourceConnection session, JID userJid) throws TigaseStringprepException {\n\t\tPacket p = Packet.packetInstance(\"iq\", userJid.toString(), userJid.toString(), StanzaType.set);\n\t\tp.getElement().addChild(new Element(\"mobile\", new String[] { \"xmlns\", \"enable\" }, \n\t\t\t\tnew String[] { \"http://tigase.org/protocol/mobile#v3\", \"true\" }));\n\t\tArrayDeque<Packet> results = new ArrayDeque<Packet>();\n\t\tmobileV3.process(p, session, null, results, null);\n\t\treturn results;\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/OfflineMessagesTest.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\nimport tigase.db.DBInitException;\nimport tigase.db.MsgRepositoryIfc;\nimport tigase.db.NonAuthUserRepository;\nimport tigase.db.UserNotFoundException;\nimport tigase.server.Packet;\nimport tigase.xml.Element;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.XMPPResourceConnection;\n\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n *\n * @author andrzej\n */\npublic class OfflineMessagesTest extends ProcessorTestCase {\n\t\n\tprivate OfflineMessages offlineProcessor;\n\tprivate MsgRepositoryIfcImpl msgRepo;\n\t\n\t@Before\n\t@Override\n\tpublic void setUp() throws Exception {\n\t\tmsgRepo = new MsgRepositoryIfcImpl();\n\t\tofflineProcessor = new OfflineMessages() {\n\t\t\t@Override\n\t\t\tprotected MsgRepositoryIfc getMsgRepoImpl(NonAuthUserRepository repo, XMPPResourceConnection conn) {\n\t\t\t\treturn msgRepo;\n\t\t\t}\n\t\t};\n\t\tofflineProcessor.init(new HashMap<String,Object>());\n\t\tsuper.setUp();\n\t}\n\t\n\t@After\n\t@Override\n\tpublic void tearDown() throws Exception {\n\t\tofflineProcessor = null;\n\t\tmsgRepo = null;\n\t\tsuper.tearDown();\n\t}\t\n\n\t@Test\n\tpublic void testStorageOfflineMessageForBareJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", userJid.toString() });\n\t\tpacketEl.addChild(new Element(\"body\", \"Test message\"));\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"no message stored, while it should be stored\", !msgRepo.getStored().isEmpty());\n\t\t\n\t\tmsgRepo.getStored().clear();\n\t\t\n\t\tsession1.setPriority(1);\n\t\tresults = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"no message stored, while it should be stored\", !msgRepo.getStored().isEmpty());\n\t\t\n\t\tmsgRepo.getStored().clear();\t\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"message stored, while it should not be stored\", msgRepo.getStored().isEmpty());\t\t\n\t\t\n\t\tmsgRepo.getStored().clear();\n\t}\t\n\t\n\t@Test\n\tpublic void testStorageOfflineMessageForFullJid() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\t\n\t\tElement packetEl = new Element(\"message\", new String[] { \"type\", \"from\", \"to\" },\n\t\t\t\tnew String[] { \"chat\", \"remote-user@test.com/res1\", res2.toString() });\n\t\tpacketEl.addChild(new Element(\"body\", \"Test message\"));\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tQueue<Packet> results = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"message stored, while it should not be stored\", msgRepo.getStored().isEmpty());\n\t\t\n\t\tmsgRepo.getStored().clear();\n\t\t\n\t\tsession1.setPriority(1);\n\t\tresults = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"message stored, while it should not be stored\", msgRepo.getStored().isEmpty());\n\t\t\n\t\tmsgRepo.getStored().clear();\t\n\t\t\n\t\tsession1.setPresence(new Element(\"presence\"));\n\t\tresults = new ArrayDeque<Packet>();\n\t\tofflineProcessor.postProcess(packet, session1, null, results, null);\n\t\tassertTrue(\"generated result even than no result should be generated\", results.isEmpty());\n\t\tassertTrue(\"message stored, while it should not be stored\", msgRepo.getStored().isEmpty());\n\t\t\n\t\tmsgRepo.getStored().clear();\n\t}\t\t\n\n\n\t@Test\n\tpublic void testRestorePacketForOffLineUser() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\n\t\tassertEquals(Arrays.asList(session1), session1.getActiveSessions());\n\n\t\tElement packetEl = new Element(\"iq\", new String[] { \"type\", \"from\", \"to\", \"time\" },\n\t\t\t\tnew String[] { \"set\", \"dip1@test.com/res1\", userJid.toString(), \"1440810935000\" });\n\t\tpacketEl.addChild(new Element(\"jingle\", new String[] { \"action\", \"sid\", \"offline\", \"xmlns\" },\n\t\t\t\tnew String[] { \"session-terminate\", UUID.randomUUID().toString(), \"true\", \"urn:xmpp:jingle:1\" }));\n\t\tPacket packet = Packet.packetInstance(packetEl);\n\t\tmsgRepo.storeMessage( packet.getFrom(), packet.getTo(), null, packet.getElement(), null);\n\n\t\tpacketEl = new Element(\"iq\", new String[] { \"type\", \"from\", \"to\", \"time\" },\n\t\t\t\tnew String[] { \"set\", \"dip1@test.com/res1\", userJid.toString(), \"1440810972000\" });\n\t\tpacketEl.addChild(new Element(\"jingle\", new String[] { \"action\", \"sid\", \"offline\", \"xmlns\" },\n\t\t\t\tnew String[] { \"session-terminate\", UUID.randomUUID().toString(), \"true\", \"urn:xmpp:jingle:1\" }));\n\t\tpacket = Packet.packetInstance(packetEl);\n\t\tmsgRepo.storeMessage( packet.getFrom(), packet.getTo(), null, packet.getElement(), null);\n\n\t\tassertTrue(\"no message stored, while it should be stored\", !msgRepo.getStored().isEmpty());\n\n\t\tQueue<Packet> restorePacketForOffLineUser = offlineProcessor.restorePacketForOffLineUser( session1, msgRepo );\n\n\t\tassertEquals(\"number of restored messages differ!\", restorePacketForOffLineUser.size(), 2);\n\n\t\tmsgRepo.getStored().clear();\n\t}\n\n\t@Test\n\tpublic void testLoadOfflineMessages() throws Exception {\n\t\tBareJID userJid = BareJID.bareJIDInstance(\"user1@example.com\");\n\t\tJID res1 = JID.jidInstance(userJid, \"res1\");\n\t\tJID res2 = JID.jidInstance(userJid, \"res2\");\n\t\tXMPPResourceConnection session1 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res1);\n\t\tXMPPResourceConnection session2 = getSession(JID.jidInstance(\"c2s@example.com/\" + UUID.randomUUID().toString()), res2);\n\t\t\n\t\tassertEquals(Arrays.asList(session1, session2), session1.getActiveSessions());\n\t\t\n\t\tElement presenceEl = new Element(\"presence\", new String[] { \"from\", \"to\" }, new String[] { res1.toString(), res2.toString() });\n\t\tPacket packet = Packet.packetInstance(presenceEl);\n\t\tassertFalse(offlineProcessor.loadOfflineMessages(packet, session1));\n\t\t\n\t\tpresenceEl = new Element(\"presence\", new String[] { \"from\" }, new String[] { res1.toString() });\n\t\tpacket = Packet.packetInstance(presenceEl);\n\t\tassertTrue(offlineProcessor.loadOfflineMessages(packet, session1));\t\n\t}\t\n\t\n\t@Test\n\tpublic void testIsAllowedForOfflineStorage() throws Exception {\n\t\tPacket packet = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"body\", \"Test message\")\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\n\t\tassertTrue(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t\t\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"storeMe1\", new String[] { \"xmlns\" }, new String[] { \"custom_xmlns\" })\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\t\t\n\t\t\n\t\tassertFalse(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t\t\n\t\tMap<String,Object> settings = new HashMap<>();\n\t\tsettings.put(\"msg-store-offline-paths\", new String[] {\n\t\t\t\"/message/storeMe1[custom_xmlns]\",\n\t\t\t\"/message/storeMe2\",\n\t\t\t\"-/message/noStore1\"\n\t\t});\n\t\tofflineProcessor.init(settings);\t\n\n\t\tassertTrue(offlineProcessor.isAllowedForOfflineStorage(packet));\n\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"storeMe2\", new String[] { \"xmlns\" }, new String[] { \"custom_xmlns\" })\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\t\t\n\n\t\tassertTrue(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t\t\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"storeMe3\", new String[] { \"xmlns\" }, new String[] { \"custom_xmlns\" })\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\t\n\t\t\n\t\tassertFalse(offlineProcessor.isAllowedForOfflineStorage(packet));\t\n\t\t\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"body\", \"Test message 123\"),\n\t\t\tnew Element(\"no-store\", new String[] { \"xmlns\" }, new String[] { \"urn:xmpp:hints\" })\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\n\t\t\n\t\tassertFalse(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t\t\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"noStore1\"), new Element(\"body\", \"body of message\")\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\t\n\t\tassertFalse(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t\t\n\t\tpacket = Packet.packetInstance(new Element(\"message\", new Element[]{\n\t\t\tnew Element(\"body\", \"body of message\")\n\t\t}, new String[] { \"from\", \"to\" }, new String[] { \"from@example.com/res1\", \"to@example.com/res2\" }));\t\n\t\tassertTrue(offlineProcessor.isAllowedForOfflineStorage(packet));\n\t}\n\t\n\tprivate static class MsgRepositoryIfcImpl implements MsgRepositoryIfc {\n\n\t\tprivate final Queue<Packet> stored = new ArrayDeque();\n\t\t\n\t\tpublic MsgRepositoryIfcImpl() {\n\t\t}\n\n\t\t@Override\n\t\tpublic Element getMessageExpired(long time, boolean delete) {\n\t\t\tthrow new UnsupportedOperationException(\"Not supported yet.\"); //To change body of generated methods, choose Tools | Templates.\n\t\t}\n\n\t\t@Override\n\t\tpublic Queue<Element> loadMessagesToJID(XMPPResourceConnection session, boolean delete) throws UserNotFoundException {\n\t\t\tQueue<Element> res = new LinkedList<Element>();\n\t\t\tfor ( Packet pac : stored ) {\n\t\t\t\tres.add( pac.getElement());\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic boolean storeMessage(JID from, JID to, Date expired, Element msg, NonAuthUserRepository userRepo) throws UserNotFoundException {\n\t\t\treturn stored.offer(Packet.packetInstance(msg, from, to));\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic void initRepository(String resource_uri, Map<String, String> params) throws DBInitException {\n\t\t}\n\t\t\n\t\tpublic Queue<Packet> getStored() {\n\t\t\treturn stored;\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/ProcessorTestCase.java",
    "content": "/*\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n * \n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, version 3 of the License,\n * or (at your option) any later version.\n * \n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n * \n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n */\npackage tigase.xmpp.impl;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport junit.framework.TestCase;\nimport tigase.db.AuthRepository;\nimport tigase.db.UserRepository;\nimport tigase.db.xml.XMLRepository;\nimport tigase.server.xmppsession.SessionManagerHandler;\nimport tigase.util.TigaseStringprepException;\nimport tigase.vhosts.VHostItem;\nimport tigase.xmpp.BareJID;\nimport tigase.xmpp.JID;\nimport tigase.xmpp.NotAuthorizedException;\nimport tigase.xmpp.XMPPResourceConnection;\nimport tigase.xmpp.XMPPSession;\n\n/**\n *\n * @author andrzej\n */\npublic abstract class ProcessorTestCase  {\n\t\n\tprivate static Logger log;\n\t\n\tprivate SessionManagerHandler loginHandler;\n\t\n\t//@Override\n\tpublic void setUp() throws Exception {\n\t\tloginHandler = new SessionManagerHandlerImpl();\n\t}\n\t\n\t//@Override\n\tpublic void tearDown() throws Exception {\n\t\tloginHandler = null;\n\t}\t\n\t\n\tprotected XMPPResourceConnection getSession( JID connId, JID userJid) throws NotAuthorizedException, TigaseStringprepException {\n\n\t\tString xmlRepositoryURI = \"memory://xmlRepo?autoCreateUser=true\";\n\t\tXMLRepository xmlRepository = new XMLRepository();\n\t\txmlRepository.initRepository( xmlRepositoryURI, null );\n\n\t\tXMPPResourceConnection conn = new XMPPResourceConnection( connId, (UserRepository) xmlRepository, (AuthRepository) xmlRepository, loginHandler );\n\t\tVHostItem vhost = new VHostItem();\n\t\tvhost.setVHost( userJid.getDomain() );\n\t\tconn.setDomain( vhost );\n\t\tconn.authorizeJID( userJid.getBareJID(), false );\n\t\tconn.setResource( userJid.getResource() );\n\n\t\treturn conn;\n\t}\t\n\n\tprivate class SessionManagerHandlerImpl implements SessionManagerHandler {\n\n\t\tpublic SessionManagerHandlerImpl() {\n\t\t}\n\t\tMap<BareJID, XMPPSession> sessions = new HashMap<BareJID, XMPPSession>();\n\n\t\t@Override\n\t\tpublic JID getComponentId() {\n\t\t\treturn JID.jidInstanceNS( \"sess-man@localhost\" );\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleLogin( BareJID userId, XMPPResourceConnection conn ) {\n\t\t\tXMPPSession session = sessions.get( userId );\n\t\t\tif ( session == null ){\n\t\t\t\tsession = new XMPPSession( userId.getLocalpart() );\n\t\t\t\tsessions.put( userId, session );\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsession.addResourceConnection( conn );\n\t\t\t} catch ( TigaseStringprepException ex ) {\n\t\t\t\tlog.log( Level.SEVERE, null, ex );\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleLogout( BareJID userId, XMPPResourceConnection conn ) {\n\t\t\tXMPPSession session = sessions.get( conn );\n\t\t\tif ( session != null ){\n\t\t\t\tsession.removeResourceConnection( conn );\n\t\t\t\tif ( session.getActiveResourcesSize() == 0 ){\n\t\t\t\t\tsessions.remove( userId );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void handlePresenceSet( XMPPResourceConnection conn ) {\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleResourceBind( XMPPResourceConnection conn ) {\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isLocalDomain( String domain, boolean includeComponents ) {\n\t\t\treturn !domain.contains( \"-ext\" );\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleDomainChange(String domain, XMPPResourceConnection conn) {\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/VCardHelperTest.java",
    "content": "package tigase.xmpp.impl;\n\nimport static org.junit.Assert.*;\nimport org.junit.Test;\nimport tigase.xml.DomBuilderHandler;\nimport tigase.xml.Element;\nimport tigase.xml.SimpleParser;\nimport tigase.xml.SingletonFactory;\n\n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/**\n *\n * @author andrzej\n */\npublic class VCardHelperTest {\n\tprivate static String VCARD_TEMP_DATA = (\"<vCard xmlns=\\\"vcard-temp\\\">\\n\" +\n\"  <FN>Peter Saint-Andre</FN>\\n\" +\n\"  <N>\\n\" +\n\"    <FAMILY>Saint-Andre</FAMILY>\\n\" +\n\"    <GIVEN>Peter</GIVEN>\\n\" +\n\"    <MIDDLE/>\\n\" +\n\"  </N>\\n\" +\n\"  <NICKNAME>stpeter</NICKNAME>\\n\" +\n\"  <NICKNAME>psa</NICKNAME>\\n\" +\n\"  <PHOTO><EXTVAL>http://stpeter.im/images/stpeter_oscon.jpg</EXTVAL></PHOTO>\\n\" +\n\"  <PHOTO><EXTVAL>http://stpeter.im/images/stpeter_hell.jpg</EXTVAL></PHOTO>\\n\" +\n\"  <BDAY>1966-08-06</BDAY>\\n\" +\n\"  <ADR>\\n\" +\n\"    <WORK/>\\n\" +\n\"    <PREF/>\\n\" +\n\"    <EXTADD>Suite 600</EXTADD>\\n\" +\n\"    <STREET>1899 Wynkoop Street</STREET>\\n\" +\n\"    <LOCALITY>Denver</LOCALITY>\\n\" +\n\"    <REGION>CO</REGION>\\n\" +\n\"    <PCODE>80202</PCODE>\\n\" +\n\"    <CTRY>USA</CTRY>\\n\" +\n\"  </ADR>\\n\" +\n\"  <ADR>\\n\" +\n\"    <HOME/>\\n\" +\n\"    <EXTADD/>\\n\" +\n\"    <STREET/>\\n\" +\n\"    <LOCALITY>Parker</LOCALITY>\\n\" +\n\"    <REGION>CO</REGION>\\n\" +\n\"    <PCODE>80138</PCODE>\\n\" +\n\"    <CTRY>USA</CTRY>\\n\" +\n\"  </ADR>\\n\" +\n\"  <TEL><WORK/><VOICE/><NUMBER>+1-303-308-3282</NUMBER><PREF/></TEL>\\n\" +\n\"  <TEL><WORK/><FAX/><NUMBER>+1-303-308-3219</NUMBER></TEL>\\n\" +\n\"  <TEL><CELL/><VOICE/><TEXT/><NUMBER>+1-720-256-6756</NUMBER></TEL>\\n\" +\n\"  <TEL><HOME/><VOICE/><NUMBER>+1-303-555-1212</NUMBER></TEL>\\n\" +\n\"  <EMAIL><INTERNET/><USERID>stpeter@jabber.org</USERID></EMAIL>\\n\" +\n\"  <EMAIL><WORK/><USERID>psaintan@cisco.com</USERID></EMAIL>\\n\" +\n\"  <JABBERID>stpeter@jabber.org</JABBERID>\\n\" +\n\"  <TZ>America/Denver</TZ>\\n\" +\n\"  <GEO><LAT>39.59</LAT><LON>-105.01</LON></GEO>\\n\" +\n\"  <TITLE>Executive Director</TITLE>\\n\" +\n\"  <ROLE>Patron Saint</ROLE>\\n\" +\n\"  <LOGO>\\n\" +\n\"    <TYPE>image/jpeg</TYPE>\\n\" +\n\"    <BINVAL>\\n\" +\n\"/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHBgUI\\n\" +\n\"BwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy\\n\" +\n\"/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy\\n\" +\n\"MjIyMjIyMjIyMjIy/8AAEQgAgQB7AwEiAAIRAQMRAf/EABsAAAMAAwEBAAAAAAAAAAAAAAQFBgAD\\n\" +\n\"BwIB/8QAPRAAAgEDAwIDBQQJBAEFAAAAAQIDAAQRBRIhMUEGE1EiYXGBkRQyobEHFSMzNEJScsEk\\n\" +\n\"YtHw0jVDc8Lh/8QAGQEAAwEBAQAAAAAAAAAAAAAAAQIEAwAF/8QAJBEAAgICAgICAgMAAAAAAAAA\\n\" +\n\"AAECEQMhEjEEQSJREzJCYXH/2gAMAwEAAhEDEQA/AOf2c0KGSY2pDFiinYMsCMfhj8aya6gdvZj9\\n\" +\n\"ryg6A8eYuORxQk1rdzSHyZGQYO0GXAPv/MV6luDp8QgntkRyhAfHJ3Y5wOoxxXncbdiA9zp/6xQG\\n\" +\n\"KaGFIhK208MwX09amCOeMEdjT3VLi1EaeVGHEi4WRCQVwAD7PY5/CkQYbcfdPUVbjTS2FGAHGele\\n\" +\n\"1nmXgOw6/iMV4LnHup/4c8L3/iWfbboIoFPt3D/dH/kfcKd0kOotukL/ALWs8SJNEPZGA4/z2omD\\n\" +\n\"T7++dY7azuLlAOPs8Jfb9P8Amu1+Hv0Z+HtPjVp7YX846yXAyM+5elX1tDa2sKxwxRxoBgKigD6U\\n\" +\n\"nJGn4a7OB+G/0Y67rlxuuIRptojDdcXS5c/2R9SfoPfXY/DvgzQvCiLJZW/m3uPavbgb5Sf9vZPl\\n\" +\n\"9TVCBAw5RfiODQ93Fdi3b9XyxiXt5iE59wNPGSEnja6N5VyCzHYh5LOcUvuNc0y0JDTtO/8ATGP8\\n\" +\n\"1Hahc6g87xX0ku9TyhbH4dKEA6AZx1prJ2n7KW58W3L5W1iS3H9XVsfGlMl3NdNvmld8/wBRoMHH\\n\" +\n\"NbM5Hw5oAoIjALHPfA59O9KL218NS3byXtjE9w+GdivqBj8MUyk5ikAOPZ61rtreDUbaO5kiTeV2\\n\" +\n\"HJ7r7P8AiuGSOXDyzBE1zlInAKFR6k9a+XFtHt8qWczjGVUKSAvPHu+VLftckzPu+62U2E5256Y7\\n\" +\n\"1S+Fkj1DxPDaXEe5YYHldc9doGAfdnFQLE+VDdCc2ZXDaQDMTgFDEC6H175zgjimcv6PfFmvXMcy\\n\" +\n\"6SttFtB8+4dIEIIz0PPfsKuE1O7tEMVoy2sfPs28Sxdev3Rmh5Jp52LyzSSnqS7E/nVkIcezrFlj\\n\" +\n\"+ibSrC3aXWNbF9dAezaad93P+6Qjp8AKsNMt4LO1hgto0ihXhVj6CldrsSLoMt7qNhuiiDJyPSsc\\n\" +\n\"k23Rfgi4qyphkCqAMcUQsue9TsGoAkDP1osXOT1oWO0x2JOeua2rPiki3GO/Hxr0L5F/nFGwNB2q\\n\" +\n\"2UWq2+MAXCcxv/g/GopkaNijqVdWIYHqDVSt9uDYbt2pRrKrJJDdgcyrh/7h/wDlawlZLnh7QB96\\n\" +\n\"E46ivSnlDXyAAyFD/Nx9elZGQ0XHJVsH3VqSntk3W7oDgEYz6ULbWkkURUuxO9ySOMksTRY5iPx5\\n\" +\n\"o6KaMxKSygnkjFdQUzhMca3Mau7KXXII28EdvnVv4FtTLq97dOwLR2PlDHUEsD/ioO1uHCg9Og9B\\n\" +\n\"mrPwXrENomp3EynYApYoMkYGOfRfaHuqeKansdlHOMTOeOSelaxjml763ayalcBplW22K8bnoCRl\\n\" +\n\"gT3x2xW21v4bosoDIRgKHGGbPTjPpzWjkmhUrYbFNhgPSjLYPN7K45oGNRtDnGCCc+6grvxhDZsY\\n\" +\n\"rS3LBeN/9VSvbPTi+KK6GwGBucg0T5HljqSPhXMz4/uFmAa1brzk4qisfFS3UIcMR6g9qL12FS5d\\n\" +\n\"FasLOOMAV5ktMDIwamLjxVFagmWTC+g60HF+kOw85UzIfftoJphbrsqTKYwynI7VlzMJdP2fzKQw\\n\" +\n\"+VDJqFjqsPmW0w8wclfWtYV3kKLzlSaeLakZ5acT6jhZIz0Vhj4HtXqQFLuTjaXGTitJztZSuGjY\\n\" +\n\"EgjHuomQ7khlHpzVh5h8Gfs+e5oK6juvtDbCQuAQMj0FGkZgweo3D8DXiUxiTBYZAHYelKdRw85h\\n\" +\n\"uPImyG3glT0z61WadpVteeCdQu4DKk8ZKFVwd53DHPUDDduDioieSYsryZIJ4JGSapvB2pG21CWz\\n\" +\n\"iLSR3kZR0ZcYI6H48kUvH2zRjLTdOngh+23gSGOFdzPMvKgEg4Pr299btN8Qw3Es8kenwolxJgvs\\n\" +\n\"BaMKPZOex+HrQXirWJdQu10m0kLwwkCUr0kk/wDFe3zo/wAP6KqxyW8hO5wWIHfHXFZSjS0beNXO\\n\" +\n\"2Uk2bmyaKH75XaAPSpC48P3qysvnJEf5VPUiq/TzsYhSckkD4U4uNLtL61Czp7XZhwR8xWKu7LeK\\n\" +\n\"emckk0a8VZGmkBYfcG7qaqvB+izSyMJh7O3INOx4bsrUmTy2kI6F2JApxo0ZWfftCx4xxTSbloEI\\n\" +\n\"KPRz7xjp89veMsSkoOmKQR2N9bTKgtzJuI7HH1zXW9XsYrq4kWZCQ3Rh1FJk8LXayfsLobO3mJuo\\n\" +\n\"xlx1QJwUttk3pDzwX8REEkTA9G6H1Hvq41Gznv8ASpoLMSCeZQIihwwbIPB7Vvh0j7PEPtDeY3rj\\n\" +\n\"AHw9KUa3c3EVmY7aXy3LfeHXHGefnSOTsbhy+Jmm61JLdHS9e/02oqTHHdNgJKf6X9D6HpTpoJYk\\n\" +\n\"aF125JIB6qf+4qXk0/8AWFnHJMfM8yMNyevFEaVq11psiWWozNLZniK4ckmP0Uk9vf2quLdbPKmq\\n\" +\n\"k0ig3AxZyOWP1IoG5jZp2IYYwPyo+RCigEdwR7/nXxolJ+5TMCOMy6cjloldDclDtjZcBh2KnOAe\\n\" +\n\"vFePCysNZkQTpbSG3lAkk6Icfn2oW3t7iBnTIwcYB7ntjPz+lPI41jucxxtPPHCHaRkUjOBk+hx+\\n\" +\n\"NYObho1SbDNGh0+3id/MJkAOd45Pfj6U6s7t0j0yWYCMzxud3Ze+KWX7Lc2lr5YjMqIY9yLgMg4y\\n\" +\n\"Pfk0PqazRaXpiSlxuQuAw6ZAroNysWMqdlIbhYH3owK9VPrX1vEwgXJcYHqaTpMG0+DJziNRSe9A\\n\" +\n\"julMn7vbuHxrDjuj0Yz1ZTxa8sjm9v8AzvsiA+yvUntTSw8b6TtKx7gOwNRL3cU1qIzcqM44z0pQ\\n\" +\n\"+lTtlrWWJjnJAcA08YJPsDyy9I68fE2jX0ixy3Pkk9Gz3oLT/FC+e9vM6syMVV+mR2rnFnpNxHNG\\n\" +\n\"8rIWzk5YGnht0lkySEkHcd6E1T0Osl9o6C2qpcIVGDxSHxBMsPh+5lI/anEafE9/oKVafLLFNtkP\\n\" +\n\"TofWvPiu9zZw2QHL/tSfdyB+dGHykLmdQbQfeuNP0G2uIQS0fkjJ/m4yR+BpmY7a7tY5gQ8cyhlB\\n\" +\n\"HUHtSfxJIX0FdoCwxvGqD19k148H3u+Oe1lbLRANCPicED5mrKPLbKDTHNl/o7pZJbM8xsCd0R9P\\n\" +\n\"7fT3+6mhuIFJUTK2OMqQB+Nabc+Vew7sja+XI6+8VN+JpLS08R3sC20MgRgC2M87RkfI8fKhdHUR\\n\" +\n\"Eqs826JiFJ3GJicNj8q1K7QasY4lUJuwgDHA+Jr5qGoFZFEC7QVwccU80S7tbjUYIjGrsrsqtJgA\\n\" +\n\"nBOPxFScZcv6NZP6FzxvFAIyCu1SQAeSCe3zzTXWJpr2y0uNUy8MGXbcAOQMc/KtfiGAx6rHBCQx\\n\" +\n\"8sbQPUscCvfimHz9G8uEYFsqkheAdowf+flVeHC6bMWwG3nVQYDIrFeMq2QOeK3TbJgsUqBjnFLv\\n\" +\n\"Clmt1aaizrgewFYDocmi/NZHCsAJAcEGpsiuWi/G6jsMHh61juRcxoGV12tG3TPrTP8AVOnMuJNO\\n\" +\n\"lRiwO5FJzwO4rxA7m2U7chhjFDy6heWr/swwHcE8Ckv7N0os3X/h+0kikksoJo2z7O4lfzpRHpN5\\n\" +\n\"YzxedcGVmzuH9NUFpfvOp3qzMemelBajMzXMa59r1rm/SOcUj2zYdWX04+NKNbnNzePtIOxAg+PJ\\n\" +\n\"/wA0RdXQhAVTlvypNLMMMzHJ3At9a2wQp2SeRk1xRaeLNsWi2sCHOJUUn4IRU/o119j1uynJOBLh\\n\" +\n\"h6huP8088Uc6Qsz8Ga4Gz3AKT/kVIGTE8RHUOCPqKoSJDqqkhsknJIOflSZ7qzhkZL1Fe53EuxQ8\\n\" +\n\"55/Iinb/AL/AHG4/8U0g01Lm2ilJiJZFzkDPAxQCcCuxslL+YoYnbjOeMVQeFjeR7GjtBcYlLKCv\\n\" +\n\"IOBk5xxkVXw6L4fsmDRWMMsi8B5zvP0PFbri+mCCKJkRcYAXgYrePhv+TOc/oU6rpkz6p9ufbCuw\\n\" +\n\"KsZbLKff9aC3tgq+DgFT3B7UyklySrcE5z76AmAwW2nGOearhj4RpGVtnrTjFBD9liQIgXgD/vNK\\n\" +\n\"tbtnBM0XDDHzFbfPMUgdTlaMd0uYd4OfdXleRheOfJdHoY8inCn2A6TrChtrH7uMBj0p3JrFtMVQ\\n\" +\n\"RqSSecdTUff2qpMWT2eeooSKS4jcMrZI6ZrHgnsP5GtF7cXsKo7sAm3sOKQrc+bcTTM37GH2nk9M\\n\" +\n\"8AUHBHLecXEh2HqF71v19o7Lw+IIgFEsiqR7hz/ihGK5DSk3GwW7Dw3UyOcurHn8vwrVbWzXtzDB\\n\" +\n\"082RUJ9Mmmtvo11rumW1/aNGZBGI5InbaxK8ZHr2r5Z2k1rrVjbSxvE5uEB3jbgZ5q9xa/wgu2OP\\n\" +\n\"HE4k+xIh/ZoZAMd8bakl5ljb1I/MVTeNCpWw8v7oMqjj4c/WphWwV5xyDSJ6CdYdv9Vnk4c1SWlq\\n\" +\n\"4tYwsgC44GKmCf2z9gGz3qxsJozYQFm5KA/WlOOXyXmV3LbuBjqFOKG86VwSu3gdCc0El/Pavtcs\\n\" +\n\"wHGCc0aJBcJ5ls6h+pU165mCudxGXYtnOOgFCzXgSJgxCRgd+rGjmkimO2T9nIOMilV/aOmWOGjJ\\n\" +\n\"/wCmhK60cgAXOx/bJIY1vWeSBtybnU9QBS2aNIs7nJ9MCt1ndMDsyfQZPU9qmbT+Mh1raDpl+0Dc\\n\" +\n\"o+tBeQ6ScJkVkd5JNqYt7OMyqAd2Ty3rj4UwhxOqyRZKn6j3GoMmNReiqMuW2b7RHwCRilviaQyf\\n\" +\n\"Y4V5wxOPU04x5ERZuTj6UhvdUtoL3eEFxMowP6F9ce+kxQVhySqNIrtDjks9DSJWG3GWVutM7e4h\\n\" +\n\"ljXzHDqP5ZBnHw7ilFrL5yQOmfLZAw+fNN7e3jVi7DrXs0qoha2aNV0uDUokEMqxSIxIDHIbIHHu\\n\" +\n\"qQvrK5sJRHPEVcA4PZvgasb28gXIVFDD+YcZoIzG/ga2uYjLG3C46qT3rGeFVaOTKQXDNKwlOT0y\\n\" +\n\"F93f51To5ihiQZAWJB0/2ipRgWiaQnLsNicDjA6mqaa1DuG2/wAqjqewAqFpp0zRHKNR/eCtel/x\\n\" +\n\"ArKyvVZmEah+9Wvp/gz8Kyspl0cIZ/3bUvi6r/dWVlSZOx4maF/6wvz/ADNOtB/eXf8A8jVlZUcz\\n\" +\n\"aPYXq38EfnUbcfxXyFZWUMQch0LTP4SH+2nX/sn4VlZXqx/VEz7EF19/50bpf8SPgPzrKyuAO4P3\\n\" +\n\"0vx/+oqw7D4D8qysrzcv7jro/9k=\\n\" +\n\"    </BINVAL>\\n\" +\n\"  </LOGO>\\n\" +\n\"  <ORG>\\n\" +\n\"    <ORGNAME>XMPP Standards Foundation</ORGNAME>\\n\" +\n\"    <ORGUNIT/>\\n\" +\n\"  </ORG>\\n\" +\n\"  <URL>https://stpeter.im/</URL>\\n\" +\n\"  <URL>http://www.saint-andre.com/</URL>\\n\" +\n\"  <KEY>\\n\" +\n\"    <CRED>\\n\" +\n\"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\" +\n\"Version: GnuPG/MacGPG2 v2.0.18 (Darwin)\\n\" +\n\"\\n\" +\n\"mQINBFETDzsBEAC0FOv1N3ZJzIIxN6cKD475KVS9CHDPeYpegcOIPnL5eY1DCHeh\\n\" +\n\"/IwS1S7RCePtmiybNoV9FsI4PKUknzXQxA6LVEdAR/LUlhgJKjq+gsgp8lqbEILh\\n\" +\n\"g13ecH66HwLS9rarbQkC47T7kL8miIPBFC6E3A4Lq1L+eueO6UcLhKgoYkMxOjdi\\n\" +\n\"WrMgKTnVpch5ydLkPm/z0Zo8zRgqlPuTLeCrXXZYnjHXLVFN2xy04UzOs7P5u5KV\\n\" +\n\"fx5Z7uQisr8pXtyLd6SpTZo6SHgKBv15uz0rqXhsJojiGtOXfWznAjaS5FUOORq9\\n\" +\n\"CklG5cMOUAT8TNftv0ktsxaWDL1ELDVQPy1m7mtzo+VREG+0xmU6AjMo/GHblW1U\\n\" +\n\"U7MI9yCiuMLsp/HLrFuiosqLVZ85wuLQ2junPe3tK8h15UcxIXAcpQ1VqIaDQFbe\\n\" +\n\"uLOXJTF8YHpHdpHYt/ZM1ll7ZBKGAo8yd7uF7wJ9D3gUazwdz9fFjWV7oIk7ATwO\\n\" +\n\"lFllzmWDn+M2ygbHOGUGMX5hSaa8eDSieiR2QoLdn27Fip7kMBTJ2+GISrfnJTN/\\n\" +\n\"OQvmj0DXXAdxHmu2C4QgmZbkge35n129yzXn9NcqzrGLroV62lL3LgX6cSbiH5i7\\n\" +\n\"GgWY6CAPb1pMogV0K475n9FvOSDRiG4QSO5yqKiA3OP5aKrIRp2TNAk4IwARAQAB\\n\" +\n\"tCZQZXRlciBTYWludC1BbmRyZSA8c3RwZXRlckBzdHBldGVyLmltPokCOQQTAQIA\\n\" +\n\"IwUCURMPOwIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEOoGpJErxa2p\\n\" +\n\"6bgQAKpxu07cMDOLc4+EG8H19NWXIVVybOEvfGuHYZaLKkPrhrMZwJiOwBpyISNR\\n\" +\n\"t9qzX1eLCVaojaoEVX6kD8MGc5zKFfiJZy3j7lBWl+Ybr7FfXYy2BbAXKx49e1n6\\n\" +\n\"ci9LmBrmVfAEaxtDNPITZ9N9oUAb9vS0nrG036EwteEHAveQvlDjO7lhz6+Cv7lZ\\n\" +\n\"QgBj9rZ6khfcQ4S3nSCQaKLQ9Iav4fqxI7SfuPKnx6quHX3JNLGnVo3wl+j/foCK\\n\" +\n\"0iTrmtHxCI3kc/bx6g32pRjHEPX0ALMBhmzU2uca+TE0zCEC96mgYXAUCwdnCFWy\\n\" +\n\"beIEbt6pz65iML13kAVAq0H/GqncnMGN0MbOatnw1Tdz/vkLojIy7QbPcQ0plUFx\\n\" +\n\"v5491xPfIrHhOWdRXp6WUt88fcqhT6MHZpVRtusj2ornKVVn+Y0GLsMMCTcrXJRG\\n\" +\n\"7Ao1YV72t/pJpzfGWSaaxolxDIZ6B+76jrIhUhiWgo/4nf+DN6BIlCZQ6j6xxjjx\\n\" +\n\"462cu02kuhIILTk2pzaMOufTBWx0uJhZk/KP2Fay/41pX7pvVOwRC4uIlKsLnJKL\\n\" +\n\"PS7EDa4BUUxENfd/9LqOGwlII8BbSe98PLMI8sXkcigc3UXMVda9ll0YhQa+lbP1\\n\" +\n\"NaszmnBhwuiCsgnPGbImsJuRzgEEgckwP/dNeyr6MlFMyfaeuQINBFETDzsBEADB\\n\" +\n\"zOsEHpUmhkRUjH9Tek87dn5P/Yh/L/HptgCGk40TL/C+kYdkd3HyteMEf061PNms\\n\" +\n\"S/Rq8k37Fu3VODYb9SPYKxtgksKSYUtIkPKvao09K9QNWPqyWuNf0F+iAjVMUuda\\n\" +\n\"EVFJ7bHF310RDwLY5IvLeCXxtvG+Vv/i+g77d2WdPDp+zLJ8306C4yBKjSJV8xW0\\n\" +\n\"cn2fd7NviIEN6cNHTsZNDZVMlgYPrxnwSq8GTEPGC7HsLIwGcx3hIe9QjnPw9CpA\\n\" +\n\"mQENpDEyWcxgF5uwo2NJECoDswKz1Nb0gfawF3ZIbD+GcLujTu94iJuVg25jATWm\\n\" +\n\"9wTgcfZo4UPllRGXdIb8uWwUFQlLQgd4ROLZZtXNGmHIymJrV2crx53gxup+1j0X\\n\" +\n\"qhlzKg8xbImWhEfS9oHZkRK8VHgmWSIt7TNwNir6N5j3lqwWVBhnu6GzF01sKGNy\\n\" +\n\"SlqNRbd0fqhakCkK71b8ot8tYTcYG5Lg10z6HTbgQx2UwLthUjqbblDQ+GLmrOhi\\n\" +\n\"WklLXRsnlnPMwnEyFePAnsT5tasy2Cn9qjpttNDah7PB8iFUi9mtTF/XDVgpFaB5\\n\" +\n\"G3CDV7Q2NgbAI6g6QhLIAmXzSP635G83mda0TKXHQXHDyLJTTn+WVFU7t4m4uLt+\\n\" +\n\"0DsWU8jXHQWyUTNG9WPUrXhusDUAPHxFCQ/n/lQVBwARAQABiQIfBBgBAgAJBQJR\\n\" +\n\"Ew87AhsMAAoJEOoGpJErxa2pqfgP/ApN+TRu2bBIgaw1dr3AznSSha84DIpXUDh3\\n\" +\n\"udZvQrGbUtz8/mA+e3iZEN/cmmBw2LGlAuQoJNILTZQ318yTP+E5QU7fJH7FVsoh\\n\" +\n\"UyvrMfyt3IMA9jg0Z9MuloLezvIjjMfFeNa0ROgDb/ubOT7JQzi1kwN8Lu3lO80H\\n\" +\n\"wqBHXEeOLoislUSnZajRKvITbKWkZ6PHRjlMw1Wk4oIi6VLHgGgj79zzL3uhML26\\n\" +\n\"63m7imShvz1QcHTwvyR5i8cZbNOEkotZyERiA1p7YHuruS+QvTi3ZPoQbnMUB3a7\\n\" +\n\"py9d11bw1+w3LiAUGZE/z5hBWOFxYtw+w/U/Vx0BwJGYlwU3M2W20uEXe+qxz7wn\\n\" +\n\"akygKjmLiD2z4njfKjcNCiV3FmXrpmWgADln1c4jfxDh0NrndrsM8FPDf1TMPtOZ\\n\" +\n\"gFDkKripc9xkZ/25P6xn27oTOHWKcAC0QhxSH+HuVBBRk8AgF+zAbDZe4/L6+kan\\n\" +\n\"SrycIXW+wCzwBq61aWsz2QhhuKjozVkhk4dRG+CfjzAFjnyxwYERn3uXVKQAwTwc\\n\" +\n\"dNcTI9RV98IsNrw9Y4lJEAg6CjNPmiD5+EASycqaOuToRSGukr8sOQLWLPyTnez/\\n\" +\n\"aG8Xf7a+fntWzK2HuDYoSDhJJrylWw/lMklOBm4wtMeNA0zcQH6AQV/GzQVQkSGq\\n\" +\n\"rLuMVIV/\\n\" +\n\"=llGw\\n\" +\n\"-----END PGP PUBLIC KEY BLOCK-----\\n\" +\n\"    </CRED>\\n\" +\n\"  </KEY>\\n\" +\n\"  <DESC>\\n\" +\n\"    More information about me is located on my \\n\" +\n\"    personal website: https://stpeter.im/\\n\" +\n\"  </DESC>\\n\" +\n\"</vCard>\").replace(\"\\n\", \"\").replace(\"  \",\"\");\n\t\n\tprivate static String VCARD4_DATA = (\"<vcard xmlns=\\\"urn:ietf:params:xml:ns:vcard-4.0\\\">\\n\" +\n\"  <fn>\\n\" +\n\"    <text>Peter Saint-Andre</text>\\n\" +\n\"  </fn>\\n\" +\n\"  <n>\\n\" +\n\"    <surname>Saint-Andre</surname>\\n\" +\n\"    <given>Peter</given>\\n\" +\n\"    <additional></additional>\\n\" +\n\"  </n>\\n\" +\n\"  <nickname>\\n\" +\n\"    <text>stpeter</text>\\n\" +\n\"  </nickname>\\n\" +\n\"  <nickname>\\n\" +\n\"    <text>psa</text>\\n\" +\n\"  </nickname>\\n\" +\n\"  <photo>\\n\" +\n\"    <uri>http://stpeter.im/images/stpeter_oscon.jpg</uri>\\n\" +\n\"  </photo>\\n\" +\n\"  <photo>\\n\" +\n\"    <uri>http://stpeter.im/images/stpeter_hell.jpg</uri>\\n\" +\n\"  </photo>\\n\" +\n\"  <bday>\\n\" +\n\"    <date>1966-08-06</date>\\n\" +\n\"  </bday>\\n\" +\n\"  <adr>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>work</text></type>\\n\" +\n\"      <pref><integer>1</integer></pref>\\n\" +\n\"    </parameters>\\n\" +\n\"    <ext>Suite 600</ext>\\n\" +\n\"    <street>1899 Wynkoop Street</street>\\n\" +\n\"    <locality>Denver</locality>\\n\" +\n\"    <region>CO</region>\\n\" +\n\"    <code>80202</code>\\n\" +\n\"    <country>USA</country>\\n\" +\n\"  </adr>\\n\" +\n\"  <adr>\\n\" +\n\"    <parameters><type><text>home</text></type></parameters>\\n\" +\n\"    <ext></ext>\\n\" +\n\"    <street></street>\\n\" +\n\"    <locality>Parker</locality>\\n\" +\n\"    <region>CO</region>\\n\" +\n\"    <code>80138</code>\\n\" +\n\"    <country>USA</country>\\n\" +\n\"  </adr>\\n\" +\n\"  <tel>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>work</text><text>voice</text></type>\\n\" +\n\"      <pref><integer>1</integer></pref>\\n\" +\n\"    </parameters>\\n\" +\n\"    <uri>tel:+1-303-308-3282</uri>\\n\" +\n\"  </tel>\\n\" +\n\"  <tel>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>work</text><text>fax</text></type>\\n\" +\n\"    </parameters>\\n\" +\n\"    <uri>tel:+1-303-308-3219</uri>\\n\" +\n\"  </tel>\\n\" +\n\"  <tel>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>cell</text><text>voice</text><text>text</text></type>\\n\" +\n\"    </parameters>\\n\" +\n\"    <uri>tel:+1-720-256-6756</uri>\\n\" +\n\"  </tel>\\n\" +\n\"  <tel>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>home</text><text>voice</text></type>\\n\" +\n\"    </parameters>\\n\" +\n\"    <uri>tel:+1-303-555-1212</uri>\\n\" +\n\"  </tel>\\n\" +\n\"  <email>\\n\" +\n\"    <text>stpeter@jabber.org</text>\\n\" +\n\"  </email>\\n\" +\n\"  <email>\\n\" +\n\"    <parameters>\\n\" +\n\"      <type><text>work</text></type>\\n\" +\n\"    </parameters>\\n\" +\n\"    <text>psaintan@cisco.com</text>\\n\" +\n\"  </email>\\n\" +\n\"  <impp>\\n\" +\n\"    <uri>xmpp:stpeter@jabber.org</uri>\\n\" +\n\"  </impp>\\n\" +\n\"  <tz>\\n\" +\n\"    <text>America/Denver</text>\\n\" +\n\"  </tz>\\n\" +\n\"  <geo>\\n\" +\n\"    <uri>geo:39.59,-105.01</uri>\\n\" +\n\"  </geo>\\n\" +\n\"  <title>\\n\" +\n\"    <text>Executive Director</text>\\n\" +\n\"  </title>\\n\" +\n\"  <role>\\n\" +\n\"    <text>Patron Saint</text>\\n\" +\n\"  </role>\\n\" +\n\"  <logo>\\n\" +\n\"    <uri>data:image/jpeg;base64,\\n\" +\n\"/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHBgUI\\n\" +\n\"BwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy\\n\" +\n\"/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy\\n\" +\n\"MjIyMjIyMjIyMjIy/8AAEQgAgQB7AwEiAAIRAQMRAf/EABsAAAMAAwEBAAAAAAAAAAAAAAQFBgAD\\n\" +\n\"BwIB/8QAPRAAAgEDAwIDBQQJBAEFAAAAAQIDAAQRBRIhMUEGE1EiYXGBkRQyobEHFSMzNEJScsEk\\n\" +\n\"YtHw0jVDc8Lh/8QAGQEAAwEBAQAAAAAAAAAAAAAAAQIEAwAF/8QAJBEAAgICAgICAgMAAAAAAAAA\\n\" +\n\"AAECEQMhEjEEQSJREzJCYXH/2gAMAwEAAhEDEQA/AOf2c0KGSY2pDFiinYMsCMfhj8aya6gdvZj9\\n\" +\n\"ryg6A8eYuORxQk1rdzSHyZGQYO0GXAPv/MV6luDp8QgntkRyhAfHJ3Y5wOoxxXncbdiA9zp/6xQG\\n\" +\n\"KaGFIhK208MwX09amCOeMEdjT3VLi1EaeVGHEi4WRCQVwAD7PY5/CkQYbcfdPUVbjTS2FGAHGele\\n\" +\n\"1nmXgOw6/iMV4LnHup/4c8L3/iWfbboIoFPt3D/dH/kfcKd0kOotukL/ALWs8SJNEPZGA4/z2omD\\n\" +\n\"T7++dY7azuLlAOPs8Jfb9P8Amu1+Hv0Z+HtPjVp7YX846yXAyM+5elX1tDa2sKxwxRxoBgKigD6U\\n\" +\n\"nJGn4a7OB+G/0Y67rlxuuIRptojDdcXS5c/2R9SfoPfXY/DvgzQvCiLJZW/m3uPavbgb5Sf9vZPl\\n\" +\n\"9TVCBAw5RfiODQ93Fdi3b9XyxiXt5iE59wNPGSEnja6N5VyCzHYh5LOcUvuNc0y0JDTtO/8ATGP8\\n\" +\n\"1Hahc6g87xX0ku9TyhbH4dKEA6AZx1prJ2n7KW58W3L5W1iS3H9XVsfGlMl3NdNvmld8/wBRoMHH\\n\" +\n\"NbM5Hw5oAoIjALHPfA59O9KL218NS3byXtjE9w+GdivqBj8MUyk5ikAOPZ61rtreDUbaO5kiTeV2\\n\" +\n\"HJ7r7P8AiuGSOXDyzBE1zlInAKFR6k9a+XFtHt8qWczjGVUKSAvPHu+VLftckzPu+62U2E5256Y7\\n\" +\n\"1S+Fkj1DxPDaXEe5YYHldc9doGAfdnFQLE+VDdCc2ZXDaQDMTgFDEC6H175zgjimcv6PfFmvXMcy\\n\" +\n\"6SttFtB8+4dIEIIz0PPfsKuE1O7tEMVoy2sfPs28Sxdev3Rmh5Jp52LyzSSnqS7E/nVkIcezrFlj\\n\" +\n\"+ibSrC3aXWNbF9dAezaad93P+6Qjp8AKsNMt4LO1hgto0ihXhVj6CldrsSLoMt7qNhuiiDJyPSsc\\n\" +\n\"k23Rfgi4qyphkCqAMcUQsue9TsGoAkDP1osXOT1oWO0x2JOeua2rPiki3GO/Hxr0L5F/nFGwNB2q\\n\" +\n\"2UWq2+MAXCcxv/g/GopkaNijqVdWIYHqDVSt9uDYbt2pRrKrJJDdgcyrh/7h/wDlawlZLnh7QB96\\n\" +\n\"E46ivSnlDXyAAyFD/Nx9elZGQ0XHJVsH3VqSntk3W7oDgEYz6ULbWkkURUuxO9ySOMksTRY5iPx5\\n\" +\n\"o6KaMxKSygnkjFdQUzhMca3Mau7KXXII28EdvnVv4FtTLq97dOwLR2PlDHUEsD/ioO1uHCg9Og9B\\n\" +\n\"mrPwXrENomp3EynYApYoMkYGOfRfaHuqeKansdlHOMTOeOSelaxjml763ayalcBplW22K8bnoCRl\\n\" +\n\"gT3x2xW21v4bosoDIRgKHGGbPTjPpzWjkmhUrYbFNhgPSjLYPN7K45oGNRtDnGCCc+6grvxhDZsY\\n\" +\n\"rS3LBeN/9VSvbPTi+KK6GwGBucg0T5HljqSPhXMz4/uFmAa1brzk4qisfFS3UIcMR6g9qL12FS5d\\n\" +\n\"FasLOOMAV5ktMDIwamLjxVFagmWTC+g60HF+kOw85UzIfftoJphbrsqTKYwynI7VlzMJdP2fzKQw\\n\" +\n\"+VDJqFjqsPmW0w8wclfWtYV3kKLzlSaeLakZ5acT6jhZIz0Vhj4HtXqQFLuTjaXGTitJztZSuGjY\\n\" +\n\"EgjHuomQ7khlHpzVh5h8Gfs+e5oK6juvtDbCQuAQMj0FGkZgweo3D8DXiUxiTBYZAHYelKdRw85h\\n\" +\n\"uPImyG3glT0z61WadpVteeCdQu4DKk8ZKFVwd53DHPUDDduDioieSYsryZIJ4JGSapvB2pG21CWz\\n\" +\n\"iLSR3kZR0ZcYI6H48kUvH2zRjLTdOngh+23gSGOFdzPMvKgEg4Pr299btN8Qw3Es8kenwolxJgvs\\n\" +\n\"BaMKPZOex+HrQXirWJdQu10m0kLwwkCUr0kk/wDFe3zo/wAP6KqxyW8hO5wWIHfHXFZSjS0beNXO\\n\" +\n\"2Uk2bmyaKH75XaAPSpC48P3qysvnJEf5VPUiq/TzsYhSckkD4U4uNLtL61Czp7XZhwR8xWKu7LeK\\n\" +\n\"emckk0a8VZGmkBYfcG7qaqvB+izSyMJh7O3INOx4bsrUmTy2kI6F2JApxo0ZWfftCx4xxTSbloEI\\n\" +\n\"KPRz7xjp89veMsSkoOmKQR2N9bTKgtzJuI7HH1zXW9XsYrq4kWZCQ3Rh1FJk8LXayfsLobO3mJuo\\n\" +\n\"xlx1QJwUttk3pDzwX8REEkTA9G6H1Hvq41Gznv8ASpoLMSCeZQIihwwbIPB7Vvh0j7PEPtDeY3rj\\n\" +\n\"AHw9KUa3c3EVmY7aXy3LfeHXHGefnSOTsbhy+Jmm61JLdHS9e/02oqTHHdNgJKf6X9D6HpTpoJYk\\n\" +\n\"aF125JIB6qf+4qXk0/8AWFnHJMfM8yMNyevFEaVq11psiWWozNLZniK4ckmP0Uk9vf2quLdbPKmq\\n\" +\n\"k0ig3AxZyOWP1IoG5jZp2IYYwPyo+RCigEdwR7/nXxolJ+5TMCOMy6cjloldDclDtjZcBh2KnOAe\\n\" +\n\"vFePCysNZkQTpbSG3lAkk6Icfn2oW3t7iBnTIwcYB7ntjPz+lPI41jucxxtPPHCHaRkUjOBk+hx+\\n\" +\n\"NYObho1SbDNGh0+3id/MJkAOd45Pfj6U6s7t0j0yWYCMzxud3Ze+KWX7Lc2lr5YjMqIY9yLgMg4y\\n\" +\n\"Pfk0PqazRaXpiSlxuQuAw6ZAroNysWMqdlIbhYH3owK9VPrX1vEwgXJcYHqaTpMG0+DJziNRSe9A\\n\" +\n\"julMn7vbuHxrDjuj0Yz1ZTxa8sjm9v8AzvsiA+yvUntTSw8b6TtKx7gOwNRL3cU1qIzcqM44z0pQ\\n\" +\n\"+lTtlrWWJjnJAcA08YJPsDyy9I68fE2jX0ixy3Pkk9Gz3oLT/FC+e9vM6syMVV+mR2rnFnpNxHNG\\n\" +\n\"8rIWzk5YGnht0lkySEkHcd6E1T0Osl9o6C2qpcIVGDxSHxBMsPh+5lI/anEafE9/oKVafLLFNtkP\\n\" +\n\"TofWvPiu9zZw2QHL/tSfdyB+dGHykLmdQbQfeuNP0G2uIQS0fkjJ/m4yR+BpmY7a7tY5gQ8cyhlB\\n\" +\n\"HUHtSfxJIX0FdoCwxvGqD19k148H3u+Oe1lbLRANCPicED5mrKPLbKDTHNl/o7pZJbM8xsCd0R9P\\n\" +\n\"7fT3+6mhuIFJUTK2OMqQB+Nabc+Vew7sja+XI6+8VN+JpLS08R3sC20MgRgC2M87RkfI8fKhdHUR\\n\" +\n\"Eqs826JiFJ3GJicNj8q1K7QasY4lUJuwgDHA+Jr5qGoFZFEC7QVwccU80S7tbjUYIjGrsrsqtJgA\\n\" +\n\"nBOPxFScZcv6NZP6FzxvFAIyCu1SQAeSCe3zzTXWJpr2y0uNUy8MGXbcAOQMc/KtfiGAx6rHBCQx\\n\" +\n\"8sbQPUscCvfimHz9G8uEYFsqkheAdowf+flVeHC6bMWwG3nVQYDIrFeMq2QOeK3TbJgsUqBjnFLv\\n\" +\n\"Clmt1aaizrgewFYDocmi/NZHCsAJAcEGpsiuWi/G6jsMHh61juRcxoGV12tG3TPrTP8AVOnMuJNO\\n\" +\n\"lRiwO5FJzwO4rxA7m2U7chhjFDy6heWr/swwHcE8Ckv7N0os3X/h+0kikksoJo2z7O4lfzpRHpN5\\n\" +\n\"YzxedcGVmzuH9NUFpfvOp3qzMemelBajMzXMa59r1rm/SOcUj2zYdWX04+NKNbnNzePtIOxAg+PJ\\n\" +\n\"/wA0RdXQhAVTlvypNLMMMzHJ3At9a2wQp2SeRk1xRaeLNsWi2sCHOJUUn4IRU/o119j1uynJOBLh\\n\" +\n\"h6huP8088Uc6Qsz8Ga4Gz3AKT/kVIGTE8RHUOCPqKoSJDqqkhsknJIOflSZ7qzhkZL1Fe53EuxQ8\\n\" +\n\"55/Iinb/AL/AHG4/8U0g01Lm2ilJiJZFzkDPAxQCcCuxslL+YoYnbjOeMVQeFjeR7GjtBcYlLKCv\\n\" +\n\"IOBk5xxkVXw6L4fsmDRWMMsi8B5zvP0PFbri+mCCKJkRcYAXgYrePhv+TOc/oU6rpkz6p9ufbCuw\\n\" +\n\"KsZbLKff9aC3tgq+DgFT3B7UyklySrcE5z76AmAwW2nGOearhj4RpGVtnrTjFBD9liQIgXgD/vNK\\n\" +\n\"tbtnBM0XDDHzFbfPMUgdTlaMd0uYd4OfdXleRheOfJdHoY8inCn2A6TrChtrH7uMBj0p3JrFtMVQ\\n\" +\n\"RqSSecdTUff2qpMWT2eeooSKS4jcMrZI6ZrHgnsP5GtF7cXsKo7sAm3sOKQrc+bcTTM37GH2nk9M\\n\" +\n\"8AUHBHLecXEh2HqF71v19o7Lw+IIgFEsiqR7hz/ihGK5DSk3GwW7Dw3UyOcurHn8vwrVbWzXtzDB\\n\" +\n\"082RUJ9Mmmtvo11rumW1/aNGZBGI5InbaxK8ZHr2r5Z2k1rrVjbSxvE5uEB3jbgZ5q9xa/wgu2OP\\n\" +\n\"HE4k+xIh/ZoZAMd8bakl5ljb1I/MVTeNCpWw8v7oMqjj4c/WphWwV5xyDSJ6CdYdv9Vnk4c1SWlq\\n\" +\n\"4tYwsgC44GKmCf2z9gGz3qxsJozYQFm5KA/WlOOXyXmV3LbuBjqFOKG86VwSu3gdCc0El/Pavtcs\\n\" +\n\"wHGCc0aJBcJ5ls6h+pU165mCudxGXYtnOOgFCzXgSJgxCRgd+rGjmkimO2T9nIOMilV/aOmWOGjJ\\n\" +\n\"/wCmhK60cgAXOx/bJIY1vWeSBtybnU9QBS2aNIs7nJ9MCt1ndMDsyfQZPU9qmbT+Mh1raDpl+0Dc\\n\" +\n\"o+tBeQ6ScJkVkd5JNqYt7OMyqAd2Ty3rj4UwhxOqyRZKn6j3GoMmNReiqMuW2b7RHwCRilviaQyf\\n\" +\n\"Y4V5wxOPU04x5ERZuTj6UhvdUtoL3eEFxMowP6F9ce+kxQVhySqNIrtDjks9DSJWG3GWVutM7e4h\\n\" +\n\"ljXzHDqP5ZBnHw7ilFrL5yQOmfLZAw+fNN7e3jVi7DrXs0qoha2aNV0uDUokEMqxSIxIDHIbIHHu\\n\" +\n\"qQvrK5sJRHPEVcA4PZvgasb28gXIVFDD+YcZoIzG/ga2uYjLG3C46qT3rGeFVaOTKQXDNKwlOT0y\\n\" +\n\"F93f51To5ihiQZAWJB0/2ipRgWiaQnLsNicDjA6mqaa1DuG2/wAqjqewAqFpp0zRHKNR/eCtel/x\\n\" +\n\"ArKyvVZmEah+9Wvp/gz8Kyspl0cIZ/3bUvi6r/dWVlSZOx4maF/6wvz/ADNOtB/eXf8A8jVlZUcz\\n\" +\n\"aPYXq38EfnUbcfxXyFZWUMQch0LTP4SH+2nX/sn4VlZXqx/VEz7EF19/50bpf8SPgPzrKyuAO4P3\\n\" +\n\"0vx/+oqw7D4D8qysrzcv7jro/9k=\\n\" +\n\"      </uri>\\n\" +\n\"    </logo>\\n\" +\n\"    <org>\\n\" +\n\"      <text>XMPP Standards Foundation</text>\\n\" +\n\"    </org>\\n\" +\n\"    <url>\\n\" +\n\"      <uri>https://stpeter.im/</uri>\\n\" +\n\"    </url>\\n\" +\n\"    <url>\\n\" +\n\"      <uri>http://www.saint-andre.com/</uri>\\n\" +\n\"    </url>\\n\" +\n\"    <key>\\n\" +\n\"      <text>\\n\" +\n\"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\" +\n\"Version: GnuPG/MacGPG2 v2.0.18 (Darwin)\\n\" +\n\"\\n\" +\n\"mQINBFETDzsBEAC0FOv1N3ZJzIIxN6cKD475KVS9CHDPeYpegcOIPnL5eY1DCHeh\\n\" +\n\"/IwS1S7RCePtmiybNoV9FsI4PKUknzXQxA6LVEdAR/LUlhgJKjq+gsgp8lqbEILh\\n\" +\n\"g13ecH66HwLS9rarbQkC47T7kL8miIPBFC6E3A4Lq1L+eueO6UcLhKgoYkMxOjdi\\n\" +\n\"WrMgKTnVpch5ydLkPm/z0Zo8zRgqlPuTLeCrXXZYnjHXLVFN2xy04UzOs7P5u5KV\\n\" +\n\"fx5Z7uQisr8pXtyLd6SpTZo6SHgKBv15uz0rqXhsJojiGtOXfWznAjaS5FUOORq9\\n\" +\n\"CklG5cMOUAT8TNftv0ktsxaWDL1ELDVQPy1m7mtzo+VREG+0xmU6AjMo/GHblW1U\\n\" +\n\"U7MI9yCiuMLsp/HLrFuiosqLVZ85wuLQ2junPe3tK8h15UcxIXAcpQ1VqIaDQFbe\\n\" +\n\"uLOXJTF8YHpHdpHYt/ZM1ll7ZBKGAo8yd7uF7wJ9D3gUazwdz9fFjWV7oIk7ATwO\\n\" +\n\"lFllzmWDn+M2ygbHOGUGMX5hSaa8eDSieiR2QoLdn27Fip7kMBTJ2+GISrfnJTN/\\n\" +\n\"OQvmj0DXXAdxHmu2C4QgmZbkge35n129yzXn9NcqzrGLroV62lL3LgX6cSbiH5i7\\n\" +\n\"GgWY6CAPb1pMogV0K475n9FvOSDRiG4QSO5yqKiA3OP5aKrIRp2TNAk4IwARAQAB\\n\" +\n\"tCZQZXRlciBTYWludC1BbmRyZSA8c3RwZXRlckBzdHBldGVyLmltPokCOQQTAQIA\\n\" +\n\"IwUCURMPOwIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEOoGpJErxa2p\\n\" +\n\"6bgQAKpxu07cMDOLc4+EG8H19NWXIVVybOEvfGuHYZaLKkPrhrMZwJiOwBpyISNR\\n\" +\n\"t9qzX1eLCVaojaoEVX6kD8MGc5zKFfiJZy3j7lBWl+Ybr7FfXYy2BbAXKx49e1n6\\n\" +\n\"ci9LmBrmVfAEaxtDNPITZ9N9oUAb9vS0nrG036EwteEHAveQvlDjO7lhz6+Cv7lZ\\n\" +\n\"QgBj9rZ6khfcQ4S3nSCQaKLQ9Iav4fqxI7SfuPKnx6quHX3JNLGnVo3wl+j/foCK\\n\" +\n\"0iTrmtHxCI3kc/bx6g32pRjHEPX0ALMBhmzU2uca+TE0zCEC96mgYXAUCwdnCFWy\\n\" +\n\"beIEbt6pz65iML13kAVAq0H/GqncnMGN0MbOatnw1Tdz/vkLojIy7QbPcQ0plUFx\\n\" +\n\"v5491xPfIrHhOWdRXp6WUt88fcqhT6MHZpVRtusj2ornKVVn+Y0GLsMMCTcrXJRG\\n\" +\n\"7Ao1YV72t/pJpzfGWSaaxolxDIZ6B+76jrIhUhiWgo/4nf+DN6BIlCZQ6j6xxjjx\\n\" +\n\"462cu02kuhIILTk2pzaMOufTBWx0uJhZk/KP2Fay/41pX7pvVOwRC4uIlKsLnJKL\\n\" +\n\"PS7EDa4BUUxENfd/9LqOGwlII8BbSe98PLMI8sXkcigc3UXMVda9ll0YhQa+lbP1\\n\" +\n\"NaszmnBhwuiCsgnPGbImsJuRzgEEgckwP/dNeyr6MlFMyfaeuQINBFETDzsBEADB\\n\" +\n\"zOsEHpUmhkRUjH9Tek87dn5P/Yh/L/HptgCGk40TL/C+kYdkd3HyteMEf061PNms\\n\" +\n\"S/Rq8k37Fu3VODYb9SPYKxtgksKSYUtIkPKvao09K9QNWPqyWuNf0F+iAjVMUuda\\n\" +\n\"EVFJ7bHF310RDwLY5IvLeCXxtvG+Vv/i+g77d2WdPDp+zLJ8306C4yBKjSJV8xW0\\n\" +\n\"cn2fd7NviIEN6cNHTsZNDZVMlgYPrxnwSq8GTEPGC7HsLIwGcx3hIe9QjnPw9CpA\\n\" +\n\"mQENpDEyWcxgF5uwo2NJECoDswKz1Nb0gfawF3ZIbD+GcLujTu94iJuVg25jATWm\\n\" +\n\"9wTgcfZo4UPllRGXdIb8uWwUFQlLQgd4ROLZZtXNGmHIymJrV2crx53gxup+1j0X\\n\" +\n\"qhlzKg8xbImWhEfS9oHZkRK8VHgmWSIt7TNwNir6N5j3lqwWVBhnu6GzF01sKGNy\\n\" +\n\"SlqNRbd0fqhakCkK71b8ot8tYTcYG5Lg10z6HTbgQx2UwLthUjqbblDQ+GLmrOhi\\n\" +\n\"WklLXRsnlnPMwnEyFePAnsT5tasy2Cn9qjpttNDah7PB8iFUi9mtTF/XDVgpFaB5\\n\" +\n\"G3CDV7Q2NgbAI6g6QhLIAmXzSP635G83mda0TKXHQXHDyLJTTn+WVFU7t4m4uLt+\\n\" +\n\"0DsWU8jXHQWyUTNG9WPUrXhusDUAPHxFCQ/n/lQVBwARAQABiQIfBBgBAgAJBQJR\\n\" +\n\"Ew87AhsMAAoJEOoGpJErxa2pqfgP/ApN+TRu2bBIgaw1dr3AznSSha84DIpXUDh3\\n\" +\n\"udZvQrGbUtz8/mA+e3iZEN/cmmBw2LGlAuQoJNILTZQ318yTP+E5QU7fJH7FVsoh\\n\" +\n\"UyvrMfyt3IMA9jg0Z9MuloLezvIjjMfFeNa0ROgDb/ubOT7JQzi1kwN8Lu3lO80H\\n\" +\n\"wqBHXEeOLoislUSnZajRKvITbKWkZ6PHRjlMw1Wk4oIi6VLHgGgj79zzL3uhML26\\n\" +\n\"63m7imShvz1QcHTwvyR5i8cZbNOEkotZyERiA1p7YHuruS+QvTi3ZPoQbnMUB3a7\\n\" +\n\"py9d11bw1+w3LiAUGZE/z5hBWOFxYtw+w/U/Vx0BwJGYlwU3M2W20uEXe+qxz7wn\\n\" +\n\"akygKjmLiD2z4njfKjcNCiV3FmXrpmWgADln1c4jfxDh0NrndrsM8FPDf1TMPtOZ\\n\" +\n\"gFDkKripc9xkZ/25P6xn27oTOHWKcAC0QhxSH+HuVBBRk8AgF+zAbDZe4/L6+kan\\n\" +\n\"SrycIXW+wCzwBq61aWsz2QhhuKjozVkhk4dRG+CfjzAFjnyxwYERn3uXVKQAwTwc\\n\" +\n\"dNcTI9RV98IsNrw9Y4lJEAg6CjNPmiD5+EASycqaOuToRSGukr8sOQLWLPyTnez/\\n\" +\n\"aG8Xf7a+fntWzK2HuDYoSDhJJrylWw/lMklOBm4wtMeNA0zcQH6AQV/GzQVQkSGq\\n\" +\n\"rLuMVIV/\\n\" +\n\"=llGw\\n\" +\n\"-----END PGP PUBLIC KEY BLOCK-----\\n\" +\n\"      </text>\\n\" +\n\"    </key>\\n\" +\n\"    <note>\\n\" +\n\"      <text>\\n\" +\n\"More information about me is located on my \\n\" +\n\"personal website: https://stpeter.im/\\n\" +\n\"    </text>\\n\" +\n\"  </note>\\n\" +\n\"</vcard>\").replace(\"\\n\", \"\").replace(\"  \",\"\");\n\n\tprivate static String VCARD2_TEMP_DATA = (\"<vCard xmlns=\\\"vcard-temp\\\">\\n\" +\n\"  <FN>Peter Saint-Andre</FN>\\n\" +\n\"  <N>\\n\" +\n\"    <FAMILY>Saint-Andre</FAMILY>\\n\" +\n\"    <GIVEN>Peter</GIVEN>\\n\" +\n\"    <MIDDLE/>\\n\" +\n\"  </N>\\n\" +\n\"  <NICKNAME>stpeter</NICKNAME>\\n\" +\n\"  <NICKNAME>psa</NICKNAME>\\n\" +\n\"  <PHOTO><EXTVAL>http://stpeter.im/images/stpeter_oscon.jpg</EXTVAL></PHOTO>\\n\" +\n\"  <PHOTO><EXTVAL>http://stpeter.im/images/stpeter_hell.jpg</EXTVAL></PHOTO>\\n\" +\n\"  <BDAY>1966-08-06</BDAY>\\n\" +\n\"  <ADR>\\n\" +\n\"    <WORK/>\\n\" +\n\"    <PREF/>\\n\" +\n\"    <EXTADD>Suite 600</EXTADD>\\n\" +\n\"    <STREET>1899 Wynkoop Street</STREET>\\n\" +\n\"    <LOCALITY>Denver</LOCALITY>\\n\" +\n\"    <REGION>CO</REGION>\\n\" +\n\"    <PCODE>80202</PCODE>\\n\" +\n\"    <CTRY>USA</CTRY>\\n\" +\n\"  </ADR>\\n\" +\n\"  <ADR>\\n\" +\n\"    <HOME/>\\n\" +\n\"    <EXTADD/>\\n\" +\n\"    <STREET/>\\n\" +\n\"    <LOCALITY>Parker</LOCALITY>\\n\" +\n\"    <REGION>CO</REGION>\\n\" +\n\"    <PCODE>80138</PCODE>\\n\" +\n\"    <CTRY>USA</CTRY>\\n\" +\n\"  </ADR>\\n\" +\n\"  <TEL><WORK/><VOICE/><PREF/><NUMBER>+1-303-308-3282</NUMBER></TEL>\\n\" +\n\"  <TEL><WORK/><FAX/><NUMBER>+1-303-308-3219</NUMBER></TEL>\\n\" +\n\"  <TEL><CELL/><VOICE/><TEXT/><NUMBER>+1-720-256-6756</NUMBER></TEL>\\n\" +\n\"  <TEL><HOME/><VOICE/><NUMBER>+1-303-555-1212</NUMBER></TEL>\\n\" +\n\"  <EMAIL><USERID>stpeter@jabber.org</USERID></EMAIL>\\n\" +\n\"  <EMAIL><WORK/><USERID>psaintan@cisco.com</USERID></EMAIL>\\n\" +\n\"  <JABBERID>stpeter@jabber.org</JABBERID>\\n\" +\n\"  <TZ>America/Denver</TZ>\\n\" +\n\"  <GEO><LAT>39.59</LAT><LON>-105.01</LON></GEO>\\n\" +\n\"  <TITLE>Executive Director</TITLE>\\n\" +\n\"  <ROLE>Patron Saint</ROLE>\\n\" +\n\"  <LOGO>\\n\" +\n\"    <TYPE>image/jpeg</TYPE>\\n\" +\n\"    <BINVAL>\\n\" +\n\"/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHBgUI\\n\" +\n\"BwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy\\n\" +\n\"/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy\\n\" +\n\"MjIyMjIyMjIyMjIy/8AAEQgAgQB7AwEiAAIRAQMRAf/EABsAAAMAAwEBAAAAAAAAAAAAAAQFBgAD\\n\" +\n\"BwIB/8QAPRAAAgEDAwIDBQQJBAEFAAAAAQIDAAQRBRIhMUEGE1EiYXGBkRQyobEHFSMzNEJScsEk\\n\" +\n\"YtHw0jVDc8Lh/8QAGQEAAwEBAQAAAAAAAAAAAAAAAQIEAwAF/8QAJBEAAgICAgICAgMAAAAAAAAA\\n\" +\n\"AAECEQMhEjEEQSJREzJCYXH/2gAMAwEAAhEDEQA/AOf2c0KGSY2pDFiinYMsCMfhj8aya6gdvZj9\\n\" +\n\"ryg6A8eYuORxQk1rdzSHyZGQYO0GXAPv/MV6luDp8QgntkRyhAfHJ3Y5wOoxxXncbdiA9zp/6xQG\\n\" +\n\"KaGFIhK208MwX09amCOeMEdjT3VLi1EaeVGHEi4WRCQVwAD7PY5/CkQYbcfdPUVbjTS2FGAHGele\\n\" +\n\"1nmXgOw6/iMV4LnHup/4c8L3/iWfbboIoFPt3D/dH/kfcKd0kOotukL/ALWs8SJNEPZGA4/z2omD\\n\" +\n\"T7++dY7azuLlAOPs8Jfb9P8Amu1+Hv0Z+HtPjVp7YX846yXAyM+5elX1tDa2sKxwxRxoBgKigD6U\\n\" +\n\"nJGn4a7OB+G/0Y67rlxuuIRptojDdcXS5c/2R9SfoPfXY/DvgzQvCiLJZW/m3uPavbgb5Sf9vZPl\\n\" +\n\"9TVCBAw5RfiODQ93Fdi3b9XyxiXt5iE59wNPGSEnja6N5VyCzHYh5LOcUvuNc0y0JDTtO/8ATGP8\\n\" +\n\"1Hahc6g87xX0ku9TyhbH4dKEA6AZx1prJ2n7KW58W3L5W1iS3H9XVsfGlMl3NdNvmld8/wBRoMHH\\n\" +\n\"NbM5Hw5oAoIjALHPfA59O9KL218NS3byXtjE9w+GdivqBj8MUyk5ikAOPZ61rtreDUbaO5kiTeV2\\n\" +\n\"HJ7r7P8AiuGSOXDyzBE1zlInAKFR6k9a+XFtHt8qWczjGVUKSAvPHu+VLftckzPu+62U2E5256Y7\\n\" +\n\"1S+Fkj1DxPDaXEe5YYHldc9doGAfdnFQLE+VDdCc2ZXDaQDMTgFDEC6H175zgjimcv6PfFmvXMcy\\n\" +\n\"6SttFtB8+4dIEIIz0PPfsKuE1O7tEMVoy2sfPs28Sxdev3Rmh5Jp52LyzSSnqS7E/nVkIcezrFlj\\n\" +\n\"+ibSrC3aXWNbF9dAezaad93P+6Qjp8AKsNMt4LO1hgto0ihXhVj6CldrsSLoMt7qNhuiiDJyPSsc\\n\" +\n\"k23Rfgi4qyphkCqAMcUQsue9TsGoAkDP1osXOT1oWO0x2JOeua2rPiki3GO/Hxr0L5F/nFGwNB2q\\n\" +\n\"2UWq2+MAXCcxv/g/GopkaNijqVdWIYHqDVSt9uDYbt2pRrKrJJDdgcyrh/7h/wDlawlZLnh7QB96\\n\" +\n\"E46ivSnlDXyAAyFD/Nx9elZGQ0XHJVsH3VqSntk3W7oDgEYz6ULbWkkURUuxO9ySOMksTRY5iPx5\\n\" +\n\"o6KaMxKSygnkjFdQUzhMca3Mau7KXXII28EdvnVv4FtTLq97dOwLR2PlDHUEsD/ioO1uHCg9Og9B\\n\" +\n\"mrPwXrENomp3EynYApYoMkYGOfRfaHuqeKansdlHOMTOeOSelaxjml763ayalcBplW22K8bnoCRl\\n\" +\n\"gT3x2xW21v4bosoDIRgKHGGbPTjPpzWjkmhUrYbFNhgPSjLYPN7K45oGNRtDnGCCc+6grvxhDZsY\\n\" +\n\"rS3LBeN/9VSvbPTi+KK6GwGBucg0T5HljqSPhXMz4/uFmAa1brzk4qisfFS3UIcMR6g9qL12FS5d\\n\" +\n\"FasLOOMAV5ktMDIwamLjxVFagmWTC+g60HF+kOw85UzIfftoJphbrsqTKYwynI7VlzMJdP2fzKQw\\n\" +\n\"+VDJqFjqsPmW0w8wclfWtYV3kKLzlSaeLakZ5acT6jhZIz0Vhj4HtXqQFLuTjaXGTitJztZSuGjY\\n\" +\n\"EgjHuomQ7khlHpzVh5h8Gfs+e5oK6juvtDbCQuAQMj0FGkZgweo3D8DXiUxiTBYZAHYelKdRw85h\\n\" +\n\"uPImyG3glT0z61WadpVteeCdQu4DKk8ZKFVwd53DHPUDDduDioieSYsryZIJ4JGSapvB2pG21CWz\\n\" +\n\"iLSR3kZR0ZcYI6H48kUvH2zRjLTdOngh+23gSGOFdzPMvKgEg4Pr299btN8Qw3Es8kenwolxJgvs\\n\" +\n\"BaMKPZOex+HrQXirWJdQu10m0kLwwkCUr0kk/wDFe3zo/wAP6KqxyW8hO5wWIHfHXFZSjS0beNXO\\n\" +\n\"2Uk2bmyaKH75XaAPSpC48P3qysvnJEf5VPUiq/TzsYhSckkD4U4uNLtL61Czp7XZhwR8xWKu7LeK\\n\" +\n\"emckk0a8VZGmkBYfcG7qaqvB+izSyMJh7O3INOx4bsrUmTy2kI6F2JApxo0ZWfftCx4xxTSbloEI\\n\" +\n\"KPRz7xjp89veMsSkoOmKQR2N9bTKgtzJuI7HH1zXW9XsYrq4kWZCQ3Rh1FJk8LXayfsLobO3mJuo\\n\" +\n\"xlx1QJwUttk3pDzwX8REEkTA9G6H1Hvq41Gznv8ASpoLMSCeZQIihwwbIPB7Vvh0j7PEPtDeY3rj\\n\" +\n\"AHw9KUa3c3EVmY7aXy3LfeHXHGefnSOTsbhy+Jmm61JLdHS9e/02oqTHHdNgJKf6X9D6HpTpoJYk\\n\" +\n\"aF125JIB6qf+4qXk0/8AWFnHJMfM8yMNyevFEaVq11psiWWozNLZniK4ckmP0Uk9vf2quLdbPKmq\\n\" +\n\"k0ig3AxZyOWP1IoG5jZp2IYYwPyo+RCigEdwR7/nXxolJ+5TMCOMy6cjloldDclDtjZcBh2KnOAe\\n\" +\n\"vFePCysNZkQTpbSG3lAkk6Icfn2oW3t7iBnTIwcYB7ntjPz+lPI41jucxxtPPHCHaRkUjOBk+hx+\\n\" +\n\"NYObho1SbDNGh0+3id/MJkAOd45Pfj6U6s7t0j0yWYCMzxud3Ze+KWX7Lc2lr5YjMqIY9yLgMg4y\\n\" +\n\"Pfk0PqazRaXpiSlxuQuAw6ZAroNysWMqdlIbhYH3owK9VPrX1vEwgXJcYHqaTpMG0+DJziNRSe9A\\n\" +\n\"julMn7vbuHxrDjuj0Yz1ZTxa8sjm9v8AzvsiA+yvUntTSw8b6TtKx7gOwNRL3cU1qIzcqM44z0pQ\\n\" +\n\"+lTtlrWWJjnJAcA08YJPsDyy9I68fE2jX0ixy3Pkk9Gz3oLT/FC+e9vM6syMVV+mR2rnFnpNxHNG\\n\" +\n\"8rIWzk5YGnht0lkySEkHcd6E1T0Osl9o6C2qpcIVGDxSHxBMsPh+5lI/anEafE9/oKVafLLFNtkP\\n\" +\n\"TofWvPiu9zZw2QHL/tSfdyB+dGHykLmdQbQfeuNP0G2uIQS0fkjJ/m4yR+BpmY7a7tY5gQ8cyhlB\\n\" +\n\"HUHtSfxJIX0FdoCwxvGqD19k148H3u+Oe1lbLRANCPicED5mrKPLbKDTHNl/o7pZJbM8xsCd0R9P\\n\" +\n\"7fT3+6mhuIFJUTK2OMqQB+Nabc+Vew7sja+XI6+8VN+JpLS08R3sC20MgRgC2M87RkfI8fKhdHUR\\n\" +\n\"Eqs826JiFJ3GJicNj8q1K7QasY4lUJuwgDHA+Jr5qGoFZFEC7QVwccU80S7tbjUYIjGrsrsqtJgA\\n\" +\n\"nBOPxFScZcv6NZP6FzxvFAIyCu1SQAeSCe3zzTXWJpr2y0uNUy8MGXbcAOQMc/KtfiGAx6rHBCQx\\n\" +\n\"8sbQPUscCvfimHz9G8uEYFsqkheAdowf+flVeHC6bMWwG3nVQYDIrFeMq2QOeK3TbJgsUqBjnFLv\\n\" +\n\"Clmt1aaizrgewFYDocmi/NZHCsAJAcEGpsiuWi/G6jsMHh61juRcxoGV12tG3TPrTP8AVOnMuJNO\\n\" +\n\"lRiwO5FJzwO4rxA7m2U7chhjFDy6heWr/swwHcE8Ckv7N0os3X/h+0kikksoJo2z7O4lfzpRHpN5\\n\" +\n\"YzxedcGVmzuH9NUFpfvOp3qzMemelBajMzXMa59r1rm/SOcUj2zYdWX04+NKNbnNzePtIOxAg+PJ\\n\" +\n\"/wA0RdXQhAVTlvypNLMMMzHJ3At9a2wQp2SeRk1xRaeLNsWi2sCHOJUUn4IRU/o119j1uynJOBLh\\n\" +\n\"h6huP8088Uc6Qsz8Ga4Gz3AKT/kVIGTE8RHUOCPqKoSJDqqkhsknJIOflSZ7qzhkZL1Fe53EuxQ8\\n\" +\n\"55/Iinb/AL/AHG4/8U0g01Lm2ilJiJZFzkDPAxQCcCuxslL+YoYnbjOeMVQeFjeR7GjtBcYlLKCv\\n\" +\n\"IOBk5xxkVXw6L4fsmDRWMMsi8B5zvP0PFbri+mCCKJkRcYAXgYrePhv+TOc/oU6rpkz6p9ufbCuw\\n\" +\n\"KsZbLKff9aC3tgq+DgFT3B7UyklySrcE5z76AmAwW2nGOearhj4RpGVtnrTjFBD9liQIgXgD/vNK\\n\" +\n\"tbtnBM0XDDHzFbfPMUgdTlaMd0uYd4OfdXleRheOfJdHoY8inCn2A6TrChtrH7uMBj0p3JrFtMVQ\\n\" +\n\"RqSSecdTUff2qpMWT2eeooSKS4jcMrZI6ZrHgnsP5GtF7cXsKo7sAm3sOKQrc+bcTTM37GH2nk9M\\n\" +\n\"8AUHBHLecXEh2HqF71v19o7Lw+IIgFEsiqR7hz/ihGK5DSk3GwW7Dw3UyOcurHn8vwrVbWzXtzDB\\n\" +\n\"082RUJ9Mmmtvo11rumW1/aNGZBGI5InbaxK8ZHr2r5Z2k1rrVjbSxvE5uEB3jbgZ5q9xa/wgu2OP\\n\" +\n\"HE4k+xIh/ZoZAMd8bakl5ljb1I/MVTeNCpWw8v7oMqjj4c/WphWwV5xyDSJ6CdYdv9Vnk4c1SWlq\\n\" +\n\"4tYwsgC44GKmCf2z9gGz3qxsJozYQFm5KA/WlOOXyXmV3LbuBjqFOKG86VwSu3gdCc0El/Pavtcs\\n\" +\n\"wHGCc0aJBcJ5ls6h+pU165mCudxGXYtnOOgFCzXgSJgxCRgd+rGjmkimO2T9nIOMilV/aOmWOGjJ\\n\" +\n\"/wCmhK60cgAXOx/bJIY1vWeSBtybnU9QBS2aNIs7nJ9MCt1ndMDsyfQZPU9qmbT+Mh1raDpl+0Dc\\n\" +\n\"o+tBeQ6ScJkVkd5JNqYt7OMyqAd2Ty3rj4UwhxOqyRZKn6j3GoMmNReiqMuW2b7RHwCRilviaQyf\\n\" +\n\"Y4V5wxOPU04x5ERZuTj6UhvdUtoL3eEFxMowP6F9ce+kxQVhySqNIrtDjks9DSJWG3GWVutM7e4h\\n\" +\n\"ljXzHDqP5ZBnHw7ilFrL5yQOmfLZAw+fNN7e3jVi7DrXs0qoha2aNV0uDUokEMqxSIxIDHIbIHHu\\n\" +\n\"qQvrK5sJRHPEVcA4PZvgasb28gXIVFDD+YcZoIzG/ga2uYjLG3C46qT3rGeFVaOTKQXDNKwlOT0y\\n\" +\n\"F93f51To5ihiQZAWJB0/2ipRgWiaQnLsNicDjA6mqaa1DuG2/wAqjqewAqFpp0zRHKNR/eCtel/x\\n\" +\n\"ArKyvVZmEah+9Wvp/gz8Kyspl0cIZ/3bUvi6r/dWVlSZOx4maF/6wvz/ADNOtB/eXf8A8jVlZUcz\\n\" +\n\"aPYXq38EfnUbcfxXyFZWUMQch0LTP4SH+2nX/sn4VlZXqx/VEz7EF19/50bpf8SPgPzrKyuAO4P3\\n\" +\n\"0vx/+oqw7D4D8qysrzcv7jro/9k=\\n\" +\n\"    </BINVAL>\\n\" +\n\"  </LOGO>\\n\" +\n\"  <ORG>\\n\" +\n\"    <ORGNAME>XMPP Standards Foundation</ORGNAME>\\n\" +\n\"  </ORG>\\n\" +\n\"  <URL>https://stpeter.im/</URL>\\n\" +\n\"  <URL>http://www.saint-andre.com/</URL>\\n\" +\n\"  <KEY>\\n\" +\n\"    <CRED>\\n\" +\n\"-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\" +\n\"Version: GnuPG/MacGPG2 v2.0.18 (Darwin)\\n\" +\n\"\\n\" +\n\"mQINBFETDzsBEAC0FOv1N3ZJzIIxN6cKD475KVS9CHDPeYpegcOIPnL5eY1DCHeh\\n\" +\n\"/IwS1S7RCePtmiybNoV9FsI4PKUknzXQxA6LVEdAR/LUlhgJKjq+gsgp8lqbEILh\\n\" +\n\"g13ecH66HwLS9rarbQkC47T7kL8miIPBFC6E3A4Lq1L+eueO6UcLhKgoYkMxOjdi\\n\" +\n\"WrMgKTnVpch5ydLkPm/z0Zo8zRgqlPuTLeCrXXZYnjHXLVFN2xy04UzOs7P5u5KV\\n\" +\n\"fx5Z7uQisr8pXtyLd6SpTZo6SHgKBv15uz0rqXhsJojiGtOXfWznAjaS5FUOORq9\\n\" +\n\"CklG5cMOUAT8TNftv0ktsxaWDL1ELDVQPy1m7mtzo+VREG+0xmU6AjMo/GHblW1U\\n\" +\n\"U7MI9yCiuMLsp/HLrFuiosqLVZ85wuLQ2junPe3tK8h15UcxIXAcpQ1VqIaDQFbe\\n\" +\n\"uLOXJTF8YHpHdpHYt/ZM1ll7ZBKGAo8yd7uF7wJ9D3gUazwdz9fFjWV7oIk7ATwO\\n\" +\n\"lFllzmWDn+M2ygbHOGUGMX5hSaa8eDSieiR2QoLdn27Fip7kMBTJ2+GISrfnJTN/\\n\" +\n\"OQvmj0DXXAdxHmu2C4QgmZbkge35n129yzXn9NcqzrGLroV62lL3LgX6cSbiH5i7\\n\" +\n\"GgWY6CAPb1pMogV0K475n9FvOSDRiG4QSO5yqKiA3OP5aKrIRp2TNAk4IwARAQAB\\n\" +\n\"tCZQZXRlciBTYWludC1BbmRyZSA8c3RwZXRlckBzdHBldGVyLmltPokCOQQTAQIA\\n\" +\n\"IwUCURMPOwIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEOoGpJErxa2p\\n\" +\n\"6bgQAKpxu07cMDOLc4+EG8H19NWXIVVybOEvfGuHYZaLKkPrhrMZwJiOwBpyISNR\\n\" +\n\"t9qzX1eLCVaojaoEVX6kD8MGc5zKFfiJZy3j7lBWl+Ybr7FfXYy2BbAXKx49e1n6\\n\" +\n\"ci9LmBrmVfAEaxtDNPITZ9N9oUAb9vS0nrG036EwteEHAveQvlDjO7lhz6+Cv7lZ\\n\" +\n\"QgBj9rZ6khfcQ4S3nSCQaKLQ9Iav4fqxI7SfuPKnx6quHX3JNLGnVo3wl+j/foCK\\n\" +\n\"0iTrmtHxCI3kc/bx6g32pRjHEPX0ALMBhmzU2uca+TE0zCEC96mgYXAUCwdnCFWy\\n\" +\n\"beIEbt6pz65iML13kAVAq0H/GqncnMGN0MbOatnw1Tdz/vkLojIy7QbPcQ0plUFx\\n\" +\n\"v5491xPfIrHhOWdRXp6WUt88fcqhT6MHZpVRtusj2ornKVVn+Y0GLsMMCTcrXJRG\\n\" +\n\"7Ao1YV72t/pJpzfGWSaaxolxDIZ6B+76jrIhUhiWgo/4nf+DN6BIlCZQ6j6xxjjx\\n\" +\n\"462cu02kuhIILTk2pzaMOufTBWx0uJhZk/KP2Fay/41pX7pvVOwRC4uIlKsLnJKL\\n\" +\n\"PS7EDa4BUUxENfd/9LqOGwlII8BbSe98PLMI8sXkcigc3UXMVda9ll0YhQa+lbP1\\n\" +\n\"NaszmnBhwuiCsgnPGbImsJuRzgEEgckwP/dNeyr6MlFMyfaeuQINBFETDzsBEADB\\n\" +\n\"zOsEHpUmhkRUjH9Tek87dn5P/Yh/L/HptgCGk40TL/C+kYdkd3HyteMEf061PNms\\n\" +\n\"S/Rq8k37Fu3VODYb9SPYKxtgksKSYUtIkPKvao09K9QNWPqyWuNf0F+iAjVMUuda\\n\" +\n\"EVFJ7bHF310RDwLY5IvLeCXxtvG+Vv/i+g77d2WdPDp+zLJ8306C4yBKjSJV8xW0\\n\" +\n\"cn2fd7NviIEN6cNHTsZNDZVMlgYPrxnwSq8GTEPGC7HsLIwGcx3hIe9QjnPw9CpA\\n\" +\n\"mQENpDEyWcxgF5uwo2NJECoDswKz1Nb0gfawF3ZIbD+GcLujTu94iJuVg25jATWm\\n\" +\n\"9wTgcfZo4UPllRGXdIb8uWwUFQlLQgd4ROLZZtXNGmHIymJrV2crx53gxup+1j0X\\n\" +\n\"qhlzKg8xbImWhEfS9oHZkRK8VHgmWSIt7TNwNir6N5j3lqwWVBhnu6GzF01sKGNy\\n\" +\n\"SlqNRbd0fqhakCkK71b8ot8tYTcYG5Lg10z6HTbgQx2UwLthUjqbblDQ+GLmrOhi\\n\" +\n\"WklLXRsnlnPMwnEyFePAnsT5tasy2Cn9qjpttNDah7PB8iFUi9mtTF/XDVgpFaB5\\n\" +\n\"G3CDV7Q2NgbAI6g6QhLIAmXzSP635G83mda0TKXHQXHDyLJTTn+WVFU7t4m4uLt+\\n\" +\n\"0DsWU8jXHQWyUTNG9WPUrXhusDUAPHxFCQ/n/lQVBwARAQABiQIfBBgBAgAJBQJR\\n\" +\n\"Ew87AhsMAAoJEOoGpJErxa2pqfgP/ApN+TRu2bBIgaw1dr3AznSSha84DIpXUDh3\\n\" +\n\"udZvQrGbUtz8/mA+e3iZEN/cmmBw2LGlAuQoJNILTZQ318yTP+E5QU7fJH7FVsoh\\n\" +\n\"UyvrMfyt3IMA9jg0Z9MuloLezvIjjMfFeNa0ROgDb/ubOT7JQzi1kwN8Lu3lO80H\\n\" +\n\"wqBHXEeOLoislUSnZajRKvITbKWkZ6PHRjlMw1Wk4oIi6VLHgGgj79zzL3uhML26\\n\" +\n\"63m7imShvz1QcHTwvyR5i8cZbNOEkotZyERiA1p7YHuruS+QvTi3ZPoQbnMUB3a7\\n\" +\n\"py9d11bw1+w3LiAUGZE/z5hBWOFxYtw+w/U/Vx0BwJGYlwU3M2W20uEXe+qxz7wn\\n\" +\n\"akygKjmLiD2z4njfKjcNCiV3FmXrpmWgADln1c4jfxDh0NrndrsM8FPDf1TMPtOZ\\n\" +\n\"gFDkKripc9xkZ/25P6xn27oTOHWKcAC0QhxSH+HuVBBRk8AgF+zAbDZe4/L6+kan\\n\" +\n\"SrycIXW+wCzwBq61aWsz2QhhuKjozVkhk4dRG+CfjzAFjnyxwYERn3uXVKQAwTwc\\n\" +\n\"dNcTI9RV98IsNrw9Y4lJEAg6CjNPmiD5+EASycqaOuToRSGukr8sOQLWLPyTnez/\\n\" +\n\"aG8Xf7a+fntWzK2HuDYoSDhJJrylWw/lMklOBm4wtMeNA0zcQH6AQV/GzQVQkSGq\\n\" +\n\"rLuMVIV/\\n\" +\n\"=llGw\\n\" +\n\"-----END PGP PUBLIC KEY BLOCK-----\\n\" +\n\"    </CRED>\\n\" +\n\"  </KEY>\\n\" +\n\"  <NOTE>\\n\" +\n\"    More information about me is located on my \\n\" +\n\"    personal website: https://stpeter.im/\\n\" +\n\"  </NOTE>\\n\" +\n\"</vCard>\").replace(\"\\n\", \"\").replace(\"  \",\"\");\n\t\n\t\n\tprotected SimpleParser        parser = SingletonFactory.getParserInstance();\n\t\n\t@Test\n\tpublic void testVCardTempToVCard4() {\n\t\tchar[] data = VCARD_TEMP_DATA.toCharArray();\n\t\tDomBuilderHandler handler = new DomBuilderHandler();\n\t\tparser.parse(handler, data, 0, data.length);\n\t\tElement vcardTemp = handler.getParsedElements().poll();\n\t\tdata = VCARD4_DATA.toCharArray();\n\t\tparser.parse(handler, data, 0, data.length);\n\t\tElement expResult = handler.getParsedElements().poll();\n\t\t\n\t\tElement vcard4 = VCardXMPPProcessorAbstract.convertVCardTempToVCard4(vcardTemp);\n\t\tassertNotEquals(vcardTemp, vcard4);\n\t\tassertEquals(expResult.toString(), vcard4.toString());\n\t}\n\n\t@Test\n\tpublic void testVCard4ToVCardTemp() {\n\t\tchar[] data = VCARD4_DATA.toCharArray();\n\t\tDomBuilderHandler handler = new DomBuilderHandler();\n\t\tparser.parse(handler, data, 0, data.length);\n\t\tElement vcard4 = handler.getParsedElements().poll();\n\t\tdata = VCARD2_TEMP_DATA.toCharArray();\n\t\tparser.parse(handler, data, 0, data.length);\n\t\tElement expResult = handler.getParsedElements().poll();\n\t\t\n\t\tElement vcardTemp = VCardXMPPProcessorAbstract.convertVCard4ToVCardTemp(vcard4);\n\t\tassertNotEquals(vcard4, vcardTemp);\n\t\tassertEquals(expResult.toString(), vcardTemp.toString());\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/annotation/AnnotatedXMPPProcessorTest.java",
    "content": "/*\n * AnnotatedXMPPProcessorTest.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport tigase.server.Packet;\nimport tigase.util.TigaseStringprepException;\nimport tigase.xml.Element;\nimport tigase.xmpp.Authorization;\nimport tigase.xmpp.ProcessorFactory;\nimport tigase.xmpp.StanzaType;\nimport tigase.xmpp.XMPPProcessorIfc;\nimport tigase.xmpp.impl.SessionBind;\n\n/**\n *\n * @author andrzej\n */\npublic class AnnotatedXMPPProcessorTest {\n\t\n\t@Test\n\tpublic void test1() {\n\t\tTestAnnotatedXMPPProcessor test1 = new TestAnnotatedXMPPProcessor();\n\t\tfor (String[] path : test1.supElementNamePaths()) {\n\t\t\tAssert.assertArrayEquals(\"Wrong element paths\", new String[] { \"iq\", \"query\" }, path);\n\t\t}\n\t\tAssert.assertArrayEquals(\"Wrong xmlnss\", new String[] { \"tigase:test1\", \"tigase:test2\" }, test1.supNamespaces());\n\t\t\n\t\tAssert.assertArrayEquals(\"Wrong disco features\", new Element[] { \n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"tigase:test1\" }), \n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"tigase:test2\" }) }, test1.supDiscoFeatures(null));\n\t\tAssert.assertArrayEquals(\"Wrong stream features\", new Element[] {\n\t\t\tnew Element(\"bind\", new String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-bind\" })\n\t\t}, test1.supStreamFeatures(null));\n\t\tAssert.assertTrue(\"Stanza type not set as 'get'\", test1.supTypes().contains(StanzaType.get));\n\t}\n\n\t@Test\n\tpublic void test2() {\n\t\tTestAnnotatedXMPPProcessor2 test2 = new TestAnnotatedXMPPProcessor2();\n\t\tAssert.assertNull(\"Wrong element paths, should not be inherited\", test2.supElementNamePaths());\n\n\t\tAssert.assertNull(\"Wrong xmlnss\",test2.supNamespaces());\n\t\t\n\t\tAssert.assertNull(\"Wrong disco features\", test2.supDiscoFeatures(null));\n\t\tAssert.assertNull(\"Wrong stream features\", test2.supStreamFeatures(null));\n\t}\n\n\t@Test\n\tpublic void testSessionBind() {\n\t\tSessionBind sessionBind = new SessionBind();\n\t\tAssert.assertEquals(\"Wrong processor id\", \"urn:ietf:params:xml:ns:xmpp-session\", sessionBind.id());\n\t\tfor (String[] path : sessionBind.supElementNamePaths()) {\n\t\t\tAssert.assertArrayEquals(\"Wrong element paths\", new String[] { \"iq\", \"session\" }, path);\n\t\t}\n\t\tAssert.assertArrayEquals(\"Wrong xmlnss\", new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" }, sessionBind.supNamespaces());\n\t\t\n\t\tAssert.assertArrayEquals(\"Wrong disco features\", new Element[] { \n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" })\n\t\t}, sessionBind.supDiscoFeatures(null));\n//\t\tAssert.assertArrayEquals(\"Wrong stream features\", new Element[] {\n//\t\t\tnew Element(\"session\", new String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" })\n//\t\t}, sessionBind.supStreamFeatures(null));\t\t\n\t}\n\t\n\t@Test\n\tpublic void testProcessorFactorySessionBind() throws TigaseStringprepException {\n\t\tXMPPProcessorIfc sessionBind = ProcessorFactory.getProcessor(\"urn:ietf:params:xml:ns:xmpp-session\");\n\t\tAssert.assertEquals(\"Wrong processor id\", \"urn:ietf:params:xml:ns:xmpp-session\", sessionBind.id());\n\t\tfor (String[] path : sessionBind.supElementNamePaths()) {\n\t\t\tAssert.assertArrayEquals(\"Wrong element paths\", new String[] { \"iq\", \"session\" }, path);\n\t\t}\n\t\tAssert.assertArrayEquals(\"Wrong xmlnss\", new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" }, sessionBind.supNamespaces());\n\t\t\n\t\tAssert.assertArrayEquals(\"Wrong disco features\", new Element[] { \n\t\t\tnew Element(\"feature\", new String[] { \"var\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" })\n\t\t}, sessionBind.supDiscoFeatures(null));\n//\t\tAssert.assertArrayEquals(\"Wrong stream features\", new Element[] {\n//\t\t\tnew Element(\"session\", new String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" })\n//\t\t}, sessionBind.supStreamFeatures(null));\t\t\t\n\t\t\n\t\tElement iqEl = new Element(\"iq\", new String[] {\"type\", \"id\"}, new String[] { \"set\", \"test1\" });\n\t\tiqEl.addChild(new Element(\"session\", new String[] { \"xmlns\" }, new String[] { \"urn:ietf:params:xml:ns:xmpp-session\" }));\n\t\t\n\t\tPacket iq = Packet.packetInstance(iqEl);\n\t\tAssert.assertTrue(\"Packet not handled!\", sessionBind.canHandle(iq, null) == Authorization.AUTHORIZED);\n\t}\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/annotation/TestAnnotatedXMPPProcessor.java",
    "content": "/*\n * TestAnnotatedXMPPProcessor.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\nimport tigase.xmpp.StanzaType;\nimport static tigase.xmpp.impl.annotation.TestAnnotatedXMPPProcessor.*;\n\n/**\n *\n * @author andrzej\n */\n@Id(ID)\n@Handles({\n\t@Handle(path={ \"iq\", \"query\" }, xmlns=XMLNS1),\n\t@Handle(pathStr=IQ_QUERY_PATH, xmlns=XMLNS2)\n})\n@DiscoFeatures({\n\tXMLNS1,\n\tXMLNS2\n})\n@StreamFeatures({\n\t@StreamFeature(elem=\"bind\", xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\")\n})\n@HandleStanzaTypes({\n\tStanzaType.get\n})\nclass TestAnnotatedXMPPProcessor extends AnnotatedXMPPProcessor {\n\t\n\tprotected static final String ID = \"test-123\";\n\tprotected static final String XMLNS1 = \"tigase:test1\";\n\tprotected static final String XMLNS2 = \"tigase:test2\";\n\tprotected static final String IQ_QUERY_PATH = \"iq/query\";\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/annotation/TestAnnotatedXMPPProcessor2.java",
    "content": "/*\n * TestAnnotatedXMPPProcessor2.java\n *\n * Tigase Jabber/XMPP Server\n * Copyright (C) 2004-2015 \"Tigase, Inc.\" <office@tigase.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. Look for COPYING file in the top folder.\n * If not, see http://www.gnu.org/licenses/.\n *\n */\npackage tigase.xmpp.impl.annotation;\n\n/**\n *\n * @author andrzej\n */\nclass TestAnnotatedXMPPProcessor2 extends TestAnnotatedXMPPProcessor {\n\t\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/roster/RosterElementTest.java",
    "content": "package tigase.xmpp.impl.roster;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\nimport tigase.xmpp.JID;\n\npublic class RosterElementTest {\n\n\t@Test\n\tpublic void testSetName() {\n\t\tRosterElement e = new RosterElement(JID.jidInstanceNS(\"a@b.c\"), null, new String[] {}, null);\n\t\tassertNull(e.getName());\n\t\tassertTrue(e.isModified());\n\n\t\te.getRosterElement();\n\t\tassertFalse(e.isModified());\n\n\t\te.setName(null);\n\t\tassertFalse(e.isModified());\n\t\tassertNull(e.getName());\n\n\t\te.setName(\"jeff\");\n\t\tassertTrue(e.isModified());\n\t\tassertEquals(\"jeff\", e.getName());\n\n\t\te.getRosterElement();\n\t\tassertFalse(e.isModified());\n\n\t\te.setName(\"jeff\");\n\t\tassertFalse(e.isModified());\n\t\tassertEquals(\"jeff\", e.getName());\n\n\t\te.setName(\"bob\");\n\t\tassertTrue(e.isModified());\n\t\tassertEquals(\"bob\", e.getName());\n\n\t\te.getRosterElement();\n\t\tassertFalse(e.isModified());\n\n\t\te.setName(null);\n\t\tassertTrue(e.isModified());\n\t\tassertNull(e.getName());\n\n\t\te.getRosterElement();\n\t\tassertFalse(e.isModified());\n\n\t\te.setName(null);\n\t\tassertFalse(e.isModified());\n\t\tassertNull(e.getName());\n\t}\n\n}\n"
  },
  {
    "path": "tigase-server 7.1.0/tests/data/telnet-test.xml",
    "content": "<stream:stream to=\"kobit\" id=\"abc1\" version=\"1.0\" xml:lang=\"en\"\nxmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\">\n<hello to=\"artur@kobit\" from=\"tus@kobit\"/>\n"
  },
  {
    "path": "tigase-server 7.1.0/tests/data/test_config.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n\n<preferences>\n <root name='test_1_Component'>\n  <map>\n   <entry key='' value='muc' type='String'/>\n   <entry key='bool_false' value='false' type='Boolean'/>\n   <entry key='bool_true' value='true' type='Boolean'/>\n   <entry key='bools' type='boolean[]'>\n    <item value='true'/>\n    <item value='false'/>\n   </entry>\n   <entry key='double' value='12.34' type='Double'/>\n   <entry key='doubles' type='double[]'>\n    <item value='1.2'/>\n    <item value='2.3'/>\n    <item value='3.4'/>\n    <item value='4.5'/>\n   </entry>\n   <entry key='int_12345' value='12345' type='Integer'/>\n   <entry key='ints_12345' type='int[]'>\n    <item value='1'/>\n    <item value='2'/>\n    <item value='3'/>\n    <item value='4'/>\n    <item value='5'/>\n   </entry>\n   <entry key='string' value='Just a string.' type='String'/>\n   <entry key='strings' type='String[]'>\n    <item value='str_1'/>\n    <item value='str_2'/>\n    <item value='str_3'/>\n   </entry>\n  </map>\n  <node name='component'>\n   <map>\n    <entry key='.accept' value='true' type='Boolean'/>\n    <entry key='ports' type='int[]'>\n     <item value='1'/>\n     <item value='22'/>\n     <item value='333'/>\n     <item value='4444'/>\n    </entry>\n    <entry key='treshold' value='12.34' type='Double'/>\n   </map>\n  </node>\n  <node name='server'>\n   <map/>\n   <node name='params'>\n    <map>\n     <entry key='bool_false' value='false' type='Boolean'/>\n     <entry key='bool_true' value='true' type='Boolean'/>\n     <entry key='bools' type='boolean[]'>\n      <item value='true'/>\n      <item value='false'/>\n     </entry>\n     <entry key='double' value='12.34' type='Double'/>\n     <entry key='doubles' type='double[]'>\n      <item value='1.2'/>\n      <item value='2.3'/>\n      <item value='3.4'/>\n      <item value='4.5'/>\n     </entry>\n     <entry key='int_12345' value='12345' type='Integer'/>\n     <entry key='ints_12345' type='int[]'>\n      <item value='1'/>\n      <item value='2'/>\n      <item value='3'/>\n      <item value='4'/>\n      <item value='5'/>\n     </entry>\n     <entry key='string' value='Just a string.' type='String'/>\n     <entry key='strings' type='String[]'>\n      <item value='str_1'/>\n      <item value='str_2'/>\n      <item value='str_3'/>\n     </entry>\n    </map>\n   </node>\n  </node>\n </root>\n</preferences>\n"
  },
  {
    "path": "tigase-server 7.1.0/tests/data/tigase-config-1.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n\n<tigase-config>\n <component name=\"basic-conf\">\n  <map/>\n  <node name=\"logging\">\n   <map>\n    <entry key=\".level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"tigase.xml.level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"tigase.util.level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"tigase.io.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.io.TLSIO.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.net.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.net.IOService.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.XMPPIOService.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.xmppcomponent.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.xmppclient.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.MessageRouter.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.ConnectionManager.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.XMPPDomBuilderHandler.level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"handlers\" value=\"java.util.logging.ConsoleHandler\" type=\"String\"/>\n    <entry key=\"java.util.logging.ConsoleHandler.formatter\" value=\"tigase.util.LogFormatter\" type=\"String\"/>\n    <entry key=\"java.util.logging.ConsoleHandler.level\" value=\"ALL\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.append\" value=\"true\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.count\" value=\"5\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.formatter\" value=\"tigase.util.LogFormatter\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.level\" value=\"ALL\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.limit\" value=\"100000\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.pattern\" value=\"logs/java_%g.log\" type=\"String\"/>\n    <entry key=\"tigase.handlers\" value=\"java.util.logging.FileHandler\" type=\"String\"/>\n    <entry key=\"tigase.useParentHandlers\" value=\"true\" type=\"String\"/>\n   </map>\n  </node>\n </component>\n <component name=\"tigase-xmpp-server\">\n  <map>\n   <entry key=\"local-addresses\" type=\"String[]\">\n    <item value=\"localhost-1\"/>\n   </entry>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n  </map>\n  <node name=\"components\">\n   <map/>\n   <node name=\"msg-receivers\">\n    <map>\n     <entry key=\"client_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"client_1.class\" value=\"tigase.server.xmppclient.ClientConnectionManager\" type=\"String\"/>\n     <entry key=\"comp_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"comp_1.class\" value=\"tigase.server.xmppcomponent.ComponentConnectionManager\" type=\"String\"/>\n     <entry key=\"id-names\" type=\"String[]\">\n      <item value=\"client_1\"/>\n      <item value=\"server_1\"/>\n      <item value=\"comp_1\"/>\n      <item value=\"session_1\"/>\n     </entry>\n     <entry key=\"server_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"server_1.class\" value=\"tigase.server.xmppserver.ServerConnectionManager\" type=\"String\"/>\n     <entry key=\"session_1.active\" value=\"false\" type=\"Boolean\"/>\n     <entry key=\"session_1.class\" value=\"tigase.server.xmppsession.SessionManager\" type=\"String\"/>\n    </map>\n   </node>\n   <node name=\"registrators\">\n    <map>\n     <entry key=\"id-names\" type=\"String[]\">\n      <item value=\"stat_1\"/>\n      <item value=\"service_1\"/>\n     </entry>\n     <entry key=\"service_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"service_1.class\" value=\"tigase.server.XMPPServiceCollector\" type=\"String\"/>\n     <entry key=\"stat_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"stat_1.class\" value=\"tigase.stats.StatisticsCollector\" type=\"String\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"client_1\">\n  <map>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n   <entry key=\"hostnames\" type=\"String[]\">\n    <item value=\"localhost-1\"/>\n   </entry>\n  </map>\n  <node name=\"routings\">\n   <map>\n    <entry key=\".+\" value=\"session_1@localhost-2\" type=\"String\"/>\n    <entry key=\"multi-mode\" value=\"true\" type=\"Boolean\"/>\n    <entry key=\".+@localhost\" value=\"session_1@localhost-2\" type=\"String\"/>\n   </map>\n  </node>\n  <node name=\"connections\">\n   <map>\n    <entry key=\"ports\" type=\"int[]\">\n     <item value=\"5222\"/>\n     <item value=\"5223\"/>\n    </entry>\n   </map>\n   <node name=\"5222\">\n    <map>\n     <entry key=\"ifc\" type=\"String[]\">\n      <item value=\"*\"/>\n     </entry>\n     <entry key=\"remote-host\" value=\"localhost-1\" type=\"String\"/>\n     <entry key=\"socket\" value=\"plain\" type=\"String\"/>\n     <entry key=\"type\" value=\"accept\" type=\"String\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry key=\"required\" value=\"false\" type=\"Boolean\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"5223\">\n    <map>\n     <entry key=\"ifc\" type=\"String[]\">\n      <item value=\"*\"/>\n     </entry>\n     <entry key=\"remote-host\" value=\"localhost-1\" type=\"String\"/>\n     <entry key=\"socket\" value=\"ssl\" type=\"String\"/>\n     <entry key=\"type\" value=\"accept\" type=\"String\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry key=\"required\" value=\"false\" type=\"Boolean\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"tls\">\n    <map>\n     <entry key=\"keys-store\" value=\"certs/keystore\" type=\"String\"/>\n     <entry key=\"keys-store-password\" value=\"keystore\" type=\"String\"/>\n     <entry key=\"trusts-store\" value=\"certs/truststore\" type=\"String\"/>\n     <entry key=\"trusts-store-password\" value=\"truststore\" type=\"String\"/>\n     <entry key=\"use\" value=\"true\" type=\"Boolean\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"server_1\">\n  <map>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n  </map>\n </component>\n <component name=\"comp_1\">\n  <map>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n  </map>\n  <node name=\"connections\">\n   <map>\n    <entry key=\"ports\" type=\"int[]\">\n     <item value=\"5555\"/>\n    </entry>\n   </map>\n   <node name=\"5555\">\n    <map>\n     <entry key=\"ifc\" type=\"String[]\">\n      <item value=\"127.0.0.1\"/>\n     </entry>\n     <entry key=\"remote-host\" value=\"localhost-2\" type=\"String\"/>\n     <entry key=\"secret\" value=\"someSecret\" type=\"String\"/>\n     <entry key=\"socket\" value=\"plain\" type=\"String\"/>\n     <entry key=\"type\" value=\"accept\" type=\"String\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry key=\"required\" value=\"false\" type=\"Boolean\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"tls\">\n    <map>\n     <entry key=\"keys-store\" value=\"certs/keystore\" type=\"String\"/>\n     <entry key=\"keys-store-password\" value=\"keystore\" type=\"String\"/>\n     <entry key=\"trusts-store\" value=\"certs/truststore\" type=\"String\"/>\n     <entry key=\"trusts-store-password\" value=\"truststore\" type=\"String\"/>\n     <entry key=\"use\" value=\"true\" type=\"Boolean\"/>\n    </map>\n   </node>\n  </node>\n </component>\n</tigase-config>\n"
  },
  {
    "path": "tigase-server 7.1.0/tests/data/tigase-config-2.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n\n<tigase-config>\n <component name=\"basic-conf\">\n  <map/>\n  <node name=\"logging\">\n   <map>\n    <entry key=\".level\" value=\"INFO\" type=\"String\"/>\n    <entry key=\"tigase.xml.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.auth.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.impl.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.io.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.net.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.XMPPIOService.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.impl.JabberIqStats.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.xmpp.impl.Message.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.xmppcomponent.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.xmppsession.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.ConnectionManager.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"tigase.server.MessageRouter.level\" value=\"FINE\" type=\"String\"/>\n    <entry key=\"handlers\" value=\"java.util.logging.ConsoleHandler\" type=\"String\"/>\n    <entry key=\"java.util.logging.ConsoleHandler.formatter\" value=\"tigase.util.LogFormatter\" type=\"String\"/>\n    <entry key=\"java.util.logging.ConsoleHandler.level\" value=\"ALL\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.append\" value=\"true\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.count\" value=\"5\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.formatter\" value=\"tigase.util.LogFormatter\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.level\" value=\"ALL\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.limit\" value=\"100000\" type=\"String\"/>\n    <entry key=\"java.util.logging.FileHandler.pattern\" value=\"logs/java_%g.log\" type=\"String\"/>\n    <entry key=\"tigase.handlers\" value=\"java.util.logging.FileHandler\" type=\"String\"/>\n    <entry key=\"tigase.useParentHandlers\" value=\"true\" type=\"String\"/>\n   </map>\n  </node>\n </component>\n <component name=\"tigase-xmpp-server\">\n  <map>\n   <entry key=\"local-addresses\" type=\"String[]\">\n    <item value=\"localhost-2\"/>\n   </entry>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n  </map>\n  <node name=\"components\">\n   <map/>\n   <node name=\"msg-receivers\">\n    <map>\n     <entry key=\"client_1.active\" value=\"false\" type=\"Boolean\"/>\n     <entry key=\"client_1.class\" value=\"tigase.server.xmppclient.ClientConnectionManager\" type=\"String\"/>\n     <entry key=\"comp_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"comp_1.class\" value=\"tigase.server.xmppcomponent.ComponentConnectionManager\" type=\"String\"/>\n     <entry key=\"id-names\" type=\"String[]\">\n      <item value=\"client_1\"/>\n      <item value=\"server_1\"/>\n      <item value=\"comp_1\"/>\n      <item value=\"session_1\"/>\n     </entry>\n     <entry key=\"server_1.active\" value=\"false\" type=\"Boolean\"/>\n     <entry key=\"server_1.class\" value=\"tigase.server.xmppserver.ServerConnectionManager\" type=\"String\"/>\n     <entry key=\"session_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"session_1.class\" value=\"tigase.server.xmppsession.SessionManager\" type=\"String\"/>\n    </map>\n   </node>\n   <node name=\"registrators\">\n    <map>\n     <entry key=\"id-names\" type=\"String[]\">\n      <item value=\"stat_1\"/>\n      <item value=\"service_1\"/>\n     </entry>\n     <entry key=\"service_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"service_1.class\" value=\"tigase.server.XMPPServiceCollector\" type=\"String\"/>\n     <entry key=\"stat_1.active\" value=\"true\" type=\"Boolean\"/>\n     <entry key=\"stat_1.class\" value=\"tigase.stats.StatisticsCollector\" type=\"String\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"comp_1\">\n  <map>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n  </map>\n  <node name=\"connections\">\n   <map>\n    <entry key=\"ports\" type=\"int[]\">\n     <item value=\"5555\"/>\n    </entry>\n   </map>\n   <node name=\"5555\">\n    <map>\n     <entry key=\"ifc\" type=\"String[]\">\n      <item value=\"127.0.0.1\"/>\n     </entry>\n     <entry key=\"remote-host\" value=\"localhost-1\" type=\"String\"/>\n     <entry key=\"secret\" value=\"someSecret\" type=\"String\"/>\n     <entry key=\"socket\" value=\"plain\" type=\"String\"/>\n     <entry key=\"type\" value=\"connect\" type=\"String\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry key=\"required\" value=\"false\" type=\"Boolean\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"tls\">\n    <map>\n     <entry key=\"keys-store\" value=\"certs/keystore\" type=\"String\"/>\n     <entry key=\"keys-store-password\" value=\"keystore\" type=\"String\"/>\n     <entry key=\"trusts-store\" value=\"certs/truststore\" type=\"String\"/>\n     <entry key=\"trusts-store-password\" value=\"truststore\" type=\"String\"/>\n     <entry key=\"use\" value=\"true\" type=\"Boolean\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"session_1\">\n  <map>\n   <entry key=\"max-queue-size\" value=\"2147483647\" type=\"Integer\"/>\n   <entry key=\"repository-url\" value=\"user-repository.xml\" type=\"String\"/>\n   <entry key=\"components\" type=\"String[]\">\n    <item value=\"jabber:iq:register\"/>\n    <item value=\"jabber:iq:auth\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-bind\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-session\"/>\n    <item value=\"message\"/>\n    <item value=\"jabber:iq:roster\"/>\n    <item value=\"presence\"/>\n    <item value=\"jabber:iq:version\"/>\n    <item value=\"jabber:iq:stats\"/>\n    <item value=\"starttls\"/>\n    <item value=\"disco\"/>\n   </entry>\n   <entry key=\"hostnames\" type=\"String[]\">\n    <item value=\"localhost-2\"/>\n   </entry>\n  </map>\n  <node name=\"security\">\n   <map>\n    <entry key=\"authentication-ids\" type=\"String[]\">\n     <item value=\"auth-plain\"/>\n     <item value=\"auth-digest\"/>\n     <item value=\"auth-sasl\"/>\n    </entry>\n   </map>\n   <node name=\"auth-digest\">\n    <map>\n     <entry key=\"class\" value=\"tigase.auth.DigestAuth\" type=\"String\"/>\n     <entry key=\"flag\" value=\"sufficient\" type=\"String\"/>\n    </map>\n   </node>\n   <node name=\"auth-plain\">\n    <map>\n     <entry key=\"class\" value=\"tigase.auth.PlainAuth\" type=\"String\"/>\n     <entry key=\"flag\" value=\"sufficient\" type=\"String\"/>\n    </map>\n   </node>\n   <node name=\"auth-sasl\">\n    <map>\n     <entry key=\"class\" value=\"None\" type=\"String\"/>\n     <entry key=\"flag\" value=\"sufficient\" type=\"String\"/>\n    </map>\n   </node>\n  </node>\n </component>\n</tigase-config>\n"
  },
  {
    "path": "tigase-server 7.1.0/tests/data/tigase-config.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n\n<tigase-config>\n <component name=\"basic-conf\">\n  <map/>\n  <node name=\"logging\">\n   <map>\n    <entry value=\"WARNING\" type=\"String\" key=\".level\"/>\n    <entry value=\"ALL\" type=\"String\" key=\"tigase.server.xmppserver.level\"/>\n    <entry value=\"WARNING\" type=\"String\" key=\"tigase.server.xmppsession.level\"/>\n    <entry value=\"ALL\" type=\"String\" key=\"tigase.server.MessageRouter.level\"/>\n    <entry value=\"ALL\" type=\"String\" key=\"tigase.xmpp.impl.Presence.level\"/>\n    <entry value=\"WARNING\" type=\"String\" key=\"tigase.xmpp.impl.level\"/>\n    <entry value=\"WARNING\" type=\"String\" key=\"tigase.xmpp.XMPPDomBuilderHandler.level\"/>\n    <entry value=\"WARNING\" type=\"String\" key=\"tigase.auth.level\"/>\n    <entry value=\"WARNING\" type=\"String\" key=\"tigase.net.level\"/>\n    <entry value=\"java.util.logging.ConsoleHandler\" type=\"String\" key=\"handlers\"/>\n    <entry value=\"tigase.util.LogFormatter\" type=\"String\" key=\"java.util.logging.ConsoleHandler.formatter\"/>\n    <entry value=\"ALL\" type=\"String\" key=\"java.util.logging.ConsoleHandler.level\"/>\n    <entry value=\"true\" type=\"String\" key=\"java.util.logging.FileHandler.append\"/>\n    <entry value=\"5\" type=\"String\" key=\"java.util.logging.FileHandler.count\"/>\n    <entry value=\"tigase.util.LogFormatter\" type=\"String\" key=\"java.util.logging.FileHandler.formatter\"/>\n    <entry value=\"ALL\" type=\"String\" key=\"java.util.logging.FileHandler.level\"/>\n    <entry value=\"100000\" type=\"String\" key=\"java.util.logging.FileHandler.limit\"/>\n    <entry value=\"logs/java_%g.log\" type=\"String\" key=\"java.util.logging.FileHandler.pattern\"/>\n    <entry value=\"java.util.logging.FileHandler\" type=\"String\" key=\"tigase.handlers\"/>\n    <entry value=\"true\" type=\"String\" key=\"tigase.useParentHandlers\"/>\n   </map>\n  </node>\n </component>\n <component name=\"tigase-xmpp-server\">\n  <map>\n   <entry type=\"String[]\" key=\"local-addresses\">\n    <item value=\"dell\"/>\n   </entry>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n  </map>\n  <node name=\"components\">\n   <map/>\n   <node name=\"msg-receivers\">\n    <map>\n     <entry value=\"true\" type=\"Boolean\" key=\"client_1.active\"/>\n     <entry value=\"tigase.server.xmppclient.ClientConnectionManager\" type=\"String\" key=\"client_1.class\"/>\n     <entry value=\"false\" type=\"Boolean\" key=\"comp_1.active\"/>\n     <entry value=\"tigase.server.xmppcomponent.ComponentConnectionManager\" type=\"String\" key=\"comp_1.class\"/>\n     <entry type=\"String[]\" key=\"id-names\">\n      <item value=\"client_1\"/>\n      <item value=\"server_1\"/>\n      <item value=\"comp_1\"/>\n      <item value=\"session_1\"/>\n     </entry>\n     <entry value=\"true\" type=\"Boolean\" key=\"server_1.active\"/>\n     <entry value=\"tigase.server.xmppserver.ServerConnectionManager\" type=\"String\" key=\"server_1.class\"/>\n     <entry value=\"true\" type=\"Boolean\" key=\"session_1.active\"/>\n     <entry value=\"tigase.server.xmppsession.SessionManager\" type=\"String\" key=\"session_1.class\"/>\n    </map>\n   </node>\n   <node name=\"registrators\">\n    <map>\n     <entry type=\"String[]\" key=\"id-names\">\n      <item value=\"stat_1\"/>\n      <item value=\"service_1\"/>\n     </entry>\n     <entry value=\"true\" type=\"Boolean\" key=\"service_1.active\"/>\n     <entry value=\"tigase.server.XMPPServiceCollector\" type=\"String\" key=\"service_1.class\"/>\n     <entry value=\"true\" type=\"Boolean\" key=\"stat_1.active\"/>\n     <entry value=\"tigase.stats.StatisticsCollector\" type=\"String\" key=\"stat_1.class\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"client_1\">\n  <map>\n   <entry type=\"String[]\" key=\"hostnames\">\n    <item value=\"dell-1\"/>\n   </entry>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n  </map>\n  <node name=\"connections\">\n   <map>\n    <entry type=\"int[]\" key=\"ports\">\n     <item value=\"5222\"/>\n     <item value=\"5223\"/>\n    </entry>\n   </map>\n   <node name=\"5222\">\n    <map>\n     <entry type=\"String[]\" key=\"ifc\">\n      <item value=\"*\"/>\n     </entry>\n     <entry value=\"dell\" type=\"String\" key=\"remote-host\"/>\n     <entry value=\"plain\" type=\"String\" key=\"socket\"/>\n     <entry value=\"accept\" type=\"String\" key=\"type\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry value=\"false\" type=\"Boolean\" key=\"required\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"5223\">\n    <map>\n     <entry type=\"String[]\" key=\"ifc\">\n      <item value=\"*\"/>\n     </entry>\n     <entry value=\"dell\" type=\"String\" key=\"remote-host\"/>\n     <entry value=\"ssl\" type=\"String\" key=\"socket\"/>\n     <entry value=\"accept\" type=\"String\" key=\"type\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry value=\"false\" type=\"Boolean\" key=\"required\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"tls\">\n    <map>\n     <entry value=\"certs/keystore\" type=\"String\" key=\"keys-store\"/>\n     <entry value=\"keystore\" type=\"String\" key=\"keys-store-password\"/>\n     <entry value=\"certs/truststore\" type=\"String\" key=\"trusts-store\"/>\n     <entry value=\"truststore\" type=\"String\" key=\"trusts-store-password\"/>\n     <entry value=\"true\" type=\"Boolean\" key=\"use\"/>\n    </map>\n   </node>\n  </node>\n  <node name=\"routings\">\n   <map>\n    <entry value=\"session_1@dell\" type=\"String\" key=\".+\"/>\n    <entry value=\"true\" type=\"Boolean\" key=\"multi-mode\"/>\n   </map>\n  </node>\n </component>\n <component name=\"server_1\">\n  <map>\n   <entry type=\"String[]\" key=\"components\">\n    <item value=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>\n    <item value=\"jabber:iq:version\"/>\n    <item value=\"jabber:iq:stats\"/>\n    <item value=\"starttls\"/>\n    <item value=\"jabber:server:dialback\"/>\n   </entry>\n   <entry type=\"String[]\" key=\"hostnames\">\n    <item value=\"dell\"/>\n    <item value=\"tigase.org\"/>\n    <item value=\"hefczyc.net\"/>\n   </entry>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n  </map>\n  <node name=\"connections\">\n   <map>\n    <entry type=\"int[]\" key=\"ports\">\n     <item value=\"5269\"/>\n    </entry>\n   </map>\n   <node name=\"tls\">\n    <map>\n     <entry value=\"certs/keystore\" type=\"String\" key=\"keys-store\"/>\n     <entry value=\"keystore\" type=\"String\" key=\"keys-store-password\"/>\n     <entry value=\"certs/truststore\" type=\"String\" key=\"trusts-store\"/>\n     <entry value=\"truststore\" type=\"String\" key=\"trusts-store-password\"/>\n     <entry value=\"true\" type=\"Boolean\" key=\"use\"/>\n    </map>\n   </node>\n   <node name=\"5269\">\n    <map>\n     <entry type=\"String[]\" key=\"ifc\">\n      <item value=\"*\"/>\n     </entry>\n     <entry value=\"localhost\" type=\"String\" key=\"remote-host\"/>\n     <entry value=\"plain\" type=\"String\" key=\"socket\"/>\n     <entry value=\"accept\" type=\"String\" key=\"type\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry value=\"false\" type=\"Boolean\" key=\"required\"/>\n     </map>\n    </node>\n   </node>\n  </node>\n  <node name=\"security\">\n   <map>\n    <entry type=\"String[]\" key=\"authentication-ids\">\n     <item value=\"dialback\"/>\n    </entry>\n   </map>\n   <node name=\"dialback\">\n    <map>\n     <entry value=\"tigase.auth.DialbackAuth\" type=\"String\" key=\"class\"/>\n     <entry value=\"sufficient\" type=\"String\" key=\"flag\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"comp_1\">\n  <map>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n  </map>\n  <node name=\"connections\">\n   <map>\n    <entry type=\"int[]\" key=\"ports\">\n     <item value=\"5555\"/>\n    </entry>\n   </map>\n   <node name=\"5555\">\n    <map>\n     <entry type=\"String[]\" key=\"ifc\">\n      <item value=\"*\"/>\n     </entry>\n     <entry value=\"dell\" type=\"String\" key=\"remote-host\"/>\n     <entry value=\"someSecret\" type=\"String\" key=\"secret\"/>\n     <entry value=\"plain\" type=\"String\" key=\"socket\"/>\n     <entry value=\"accept\" type=\"String\" key=\"type\"/>\n    </map>\n    <node name=\"tls\">\n     <map>\n      <entry value=\"false\" type=\"Boolean\" key=\"required\"/>\n     </map>\n    </node>\n   </node>\n   <node name=\"tls\">\n    <map>\n     <entry value=\"certs/keystore\" type=\"String\" key=\"keys-store\"/>\n     <entry value=\"keystore\" type=\"String\" key=\"keys-store-password\"/>\n     <entry value=\"certs/truststore\" type=\"String\" key=\"trusts-store\"/>\n     <entry value=\"truststore\" type=\"String\" key=\"trusts-store-password\"/>\n     <entry value=\"true\" type=\"Boolean\" key=\"use\"/>\n    </map>\n   </node>\n  </node>\n </component>\n <component name=\"session_1\">\n  <map>\n   <entry type=\"String[]\" key=\"components\">\n    <item value=\"jabber:iq:register\"/>\n    <item value=\"jabber:iq:auth\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-bind\"/>\n    <item value=\"urn:ietf:params:xml:ns:xmpp-session\"/>\n    <item value=\"message\"/>\n    <item value=\"jabber:iq:roster\"/>\n    <item value=\"presence\"/>\n    <item value=\"jabber:iq:version\"/>\n    <item value=\"jabber:iq:stats\"/>\n    <item value=\"starttls\"/>\n    <item value=\"disco\"/>\n   </entry>\n   <entry type=\"String[]\" key=\"hostnames\">\n    <item value=\"dell\"/>\n   </entry>\n   <entry value=\"1000\" type=\"Integer\" key=\"max-queue-size\"/>\n   <entry value=\"user-repository.xml\" type=\"String\" key=\"repository-url\"/>\n  </map>\n  <node name=\"security\">\n   <map>\n    <entry type=\"String[]\" key=\"authentication-ids\">\n     <item value=\"auth-plain\"/>\n     <item value=\"auth-digest\"/>\n     <item value=\"auth-sasl\"/>\n    </entry>\n   </map>\n   <node name=\"auth-digest\">\n    <map>\n     <entry value=\"tigase.auth.DigestAuth\" type=\"String\" key=\"class\"/>\n     <entry value=\"sufficient\" type=\"String\" key=\"flag\"/>\n    </map>\n   </node>\n   <node name=\"auth-plain\">\n    <map>\n     <entry value=\"tigase.auth.PlainAuth\" type=\"String\" key=\"class\"/>\n     <entry value=\"sufficient\" type=\"String\" key=\"flag\"/>\n    </map>\n   </node>\n   <node name=\"auth-sasl\">\n    <map>\n     <entry value=\"None\" type=\"String\" key=\"class\"/>\n     <entry value=\"sufficient\" type=\"String\" key=\"flag\"/>\n    </map>\n   </node>\n  </node>\n </component>\n</tigase-config>\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/Licence.txt",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU Affero General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU Affero General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/Setup.bat",
    "content": "copy \"tigase.ico\" \"..\\\"\ncopy \"wrapper\\wrapper.jar\" \"..\\jars\"\ncopy \"wrapper\\wrapper.dll\" \"..\\jars\"\ncopy \"wrapper\\wrapper.exe\" \"..\\\"\ncopy \"wrapper\\wrapper.conf\" \"..\\\"\ncopy \"wrapper\\wrapper-community-license-1.2.txt\" \"..\\\"\ncopy \"scripts\\*.*\" \"..\\\""
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/Tigase-minimal.iss",
    "content": "#define ver \"3.1.1-b745\";\n\n[Setup]\nAppName=Tigase Server\nAppVersion={#ver}\nAppVerName=Tigase XMPP Server {#ver}\nAppPublisher=Tigase.org\nAppPublisherURL=http://www.tigase.org/\nAppSupportURL=http://www.tigase.org/\nAppUpdatesURL=http://www.tigase.org/\nDefaultDirName={pf}\\Tigase\nDefaultGroupName=Tigase Server\nAllowNoIcons=true\nLicenseFile=Licence.txt\nOutputDir=..\\packages\nOutputBaseFilename=tigase-server-minimal-{#ver}\nCompression=lzma\nSolidCompression=true\nUninstallDisplayIcon={app}\\Tigase.ico\nVersionInfoCopyright=Artur Hefczyc\nAppCopyright=Artur Hefczyc\n\n[Languages]\nName: english; MessagesFile: compiler:Default.isl\nName: basque; MessagesFile: compiler:Languages\\Basque.isl\nName: brazilianportuguese; MessagesFile: compiler:Languages\\BrazilianPortuguese.isl\nName: catalan; MessagesFile: compiler:Languages\\Catalan.isl\nName: czech; MessagesFile: compiler:Languages\\Czech.isl\nName: danish; MessagesFile: compiler:Languages\\Danish.isl\nName: dutch; MessagesFile: compiler:Languages\\Dutch.isl\nName: finnish; MessagesFile: compiler:Languages\\Finnish.isl\nName: french; MessagesFile: compiler:Languages\\French.isl\nName: german; MessagesFile: compiler:Languages\\German.isl\nName: hungarian; MessagesFile: compiler:Languages\\Hungarian.isl\nName: italian; MessagesFile: compiler:Languages\\Italian.isl\nName: norwegian; MessagesFile: compiler:Languages\\Norwegian.isl\nName: polish; MessagesFile: compiler:Languages\\Polish.isl\nName: portuguese; MessagesFile: compiler:Languages\\Portuguese.isl\nName: russian; MessagesFile: compiler:Languages\\Russian.isl\nName: slovak; MessagesFile: compiler:Languages\\Slovak.isl\nName: slovenian; MessagesFile: compiler:Languages\\Slovenian.isl\nName: spanish; MessagesFile: compiler:Languages\\Spanish.isl\n\n[Files]\n\n\nSource: wrapper\\wrapper.exe; DestDir: {app}; Flags: ignoreversion\nSource: ..\\certs\\*; DestDir: {app}\\certs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\docs-tigase-server\\*; DestDir: {app}\\docs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\jars\\*; DestDir: {app}\\jars; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: z:\\home\\kobit\\projects\\tigase\\server\\libs\\tigase-utils.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: z:\\home\\kobit\\projects\\tigase\\server\\libs\\tigase-xmltools.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: z:\\home\\kobit\\projects\\tigase\\server\\database\\mysql-schema.sql; DestDir: {app}\\database\\mysql-schema.sql; Flags: ignoreversion\nSource: z:\\home\\kobit\\projects\\tigase\\server\\database\\postgresql-schema.sql; DestDir: {app}\\database\\postgresql-schema.sql; Flags: ignoreversion\nSource: wrapper\\wrapper.conf; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\InstallTigaseService.bat; DestDir: {app}; Flags: ignoreversion\nSource: ..\\README.html; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Run.bat; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Tigase.bat; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\UninstallTigaseService.bat; DestDir: {app}; Flags: ignoreversion\nSource: Tigase.ico; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Uninst.bat; DestDir: {app}; Flags: ignoreversion\n; NOTE: Don't use \"Flags: ignoreversion\" on any shared system files\nSource: Licence.txt; DestDir: {app}; Flags: ignoreversion\nSource: wrapper\\wrapper.dll; DestDir: {app}\\libs; Flags: ignoreversion\nSource: wrapper\\wrapper.jar; DestDir: {app}\\libs; Flags: ignoreversion\nSource: ..\\etc\\tigase.conf; DestDir: {app}\\etc; Flags: ignoreversion\nSource: ..\\etc\\initial.properties; DestDir: {app}\\etc; Flags: ignoreversion\n\n\n[Dirs]\nName: {app}\\logs\n\n[Icons]\nName: {group}\\Start Tigase Server; Filename: {app}\\Run.bat; WorkingDir: {app}; IconFilename: {app}\\Tigase.ico\nName: {group}\\Install Tigase Service; Filename: {app}\\InstallTigaseService.bat\nName: {group}\\Uninstall Tigase Service; Filename: {app}\\UninstallTigaseService.bat\nName: {group}\\{cm:ProgramOnTheWeb,Tigase}; Filename: http://www.tigase.org/\n\n[UninstallRun]\nFilename: {app}\\Uninst.bat\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/Tigase.iss",
    "content": "#define ver \"3.3.2-b889\";\n\n[Setup]\nAppName=Tigase Server\nAppVersion={#ver}\nAppVerName=Tigase XMPP Server {#ver}\nAppPublisher=Tigase.org\nAppPublisherURL=http://www.tigase.org/\nAppSupportURL=http://www.tigase.org/\nAppUpdatesURL=http://www.tigase.org/\nDefaultDirName={pf}\\Tigase\nDefaultGroupName=Tigase Server\nAllowNoIcons=true\nLicenseFile=Licence.txt\nOutputDir=..\\packages\nOutputBaseFilename=tigase-server-{#ver}\nCompression=lzma\nSolidCompression=true\nUninstallDisplayIcon={app}\\Tigase.ico\nVersionInfoCopyright=Artur Hefczyc\nAppCopyright=Artur Hefczyc\n\n[Languages]\nName: english; MessagesFile: compiler:Default.isl\nName: basque; MessagesFile: compiler:Languages\\Basque.isl\nName: brazilianportuguese; MessagesFile: compiler:Languages\\BrazilianPortuguese.isl\nName: catalan; MessagesFile: compiler:Languages\\Catalan.isl\nName: czech; MessagesFile: compiler:Languages\\Czech.isl\nName: danish; MessagesFile: compiler:Languages\\Danish.isl\nName: dutch; MessagesFile: compiler:Languages\\Dutch.isl\nName: finnish; MessagesFile: compiler:Languages\\Finnish.isl\nName: french; MessagesFile: compiler:Languages\\French.isl\nName: german; MessagesFile: compiler:Languages\\German.isl\nName: hungarian; MessagesFile: compiler:Languages\\Hungarian.isl\nName: italian; MessagesFile: compiler:Languages\\Italian.isl\nName: norwegian; MessagesFile: compiler:Languages\\Norwegian.isl\nName: polish; MessagesFile: compiler:Languages\\Polish.isl\nName: portuguese; MessagesFile: compiler:Languages\\Portuguese.isl\nName: russian; MessagesFile: compiler:Languages\\Russian.isl\nName: slovak; MessagesFile: compiler:Languages\\Slovak.isl\nName: slovenian; MessagesFile: compiler:Languages\\Slovenian.isl\nName: spanish; MessagesFile: compiler:Languages\\Spanish.isl\n\n[Files]\nSource: wrapper\\wrapper.exe; DestDir: {app}; Flags: ignoreversion; Languages: \nSource: ..\\certs\\dummy.cer; DestDir: {app}\\certs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\certs\\rsa-keystore; DestDir: {app}\\certs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\certs\\truststore; DestDir: {app}\\certs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\certs\\localhost.pem; DestDir: {app}\\certs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\docs-tigase-server\\*; DestDir: {app}\\docs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\jars\\*; DestDir: {app}\\jars; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\tigase-utils.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\tigase-xmltools.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\bcprov-jdk16-136.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\cindy.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\commons-logging.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\jdbc-mysql.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\jdbc-postgresql.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\jml-1.0b2.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\jtds-1.2.2.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\tigase-extras-0.2.0-SNAPSHOT.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\libs\\tigase-muc-0.1.6-SNAPSHOT.jar; DestDir: {app}\\libs; Flags: ignoreversion recursesubdirs createallsubdirs\nSource: ..\\database\\mysql-schema.sql; DestDir: {app}\\database; Flags: ignoreversion\nSource: ..\\database\\postgresql-schema.sql; DestDir: {app}\\database; Flags: ignoreversion\nSource: ..\\database\\sqlserver-schema.sql; DestDir: {app}\\database; Flags: ignoreversion\nSource: wrapper\\wrapper.conf; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\InstallTigaseService.bat; DestDir: {app}; Flags: ignoreversion\nSource: ..\\README.html; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Run.bat; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Tigase.bat; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\UninstallTigaseService.bat; DestDir: {app}; Flags: ignoreversion\nSource: Tigase.ico; DestDir: {app}; Flags: ignoreversion\nSource: scripts\\Uninst.bat; DestDir: {app}; Flags: ignoreversion\n; NOTE: Don't use \"Flags: ignoreversion\" on any shared system files\nSource: Licence.txt; DestDir: {app}; Flags: ignoreversion\nSource: wrapper\\wrapper.dll; DestDir: {app}\\libs; Flags: ignoreversion\nSource: wrapper\\wrapper.jar; DestDir: {app}\\libs; Flags: ignoreversion\nSource: ..\\etc\\tigase.conf; DestDir: {app}\\etc; Flags: ignoreversion\nSource: ..\\etc\\init.properties; DestDir: {app}\\etc; Flags: ignoreversion\n\n[Dirs]\nName: {app}\\logs\n\n\n[Icons]\nName: {group}\\Start Tigase Server; Filename: {app}\\Run.bat; WorkingDir: {app}; IconFilename: {app}\\Tigase.ico\nName: {group}\\Install Tigase Service; Filename: {app}\\InstallTigaseService.bat\nName: {group}\\Uninstall Tigase Service; Filename: {app}\\UninstallTigaseService.bat\nName: {group}\\{cm:ProgramOnTheWeb,Tigase}; Filename: http://www.tigase.org/\n\n[UninstallRun]\nFilename: {app}\\Uninst.bat\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/scripts/InstallTigaseService.bat",
    "content": "@echo off\nsetlocal\n\nrem ******************************************************\nrem Java Service Wrapper general NT service install script\nrem ******************************************************\n\nif \"%OS%\"==\"Windows_NT\" goto nt\necho This script only works with NT-based versions of Windows.\ngoto :eof\n\n:nt\nrem\nrem Find the application home.\nrem\nrem %~dp0 is location of current script under NT\nset _REALPATH=%~dp0\n\nrem Decide on the wrapper binary.\nset _WRAPPER_BASE=wrapper\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\necho Unable to locate a Wrapper executable using any of the following names:\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\necho %_REALPATH%%_WRAPPER_BASE%.exe\npause\ngoto :eof\n\nrem\nrem Find the wrapper.conf\nrem\n:conf\nset _WRAPPER_CONF=\"%~f1\"\nif not %_WRAPPER_CONF%==\"\" goto startup\nset _WRAPPER_CONF=\"%_REALPATH%wrapper.conf\"\n\nrem\nrem Install the Wrapper as an NT service.\nrem\n:startup\n\"%_WRAPPER_EXE%\" -i %_WRAPPER_CONF%\npause\n\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/scripts/Run.bat",
    "content": "java -cp \"jars/*\" -Djdbc.drivers=com.mysql.jdbc.Driver tigase.server.XMPPServer --property-file etc/init.properties\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/scripts/Tigase.bat",
    "content": "@echo off\nsetlocal\n\n\nrem *******************************************\nrem Java Service Wrapper general startup script\nrem *******************************************\n\nrem\nrem Resolve the real path of the wrapper.exe\nrem  For non NT systems, the _REALPATH and _WRAPPER_CONF values\nrem  can be hard-coded below and the following test removed.\nrem\nif \"%OS%\"==\"Windows_NT\" goto nt\necho This script only works with NT-based versions of Windows.\ngoto :eof\n\n:nt\nrem\nrem Find the application home.\nrem\nrem %~dp0 is location of current script under NT\nset _REALPATH=%~dp0\n\nrem Decide on the wrapper binary.\nset _WRAPPER_BASE=wrapper\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\necho Unable to locate a Wrapper executable using any of the following names:\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\necho %_REALPATH%%_WRAPPER_BASE%.exe\npause\ngoto :eof\n\nrem\nrem Find the wrapper.conf\nrem\n:conf\nset _WRAPPER_CONF=\"%~f1\"\nif not %_WRAPPER_CONF%==\"\" goto startup\nset _WRAPPER_CONF=\"%_REALPATH%wrapper.conf\"\n\nrem\nrem Start the Wrapper\nrem\n:startup\n\"%_WRAPPER_EXE%\" -c %_WRAPPER_CONF%\nif not errorlevel 1 goto :eof\npause\n\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/scripts/Uninst.bat",
    "content": "@echo off\nsetlocal\n\n\nrem *****************************\nrem This script runs on uninstall\nrem *****************************\n\nif \"%OS%\"==\"Windows_NT\" goto nt\necho This script only works with NT-based versions of Windows.\ngoto :eof\n\n:nt\nrem\nrem Find the application home.\nrem\nrem %~dp0 is location of current script under NT\nset _REALPATH=%~dp0\n\nrem Decide on the wrapper binary.\nset _WRAPPER_BASE=wrapper\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\necho Unable to locate a Wrapper executable using any of the following names:\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\necho %_REALPATH%%_WRAPPER_BASE%.exe\ngoto :eof\n\nrem\nrem Find the wrapper.conf\nrem\n:conf\nset _WRAPPER_CONF=\"%~f1\"\nif not %_WRAPPER_CONF%==\"\" goto startup\nset _WRAPPER_CONF=\"%_REALPATH%wrapper.conf\"\n\nrem\nrem Uninstall the Wrapper as an NT service.\nrem\n:startup\n\"%_WRAPPER_EXE%\" -r %_WRAPPER_CONF%\n\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/scripts/UninstallTigaseService.bat",
    "content": "@echo off\nsetlocal\n\n\nrem ********************************************************\nrem Java Service Wrapper general NT service uninstall script\nrem ********************************************************\n\nif \"%OS%\"==\"Windows_NT\" goto nt\necho This script only works with NT-based versions of Windows.\ngoto :eof\n\n:nt\nrem\nrem Find the application home.\nrem\nrem %~dp0 is location of current script under NT\nset _REALPATH=%~dp0\n\nrem Decide on the wrapper binary.\nset _WRAPPER_BASE=wrapper\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\nset _WRAPPER_EXE=%_REALPATH%%_WRAPPER_BASE%.exe\nif exist \"%_WRAPPER_EXE%\" goto conf\necho Unable to locate a Wrapper executable using any of the following names:\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-32.exe\necho %_REALPATH%%_WRAPPER_BASE%-windows-x86-64.exe\necho %_REALPATH%%_WRAPPER_BASE%.exe\npause\ngoto :eof\n\nrem\nrem Find the wrapper.conf\nrem\n:conf\nset _WRAPPER_CONF=\"%~f1\"\nif not %_WRAPPER_CONF%==\"\" goto startup\nset _WRAPPER_CONF=\"%_REALPATH%wrapper.conf\"\n\nrem\nrem Uninstall the Wrapper as an NT service.\nrem\n:startup\n\"%_WRAPPER_EXE%\" -r %_WRAPPER_CONF%\npause\n\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/wrapper/wrapper-community-license-1.2.txt",
    "content": "----------------------------------------------------------------------\n-----------------                                    -----------------\n                         Tanuki Software, Ltd. \n                 Community Software License Agreement\n                             Version 1.2\n\nIMPORTANT-READ CAREFULLY: This license agreement is a legal agreement\nbetween you (\"Licensee\") and Tanuki Software, Ltd. (\"TSI\"), which\nincludes computer software, associated media, printed materials, and\nmay include online or electronic documentation ( Software ).  PLEASE\nREAD THIS AGREEMENT CAREFULLY BEFORE YOU INSTALL, COPY, DOWNLOAD OR\nUSE THE SOFTWARE ACCOMPANYING THIS PACKAGE.\n\nSection 1 - Grant of License\n\nCommunity editions of the Software are made available on the GNU\nGeneral Public License, Version 2 (\"GPLv2\"), included in Section 4 of\nthis license document.  All sections of the Community Software License\nAgreement must be complied with in addition to those of the GPLv2.\n\n\nSection 2 - Definitions \n\n2.1. \"Community Edition\" shall mean versions of the Software Program\ndistributed in source form under this license agreement, and all new\nreleases, corrections, enhancements and updates to the Software\nProgram, which TSI makes generally available under this agreement.\n\n2.2. \"Documentation\" shall mean the contents of the website\ndescribing the functionality and use of the Software Program, located\nat http://wrapper.tanukisoftware.org\n\n2.3. \"Product\" shall mean the computer programs, that are provided by\nLicensee to Licensee customers or potential customers, and that\ncontain both the Software Program as a component of the Product, and a\ncomponent or components (other than the Software Program) that provide\nthe material functionality of the Product.  If the Product is released\nin source form, the Software Program or any of its components may only\nbe included in executable form.\n\n2.4. \"Software Program\" shall mean the computer software and license\nfile provided by TSI under this Agreement, including all new releases,\ncorrections, enhancements and updates to such computer software, which\nTSI makes generally available and which Licensee receive pursuant to\nLicensee subscription to TSIMS. Some specific features or platforms\nmay not be enabled if they do not fall under the feature set(s)\ncovered by the specific license fees paid.\n\n2.5 \"End User\" shall mean the customers of the Licensee or any\nrecipient of the Product whether or not any payment is made to use\nthe Product.\n\n\nSection 3 - Licensee Obligations\n\nA copy of this license must be distributed in full with the Product\nin a location that is obvious to any End User.\n\nIn accordance with Section 4, the full source code of all components\nof the Product must be made available to any and all End Users.\n\nLicensee may extend and/or modify the Software Program and distribute\nunder the terms of this agreement provided that the copyright notice\nand license information displayed in the console and log files are\nnot obfuscated or obstructed in any way.\n\n\nSection 4 - GPLv2 License Agreement\n\n                        GNU GENERAL PUBLIC LICENSE\n                           Version 2, June 1991\n\n         Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n       51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\n    Everyone is permitted to copy and distribute verbatim copies of\n    this license document, but changing it is not allowed.\n\n    Preamble\n\n    The licenses for most software are designed to take away your\n    freedom to share and change it. By contrast, the GNU General\n    Public License is intended to guarantee your freedom to share and\n    change free software--to make sure the software is free for all\n    its users. This General Public License applies to most of the Free\n    Software Foundation's software and to any other program whose\n    authors commit to using it.  (Some other Free Software Foundation\n    software is covered by the GNU Library General Public License\n    instead.) You can apply it to your programs, too.\n\n    When we speak of free software, we are referring to freedom, not\n    price. Our General Public Licenses are designed to make sure that\n    you have the freedom to distribute copies of free software (and\n    charge for this service if you wish), that you receive source code\n    or can get it if you want it, that you can change the software or\n    use pieces of it in new free programs; and that you know you can\n    do these things.\n\n    To protect your rights, we need to make restrictions that forbid\n    anyone to deny you these rights or to ask you to surrender the\n    rights. These restrictions translate to certain responsibilities\n    for you if you distribute copies of the software, or if you modify\n    it.\n\n    For example, if you distribute copies of such a program, whether\n    gratis or for a fee, you must give the recipients all the rights\n    that you have. You must make sure that they, too, receive or can\n    get the source code. And you must show them these terms so they\n    know their rights.\n\n    We protect your rights with two steps:\n\n    (1) copyright the software, and\n    (2) offer you this license which gives you legal permission to\n    copy, distribute and/or modify the software.\n\n    Also, for each author's protection and ours, we want to make\n    certain that everyone understands that there is no warranty for\n    this free software. If the software is modified by someone else\n    and passed on, we want its recipients to know that what they have\n    is not the original, so that any problems introduced by others\n    will not reflect on the original authors' reputations.\n\n    Finally, any free program is threatened constantly by software\n    patents. We wish to avoid the danger that redistributors of a free\n    program will individually obtain patent licenses, in effect making\n    the program proprietary. To prevent this, we have made it clear\n    that any patent must be licensed for everyone's free use or not\n    licensed at all.\n\n    The precise terms and conditions for copying, distribution and\n    modification follow.\n    GNU GENERAL PUBLIC LICENSE\n    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n    0. This License applies to any program or other work which\n    contains a notice placed by the copyright holder saying it may be\n    distributed under the terms of this General Public License. The\n    \"Program\", below, refers to any such program or work, and a \"work\n    based on the Program\" means either the Program or any derivative\n    work under copyright law: that is to say, a work containing the\n    Program or a portion of it, either verbatim or with modifications\n    and/or translated into another language. (Hereinafter, translation\n    is included without limitation in the term \"modification\".) Each\n    licensee is addressed as \"you\".\n\n    Activities other than copying, distribution and modification are\n    not covered by this License; they are outside its scope. The act\n    of running the Program is not restricted, and the output from the\n    Program is covered only if its contents constitute a work based on\n    the Program (independent of having been made by running the\n    Program). Whether that is true depends on what the Program does.\n\n    1. You may copy and distribute verbatim copies of the Program's\n    source code as you receive it, in any medium, provided that you\n    conspicuously and appropriately publish on each copy an\n    appropriate copyright notice and disclaimer of warranty; keep\n    intact all the notices that refer to this License and to the\n    absence of any warranty; and give any other recipients of the\n    Program a copy of this License along with the Program.\n\n    You may charge a fee for the physical act of transferring a copy,\n    and you may at your option offer warranty protection in exchange\n    for a fee.\n\n    2. You may modify your copy or copies of the Program or any\n    portion of it, thus forming a work based on the Program, and copy\n    and distribute such modifications or work under the terms of\n    Section 1 above, provided that you also meet all of these\n    conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License. (Exception: if the Program itself is interactive but does\n    not normally print such an announcement, your work based on the\n    Program is not required to print an announcement.)\n\n    These requirements apply to the modified work as a whole. If\n    identifiable sections of that work are not derived from the\n    Program, and can be reasonably considered independent and separate\n    works in themselves, then this License, and its terms, do not\n    apply to those sections when you distribute them as separate works.\n    But when you distribute the same sections as part of a whole which\n    is a work based on the Program, the distribution of the whole must\n    be on the terms of this License, whose permissions for other\n    licensees extend to the entire whole, and thus to each and every\n    part regardless of who wrote it.\n\n    Thus, it is not the intent of this section to claim rights or\n    contest your rights to work written entirely by you; rather, the\n    intent is to exercise the right to control the distribution of\n    derivative or collective works based on the Program.\n\n    In addition, mere aggregation of another work not based on the\n    Program with the Program (or with a work based on the Program) on\n    a volume of a storage or distribution medium does not bring the\n    other work under the scope of this License.\n\n    3. You may copy and distribute the Program (or a work based on it,\n    under Section 2) in object code or executable form under the terms\n    of Sections 1 and 2 above provided that you also do one of the\n    following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software\n    interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code. (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\n    The source code for a work means the preferred form of the work\n    for making modifications to it. For an executable work, complete\n    source code means all the source code for all modules it contains,\n    plus any associated interface definition files, plus the scripts\n    used to control compilation and installation of the executable.\n    However, as a special exception, the source code distributed need\n    not include anything that is normally distributed (in either\n    source or binary form) with the major components (compiler,\n    kernel, and so on) of the operating system on which the executable\n    runs, unless that component itself accompanies the executable.\n\n    If distribution of executable or object code is made by offering\n    access to copy from a designated place, then offering equivalent\n    access to copy the source code from the same place counts as\n    distribution of the source code, even though third parties are not\n    compelled to copy the source along with the object code.\n\n    4. You may not copy, modify, sublicense, or distribute the Program\n    except as expressly provided under this License. Any attempt\n    otherwise to copy, modify, sublicense or distribute the Program is\n    void, and will automatically terminate your rights under this\n    License. However, parties who have received copies, or rights,\n    from you under this License will not have their licenses\n    terminated so long as such parties remain in full compliance.\n\n    5. You are not required to accept this License, since you have not\n    signed it. However, nothing else grants you permission to modify\n    or distribute the Program or its derivative works. These actions\n    are prohibited by law if you do not accept this License.\n    Therefore, by modifying or distributing the Program (or any work\n    based on the Program), you indicate your acceptance of this\n    License to do so, and all its terms and conditions for copying,\n    distributing or modifying the Program or works based on it.\n\n    6. Each time you redistribute the Program (or any work based on\n    the Program), the recipient automatically receives a license from\n    the original licensor to copy, distribute or modify the Program\n    subject to these terms and conditions. You may not impose any\n    further restrictions on the recipients' exercise of the rights\n    granted herein. You are not responsible for enforcing compliance\n    by third parties to this License.\n\n    7. If, as a consequence of a court judgment or allegation of\n    patent infringement or for any other reason (not limited to\n    patent issues), conditions are imposed on you (whether by court\n    order, agreement or otherwise) that contradict the conditions of\n    this License, they do not excuse you from the conditions of this\n    License. If you cannot distribute so as to satisfy simultaneously\n    your obligations under this License and any other pertinent\n    obligations, then as a consequence you may not distribute the\n    Program at all. For example, if a patent license would not permit\n    royalty-free redistribution of the Program by all those who\n    receive copies directly or indirectly through you, then the only\n    way you could satisfy both it and this License would be to refrain\n    entirely from distribution of the Program.\n\n    If any portion of this section is held invalid or unenforceable\n    under any particular circumstance, the balance of the section is\n    intended to apply and the section as a whole is intended to apply\n    in other circumstances.\n\n    It is not the purpose of this section to induce you to infringe\n    any patents or other property right claims or to contest validity\n    of any such claims; this section has the sole purpose of\n    protecting the integrity of the free software distribution system,\n    which is implemented by public license practices. Many people have\n    made generous contributions to the wide range of software\n    distributed through that system in reliance on consistent\n    application of that system; it is up to the author/donor to decide\n    if he or she is willing to distribute software through any other\n    system and a licensee cannot impose that choice.\n\n    This section is intended to make thoroughly clear what is believed\n    to be a consequence of the rest of this License.\n\n    8. If the distribution and/or use of the Program is restricted in\n    certain countries either by patents or by copyrighted interfaces,\n    the original copyright holder who places the Program under this\n    License may add an explicit geographical distribution limitation\n    excluding those countries, so that distribution is permitted only\n    in or among countries not thus excluded. In such case, this\n    License incorporates the limitation as if written in the body of\n    this License.\n\n    9. The Free Software Foundation may publish revised and/or new\n    versions of the General Public License from time to time. Such new\n    versions will be similar in spirit to the present version, but may\n    differ in detail to address new problems or concerns.\n\n    Each version is given a distinguishing version number. If the\n    Program specifies a version number of this License which applies\n    to it and \"any later version\", you have the option of following\n    the terms and conditions either of that version or of any later\n    version published by the Free Software Foundation. If the Program\n    does not specify a version number of this License, you may choose\n    any version ever published by the Free Software Foundation.\n\n    10. If you wish to incorporate parts of the Program into other\n    free programs whose distribution conditions are different, write\n    to the author to ask for permission. For software which is\n    copyrighted by the Free Software Foundation, write to the Free\n    Software Foundation; we sometimes make exceptions for this. Our\n    decision will be guided by the two goals of preserving the free\n    status of all derivatives of our free software and of promoting\n    the sharing and reuse of software generally.\n    \n    NO WARRANTY\n\n    11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO\n    WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE\n    LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS\n    AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\n    OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n    FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\n    PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\n    DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR\n    OR CORRECTION.\n\n    12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\n    WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY\n    MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE\n    LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,\n    INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR\n    INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n    DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU\n    OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY\n    OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN\n    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n    END OF TERMS AND CONDITIONS\n\n\nSection 4 - 3rd Party Components\n\n(1) The Software Program includes software and documentation components\ndeveloped in part by Silver Egg Technology, Inc.(\"SET\") prior to 2001\nand released under the following license.\n\n    Copyright (c) 2001 Silver Egg Technology\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation\n    files (the \"Software\"), to deal in the Software without\n    restriction, including without limitation the rights to use,\n    copy, modify, merge, publish, distribute, sub-license, and/or\n    sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following\n    conditions:\n    \n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n    NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n    OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "tigase-server 7.1.0/win-stuff/wrapper/wrapper.conf",
    "content": "#********************************************************************\n# Wrapper Properties\n#********************************************************************\n# Java Application\nwrapper.java.command=java\n\n# Java Main class.  This class must implement the WrapperListener interface\n#  or guarantee that the WrapperManager class is initialized.  Helper\n#  classes are provided to do this for you.  See the Integration section\n#  of the documentation for details.\nwrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp\n\n# Java Classpath (include wrapper.jar)  Add class path elements as\n#  needed starting from 1\nwrapper.java.classpath.1=jars/*.jar\n\n\n# Java Library Path (location of Wrapper.DLL or libwrapper.so)\nwrapper.java.library.path.1=jars\n\n# Java Additional Parameters\nwrapper.java.additional.1=-Dfile.encoding=UTF-8\nwrapper.java.additional.2=-Dsun.jnu.encoding=UTF-8\nwrapper.java.additional.3=-Djdbc.drivers=com.mysql.jdbc.Driver;org.postgresql.Driver;org.apache.derby.jdbc.EmbeddedDriver\n\n# Initial Java Heap Size (in MB) # needs to be changed for production deployment!\n#wrapper.java.initmemory=5000\n\n# Maximum Java Heap Size (in MB) # needs to be changed for production deployment!\n#wrapper.java.maxmemory=5000\n\n# Application parameters.  Add parameters as needed starting from 1\nwrapper.app.parameter.1=tigase.server.XMPPServer\nwrapper.app.parameter.2=--property-file\nwrapper.app.parameter.3=etc/init.properties\n\n#********************************************************************\n# Wrapper Logging Properties\n#********************************************************************\n# Format of output for the console.  (See docs for formats)\nwrapper.console.format=PM\n\n# Log Level for console output.  (See docs for log levels)\nwrapper.console.loglevel=INFO\n\n# Log file to use for wrapper output logging.\nwrapper.logfile=logs/wrapper.log\n\n# Format of output for the log file.  (See docs for formats)\nwrapper.logfile.format=LPTM\n\n# Log Level for log file output.  (See docs for log levels)\nwrapper.logfile.loglevel=INFO\n\n# Maximum size that the log file will be allowed to grow to before\n#  the log is rolled. Size is specified in bytes.  The default value\n#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or\n#  'm' (mb) suffix.  For example: 10m = 10 megabytes.\nwrapper.logfile.maxsize=0\n\n# Maximum number of rolled log files which will be allowed before old\n#  files are deleted.  The default value of 0 implies no limit.\nwrapper.logfile.maxfiles=0\n\n# Log Level for sys/event log output.  (See docs for log levels)\nwrapper.syslog.loglevel=NONE\n\n#********************************************************************\n# Wrapper Windows Properties\n#********************************************************************\n# Title to use when running as a console\nwrapper.console.title=Tigase XMPP server\n\n#********************************************************************\n# Wrapper Windows NT/2000/XP Service Properties\n#********************************************************************\n# WARNING - Do not modify any of these properties when an application\n#  using this configuration file has been installed as a service.\n#  Please uninstall the service before modifying this section.  The\n#  service can then be reinstalled.\n\n# Name of the service\nwrapper.ntservice.name=Tigase\n\n# Display name of the service\nwrapper.ntservice.displayname=Tigase XMPP server\n\n# Description of the service\nwrapper.ntservice.description=Tigase XMPP server\n\n# Service dependencies.  Add dependencies as needed starting from 1\nwrapper.ntservice.dependency.1=\n\n# Mode in which the service is installed.  AUTO_START or DEMAND_START\nwrapper.ntservice.starttype=AUTO_START\n\n# Allow the service to interact with the desktop.\nwrapper.ntservice.interactive=false\n"
  },
  {
    "path": "tigase.sql",
    "content": "/*\nNavicat MySQL Data Transfer\n\nSource Server         : zy\nSource Server Version : 50632\nSource Host           : 106.14.239.204:3306\nSource Database       : tigase\n\nTarget Server Type    : MYSQL\nTarget Server Version : 50632\nFile Encoding         : 65001\n\nDate: 2017-07-05 16:34:18\n*/\n\n\nSET FOREIGN_KEY_CHECKS=0;\n\n\n-- ----------------------------\n-- Table structure for msg_history\n-- ----------------------------\nDROP TABLE IF EXISTS `msg_history`;\nCREATE TABLE `msg_history` (\n  `msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `expired` datetime DEFAULT NULL,\n  `sender_uid` bigint(20) unsigned DEFAULT NULL,\n  `receiver_uid` bigint(20) unsigned NOT NULL,\n  `msg_type` int(11) NOT NULL,\n  `message` varchar(4096) NOT NULL,\n  UNIQUE KEY `msg_id` (`msg_id`),\n  KEY `expired` (`expired`),\n  KEY `sender_uid` (`sender_uid`,`receiver_uid`),\n  KEY `receiver_uid` (`receiver_uid`,`sender_uid`)\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n-- ----------------------------\n-- Table structure for short_news\n-- ----------------------------\nDROP TABLE IF EXISTS `short_news`;\nCREATE TABLE `short_news` (\n  `snid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `publishing_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `news_type` varchar(10) DEFAULT NULL,\n  `author` varchar(128) NOT NULL,\n  `subject` varchar(128) NOT NULL,\n  `body` varchar(1024) NOT NULL,\n  PRIMARY KEY (`snid`),\n  KEY `publishing_time` (`publishing_time`),\n  KEY `author` (`author`),\n  KEY `news_type` (`news_type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n\n-- ----------------------------\n-- Table structure for tig_ma_jids\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_ma_jids`;\nCREATE TABLE `tig_ma_jids` (\n  `jid_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `jid` varchar(2049) DEFAULT NULL,\n  `domain` varchar(1024) DEFAULT NULL,\n  PRIMARY KEY (`jid_id`),\n  KEY `tig_ma_jids_domain_index` (`domain`(255))\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;\n\n-- ----------------------------\n-- Table structure for tig_ma_msgs\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_ma_msgs`;\nCREATE TABLE `tig_ma_msgs` (\n  `msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `owner_id` bigint(20) unsigned DEFAULT NULL,\n  `buddy_id` bigint(20) unsigned DEFAULT NULL,\n  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `direction` smallint(6) DEFAULT NULL,\n  `type` varchar(20) DEFAULT NULL,\n  `body` text,\n  `msg` text,\n  `stanza_hash` varchar(50) DEFAULT NULL,\n  `buddy_res` varchar(1024) DEFAULT NULL,\n  PRIMARY KEY (`msg_id`),\n  UNIQUE KEY `owner_id_4` (`owner_id`,`ts`,`buddy_id`,`stanza_hash`) USING HASH,\n  UNIQUE KEY `tig_ma_msgs_owner_id_buddy_id_stanza_hash_index` (`owner_id`,`buddy_id`,`stanza_hash`),\n  KEY `buddy_id` (`buddy_id`),\n  KEY `owner_id` (`owner_id`),\n  KEY `owner_id_2` (`owner_id`,`buddy_id`),\n  KEY `owner_id_3` (`owner_id`,`ts`,`buddy_id`),\n  KEY `tig_ma_msgs_owner_id_buddy_id_buddy_res_index` (`owner_id`,`buddy_id`,`buddy_res`(255)),\n  KEY `tig_ma_msgs_ts_index` (`ts`),\n  CONSTRAINT `tig_ma_msgs_ibfk_1` FOREIGN KEY (`buddy_id`) REFERENCES `tig_ma_jids` (`jid_id`),\n  CONSTRAINT `tig_ma_msgs_ibfk_2` FOREIGN KEY (`owner_id`) REFERENCES `tig_ma_jids` (`jid_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;\n\n-- ----------------------------\n-- Table structure for tig_ma_msgs_tags\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_ma_msgs_tags`;\nCREATE TABLE `tig_ma_msgs_tags` (\n  `msg_id` bigint(20) unsigned NOT NULL,\n  `tag_id` bigint(20) unsigned NOT NULL,\n  KEY `tig_ma_msgs_tags_msg_id` (`msg_id`),\n  KEY `tig_ma_msgs_tags_tag_id` (`tag_id`),\n  CONSTRAINT `tig_ma_msgs_tags_ibfk_1` FOREIGN KEY (`msg_id`) REFERENCES `tig_ma_msgs` (`msg_id`) ON DELETE CASCADE,\n  CONSTRAINT `tig_ma_msgs_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tig_ma_tags` (`tag_id`) ON DELETE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n\n-- ----------------------------\n-- Table structure for tig_ma_tags\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_ma_tags`;\nCREATE TABLE `tig_ma_tags` (\n  `tag_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `tag` varchar(255) DEFAULT NULL,\n  `owner_id` bigint(20) unsigned NOT NULL,\n  PRIMARY KEY (`tag_id`),\n  UNIQUE KEY `tig_ma_tags_tag_owner_id` (`owner_id`,`tag`),\n  KEY `tig_ma_tags_owner_id` (`owner_id`),\n  CONSTRAINT `tig_ma_tags_ibfk_1` FOREIGN KEY (`owner_id`) REFERENCES `tig_ma_jids` (`jid_id`) ON DELETE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n\n-- ----------------------------\n-- Table structure for tig_nodes\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_nodes`;\nCREATE TABLE `tig_nodes` (\n  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `parent_nid` bigint(20) unsigned DEFAULT NULL,\n  `uid` bigint(20) unsigned NOT NULL,\n  `node` varchar(255) NOT NULL,\n  PRIMARY KEY (`nid`),\n  UNIQUE KEY `tnode` (`parent_nid`,`uid`,`node`),\n  KEY `node` (`node`),\n  KEY `uid` (`uid`),\n  KEY `parent_nid` (`parent_nid`),\n  CONSTRAINT `tig_nodes_constr` FOREIGN KEY (`uid`) REFERENCES `tig_users` (`uid`)\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n-- ----------------------------\n-- Table structure for tig_pairs\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_pairs`;\nCREATE TABLE `tig_pairs` (\n  `nid` bigint(20) unsigned DEFAULT NULL,\n  `uid` bigint(20) unsigned NOT NULL,\n  `pkey` varchar(255) NOT NULL,\n  `pval` mediumtext,\n  KEY `pkey` (`pkey`),\n  KEY `uid` (`uid`),\n  KEY `nid` (`nid`),\n  CONSTRAINT `tig_pairs_constr_1` FOREIGN KEY (`uid`) REFERENCES `tig_users` (`uid`),\n  CONSTRAINT `tig_pairs_constr_2` FOREIGN KEY (`nid`) REFERENCES `tig_nodes` (`nid`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n-- ----------------------------\n-- Table structure for tig_users\n-- ----------------------------\nDROP TABLE IF EXISTS `tig_users`;\nCREATE TABLE `tig_users` (\n  `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `user_id` varchar(255) NOT NULL,\n  `sha1_user_id` char(128) NOT NULL,\n  `user_pw` varchar(255) DEFAULT NULL,\n  `acc_create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `last_logout` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `online_status` int(11) DEFAULT '0',\n  `failed_logins` int(11) DEFAULT '0',\n  `account_status` int(11) DEFAULT '1',\n  `push_token` varchar(255) DEFAULT NULL,\n  PRIMARY KEY (`uid`),\n  UNIQUE KEY `sha1_user_id` (`sha1_user_id`),\n  KEY `user_pw` (`user_pw`),\n  KEY `user_id` (`user_id`),\n  KEY `last_login` (`last_login`),\n  KEY `last_logout` (`last_logout`),\n  KEY `account_status` (`account_status`),\n  KEY `online_status` (`online_status`)\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n-- ----------------------------\n-- Table structure for user_jid\n-- ----------------------------\nDROP TABLE IF EXISTS `user_jid`;\nCREATE TABLE `user_jid` (\n  `jid_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `jid_sha` char(128) NOT NULL,\n  `jid` varchar(2049) NOT NULL,\n  `history_enabled` int(11) DEFAULT '0',\n  PRIMARY KEY (`jid_id`),\n  UNIQUE KEY `jid_id` (`jid_id`),\n  UNIQUE KEY `jid_sha` (`jid_sha`),\n  KEY `jid` (`jid`(255))\n) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;\n\n-- ----------------------------\n-- Table structure for xmpp_stanza\n-- ----------------------------\nDROP TABLE IF EXISTS `xmpp_stanza`;\nCREATE TABLE `xmpp_stanza` (\n  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `stanza` text NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;\n\n-- ----------------------------\n-- Procedure structure for TigActiveAccounts\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigActiveAccounts`;\nDELIMITER ;;\nCREATE PROCEDURE `TigActiveAccounts`()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status > 0;\nend\n;;\nDELIMITER ;\n\n\n-- ----------------------------\n-- Procedure structure for TigAddNode\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigAddNode`;\nDELIMITER ;;\nCREATE PROCEDURE `TigAddNode`(_parent_nid bigint, _uid bigint, _node varchar(255) CHARSET utf8)\nbegin\n\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (_parent_nid, _uid, _node);\n\tselect LAST_INSERT_ID() as nid;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigAddUser\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigAddUser`;\nDELIMITER ;;\nCREATE PROCEDURE `TigAddUser`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tdeclare res_uid bigint unsigned;\n\n\tinsert into tig_users (user_id, sha1_user_id, user_pw)\n\t\tvalues (_user_id, sha1(lower(_user_id)), _user_pw);\n\n\tselect LAST_INSERT_ID() into res_uid;\n\n\tinsert into tig_nodes (parent_nid, uid, node)\n\t\tvalues (NULL, res_uid, 'root');\n\n\tif _user_pw is NULL then\n\t\tupdate tig_users set account_status = -1 where uid = res_uid;\n\tend if;\n\n\tselect res_uid as uid;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigAddUserPlainPw\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigAddUserPlainPw`;\nDELIMITER ;;\nCREATE PROCEDURE `TigAddUserPlainPw`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigAddUser(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigAddUser(_user_id, _user_pw);\n\t\tend case;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigAllUsers\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigAllUsers`;\nDELIMITER ;;\nCREATE PROCEDURE `TigAllUsers`()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigAllUsersCount\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigAllUsersCount`;\nDELIMITER ;;\nCREATE PROCEDURE `TigAllUsersCount`()\nbegin\n\tselect count(*) from tig_users;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigDisableAccount\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigDisableAccount`;\nDELIMITER ;;\nCREATE PROCEDURE `TigDisableAccount`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users set account_status = 0 where sha1_user_id = sha1(lower(_user_id));\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigDisabledAccounts\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigDisabledAccounts`;\nDELIMITER ;;\nCREATE PROCEDURE `TigDisabledAccounts`()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where account_status = 0;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigEnableAccount\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigEnableAccount`;\nDELIMITER ;;\nCREATE PROCEDURE `TigEnableAccount`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users set account_status = 1 where sha1_user_id = sha1(lower(_user_id));\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigGetPassword\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigGetPassword`;\nDELIMITER ;;\nCREATE PROCEDURE `TigGetPassword`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tselect user_pw from tig_users where sha1_user_id = sha1(lower(_user_id));\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigGetUserDBUid\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigGetUserDBUid`;\nDELIMITER ;;\nCREATE PROCEDURE `TigGetUserDBUid`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tselect uid from tig_users where sha1_user_id = sha1(lower(_user_id));\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigInitdb\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigInitdb`;\nDELIMITER ;;\nCREATE PROCEDURE `TigInitdb`()\nbegin\n  update tig_users set online_status = 0;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigOfflineUsers\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigOfflineUsers`;\nDELIMITER ;;\nCREATE PROCEDURE `TigOfflineUsers`()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status = 0;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigOnlineUsers\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigOnlineUsers`;\nDELIMITER ;;\nCREATE PROCEDURE `TigOnlineUsers`()\nbegin\n\tselect user_id, last_login, last_logout, online_status, failed_logins, account_status\n\t\tfrom tig_users where online_status > 0;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigPutDBProperty\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigPutDBProperty`;\nDELIMITER ;;\nCREATE PROCEDURE `TigPutDBProperty`(_tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists( select 1 from tig_pairs, tig_users where\n    (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n    AND (pkey = _tkey))\n  then\n    update tig_pairs, tig_users set pval = _tval\n    where (sha1_user_id = sha1(lower('db-properties'))) AND (tig_users.uid = tig_pairs.uid)\n      AND (pkey = _tkey);\n  else\n    insert into tig_pairs (pkey, pval, uid)\n      select _tkey, _tval, uid from tig_users\n        where (sha1_user_id = sha1(lower('db-properties')));\n  end if;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigRemoveUser\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigRemoveUser`;\nDELIMITER ;;\nCREATE PROCEDURE `TigRemoveUser`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tdeclare res_uid bigint unsigned;\n\n\tselect uid into res_uid from tig_users where sha1_user_id = sha1(lower(_user_id));\n\n\tdelete from tig_pairs where uid = res_uid;\n\tdelete from tig_nodes where uid = res_uid;\n\tdelete from tig_users where uid = res_uid;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigTestAddUser\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigTestAddUser`;\nDELIMITER ;;\nCREATE PROCEDURE `TigTestAddUser`(_user_id varchar(2049) CHARSET utf8, _user_passwd varchar(255) CHARSET utf8,\n\t\t\t success_text text CHARSET utf8, failure_text text CHARSET utf8)\nbegin\n\tdeclare insert_status int default 0;\n\tDECLARE CONTINUE HANDLER FOR 1062 SET insert_status=1;\n\tcall TigAddUserPLainPw(_user_id, _user_passwd);\n\tif insert_status = 0 then\n\t\t select success_text;\n \telse\n\t\t select failure_text;\n\tend if;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUpdatePairs\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUpdatePairs`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUpdatePairs`(_nid bigint, _uid bigint, _tkey varchar(255) CHARSET utf8, _tval mediumtext CHARSET utf8)\nbegin\n  if exists(SELECT 1 FROM tig_pairs WHERE nid = _nid AND uid = _uid AND pkey = _tkey)\n  then\n    UPDATE tig_pairs SET pval = _tval WHERE nid = _nid AND uid = _uid AND pkey = _tkey;\n  ELSE\n    INSERT INTO tig_pairs (nid, uid, pkey, pval) VALUES (_nid, _uid, _tkey, _tval);\n  END IF;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUpdatePassword\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUpdatePassword`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUpdatePassword`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tupdate tig_users set user_pw = _user_pw where sha1_user_id = sha1(lower(_user_id));\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUpdatePasswordPlainPw\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUpdatePasswordPlainPw`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUpdatePasswordPlainPw`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigUpdatePassword(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigUpdatePassword(_user_id, _user_pw);\n\t\tend case;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUpdatePasswordPlainPwRev\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUpdatePasswordPlainPwRev`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUpdatePasswordPlainPwRev`(_user_pw varchar(255) CHARSET utf8, _user_id varchar(2049) CHARSET utf8)\nbegin\n\tcall TigUpdatePasswordPlainPw(_user_id, _user_pw);\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUserLogin\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUserLogin`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUserLogin`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tif exists(select 1 from tig_users\n\t\twhere (account_status > 0) AND (sha1_user_id = sha1(lower(_user_id))) AND (user_pw = _user_pw) AND (user_id = _user_id))\n\tthen\n\t\tupdate tig_users\n\t\t\tset online_status = online_status + 1, last_login = CURRENT_TIMESTAMP\n\t\t\twhere sha1_user_id = sha1(lower(_user_id));\n\t\tselect _user_id as user_id;\n\telse\n\t\tupdate tig_users set failed_logins = failed_logins + 1 where sha1_user_id = sha1(lower(_user_id));\n\t\tselect NULL as user_id;\n\tend if;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUserLoginPlainPw\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUserLoginPlainPw`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUserLoginPlainPw`(_user_id varchar(2049) CHARSET utf8, _user_pw varchar(255) CHARSET utf8)\nbegin\n\tcase TigGetDBProperty('password-encoding')\n\t\twhen 'MD5-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(_user_pw));\n\t\twhen 'MD5-USERID-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(CONCAT(_user_id, _user_pw)));\n\t\twhen 'MD5-USERNAME-PASSWORD' then\n\t\t\tcall TigUserLogin(_user_id, MD5(CONCAT(substring_index(_user_id, '@', 1), _user_pw)));\n\t\telse\n\t\t\tcall TigUserLogin(_user_id, _user_pw);\n\t\tend case;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUserLogout\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUserLogout`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUserLogout`(_user_id varchar(2049) CHARSET utf8)\nbegin\n\tupdate tig_users\n\t\tset online_status = greatest(online_status - 1, 0),\n\t\t\tlast_logout = CURRENT_TIMESTAMP\n\t\twhere user_id = _user_id;\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Procedure structure for TigUsers2Ver4Convert\n-- ----------------------------\nDROP PROCEDURE IF EXISTS `TigUsers2Ver4Convert`;\nDELIMITER ;;\nCREATE PROCEDURE `TigUsers2Ver4Convert`()\nbegin\n\n\tdeclare _user_id varchar(2049) CHARSET utf8;\n\tdeclare _password varchar(255) CHARSET utf8;\n\tdeclare _parent_nid bigint;\n\tdeclare _uid bigint;\n\tdeclare _node varchar(255) CHARSET utf8;\n\tdeclare l_last_row_fetched int default 0;\n\n\tDECLARE cursor_users CURSOR FOR\n\t\tselect user_id, pval as password\n\t\t\tfrom tig_users, tig_pairs\n\t\t\twhere tig_users.uid = tig_pairs.uid and pkey = 'password';\n\tDECLARE CONTINUE HANDLER FOR NOT FOUND SET l_last_row_fetched=1;\n\n\tSTART TRANSACTION;\n\n\t\tSET l_last_row_fetched=0;\n\n\t\tOPEN cursor_users;\n\t\t\tcursor_loop:LOOP\n\t\t\t\tFETCH cursor_users INTO _user_id, _password;\n    \t\tIF l_last_row_fetched=1 THEN\n      \t\tLEAVE cursor_loop;\n    \t\tEND IF;\n\t\t\t\tcall TigUpdatePasswordPlainPw(_user_id, _password);\n\t\t\tEND LOOP cursor_loop;\n\t\tCLOSE cursor_users;\n\n\t\tSET l_last_row_fetched=0;\n\n\tCOMMIT;\n\nend\n;;\nDELIMITER ;\n\n-- ----------------------------\n-- Function structure for TigGetDBProperty\n-- ----------------------------\nDROP FUNCTION IF EXISTS `TigGetDBProperty`;\nDELIMITER ;;\nCREATE FUNCTION `TigGetDBProperty`(_tkey varchar(255) CHARSET utf8) RETURNS mediumtext CHARSET utf8\n    READS SQL DATA\nbegin\n\tdeclare _result mediumtext CHARSET utf8;\n\n\tselect pval into _result from tig_pairs, tig_users\n\t\twhere (pkey = _tkey) AND (sha1_user_id = sha1(lower('db-properties')))\n\t\t\t\t\tAND (tig_pairs.uid = tig_users.uid);\n\n\treturn (_result);\nend\n;;\nDELIMITER ;\n\n\n-- ----------------------------\n-- Event structure for delete_msg_history_7day_before\n-- ----------------------------\nDROP EVENT IF EXISTS `delete_msg_history_7day_before`;\nDELIMITER ;;\nCREATE DEFINER=`root`@`%` EVENT `delete_msg_history_7day_before` ON SCHEDULE EVERY 1 DAY STARTS '2017-03-10 16:25:00' ON COMPLETION NOT PRESERVE ENABLE DO BEGIN\nDELETE FROM `msg_history` WHERE ts < DATE_ADD(CURDATE(),INTERVAL -7 DAY);\nEND\n;;\nDELIMITER ;\n\n\ncall TigAddUserPlainPw('db-properties', NULL);\n-- QUERY END:\n\nselect NOW(), ' - Setting schema version to 7.1';\n\n-- QUERY START:\ncall TigPutDBProperty('schema-version', '7.1');\n-- QUERY END:\n\n-- QUERY START:\ncall TigPutDBProperty('password-encoding', 'MD5-USERID-PASSWORD');\n-- QUERY END:\n"
  }
]